Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data picker - move the picker next to the prop name #4885

Merged
merged 3 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -165,23 +165,6 @@ export const ParseErrorControl = React.memo((props: ParseErrorProps) => {
)
})

const WarningTooltip = React.memo(({ warning }: { warning: string }) => {
const colorTheme = useColorTheme()
return (
<Tooltip title={warning}>
<div
style={{
width: 5,
height: 5,
background: colorTheme.warningBgSolid.value,
borderRadius: '50%',
marginRight: 4,
}}
/>
</Tooltip>
)
})

interface AbstractRowForControlProps {
propPath: PropertyPath
isScene: boolean
Expand Down Expand Up @@ -209,6 +192,81 @@ function getLabelControlStyle(
}
}

const isBaseIndentationLevel = (props: AbstractRowForControlProps) => props.indentationLevel === 1

function useDataPickerButton(propPath: PropertyPath) {
const [referenceElement, setReferenceElement] = React.useState<HTMLDivElement | null>(null)
const [popperElement, setPopperElement] = React.useState<HTMLDivElement | null>(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(
() => (
<DataPickerPopup
{...popper.attributes.popper}
style={popper.styles.popper}
closePopup={closePopup}
ref={setPopperElement}
propPath={propPath}
/>
),
[closePopup, popper.attributes.popper, popper.styles.popper, propPath],
)

const DataPickerOpener = React.useMemo(
() => (
<Button
onClick={onClick}
data-testid={DataPickerPopupButtonTestId}
disabled={!variablePickerButtonAvailable}
>
<Icn
type='pipette'
color='secondary'
tooltipText={variablePickerButtonTooltipText}
width={18}
height={18}
/>
</Button>
),
[onClick, variablePickerButtonAvailable, variablePickerButtonTooltipText],
)

return {
popupIsOpen,
DataPickerOpener,
DataPickerComponent,
setReferenceElement,
}
}

interface RowForBaseControlProps extends AbstractRowForControlProps {
label?: React.ComponentType<React.PropsWithChildren<any>> // TODO Before Merge this probably should not be a component
controlDescription: BaseControlDescription
Expand Down Expand Up @@ -256,35 +314,7 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => {
<props.label />
)

const [referenceElement, setReferenceElement] = React.useState<HTMLDivElement | null>(null)
const [popperElement, setPopperElement] = React.useState<HTMLDivElement | null>(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
Expand All @@ -298,22 +328,14 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => {
items={contextMenuItems}
data={null}
>
{popupIsOpen ? (
<DataPickerPopup
{...attributes.popper}
style={styles.popper}
closePopup={closePopup}
ref={setPopperElement}
propPath={propPath}
/>
) : null}
{dataPickerButtonData.popupIsOpen ? dataPickerButtonData.DataPickerComponent : null}
<UIGridRow
padded={false}
style={{ paddingLeft: 0, paddingRight: 8, paddingTop: 3, paddingBottom: 3 }}
variant='<--1fr--><--1fr-->|-18px-|'
>
{propertyLabel}
<div ref={setReferenceElement}>
<div ref={dataPickerButtonData.setReferenceElement}>
<ControlForProp
propPath={propPath}
propName={propName}
Expand All @@ -323,19 +345,7 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => {
focusOnMount={props.focusOnMount}
/>
</div>
<Button
onClick={onClick}
data-testid={DataPickerPopupButtonTestId}
disabled={!variablePickerButtonAvailable}
>
<Icn
type='pipette'
color='secondary'
tooltipText={variablePickerButtonTooltipText}
width={18}
height={18}
/>
</Button>
{when(isBaseIndentationLevel(props), dataPickerButtonData.DataPickerOpener)}
</UIGridRow>
</InspectorContextMenuWrapper>
)
Expand Down Expand Up @@ -528,34 +538,45 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => {
false,
)

const dataPickerButtonData = useDataPickerButton(props.propPath)

return (
<React.Fragment>
{when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)}
<InspectorSectionHeader>
<SimpleFlexRow style={{ flexGrow: 1, gap: 5 }}>
<PropertyLabel target={[propPath]} style={{ textTransform: 'capitalize', paddingTop: 2 }}>
{title}
</PropertyLabel>
{propertyStatus.overwritable ? (
<SquareButton
highlight
onMouseDown={toggleInsertRow}
data-testid={`toggle-insert-${PP.toString(propPath)}`}
<SimpleFlexRow
style={{ gap: 5, justifyContent: 'space-between', flexGrow: 1, paddingRight: 3 }}
>
<FlexRow style={{ gap: 5 }} ref={dataPickerButtonData.setReferenceElement}>
<PropertyLabel
target={[propPath]}
style={{ textTransform: 'capitalize', paddingTop: 2 }}
>
{insertingRow ? (
<Icons.Minus
color={propertyStatus.controlled ? 'dynamic' : 'secondary'}
width={16}
height={16}
/>
) : (
<Icons.Plus
color={propertyStatus.controlled ? 'dynamic' : 'secondary'}
width={16}
height={16}
/>
)}
</SquareButton>
) : null}
{title}
</PropertyLabel>
{propertyStatus.overwritable ? (
<SquareButton
highlight
onMouseDown={toggleInsertRow}
data-testid={`toggle-insert-${PP.toString(propPath)}`}
>
{insertingRow ? (
<Icons.Minus
color={propertyStatus.controlled ? 'dynamic' : 'secondary'}
width={16}
height={16}
/>
) : (
<Icons.Plus
color={propertyStatus.controlled ? 'dynamic' : 'secondary'}
width={16}
height={16}
/>
)}
</SquareButton>
) : null}
</FlexRow>
{when(isBaseIndentationLevel(props), dataPickerButtonData.DataPickerOpener)}
</SimpleFlexRow>
</InspectorSectionHeader>
<div
Expand Down Expand Up @@ -631,7 +652,7 @@ const ArrayControlItem = React.memo((props: ArrayControlItemProps) => {
isScene={isScene}
propPath={PP.appendPropertyPathElems(propPath, [index])}
setGlobalCursor={props.setGlobalCursor}
indentationLevel={1}
indentationLevel={2}
focusOnMount={props.focusOnMount && index === 0}
disableToggling={true}
/>
Expand Down Expand Up @@ -687,6 +708,7 @@ const RowForTupleControl = React.memo((props: RowForTupleControlProps) => {
<React.Fragment>
<InspectorSectionHeader>
<SimpleFlexRow style={{ flexGrow: 1 }}>
{when(isBaseIndentationLevel(props), <div>I0</div>)}
<PropertyLabel target={[propPath]} style={{ textTransform: 'capitalize' }}>
{title}
</PropertyLabel>
Expand Down Expand Up @@ -794,6 +816,8 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => {
addOnUnsetValues([PP.lastPart(propPath)], propMetadata.onUnsetValues),
])

const dataPickerButtonData = useDataPickerButton(props.propPath)

return (
<div
css={{
Expand All @@ -807,30 +831,37 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => {
},
}}
>
<div onClick={handleOnClick}>
<div>
<InspectorContextMenuWrapper
id={`context-menu-for-${PP.toString(propPath)}`}
items={contextMenuItems}
data={null}
>
<SimpleFlexRow style={{ flexGrow: 1, paddingRight: 8 }}>
<PropertyLabel
target={[propPath]}
style={{
textTransform: 'capitalize',
paddingLeft: indentation,
display: 'flex',
alignItems: 'center',
height: 34,
fontWeight: 500,
gap: 4,
cursor: props.disableToggling ? 'default' : 'pointer',
}}
>
{title}
{unless(props.disableToggling, <ObjectIndicator open={open} />)}
</PropertyLabel>
</SimpleFlexRow>
{when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)}
<FlexRow
style={{ flexGrow: 1, justifyContent: 'space-between', paddingRight: 10 }}
ref={dataPickerButtonData.setReferenceElement}
>
<SimpleFlexRow style={{ flexGrow: 1, paddingRight: 8 }} onClick={handleOnClick}>
<PropertyLabel
target={[propPath]}
style={{
textTransform: 'capitalize',
paddingLeft: indentation,
display: 'flex',
alignItems: 'center',
height: 34,
fontWeight: 500,
gap: 4,
cursor: props.disableToggling ? 'default' : 'pointer',
}}
>
{title}
{unless(props.disableToggling, <ObjectIndicator open={open} />)}
</PropertyLabel>
</SimpleFlexRow>
{when(isBaseIndentationLevel(props), dataPickerButtonData.DataPickerOpener)}
</FlexRow>
</InspectorContextMenuWrapper>
</div>
{when(
Expand Down Expand Up @@ -921,6 +952,7 @@ const RowForUnionControl = React.memo((props: RowForUnionControlProps) => {
} else {
return (
<React.Fragment>
{when(isBaseIndentationLevel(props), <div>I0</div>)}
{label}
<RowForControl {...props} controlDescription={controlToUse} focusOnMount={false} />
</React.Fragment>
Expand Down
Loading
Loading