Skip to content
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
14 changes: 14 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ When a missing intermediate container is created, the JSON Schema decides whethe

If you dispatch update actions yourself, make sure to use dot-separated paths (e.g. `update('list.0.name', ...)`) instead of lodash bracket syntax (e.g. `update('list[0].name', ...)`), which is no longer interpreted.

### React Material renderers now require Material UI v9

The React Material renderers (`@jsonforms/material-renderers`) were upgraded from Material UI v7 to v9.
When using JSON Forms 3.9, your application now needs to provide `@mui/material` and `@mui/icons-material` in version 9, as well as `@mui/x-date-pickers` in version 9 (previously version 8).

To upgrade your application, follow the official [Material UI upgrade guide](https://mui.com/material-ui/migration/upgrade-to-v9/) and the [MUI X Date Pickers migration guide](https://mui.com/x/migration/migration-pickers-v8/).

Use JSON Forms 3.8 if you need to stay on Material UI v7.

As part of this upgrade, layouts that arrange their children vertically (e.g. `VerticalLayout`, `Group`, `Categorization`) now render a MUI `Stack` instead of a `Grid` container with `direction="column"`, and their children are no longer wrapped in `Grid` items.
If you apply custom styling that relies on the previous `Grid`-based DOM structure of these layouts, verify that it still works as expected.
Furthermore, if you use exported method `renderLayoutElements`, it no longer wraps children in `Grid` items for direction `column`.
This should not affect you except if you explicitly use this method in custom renderers.

## Migrating to JSON Forms 3.8

### `Translator` type changed from overloaded signatures to a generic conditional type
Expand Down
2 changes: 1 addition & 1 deletion packages/examples-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"@jsonforms/core": "workspace:*",
"@jsonforms/examples": "workspace:*",
"@jsonforms/react": "workspace:*",
"@mui/material": "^7.3.0",
"@mui/material": "^9.2.0",
"@types/react-highlight": "^0.12.5",
"@types/react-tabs": "^2.3.3",
"highlight.js": "^11.3.1",
Expand Down
12 changes: 6 additions & 6 deletions packages/material-renderers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,19 @@
"@emotion/styled": "^11.3.0",
"@jsonforms/core": "3.9.0-alpha.0",
"@jsonforms/react": "3.9.0-alpha.0",
"@mui/icons-material": "^7.0.0",
"@mui/material": "^7.0.0",
"@mui/x-date-pickers": "^8.0.0",
"@mui/icons-material": "^9.0.0",
"@mui/material": "^9.0.0",
"@mui/x-date-pickers": "^9.0.0",
"react": "^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@jsonforms/core": "workspace:*",
"@jsonforms/react": "workspace:*",
"@mui/icons-material": "^7.3.0",
"@mui/material": "^7.3.0",
"@mui/x-date-pickers": "^8.11.3",
"@mui/icons-material": "^9.2.0",
"@mui/material": "^9.2.0",
"@mui/x-date-pickers": "^9.10.1",
"@rollup/plugin-commonjs": "^23.0.3",
"@rollup/plugin-json": "^5.0.2",
"@rollup/plugin-node-resolve": "^15.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export const MaterialListWithDetailRenderer = ({
createDefault={handleCreateDefaultValue}
disableAdd={doDisableAdd}
/>
<Grid container direction='row' spacing={2}>
<Grid container spacing={2}>
<Grid size={3}>
<List>
{data > 0 ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,7 @@ const NonEmptyRowComponent = ({
>
<Grid
container
direction='row'
justifyContent='flex-end'
alignItems='center'
sx={{ justifyContent: 'flex-end', alignItems: 'center' }}
>
{showSortButtons ? (
<Fragment>
Expand Down
3 changes: 1 addition & 2 deletions packages/material-renderers/src/complex/TableToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ const TableToolbar = React.memo(function TableToolbar({
<Stack>
<Grid
container
justifyContent={'flex-start'}
alignItems={'center'}
sx={{ justifyContent: 'flex-start', alignItems: 'center' }}
spacing={2}
>
<Grid>
Expand Down
4 changes: 2 additions & 2 deletions packages/material-renderers/src/complex/ValidationIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/
import React from 'react';

import { ErrorOutline } from '@mui/icons-material';
import { ErrorOutlineOutlined } from '@mui/icons-material';
import { Badge, Tooltip, styled } from '@mui/material';

const StyledBadge = styled(Badge)(({ theme }: any) => ({
Expand All @@ -40,7 +40,7 @@ const ValidationIcon: React.FC<ValidationProps> = ({ errorMessages, id }) => {
return (
<Tooltip id={id} title={errorMessages}>
<StyledBadge badgeContent={errorMessages.split('\n').length}>
<ErrorOutline color='inherit' />
<ErrorOutlineOutlined color='inherit' />
</StyledBadge>
</Tooltip>
);
Expand Down
14 changes: 8 additions & 6 deletions packages/material-renderers/src/controls/MaterialDateControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,15 @@ export const MaterialDateControl = (props: ControlProps) => {
error: !isValid,
fullWidth: !appliedUiSchemaOptions.trim,
variant: inputVariant,
inputProps: {
autoFocus: appliedUiSchemaOptions.focus,
type: 'text',
onFocus: onFocus,
onBlur: onBlurHandler,
slotProps: {
htmlInput: {
autoFocus: appliedUiSchemaOptions.focus,
type: 'text',
onFocus: onFocus,
onBlur: onBlurHandler,
},
inputLabel: data ? { shrink: true } : undefined,
},
InputLabelProps: data ? { shrink: true } : undefined,
},
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,15 @@ export const MaterialDateTimeControl = (props: ControlProps) => {
error: !isValid,
fullWidth: !appliedUiSchemaOptions.trim,
variant: inputVariant,
inputProps: {
autoFocus: appliedUiSchemaOptions.focus,
type: 'text',
onFocus: onFocus,
onBlur: onBlurHandler,
slotProps: {
htmlInput: {
autoFocus: appliedUiSchemaOptions.focus,
type: 'text',
onFocus: onFocus,
onBlur: onBlurHandler,
},
inputLabel: data ? { shrink: true } : undefined,
},
InputLabelProps: data ? { shrink: true } : undefined,
},
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const MaterialNativeControl = (props: ControlProps) => {
onFocus={onFocus}
onBlur={onBlur}
helperText={!isValid ? errors : showDescription ? description : null}
InputLabelProps={{ shrink: true }}
slotProps={{ inputLabel: { shrink: true } }}
Comment thread
lucas-koehler marked this conversation as resolved.
value={inputValue}
onChange={onChange}
/>
Expand Down
14 changes: 8 additions & 6 deletions packages/material-renderers/src/controls/MaterialTimeControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,15 @@ export const MaterialTimeControl = (props: ControlProps) => {
error: !isValid,
fullWidth: !appliedUiSchemaOptions.trim,
variant: inputVariant,
inputProps: {
autoFocus: appliedUiSchemaOptions.focus,
type: 'text',
onBlur: onBlurHandler,
onFocus: onFocus,
slotProps: {
htmlInput: {
autoFocus: appliedUiSchemaOptions.focus,
type: 'text',
onBlur: onBlurHandler,
onFocus: onFocus,
},
inputLabel: data ? { shrink: true } : undefined,
},
InputLabelProps: data ? { shrink: true } : undefined,
},
}}
/>
Expand Down
10 changes: 6 additions & 4 deletions packages/material-renderers/src/layouts/ArrayToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ export const ArrayLayoutToolbar = React.memo(function ArrayLayoutToolbar({
}: ArrayLayoutToolbarProps) {
return (
<Toolbar disableGutters={true}>
<Stack width='100%'>
<Grid container alignItems='center' justifyContent='space-between'>
<Stack sx={{ width: '100%' }}>
<Grid
container
sx={{ alignItems: 'center', justifyContent: 'space-between' }}
>
<Grid>
<Grid
container
justifyContent={'flex-start'}
alignItems={'center'}
sx={{ justifyContent: 'flex-start', alignItems: 'center' }}
spacing={2}
>
<Grid>
Expand Down
10 changes: 4 additions & 6 deletions packages/material-renderers/src/layouts/ExpandPanelRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ const ExpandPanelRendererComponent = (props: ExpandPanelProps) => {
onChange={handleExpansion(childPath)}
>
<AccordionSummary expandIcon={<ExpandMore />}>
<Grid container sx={{ width: '100%' }} alignItems={'center'}>
<Grid container sx={{ width: '100%', alignItems: 'center' }}>
<Grid size={{ xs: 7, md: 9 }}>
<Grid container alignItems={'center'}>
<Grid container sx={{ alignItems: 'center' }}>
<Grid size={{ xs: 2, md: 1 }}>
<Avatar aria-label='Index'>{index + 1}</Avatar>
</Grid>
Expand All @@ -159,13 +159,11 @@ const ExpandPanelRendererComponent = (props: ExpandPanelProps) => {
</Grid>
</Grid>
<Grid size={{ xs: 5, md: 3 }}>
<Grid container justifyContent='flex-end'>
<Grid container sx={{ justifyContent: 'flex-end' }}>
<Grid>
<Grid
container
direction='row'
justifyContent='center'
alignItems='center'
sx={{ justifyContent: 'center', alignItems: 'center' }}
>
{showSortButtons && enabled ? (
<Fragment>
Expand Down
46 changes: 23 additions & 23 deletions packages/material-renderers/src/mui-controls/MuiAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,29 +121,29 @@ export const MuiAutocomplete = (
options={options}
getOptionLabel={getOptionLabel || ((option) => option?.label)}
freeSolo={false}
renderInput={(params) => {
return (
<TextField
label={label}
type='text'
inputProps={params.inputProps}
inputRef={params.InputProps.ref}
autoFocus={appliedUiSchemaOptions.focus}
disabled={!enabled}
{...params}
id={id}
required={
required && !appliedUiSchemaOptions.hideRequiredAsterisk
}
error={!isValid}
fullWidth={!appliedUiSchemaOptions.trim}
InputLabelProps={data ? { shrink: true } : undefined}
onFocus={onFocus}
onBlur={onBlur}
focused={focused}
/>
);
}}
renderInput={(params) => (
<TextField
label={label}
type='text'
autoFocus={appliedUiSchemaOptions.focus}
disabled={!enabled}
{...params}
id={id}
required={required && !appliedUiSchemaOptions.hideRequiredAsterisk}
error={!isValid}
fullWidth={!appliedUiSchemaOptions.trim}
slotProps={{
...params.slotProps,
inputLabel: {
...params.slotProps.inputLabel,
...(data ? { shrink: true } : undefined),
},
}}
onFocus={onFocus}
onBlur={onBlur}
focused={focused}
/>
)}
renderOption={renderOption}
filterOptions={filterOptions}
/>
Expand Down
58 changes: 34 additions & 24 deletions packages/material-renderers/src/util/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
THE SOFTWARE.
*/
import isEmpty from 'lodash/isEmpty';
import React, { ComponentType } from 'react';
import React, { ComponentType, Fragment } from 'react';
import type Ajv from 'ajv';
import type { UISchemaElement } from '@jsonforms/core';
import {
Expand All @@ -34,18 +34,19 @@ import {
OwnPropsOfRenderer,
} from '@jsonforms/core';
import { JsonFormsDispatch, useJsonForms } from '@jsonforms/react';
import { Grid } from '@mui/material';
import { Grid, Stack } from '@mui/material';

export const renderLayoutElements = (
elements: UISchemaElement[],
schema: JsonSchema,
path: string,
enabled: boolean,
renderers?: JsonFormsRendererRegistryEntry[],
cells?: JsonFormsCellRendererRegistryEntry[]
cells?: JsonFormsCellRendererRegistryEntry[],
direction: 'row' | 'column' = 'row'
) => {
return elements.map((child, index) => (
<Grid key={`${path}-${index}`} size='grow'>
return elements.map((child, index) => {
const dispatch = (
<JsonFormsDispatch
uischema={child}
schema={schema}
Expand All @@ -54,8 +55,16 @@ export const renderLayoutElements = (
renderers={renderers}
cells={cells}
/>
</Grid>
));
);

return direction === 'row' ? (
<Grid key={`${path}-${index}`} size='grow'>
{dispatch}
</Grid>
) : (
<Fragment key={`${path}-${index}`}>{dispatch}</Fragment>
);
});
};

export interface MaterialLayoutRendererProps extends OwnPropsOfRenderer {
Expand All @@ -74,24 +83,25 @@ const MaterialLayoutRendererComponent = ({
}: MaterialLayoutRendererProps) => {
if (isEmpty(elements) || !visible) {
return null;
} else {
return (
<Grid
container
direction={direction}
spacing={direction === 'row' ? 2 : 0}
>
{renderLayoutElements(
elements,
schema,
path,
enabled,
renderers,
cells
)}
</Grid>
);
}

const children = renderLayoutElements(
elements,
schema,
path,
enabled,
renderers,
cells,
direction
);

return direction === 'row' ? (
<Grid container spacing={2}>
{children}
</Grid>
) : (
<Stack>{children}</Stack>
);
};
export const MaterialLayoutRenderer = React.memo(
MaterialLayoutRendererComponent
Expand Down
Loading
Loading