From f2d63c3a838c25310a39404473c1d557298463bb Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Tue, 16 Aug 2022 17:34:44 +0200 Subject: [PATCH 1/3] Add code component editor properties panel --- .../AppEditor/CodeComponentEditor/index.tsx | 53 +++++++++++++++++-- .../src/toolpad/propertyControls/string.tsx | 2 +- packages/toolpad-app/src/types.ts | 2 +- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx b/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx index a19f764857c..a2712f5d7c1 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx @@ -5,8 +5,15 @@ import createCache from '@emotion/cache'; import { CacheProvider } from '@emotion/react'; import * as ReactDOM from 'react-dom'; import { ErrorBoundary } from 'react-error-boundary'; -import { NodeId, createComponent, ToolpadComponent, TOOLPAD_COMPONENT } from '@mui/toolpad-core'; +import { + NodeId, + createComponent, + ToolpadComponent, + TOOLPAD_COMPONENT, + ArgTypeDefinitions, +} from '@mui/toolpad-core'; import { useQuery } from '@tanstack/react-query'; +import invariant from 'invariant'; import * as appDom from '../../../appDom'; import { useDom, useDomApi } from '../../DomLoader'; import { tryFormat } from '../../../utils/prettier'; @@ -17,17 +24,47 @@ import usePageTitle from '../../../utils/usePageTitle'; import useLatest from '../../../utils/useLatest'; import AppThemeProvider from '../../../runtime/AppThemeProvider'; import useCodeComponent from './useCodeComponent'; -import { mapValues } from '../../../utils/collections'; +import { filterValues, mapValues } from '../../../utils/collections'; import ErrorAlert from '../PageEditor/ErrorAlert'; import lazyComponent from '../../../utils/lazyComponent'; import CenteredSpinner from '../../../components/CenteredSpinner'; import SplitPane from '../../../components/SplitPane'; +import { getDefaultControl } from '../../propertyControls'; const TypescriptEditor = lazyComponent(() => import('../../../components/TypescriptEditor'), { noSsr: true, fallback: , }); +interface PropertiesEditorProps { + argTypes: ArgTypeDefinitions; + value: Record; + onChange: (newValue: Record) => void; +} + +function PropertiesEditor({ argTypes, value, onChange }: PropertiesEditorProps) { + return ( + + Properties: + {Object.entries(argTypes).map(([name, argType]) => { + invariant(argType, 'Argtype should be defined'); + const Control = getDefaultControl(argType); + if (!Control) { + return null; + } + return ( + onChange({ ...value, [name]: newPropValue })} + /> + ); + })} + + ); +} + const Noop = createComponent(() => null); const CanvasFrame = styled('iframe')({ @@ -148,6 +185,8 @@ function CodeComponentEditorContent({ codeComponentNode }: CodeComponentEditorCo [argTypes], ); + const [props, setProps] = React.useState({}); + return ( @@ -162,7 +201,10 @@ function CodeComponentEditorContent({ codeComponentNode }: CodeComponentEditorCo extraLibs={extraLibs} /> - + + + + } > - + typeof propValue !== 'undefined')} + /> {compileError ? : null} diff --git a/packages/toolpad-app/src/toolpad/propertyControls/string.tsx b/packages/toolpad-app/src/toolpad/propertyControls/string.tsx index f150006e2c7..0d8d86351cf 100644 --- a/packages/toolpad-app/src/toolpad/propertyControls/string.tsx +++ b/packages/toolpad-app/src/toolpad/propertyControls/string.tsx @@ -5,7 +5,7 @@ import type { EditorProps } from '../../types'; function StringPropEditor({ label, value, onChange, disabled }: EditorProps) { const handleChange = React.useCallback( (event: React.ChangeEvent) => { - onChange(event.target.value); + onChange(event.target.value || undefined); }, [onChange], ); diff --git a/packages/toolpad-app/src/types.ts b/packages/toolpad-app/src/types.ts index 162828517bb..480ef11b777 100644 --- a/packages/toolpad-app/src/types.ts +++ b/packages/toolpad-app/src/types.ts @@ -23,7 +23,7 @@ export interface EditorProps { propType: PropValueType; disabled?: boolean; value: T | undefined; - onChange: (newValue: T) => void; + onChange: (newValue: T | undefined) => void; } export type FlowDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse'; From c255111c69541009a3832a422dac132d1326963c Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Tue, 16 Aug 2022 17:52:32 +0200 Subject: [PATCH 2/3] fault tolerant --- .../AppEditor/CodeComponentEditor/index.tsx | 43 +++++++++++++------ .../src/toolpad/propertyControls/select.tsx | 2 +- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx b/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx index a2712f5d7c1..ff1f8ee0ccb 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx @@ -11,6 +11,7 @@ import { ToolpadComponent, TOOLPAD_COMPONENT, ArgTypeDefinitions, + ArgTypeDefinition, } from '@mui/toolpad-core'; import { useQuery } from '@tanstack/react-query'; import invariant from 'invariant'; @@ -30,16 +31,32 @@ import lazyComponent from '../../../utils/lazyComponent'; import CenteredSpinner from '../../../components/CenteredSpinner'; import SplitPane from '../../../components/SplitPane'; import { getDefaultControl } from '../../propertyControls'; +import { WithControlledProp } from '../../../utils/types'; const TypescriptEditor = lazyComponent(() => import('../../../components/TypescriptEditor'), { noSsr: true, fallback: , }); -interface PropertiesEditorProps { +interface PropertyEditorProps extends WithControlledProp { + name: string; + argType: ArgTypeDefinition; +} + +function PropertyEditor({ argType, name, value, onChange }: PropertyEditorProps) { + const Control = getDefaultControl(argType); + if (!Control) { + return null; + } + return ( + + + + ); +} + +interface PropertiesEditorProps extends WithControlledProp> { argTypes: ArgTypeDefinitions; - value: Record; - onChange: (newValue: Record) => void; } function PropertiesEditor({ argTypes, value, onChange }: PropertiesEditorProps) { @@ -47,18 +64,16 @@ function PropertiesEditor({ argTypes, value, onChange }: PropertiesEditorProps) Properties: {Object.entries(argTypes).map(([name, argType]) => { - invariant(argType, 'Argtype should be defined'); - const Control = getDefaultControl(argType); - if (!Control) { - return null; - } + invariant(argType, 'argType not defined'); return ( - onChange({ ...value, [name]: newPropValue })} - /> + {name}} resetKeys={[argType]}> + onChange({ ...value, [name]: newPropValue })} + /> + ); })} diff --git a/packages/toolpad-app/src/toolpad/propertyControls/select.tsx b/packages/toolpad-app/src/toolpad/propertyControls/select.tsx index ef50e0ff61c..1cabe20ed44 100644 --- a/packages/toolpad-app/src/toolpad/propertyControls/select.tsx +++ b/packages/toolpad-app/src/toolpad/propertyControls/select.tsx @@ -6,7 +6,7 @@ function SelectPropEditor({ label, propType, value, onChange, disabled }: Editor const items = propType.type === 'string' ? propType.enum ?? [] : []; const handleChange = React.useCallback( (event: React.ChangeEvent) => { - onChange(event.target.value); + onChange(event.target.value || undefined); }, [onChange], ); From 7a861d97f5cd4266e584615828b2ca4846046436 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Tue, 16 Aug 2022 19:19:01 +0200 Subject: [PATCH 3/3] Remove redundant ErrorBoundary --- .../src/toolpad/AppEditor/CodeComponentEditor/index.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx b/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx index ff1f8ee0ccb..8397d71575d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/CodeComponentEditor/index.tsx @@ -48,11 +48,7 @@ function PropertyEditor({ argType, name, value, onChange }: PropertyEditorProps) if (!Control) { return null; } - return ( - - - - ); + return ; } interface PropertiesEditorProps extends WithControlledProp> {