From f6f3261dccf2c22d43e49b26163152d2707493d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Tue, 13 Feb 2024 15:18:18 +0100 Subject: [PATCH] Data picker - move the picker next to the prop name (#4885) * `useDataPickerButton` * array & object control * update snapshots --- .../component-section/component-section.tsx | 258 ++++++++++-------- ...performance-regression-tests.spec.tsx.snap | 20 +- .../performance-regression-tests.spec.tsx | 4 +- 3 files changed, 151 insertions(+), 131 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 587a5561f378..0c1050e344f5 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -165,23 +165,6 @@ export const ParseErrorControl = React.memo((props: ParseErrorProps) => { ) }) -const WarningTooltip = React.memo(({ warning }: { warning: string }) => { - const colorTheme = useColorTheme() - return ( - -
- - ) -}) - interface AbstractRowForControlProps { propPath: PropertyPath isScene: boolean @@ -209,6 +192,81 @@ function getLabelControlStyle( } } +const isBaseIndentationLevel = (props: AbstractRowForControlProps) => props.indentationLevel === 1 + +function useDataPickerButton(propPath: PropertyPath) { + const [referenceElement, setReferenceElement] = React.useState(null) + const [popperElement, setPopperElement] = React.useState(null) + const popper = usePopper(referenceElement, popperElement, { + modifiers: [ + { + name: 'offset', + options: { + offset: [0, 8], + }, + }, + ], + }) + + const [popupIsOpen, setPopupIsOpen] = React.useState(false) + const togglePopup = React.useCallback(() => setPopupIsOpen((v) => !v), []) + const closePopup = React.useCallback(() => setPopupIsOpen(false), []) + + const onClick = React.useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + + togglePopup() + }, + [togglePopup], + ) + + const variablePickerButtonAvailable = useVariablesInScopeForSelectedElement().length > 0 + const variablePickerButtonTooltipText = variablePickerButtonAvailable + ? 'Pick data source' + : 'No data sources available' + + const DataPickerComponent = React.useMemo( + () => ( + + ), + [closePopup, popper.attributes.popper, popper.styles.popper, propPath], + ) + + const DataPickerOpener = React.useMemo( + () => ( + + ), + [onClick, variablePickerButtonAvailable, variablePickerButtonTooltipText], + ) + + return { + popupIsOpen, + DataPickerOpener, + DataPickerComponent, + setReferenceElement, + } +} + interface RowForBaseControlProps extends AbstractRowForControlProps { label?: React.ComponentType> // TODO Before Merge this probably should not be a component controlDescription: BaseControlDescription @@ -256,35 +314,7 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { ) - const [referenceElement, setReferenceElement] = React.useState(null) - const [popperElement, setPopperElement] = React.useState(null) - const { styles, attributes } = usePopper(referenceElement, popperElement, { - modifiers: [ - { - name: 'offset', - options: { - offset: [0, 8], - }, - }, - ], - }) - - const [popupIsOpen, setPopupIsOpen] = React.useState(false) - const togglePopup = React.useCallback(() => setPopupIsOpen((v) => !v), []) - const closePopup = React.useCallback(() => setPopupIsOpen(false), []) - - const onClick = React.useCallback( - (e: React.MouseEvent) => { - togglePopup() - e.stopPropagation() - }, - [togglePopup], - ) - - const variablePickerButtonAvailable = useVariablesInScopeForSelectedElement().length > 0 - const variablePickerButtonTooltipText = variablePickerButtonAvailable - ? 'Pick data source' - : 'No data sources available' + const dataPickerButtonData = useDataPickerButton(props.propPath) if (controlDescription.control === 'none') { // do not list anything for `none` controls @@ -298,22 +328,14 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { items={contextMenuItems} data={null} > - {popupIsOpen ? ( - - ) : null} + {dataPickerButtonData.popupIsOpen ? dataPickerButtonData.DataPickerComponent : null} {propertyLabel} -
+
{ focusOnMount={props.focusOnMount} />
- + {when(isBaseIndentationLevel(props), dataPickerButtonData.DataPickerOpener)} ) @@ -530,34 +540,45 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { false, ) + const dataPickerButtonData = useDataPickerButton(props.propPath) + return ( + {when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)} - - - {title} - - {propertyStatus.overwritable ? ( - + + - {insertingRow ? ( - - ) : ( - - )} - - ) : null} + {title} + + {propertyStatus.overwritable ? ( + + {insertingRow ? ( + + ) : ( + + )} + + ) : null} + + {when(isBaseIndentationLevel(props), dataPickerButtonData.DataPickerOpener)}
{ isScene={isScene} propPath={PP.appendPropertyPathElems(propPath, [index])} setGlobalCursor={props.setGlobalCursor} - indentationLevel={1} + indentationLevel={2} focusOnMount={props.focusOnMount && index === 0} disableToggling={true} /> @@ -689,6 +710,7 @@ const RowForTupleControl = React.memo((props: RowForTupleControlProps) => { + {when(isBaseIndentationLevel(props),
I0
)} {title} @@ -796,6 +818,8 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => { addOnUnsetValues([PP.lastPart(propPath)], propMetadata.onUnsetValues), ]) + const dataPickerButtonData = useDataPickerButton(props.propPath) + return (
{ }, }} > -
+
- - - {title} - {unless(props.disableToggling, )} - - + {when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)} + + + + {title} + {unless(props.disableToggling, )} + + + {when(isBaseIndentationLevel(props), dataPickerButtonData.DataPickerOpener)} +
{when( @@ -923,6 +954,7 @@ const RowForUnionControl = React.memo((props: RowForUnionControlProps) => { } else { return ( + {when(isBaseIndentationLevel(props),
I0
)} {label}
diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 93e9582a4c2b..f35d49e53b73 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -153,10 +153,11 @@ Array [ "/null///span", "/null///UtopiaSpiedClass(Tooltip)", "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", + "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", "/null///Symbol(react.memo)(Icon)", "/null///Symbol(react.forward_ref)(Styled(div)):data-testid='data-picker-popup-button-test-id'", + "/null///Symbol(react.memo)()", + "/null///div", "/null///UtopiaSpiedFunctionComponent(UIGridRow)", "/null///UtopiaSpiedClass(InspectorContextMenuWrapper)", "///UtopiaSpiedClass(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -426,8 +427,6 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///Symbol(react.memo)(Icon)", - "/null///Symbol(react.forward_ref)(Styled(div)):data-testid='data-picker-popup-button-test-id'", "/null///UtopiaSpiedFunctionComponent(UIGridRow)", "/null///UtopiaSpiedClass(InspectorContextMenuWrapper)", "///UtopiaSpiedClass(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -446,7 +445,6 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div//Symbol(react.memo)(ExpressionInputPropertyControl)", "/div//ExpressionInputPropertyControl/Symbol(react.memo)(Symbol(react.forward_ref)())", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div:data-testid='data-picker-popup-button-test-id'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", @@ -1289,8 +1287,6 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///Symbol(react.memo)(Icon)", - "/null///Symbol(react.forward_ref)(Styled(div)):data-testid='data-picker-popup-button-test-id'", "/null///UtopiaSpiedFunctionComponent(UIGridRow)", "/null///UtopiaSpiedClass(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", @@ -1568,10 +1564,9 @@ Array [ "/null///span", "/null///UtopiaSpiedClass(Tooltip)", "/null///Symbol(react.memo)(PropertyLabel)", + "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", "/null///Symbol(react.memo)()", "/null///div", - "/null///Symbol(react.memo)(Icon)", - "/null///Symbol(react.forward_ref)(Styled(div)):data-testid='data-picker-popup-button-test-id'", "/null///UtopiaSpiedFunctionComponent(UIGridRow)", "/null///UtopiaSpiedClass(InspectorContextMenuWrapper)", "///UtopiaSpiedClass(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -1597,7 +1592,6 @@ Array [ "/Symbol(react.forward_ref)()/form/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)():data-testid='onMouseDown-expression-input-property-control'", "/div/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)()/input:data-testid='onMouseDown-expression-input-property-control'", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div:data-testid='data-picker-popup-button-test-id'", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/UtopiaSpiedFunctionComponent(Item)", @@ -1756,8 +1750,6 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///Symbol(react.memo)(Icon)", - "/null///Symbol(react.forward_ref)(Styled(div)):data-testid='data-picker-popup-button-test-id'", "/null///UtopiaSpiedFunctionComponent(UIGridRow)", "/null///UtopiaSpiedClass(InspectorContextMenuWrapper)", "///UtopiaSpiedClass(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -1776,7 +1768,6 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div//Symbol(react.memo)(ExpressionInputPropertyControl)", "/div//ExpressionInputPropertyControl/Symbol(react.memo)(Symbol(react.forward_ref)())", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div:data-testid='data-picker-popup-button-test-id'", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/UtopiaSpiedFunctionComponent(Item)", @@ -1992,8 +1983,6 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///Symbol(react.memo)(Icon)", - "/null///Symbol(react.forward_ref)(Styled(div)):data-testid='data-picker-popup-button-test-id'", "/null///UtopiaSpiedFunctionComponent(UIGridRow)", "/null///UtopiaSpiedClass(InspectorContextMenuWrapper)", "///UtopiaSpiedClass(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -2012,7 +2001,6 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div//Symbol(react.memo)(ExpressionInputPropertyControl)", "/div//ExpressionInputPropertyControl/Symbol(react.memo)(Symbol(react.forward_ref)())", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div:data-testid='data-picker-popup-button-test-id'", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/span", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedClass(MomentumContextMenu)/UtopiaSpiedFunctionComponent(Item)", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index 6a9d11543625..085608fa8970 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`865`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`855`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`625`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`623`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) })