From a368ada02ce86ea5b3069d064836ea086b566a8c Mon Sep 17 00:00:00 2001 From: bytasv Date: Thu, 29 Dec 2022 17:09:50 +0200 Subject: [PATCH 1/2] Add datepicker --- .../toolpad-app/src/runtime/ToolpadApp.tsx | 12 ++- .../AppEditor/PageEditor/BindableEditor.tsx | 6 +- .../AppEditor/PageEditor/ComponentEditor.tsx | 34 +++---- .../src/toolpadComponents/index.tsx | 1 + .../toolpad-components/src/DatePicker.tsx | 93 +++++++++++++++++++ packages/toolpad-components/src/index.tsx | 2 + 6 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 packages/toolpad-components/src/DatePicker.tsx diff --git a/packages/toolpad-app/src/runtime/ToolpadApp.tsx b/packages/toolpad-app/src/runtime/ToolpadApp.tsx index a034015adb3..8985868d643 100644 --- a/packages/toolpad-app/src/runtime/ToolpadApp.tsx +++ b/packages/toolpad-app/src/runtime/ToolpadApp.tsx @@ -266,12 +266,20 @@ function RenderedNodeContent({ node, childNodeGroups, Component }: RenderedNodeC const handler = (param: any) => { const bindingId = `${nodeId}.props.${key}`; - const value = argType.onChangeHandler ? argType.onChangeHandler(param) : param; + + const defaultValues = _.mapValues(argTypes, ({ defaultValue }) => defaultValue); + const propsValues = _.mapValues(node.props, ({ value }) => value); + const props = { + ...defaultValues, + ...propsValues, + }; + + const value = argType.onChangeHandler ? argType.onChangeHandler(param, props) : param; setControlledBinding(bindingId, { value }); }; return [argType.onChangeProp, handler]; }), - [argTypes, nodeId, setControlledBinding], + [argTypes, nodeId, setControlledBinding, node.props], ); const navigateToPage = usePageNavigator(); diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/BindableEditor.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/BindableEditor.tsx index 79365357f41..2e76be4d438 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/BindableEditor.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/BindableEditor.tsx @@ -49,11 +49,13 @@ export default function BindableEditor({ ); const initConstValue = React.useCallback(() => { + let constValue = liveBinding?.value; + if (value?.type === 'const') { - return value.value; + constValue = value.value; } - return liveBinding?.value; + return constValue; }, [liveBinding, value]); const constValue = React.useMemo(initConstValue, [value, initConstValue]); diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx index 86d663d8935..eb2c50bc9bb 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx @@ -90,26 +90,20 @@ function ComponentPropsEditor

({ Layout: - {hasLayoutHorizontalControls ? ( -

- -
- ) : null} - {hasLayoutVerticalControls ? ( -
- -
- ) : null} + +
+ +
+ ) : null} diff --git a/packages/toolpad-app/src/toolpadComponents/index.tsx b/packages/toolpad-app/src/toolpadComponents/index.tsx index 4a6904ab1ce..146fe98c2b4 100644 --- a/packages/toolpad-app/src/toolpadComponents/index.tsx +++ b/packages/toolpad-app/src/toolpadComponents/index.tsx @@ -32,6 +32,7 @@ const INTERNAL_COMPONENTS = new Map([ ['Image', { displayName: 'Image', builtIn: 'Image' }], ['DataGrid', { displayName: 'Data grid', builtIn: 'DataGrid' }], ['TextField', { displayName: 'Text field', builtIn: 'TextField' }], + ['DatePicker', { displayName: 'Date picker', builtIn: 'DatePicker' }], ['Text', { displayName: 'Text', builtIn: 'Text' }], ['Select', { displayName: 'Select', builtIn: 'Select' }], ['Paper', { displayName: 'Paper', builtIn: 'Paper' }], diff --git a/packages/toolpad-components/src/DatePicker.tsx b/packages/toolpad-components/src/DatePicker.tsx new file mode 100644 index 00000000000..3848a10edc2 --- /dev/null +++ b/packages/toolpad-components/src/DatePicker.tsx @@ -0,0 +1,93 @@ +import * as React from 'react'; + +import { TextField } from '@mui/material'; + +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DesktopDatePicker, DesktopDatePickerProps } from '@mui/x-date-pickers/DesktopDatePicker'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { createComponent } from '@mui/toolpad-core'; +import { Dayjs } from 'dayjs'; + +export interface Props extends DesktopDatePickerProps { + format: string; + separator: string; + fullWidth: boolean; + variant: 'outlined' | 'filled' | 'standard'; + size: 'small' | 'medium'; + sx: any; +} + +const resolveFormat = (format: string, separator: string) => format.replaceAll(' ', separator); + +function DatePicker(props: Props) { + return ( + + ( + + )} + /> + + ); +} + +export default createComponent(DatePicker, { + argTypes: { + value: { + typeDef: { type: 'string' }, + onChangeProp: 'onChange', + onChangeHandler: (newValue: Dayjs, { format, separator }: Props) => { + return newValue.format(resolveFormat(format, separator)); + }, + defaultValue: '', + defaultValueProp: 'defaultValue', + }, + format: { + typeDef: { + type: 'string', + enum: ['DD MM YYYY', 'YYYY MM DD', 'MM DD YYYY'], + }, + defaultValue: 'YYYY MM DD', + }, + separator: { + typeDef: { + type: 'string', + enum: ['-', '/', ' '], + }, + defaultValue: '-', + }, + // @ts-ignore no idea why it complains even though it's done exactly same as TextField + defaultValue: { + typeDef: { type: 'string' }, + defaultValue: '', + }, + label: { + typeDef: { type: 'string' }, + }, + variant: { + typeDef: { type: 'string', enum: ['outlined', 'filled', 'standard'] }, + defaultValue: 'outlined', + }, + size: { + typeDef: { type: 'string', enum: ['small', 'medium'] }, + defaultValue: 'small', + }, + fullWidth: { + typeDef: { type: 'boolean' }, + }, + disabled: { + typeDef: { type: 'boolean' }, + }, + sx: { + typeDef: { type: 'object' }, + }, + }, +}); diff --git a/packages/toolpad-components/src/index.tsx b/packages/toolpad-components/src/index.tsx index ca088e73ffc..b9577f742f4 100644 --- a/packages/toolpad-components/src/index.tsx +++ b/packages/toolpad-components/src/index.tsx @@ -18,5 +18,7 @@ export { default as Paper } from './Paper.js'; export { default as Image } from './Image.js'; +export { default as DatePicker } from './DatePicker.js'; + export { CUSTOM_COLUMN_TYPES, NUMBER_FORMAT_PRESETS, inferColumns, parseColumns } from './DataGrid'; export type { SerializableGridColumn, SerializableGridColumns, NumberFormat } from './DataGrid'; From 19b11c6fb4b9b09302a6ff9d9a3e6cc228ab59b0 Mon Sep 17 00:00:00 2001 From: bytasv Date: Fri, 30 Dec 2022 10:30:54 +0200 Subject: [PATCH 2/2] Fix typing --- packages/toolpad-app/src/runtime/ToolpadApp.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/toolpad-app/src/runtime/ToolpadApp.tsx b/packages/toolpad-app/src/runtime/ToolpadApp.tsx index c67db60fd2e..b2e4a3eba65 100644 --- a/packages/toolpad-app/src/runtime/ToolpadApp.tsx +++ b/packages/toolpad-app/src/runtime/ToolpadApp.tsx @@ -268,7 +268,10 @@ function RenderedNodeContent({ node, childNodeGroups, Component }: RenderedNodeC const bindingId = `${nodeId}.props.${key}`; const defaultValues = _.mapValues(argTypes, ({ defaultValue }: any) => defaultValue); - const propsValues = _.mapValues(node.props, ({ value }) => value); + const propsValues = _.mapValues( + (node as appDom.ElementNode).props, + (prop) => prop?.value || undefined, + ); const props = { ...defaultValues, ...propsValues, @@ -279,7 +282,7 @@ function RenderedNodeContent({ node, childNodeGroups, Component }: RenderedNodeC }; return [argType.onChangeProp, handler]; }), - [argTypes, nodeId, setControlledBinding, node.props], + [argTypes, nodeId, setControlledBinding, node], ); const navigateToPage = usePageNavigator();