From 9f35f6793c76112578a89356d70c2c0b755e7b7b Mon Sep 17 00:00:00 2001 From: atanasster Date: Wed, 24 Jun 2020 14:58:42 -0400 Subject: [PATCH] fix: auto-expand first row --- ui/blocks/src/PropsTable/BasePropsTable.tsx | 425 ++++++++++---------- 1 file changed, 218 insertions(+), 207 deletions(-) diff --git a/ui/blocks/src/PropsTable/BasePropsTable.tsx b/ui/blocks/src/PropsTable/BasePropsTable.tsx index 87cc2b303..b046c478a 100644 --- a/ui/blocks/src/PropsTable/BasePropsTable.tsx +++ b/ui/blocks/src/PropsTable/BasePropsTable.tsx @@ -60,234 +60,245 @@ export const BasePropsTable: FC = ({ const { setControlValue, clickControl } = useContext(BlockControlsContext); const [copied, setCopied] = useState(false); const info: Partial = component.info || {}; - const storyControls = visibility !== 'info' ? story.controls || {} : {}; - const controls = visibleControls(storyControls); - const infoKeys = info && info.props ? Object.keys(info.props) : []; + + const controls = useMemo(() => { + const storyControls = visibility !== 'info' ? story.controls || {} : {}; + return visibleControls(storyControls); + }, [visibility, story.controls]); + const infoKeys = useMemo( + () => (info && info.props ? Object.keys(info.props) : []), + [info], + ); // check if we should display controls in the PrpsTable // at least one control's name should exist as a property name - const hasControls = !!Object.keys(controls).length; - const propControls = { ...controls }; - const { columns, rows, groupProps } = useMemo(() => { - const parents = new Set(); - const rows: (PropRow | null)[] = infoKeys - .map(key => { - //@ts-ignore - const prop = info.props[key]; - const control = propControls[key]; - const parentName = prop.parentName || control?.groupId || '-'; - const { description, label, required } = control || {}; - if (control) { - delete propControls[key]; - } else if (visibility === 'controls') { - return null; - } - parents.add(parentName); - return { - name: key, - prop: { - ...prop, - type: { - label, - required, - ...prop.type, - }, - description: description ?? prop.description, - parentName, - }, - control, - }; - }) - .filter(p => p); - if (propControls) { - const controlsRows: PropRow[] = []; - Object.keys(propControls).forEach(key => { - const control = propControls[key]; - if (!control.hidden) { - const parentName = control.groupId || '-'; + + const { hasControls, propControls } = useMemo( + () => ({ + hasControls: !!Object.keys(controls).length, + propControls: { ...controls }, + }), + [controls], + ); + const { columns, rows, groupProps } = useMemo( + () => { + const parents = new Set(); + const rows: (PropRow | null)[] = infoKeys + .map(key => { + //@ts-ignore + const prop = info.props[key]; + const control = propControls[key]; + const parentName = prop.parentName || control?.groupId || '-'; + const { description, label, required } = control || {}; + if (control) { + delete propControls[key]; + } else if (visibility === 'controls') { + return null; + } parents.add(parentName); - controlsRows.push({ + return { name: key, prop: { - description: control.description, - parentName, - defaultValue: control.defaultValue, + ...prop, type: { - name: control.type, - required: control.required, + label, + required, + ...prop.type, }, + description: description ?? prop.description, + parentName, }, control, - }); - } - }); - rows.unshift.apply(rows, controlsRows); - } - const groupProps: GroupingProps = {}; - if (parents.size > 1) { - groupProps.expanded = { - [`prop.parentName:${parents.values().next().value}`]: true, - }; - groupProps.groupBy = ['prop.parentName']; - } else { - groupProps.hiddenColumns = ['prop.parentName']; - } - const columns = [ - { - Header: 'Parent', - accessor: 'prop.parentName', - }, - { - Header: 'Name', - accessor: 'name', - Cell: ({ row: { original } }: any) => { - if (!original) { - return null; - } - const { - name, - prop: { - type: { required }, - }, - control, - } = original; - const text = ( - - {control ? control.label || name : name} - - ); - return required ? ( - - {text} - - ) : ( - text - ); - }, - }, - { - Header: 'Description', - accessor: 'prop.description', - width: '60%', - Cell: ({ row: { original } }: any) => { - if (!original) { - return null; + }; + }) + .filter(p => p); + if (propControls) { + const controlsRows: PropRow[] = []; + Object.keys(propControls).forEach(key => { + const control = propControls[key]; + if (!control.hidden) { + const parentName = control.groupId || '-'; + parents.add(parentName); + controlsRows.push({ + name: key, + prop: { + description: control.description, + parentName, + defaultValue: control.defaultValue, + type: { + name: control.type, + required: control.required, + }, + }, + control, + }); } - const { - name, - prop: { - description, - type: { raw, name: typeName, value }, - }, - } = original; - return ( - - {description && {description}} - {(raw ?? typeName) && ( - - {Array.isArray(value) && value.length > 1 - ? value.map(({ name: typeName, value }) => ( - - {value || typeName} - - )) - : raw ?? typeName} - - )} - - ); + }); + rows.unshift.apply(rows, controlsRows); + } + const groupProps: GroupingProps = {}; + if (parents.size > 1) { + const firstRowWithParent = rows.find(row => row?.prop.parentName); + if (firstRowWithParent) { + groupProps.expanded = { + [`prop.parentName:${firstRowWithParent.prop.parentName}`]: true, + }; + } + groupProps.groupBy = ['prop.parentName']; + } else { + groupProps.hiddenColumns = ['prop.parentName']; + } + const columns = [ + { + Header: 'Parent', + accessor: 'prop.parentName', }, - }, - { - Header: 'Default', - accessor: 'prop.defaultValue', - width: '40%', - Cell: ({ row: { original } }: any) => { - if (!original) { - return null; - } - const { - prop: { defaultValue }, - } = original; - let value = null; - switch (typeof defaultValue) { - case 'object': - value = JSON.stringify(defaultValue, null, 2); - break; - case 'undefined': - value = '-'; - break; - default: - value = defaultValue.toString(); - } - return ( - - {value} - - ); + { + Header: 'Name', + accessor: 'name', + Cell: ({ row: { original } }: any) => { + if (!original) { + return null; + } + const { + name, + prop: { + type: { required }, + }, + control, + } = original; + const text = ( + + {control ? control.label || name : name} + + ); + return required ? ( + + {text} + + ) : ( + text + ); + }, }, - }, - ...extraColumns, - ]; - if (hasControls) { - columns.push({ - Header: 'Controls', - accessor: 'control', - width: '30%', - Cell: ({ row: { original } }: any) => { - const { control } = original; - if (control && story) { - const InputType: PropertyEditor = - getPropertyEditor(control.type) || InvalidType; - + { + Header: 'Description', + accessor: 'prop.description', + width: '60%', + Cell: ({ row: { original } }: any) => { + if (!original) { + return null; + } + const { + name, + prop: { + description, + type: { raw, name: typeName, value }, + }, + } = original; return ( - + {description && {description}} + {(raw ?? typeName) && ( + + {Array.isArray(value) && value.length > 1 + ? value.map(({ name: typeName, value }) => ( + + {value || typeName} + + )) + : raw ?? typeName} + + )} ); - } - return null; + }, }, - }); - } - return { columns, rows, groupProps }; - }, [ - extraColumns, - hasControls, - info.props, - infoKeys, - propControls, - story, - visibility, - ]); + { + Header: 'Default', + accessor: 'prop.defaultValue', + width: '40%', + Cell: ({ row: { original } }: any) => { + if (!original) { + return null; + } + const { + prop: { defaultValue }, + } = original; + let value = null; + switch (typeof defaultValue) { + case 'object': + value = JSON.stringify(defaultValue, null, 2); + break; + case 'undefined': + value = '-'; + break; + default: + value = defaultValue.toString(); + } + return ( + + {value} + + ); + }, + }, + ...extraColumns, + ]; + if (hasControls) { + columns.push({ + Header: 'Controls', + accessor: 'control', + width: '30%', + Cell: ({ row: { original } }: any) => { + const { control } = original; + if (control) { + const InputType: PropertyEditor = + getPropertyEditor(control.type) || InvalidType; + + return ( + + + + ); + } + return null; + }, + }); + } + return { columns, rows, groupProps }; + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [extraColumns, hasControls, info.props, infoKeys, story.id, visibility], + ); const onChange = (propName: string, value: any) => { if (setControlValue && story) {