diff --git a/src/__stories__/JsonSchemaViewer.tsx b/src/__stories__/JsonSchemaViewer.tsx index 103b8962..cde18580 100644 --- a/src/__stories__/JsonSchemaViewer.tsx +++ b/src/__stories__/JsonSchemaViewer.tsx @@ -6,6 +6,7 @@ import { boolean, number, object, select, text, withKnobs } from '@storybook/add import { storiesOf } from '@storybook/react'; import { JsonSchemaViewer } from '../components'; +import { Checkbox } from '@stoplight/ui-kit'; import { JSONSchema4 } from 'json-schema'; import * as allOfSchemaResolved from '../__fixtures__/allOf/allOf-resolved.json'; import * as allOfSchema from '../__fixtures__/allOf/allOf-schema.json'; @@ -108,4 +109,19 @@ storiesOf('JsonSchemaViewer', module) onGoToRef={action('onGoToRef')} /> + )) + .add('with rowRendererRight', () => ( + ( + + + + )} + name={text('name', 'my schema')} + schema={schema as JSONSchema4} + defaultExpandedDepth={number('defaultExpandedDepth', 2)} + expanded={boolean('expanded', false)} + hideTopBar={boolean('hideTopBar', false)} + onGoToRef={action('onGoToRef')} + /> )); diff --git a/src/components/JsonSchemaViewer.tsx b/src/components/JsonSchemaViewer.tsx index 20c91473..562ac176 100644 --- a/src/components/JsonSchemaViewer.tsx +++ b/src/components/JsonSchemaViewer.tsx @@ -4,13 +4,13 @@ import { runInAction } from 'mobx'; import * as React from 'react'; import { JSONSchema4 } from 'json-schema'; -import { GoToRefHandler } from '../types'; +import { GoToRefHandler, IExtendableRenderers } from '../types'; import { isSchemaViewerEmpty, renderSchema } from '../utils'; import { SchemaTree } from './SchemaTree'; export type FallbackComponent = React.ComponentType<{ error: Error | null }>; -export interface IJsonSchemaViewer { +export interface IJsonSchemaViewer extends IExtendableRenderers { schema: JSONSchema4; dereferencedSchema?: JSONSchema4; style?: object; @@ -22,6 +22,7 @@ export interface IJsonSchemaViewer { hideTopBar?: boolean; maxRows?: number; onGoToRef?: GoToRefHandler; + mergeAllOf?: boolean; FallbackComponent?: FallbackComponent; } @@ -33,7 +34,16 @@ export class JsonSchemaViewerComponent extends React.PureComponent void; } const ICON_SIZE = 12; const ICON_DIMENSION = 20; -const ROW_OFFSET = 7; -export const SchemaRow: React.FunctionComponent = ({ node, rowOptions, onGoToRef }) => { +export const SchemaRow: React.FunctionComponent = ({ + node, + rowOptions, + onGoToRef, + rowRendererRight, + toggleExpand, +}) => { const schemaNode = node.metadata as SchemaNodeWithMeta; const { name, $ref, subtype, required } = schemaNode; @@ -58,12 +64,14 @@ export const SchemaRow: React.FunctionComponent = ({ node, rowOption ); + const combinerOffset = ICON_DIMENSION * node.level; return ( -
+
+ {/* Do not set position: relative. Divider must be relative to the parent container in order to avoid bugs related to this container calculated height changes. */}
{node.canHaveChildren && @@ -71,7 +79,7 @@ export const SchemaRow: React.FunctionComponent = ({ node, rowOption
= ({ node, rowOption )} {schemaNode.divider && ( -
+
{schemaNode.divider}
@@ -171,6 +186,7 @@ export const SchemaRow: React.FunctionComponent = ({ node, rowOption ) : ( requiredElem )} + {rowRendererRight &&
{rowRendererRight(node)}
}
); diff --git a/src/components/SchemaTree.tsx b/src/components/SchemaTree.tsx index b0262273..b62a1486 100644 --- a/src/components/SchemaTree.tsx +++ b/src/components/SchemaTree.tsx @@ -1,13 +1,12 @@ -import { TreeList, TreeListEvents, TreeStore } from '@stoplight/tree-list'; +import { TreeList, TreeStore } from '@stoplight/tree-list'; import * as cn from 'classnames'; import { JSONSchema4 } from 'json-schema'; import { observer } from 'mobx-react-lite'; import * as React from 'react'; - -import { GoToRefHandler } from '../types'; +import { GoToRefHandler, IExtendableRenderers, SchemaTreeListNode } from '../types'; import { SchemaRow } from './'; -export interface ISchemaTree { +export interface ISchemaTree extends IExtendableRenderers { treeStore: TreeStore; schema: JSONSchema4; className?: string; @@ -24,19 +23,12 @@ const canDrag = () => false; export const SchemaTree = observer(props => { const { hideTopBar, name, treeStore, maxRows, className, onGoToRef } = props; - treeStore.on(TreeListEvents.NodeClick, (e, node) => treeStore.toggleExpand(node)); - const itemData = { treeStore, count: treeStore.nodes.length, onGoToRef, }; - const rowRenderer = React.useCallback( - (node, rowOptions) => , - [itemData.count], - ); - return (
{name && @@ -50,9 +42,24 @@ export const SchemaTree = observer(props => { striped maxRows={maxRows !== undefined ? maxRows + 0.5 : maxRows} store={treeStore} - rowRenderer={rowRenderer} + rowRenderer={(node, rowOptions) => { + // TODO: add a React.useCallback to rerender only when either itemData.count or maskProps (to be found in studio) change + + return ( + { + treeStore.toggleExpand(node); + }} + rowRendererRight={props.rowRendererRight} + node={node as SchemaTreeListNode} + rowOptions={rowOptions} + {...itemData} + /> + ); + }} canDrag={canDrag} /> + {props.schemaControlsRenderer && props.schemaControlsRenderer()}
); }); diff --git a/src/components/__tests__/SchemaRow.spec.tsx b/src/components/__tests__/SchemaRow.spec.tsx index 0f362567..14aa4d76 100644 --- a/src/components/__tests__/SchemaRow.spec.tsx +++ b/src/components/__tests__/SchemaRow.spec.tsx @@ -27,7 +27,9 @@ describe('SchemaRow component', () => { isExpanded: true, }; - const wrapper = shallow(shallow() + const wrapper = shallow(shallow( + null} node={node as SchemaTreeListNode} rowOptions={rowOptions} />, + ) .find(Popover) .prop('content') as React.ReactElement); diff --git a/src/types.ts b/src/types.ts index 1720a52f..8bd7adbe 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,6 +2,11 @@ import { TreeListNode } from '@stoplight/tree-list'; import { Dictionary, JsonPath } from '@stoplight/types'; import { JSONSchema4, JSONSchema4TypeName } from 'json-schema'; +export interface IExtendableRenderers { + rowRendererRight?: (node: SchemaTreeListNode) => React.ReactElement; + schemaControlsRenderer?: () => React.ReactElement; +} + export const enum SchemaKind { Any = 'any', String = 'string',