Skip to content

Commit

Permalink
feat: inline option array and object editors
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Oct 30, 2020
1 parent 4cbd674 commit c59f400
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 30 deletions.
8 changes: 8 additions & 0 deletions core/core/src/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ export interface ComponentControlArray
* the label for the editor button
*/
editLabel?: string;
/**
* if true, the editor will be rendered inline instead of a popup
*/
inline?: boolean;
}

export interface ComponentControlObject
Expand All @@ -279,6 +283,10 @@ export interface ComponentControlObject
* the label for the editor button
*/
editLabel?: string;
/**
* if true, the editor will be rendered inline instead of a popup
*/
inline?: boolean;
}

export interface ComponentControlButton<ClickEvent = () => void>
Expand Down
6 changes: 6 additions & 0 deletions ui/components/src/ThemeContext/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ export const theme: ControlsTheme = {
width: '100%',
},
} as any,
input: {
p: 1,
},
textarea: {
p: 1,
},
},
styles: {
root: {
Expand Down
26 changes: 26 additions & 0 deletions ui/editors/src/ArrayEditor/ArrayEditor.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,29 @@ export const overview: Example = () => {
</ControlsStateProvider>
);
};

export const inline: Example = () => {
const [state, setState] = React.useState([
{ name: 'Laptop' },
{ name: 'Book' },
{ name: 'Whiskey' },
]);
return (
<ControlsStateProvider
onChange={(name, newVal) => setState(newVal)}
controls={{
prop: {
type: ControlTypes.ARRAY,
rowType: { name: { type: ControlTypes.TEXT } },
value: state,
inline: true,
},
}}
>
<ul>
{state && state.map(item => <li key={item.name}>{item.name}</li>)}
</ul>
<ArrayEditor name="prop" />
</ControlsStateProvider>
);
};
45 changes: 25 additions & 20 deletions ui/editors/src/ArrayEditor/ArrayEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { FC } from 'react';
import { Button, Box, Flex } from 'theme-ui';
/** @jsx jsx */
import { FC, useState } from 'react';
import { jsx, Button, Box, Flex } from 'theme-ui';
import { deepmerge } from '@component-controls/core';
import { TrashcanIcon, PlusIcon } from '@primer/octicons-react';
import {
Expand All @@ -9,11 +10,11 @@ import {
newControlValues,
ComponentControls,
} from '@component-controls/core';

import { Popover } from '@component-controls/components';
import { useControl, ControlsStateProvider } from '@component-controls/store';
import { PropertyEditor, PropertyControlProps } from '../types';
import { addPropertyEditor, getPropertyEditor } from '../prop-factory';
import { PopupInline } from '../PopupInline';
import { EditButton } from '../EditButton';

const ChildContainer: FC = props => (
<Box
Expand Down Expand Up @@ -81,8 +82,8 @@ export const ArrayEditor: PropertyEditor<ArrayEditorProps> = ({
editLabel = 'edit...',
}) => {
const [control, setProp] = useControl<ComponentControlArray>(name);
const { editLabel: controlEditLabel } = control;
const [isOpen, setIsOpen] = React.useState(false);
const { editLabel: controlEditLabel, inline } = control;
const [isOpen, setIsOpen] = useState(false);
const handleChange = (
rowIndex: number,
propName: string | undefined,
Expand All @@ -107,7 +108,8 @@ export const ArrayEditor: PropertyEditor<ArrayEditorProps> = ({
}
};
return (
<Popover
<PopupInline
inline={inline}
trigger="click"
placement="bottom"
tooltipShown={isOpen}
Expand All @@ -117,16 +119,18 @@ export const ArrayEditor: PropertyEditor<ArrayEditorProps> = ({
tooltip={() => (
<ChildContainer>
<table>
<thead>
<tr>
{control.rowType &&
Object.keys(control.rowType).map(key => (
<th key={`head_${key}`}>
{control.rowType[key].label || key}
</th>
))}
</tr>
</thead>
{!inline && (
<thead>
<tr>
{control.rowType &&
Object.keys(control.rowType).map(key => (
<th key={`head_${key}`}>
{control.rowType[key].label || key}
</th>
))}
</tr>
</thead>
)}
<tbody>
{Array.isArray(control.value) &&
control.value.map((row, idx) => (
Expand Down Expand Up @@ -160,6 +164,7 @@ export const ArrayEditor: PropertyEditor<ArrayEditorProps> = ({
<Button
onClick={() => handleOnDelete(idx)}
aria-label="delete row"
sx={{ py: 1 }}
>
<TrashcanIcon />
</Button>
Expand All @@ -168,19 +173,19 @@ export const ArrayEditor: PropertyEditor<ArrayEditorProps> = ({
))}
</tbody>
</table>
<Button onClick={handleOnAdd} aria-label="add new row">
<EditButton onClick={handleOnAdd} aria-label="add new row">
<PlusIcon />
{` `}
Add row
</Button>
</EditButton>
</ChildContainer>
)}
>
<Button aria-label="edit the properties of the array">
{controlEditLabel || editLabel}
<Box />
</Button>
</Popover>
</PopupInline>
);
};

Expand Down
7 changes: 7 additions & 0 deletions ui/editors/src/EditButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @jsx jsx */
import { FC } from 'react';
import { jsx, Button, ButtonProps } from 'theme-ui';

export const EditButton: FC<ButtonProps> = props => (
<Button sx={{ py: 1 }} {...props} />
);
19 changes: 19 additions & 0 deletions ui/editors/src/ObjectEditor/ObjectEditor.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,22 @@ export const editLabel: Example = () => {
</ControlsStateProvider>
);
};

export const inline: Example = () => {
const [state, setState] = React.useState<ComponentControls>({
border: { type: ControlTypes.TEXT, value: '2px dashed silver' },
borderRadius: { type: ControlTypes.NUMBER, value: 10 },
padding: { type: ControlTypes.NUMBER, value: 10 },
});

return (
<ControlsStateProvider
onChange={(_name, newVal) => setState(newVal)}
controls={{
prop: { type: ControlTypes.OBJECT, value: state, inline: true },
}}
>
<ObjectEditor name="prop" />
</ControlsStateProvider>
);
};
17 changes: 9 additions & 8 deletions ui/editors/src/ObjectEditor/ObjectEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import React, { FC } from 'react';
import { Button, Box } from 'theme-ui';
import { Box } from 'theme-ui';
import {
ControlTypes,
ComponentControl,
ComponentControlObject,
mergeControlValues,
ComponentControls,
} from '@component-controls/core';
import { Popover } from '@component-controls/components';
import { useControl, ControlsStateProvider } from '@component-controls/store';
import { PropertyEditor, PropertyControlProps } from '../types';
import { addPropertyEditor, getPropertyEditor } from '../prop-factory';
import { PopupInline } from '../PopupInline';
import { EditButton } from '../EditButton';

const ChildContainer: FC = props => (
<Box
Expand Down Expand Up @@ -40,7 +41,7 @@ export const ObjectEditor: PropertyEditor<ObjectEditorProps> = ({
}) => {
const [control, onChange] = useControl<ComponentControlObject>(name);

const { editLabel: controlEditLabel } = control;
const { editLabel: controlEditLabel, inline } = control;
const [isOpen, setIsOpen] = React.useState(false);
const handleChange = (childName: string | undefined, value: any) => {
onChange(mergeControlValues(control.value as any, childName, value));
Expand Down Expand Up @@ -69,7 +70,8 @@ export const ObjectEditor: PropertyEditor<ObjectEditorProps> = ({
}
const childControls: ComponentControls = control.value || {};
return (
<Popover
<PopupInline
inline={inline}
trigger="click"
placement="bottom"
tooltipShown={isOpen}
Expand Down Expand Up @@ -101,11 +103,10 @@ export const ObjectEditor: PropertyEditor<ObjectEditorProps> = ({
</ChildContainer>
)}
>
<Button aria-label="edit the properties of the object">
<EditButton aria-label="edit the properties of the object">
{controlEditLabel || editLabel}
<Box />
</Button>
</Popover>
</EditButton>
</PopupInline>
);
};

Expand Down
13 changes: 13 additions & 0 deletions ui/editors/src/PopupInline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { FC } from 'react';
import { Popover, PopoverProps } from '@component-controls/components';

export const PopupInline: FC<PopoverProps & { inline?: boolean }> = ({
inline,
...props
}) => {
return inline && props.tooltip ? (
<div>{props.tooltip({} as any)}</div>
) : (
<Popover {...props} />
);
};
5 changes: 3 additions & 2 deletions ui/editors/src/TextEditor/TextEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { ChangeEvent } from 'react';
import { Input, Textarea } from 'theme-ui';
/** @jsx jsx */
import { ChangeEvent } from 'react';
import { jsx, Input, Textarea } from 'theme-ui';
import { ComponentControlText, ControlTypes } from '@component-controls/core';
import { useControl } from '@component-controls/store';
import { PropertyEditor } from '../types';
Expand Down

0 comments on commit c59f400

Please sign in to comment.