From 77fde14366b6e4e1eaac749b50096ed199adbb83 Mon Sep 17 00:00:00 2001 From: Sebastian Frey Date: Fri, 29 Sep 2023 22:23:47 +0200 Subject: [PATCH] Make material renderers aware of input variant in theme --- packages/examples-react/src/App.tsx | 22 +++-- packages/examples-react/src/index.tsx | 11 ++- packages/material-renderers/example/index.ts | 28 ------ packages/material-renderers/example/index.tsx | 94 +++++++++++++++++++ .../src/cells/MaterialIntegerCell.tsx | 9 +- .../src/cells/MaterialNumberCell.tsx | 17 ++-- .../src/cells/MaterialNumberFormatCell.tsx | 7 +- .../src/cells/MaterialTextCell.tsx | 8 +- .../src/controls/MaterialDateControl.tsx | 1 - .../src/controls/MaterialDateTimeControl.tsx | 1 - .../src/controls/MaterialInputControl.tsx | 13 ++- .../src/controls/MaterialTimeControl.tsx | 1 - .../src/mui-controls/MuiAutocomplete.tsx | 1 - .../src/mui-controls/MuiInputInteger.tsx | 22 +++-- .../src/mui-controls/MuiInputNumber.tsx | 30 ++++-- .../src/mui-controls/MuiInputNumberFormat.tsx | 8 +- .../src/mui-controls/MuiInputText.tsx | 15 ++- .../src/mui-controls/MuiSelect.tsx | 10 +- packages/material-renderers/src/util/index.ts | 1 + packages/material-renderers/src/util/input.ts | 46 +++++++++ webpack/webpack.dev.base.js | 2 +- 21 files changed, 262 insertions(+), 85 deletions(-) delete mode 100644 packages/material-renderers/example/index.ts create mode 100644 packages/material-renderers/example/index.tsx create mode 100644 packages/material-renderers/src/util/input.ts diff --git a/packages/examples-react/src/App.tsx b/packages/examples-react/src/App.tsx index d34d2c31c..1ca8de9bf 100644 --- a/packages/examples-react/src/App.tsx +++ b/packages/examples-react/src/App.tsx @@ -39,6 +39,7 @@ type AppProps = { examples: ExampleDescription[]; cells: JsonFormsCellRendererRegistryEntry[]; renderers: JsonFormsRendererRegistryEntry[]; + Wrapper?: React.JSXElementConstructor; }; type Action = { @@ -69,7 +70,12 @@ const getProps = ( }; }; -const App = ({ examples, cells, renderers }: AppProps) => { +const App = ({ + examples, + cells, + renderers, + Wrapper = React.Fragment, +}: AppProps) => { const [currentExample, setExample] = useState( examples[0] ); @@ -88,7 +94,7 @@ const App = ({ examples, cells, renderers }: AppProps) => { [exampleProps.uischema] ); - const actions: Action[] = currentExample.actions; + const actions: Action[] = currentExample.actions ?? []; useEffect(() => { const hash = window.location.hash.replace('#', ''); @@ -192,11 +198,13 @@ const App = ({ examples, cells, renderers }: AppProps) => { ))}
- changeData(data)} - /> + + changeData(data)} + /> +
diff --git a/packages/examples-react/src/index.tsx b/packages/examples-react/src/index.tsx index 6bec4bb31..e9f7368da 100644 --- a/packages/examples-react/src/index.tsx +++ b/packages/examples-react/src/index.tsx @@ -30,11 +30,18 @@ import { getExamples } from '@jsonforms/examples'; export const renderExample = ( renderers: { tester: RankedTester; renderer: any }[], - cells: { tester: RankedTester; cell: any }[] + cells: { tester: RankedTester; cell: any }[], + Wrapper?: React.JSXElementConstructor ) => { + console.info({ Wrapper }); const examples = getExamples(); ReactDOM.render( - , + , document.getElementById('root') ); }; diff --git a/packages/material-renderers/example/index.ts b/packages/material-renderers/example/index.ts deleted file mode 100644 index 7488a28c7..000000000 --- a/packages/material-renderers/example/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - The MIT License - - Copyright (c) 2017-2019 EclipseSource Munich - https://github.com/eclipsesource/jsonforms - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -import { renderExample } from '../../examples-react/src/index'; -import { materialRenderers, materialCells } from '../src'; - -renderExample(materialRenderers, materialCells); diff --git a/packages/material-renderers/example/index.tsx b/packages/material-renderers/example/index.tsx new file mode 100644 index 000000000..8c4a0eb67 --- /dev/null +++ b/packages/material-renderers/example/index.tsx @@ -0,0 +1,94 @@ +/* + The MIT License + + Copyright (c) 2017-2019 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +import React from 'react'; +import { + Divider, + FormControl, + InputLabel, + MenuItem, + Select, + SelectChangeEvent, + Stack, + TextFieldProps, + ThemeProvider, + createTheme, +} from '@mui/material'; +import { renderExample } from '../../examples-react/src/index'; +import { materialRenderers, materialCells } from '../src'; + +const MuiWrapper = ({ children }: React.PropsWithChildren) => { + const [variant, setVariant] = + React.useState('standard'); + + const handleVariantChange = (event: SelectChangeEvent) => { + setVariant(event.target.value as TextFieldProps['variant']); + }; + + const theme = React.useMemo(() => { + return createTheme({ + components: { + MuiTextField: { + defaultProps: { + variant, + }, + }, + // avoid jammed look of input fields when variant is not 'standard' + ...(variant !== 'standard' + ? { + MuiFormControl: { + styleOverrides: { + root: { + marginTop: '8px', + }, + }, + }, + } + : {}), + }, + }); + }, [variant]); + + const label = 'TextField variant'; + + return ( + + + + {label} + + + + {children} + + + ); +}; + +renderExample(materialRenderers, materialCells, MuiWrapper); diff --git a/packages/material-renderers/src/cells/MaterialIntegerCell.tsx b/packages/material-renderers/src/cells/MaterialIntegerCell.tsx index 9dcafe809..a46b01689 100644 --- a/packages/material-renderers/src/cells/MaterialIntegerCell.tsx +++ b/packages/material-renderers/src/cells/MaterialIntegerCell.tsx @@ -32,10 +32,13 @@ import { } from '@jsonforms/core'; import { withJsonFormsCellProps } from '@jsonforms/react'; import { MuiInputInteger } from '../mui-controls/MuiInputInteger'; +import { useInputComponent } from '../util'; + +export const MaterialIntegerCell = (props: CellProps & WithClassname) => { + const { InputComponent } = useInputComponent(props); + return ; +}; -export const MaterialIntegerCell = (props: CellProps & WithClassname) => ( - -); export const materialIntegerCellTester: RankedTester = rankWith( 2, isIntegerControl diff --git a/packages/material-renderers/src/cells/MaterialNumberCell.tsx b/packages/material-renderers/src/cells/MaterialNumberCell.tsx index fee375a2b..f4164be6c 100644 --- a/packages/material-renderers/src/cells/MaterialNumberCell.tsx +++ b/packages/material-renderers/src/cells/MaterialNumberCell.tsx @@ -1,19 +1,19 @@ /* The MIT License - + Copyright (c) 2017-2019 EclipseSource Munich https://github.com/eclipsesource/jsonforms - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -32,10 +32,13 @@ import { } from '@jsonforms/core'; import { withJsonFormsCellProps } from '@jsonforms/react'; import { MuiInputNumber } from '../mui-controls/MuiInputNumber'; +import { useInputComponent } from '../util'; + +export const MaterialNumberCell = (props: CellProps & WithClassname) => { + const { InputComponent } = useInputComponent(props); + return ; +}; -export const MaterialNumberCell = (props: CellProps & WithClassname) => ( - -); /** * Default tester for number controls. * @type {RankedTester} diff --git a/packages/material-renderers/src/cells/MaterialNumberFormatCell.tsx b/packages/material-renderers/src/cells/MaterialNumberFormatCell.tsx index d5b3b89f8..b8f640fe6 100644 --- a/packages/material-renderers/src/cells/MaterialNumberFormatCell.tsx +++ b/packages/material-renderers/src/cells/MaterialNumberFormatCell.tsx @@ -33,10 +33,15 @@ import { } from '@jsonforms/core'; import { withJsonFormsCellProps } from '@jsonforms/react'; import { MuiInputNumberFormat } from '../mui-controls/MuiInputNumberFormat'; +import { useInputComponent } from '../util'; export const MaterialNumberFormatCell = ( props: CellProps & WithClassname & Formatted -) => ; +) => { + const { InputComponent } = useInputComponent(props); + return ; +}; + /** * Default tester for text-based/string controls. * @type {RankedTester} diff --git a/packages/material-renderers/src/cells/MaterialTextCell.tsx b/packages/material-renderers/src/cells/MaterialTextCell.tsx index 35100e091..7f9d2f839 100644 --- a/packages/material-renderers/src/cells/MaterialTextCell.tsx +++ b/packages/material-renderers/src/cells/MaterialTextCell.tsx @@ -32,10 +32,12 @@ import { } from '@jsonforms/core'; import { withJsonFormsCellProps } from '@jsonforms/react'; import { MuiInputText } from '../mui-controls/MuiInputText'; +import { useInputComponent } from '../util'; -export const MaterialTextCell = (props: CellProps & WithClassname) => ( - -); +export const MaterialTextCell = (props: CellProps & WithClassname) => { + const { InputComponent } = useInputComponent(props); + return ; +}; /** * Default tester for text-based/string controls. diff --git a/packages/material-renderers/src/controls/MaterialDateControl.tsx b/packages/material-renderers/src/controls/MaterialDateControl.tsx index 98127f923..a551f0e6a 100644 --- a/packages/material-renderers/src/controls/MaterialDateControl.tsx +++ b/packages/material-renderers/src/controls/MaterialDateControl.tsx @@ -110,7 +110,6 @@ export const MaterialDateControl = (props: ControlProps) => { InputLabelProps: data ? { shrink: true } : undefined, onFocus: onFocus, onBlur: onBlur, - variant: 'standard', }, }} /> diff --git a/packages/material-renderers/src/controls/MaterialDateTimeControl.tsx b/packages/material-renderers/src/controls/MaterialDateTimeControl.tsx index 5a83bf45b..09124c6c0 100644 --- a/packages/material-renderers/src/controls/MaterialDateTimeControl.tsx +++ b/packages/material-renderers/src/controls/MaterialDateTimeControl.tsx @@ -118,7 +118,6 @@ export const MaterialDateTimeControl = (props: ControlProps) => { InputLabelProps: data ? { shrink: true } : undefined, onFocus: onFocus, onBlur: onBlur, - variant: 'standard', }, }} /> diff --git a/packages/material-renderers/src/controls/MaterialInputControl.tsx b/packages/material-renderers/src/controls/MaterialInputControl.tsx index c9fd89bc6..98e681cc5 100644 --- a/packages/material-renderers/src/controls/MaterialInputControl.tsx +++ b/packages/material-renderers/src/controls/MaterialInputControl.tsx @@ -31,7 +31,7 @@ import { import { Hidden, InputLabel, FormControl, FormHelperText } from '@mui/material'; import merge from 'lodash/merge'; -import { useFocus } from '../util'; +import { useFocus, useInputComponent } from '../util'; export interface WithInput { input: any; @@ -50,6 +50,7 @@ export const MaterialInputControl = (props: ControlProps & WithInput) => { config, input, } = props; + const { InputComponent, variant } = useInputComponent(props); const isValid = errors.length === 0; const appliedUiSchemaOptions = merge({}, config, uischema.options); @@ -68,14 +69,20 @@ export const MaterialInputControl = (props: ControlProps & WithInput) => { const secondFormHelperText = showDescription && !isValid ? errors : null; const InnerComponent = input; + const InputMore: { label?: string } = {}; + + if (variant === 'outlined') { + InputMore.label = label; + } + return ( { {firstFormHelperText} diff --git a/packages/material-renderers/src/controls/MaterialTimeControl.tsx b/packages/material-renderers/src/controls/MaterialTimeControl.tsx index ebdaba76a..cf898845f 100644 --- a/packages/material-renderers/src/controls/MaterialTimeControl.tsx +++ b/packages/material-renderers/src/controls/MaterialTimeControl.tsx @@ -112,7 +112,6 @@ export const MaterialTimeControl = (props: ControlProps) => { InputLabelProps: data ? { shrink: true } : undefined, onFocus: onFocus, onBlur: onBlur, - variant: 'standard', }, }} /> diff --git a/packages/material-renderers/src/mui-controls/MuiAutocomplete.tsx b/packages/material-renderers/src/mui-controls/MuiAutocomplete.tsx index 3938eb6c7..e08a34245 100644 --- a/packages/material-renderers/src/mui-controls/MuiAutocomplete.tsx +++ b/packages/material-renderers/src/mui-controls/MuiAutocomplete.tsx @@ -123,7 +123,6 @@ export const MuiAutocomplete = ( return ( value === '' ? undefined : parseInt(value, 10); const eventToValue = (ev: any) => toNumber(ev.target.value); export const MuiInputInteger = React.memo(function MuiInputInteger( - props: CellProps & WithClassname + props: CellProps & WithClassname & WithInputProps & WithInputProps ) { - const { data, className, id, enabled, uischema, path, handleChange, config } = - props; + const { + data, + className, + id, + enabled, + uischema, + path, + handleChange, + config, + label, + InputComponent, + } = props; const inputProps = { step: '1' }; const appliedUiSchemaOptions = merge({}, config, uischema.options); @@ -50,7 +59,8 @@ export const MuiInputInteger = React.memo(function MuiInputInteger( ); return ( - value === '' ? undefined : parseFloat(value); const eventToValue = (ev: any) => toNumber(ev.target.value); export const MuiInputNumber = React.memo(function MuiInputNumber( - props: CellProps & WithClassname + props: CellProps & WithClassname & WithInputProps & WithInputProps ) { - const { data, className, id, enabled, uischema, path, handleChange, config } = - props; + const { + data, + className, + id, + enabled, + uischema, + path, + handleChange, + config, + label, + InputComponent, + } = props; const inputProps = { step: '0.1' }; const appliedUiSchemaOptions = merge({}, config, uischema.options); @@ -48,8 +57,9 @@ export const MuiInputNumber = React.memo(function MuiInputNumber( ); return ( - + props: CellProps & WithClassname & Formatted & WithInputProps ) { const { className, @@ -41,6 +40,7 @@ export const MuiInputNumberFormat = React.memo(function MuiInputNumberFormat( handleChange, schema, config, + InputComponent, } = props; const maxLength = schema.maxLength; const appliedUiSchemaOptions = merge({}, config, uischema.options); @@ -65,7 +65,7 @@ export const MuiInputNumberFormat = React.memo(function MuiInputNumberFormat( ); return ( - ev.target.value === '' ? undefined : ev.target.value; export const MuiInputText = React.memo(function MuiInputText( - props: CellProps & WithClassname & MuiTextInputProps + props: CellProps & WithClassname & MuiTextInputProps & WithInputProps ) { const [showAdornment, setShowAdornment] = useState(false); const { @@ -60,8 +64,10 @@ export const MuiInputText = React.memo(function MuiInputText( handleChange, schema, muiInputProps, + label, inputComponent, } = props; + const { InputComponent } = useInputComponent(props); const maxLength = schema.maxLength; const appliedUiSchemaOptions = merge({}, config, uischema.options); let inputProps: InputBaseComponentProps; @@ -97,7 +103,8 @@ export const MuiInputText = React.memo(function MuiInputText( }; return ( - ) { const { data, @@ -44,6 +47,7 @@ export const MuiSelect = React.memo(function MuiSelect( handleChange, options, config, + label, t, } = props; const appliedUiSchemaOptions = merge({}, config, uischema.options); @@ -56,12 +60,12 @@ export const MuiSelect = React.memo(function MuiSelect(