Skip to content

Commit

Permalink
migrate react json schema plugins; migrate mui FormGroup;
Browse files Browse the repository at this point in the history
  • Loading branch information
elbakerino committed Sep 27, 2023
1 parent f59a465 commit 05328af
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 129 deletions.
17 changes: 17 additions & 0 deletions packages/demo-web/src/component/useToggle.ts
@@ -0,0 +1,17 @@
import React from 'react'

export const useToggle = () => {
const [toggles, setToggle] = React.useState<{ [k: string]: boolean }>({})

const toggleDummy = React.useCallback((id: string) => {
setToggle((toggles) => ({
...toggles,
[id]: !toggles[id],
}))
}, [])
const isSet = (id: string) => {
return Boolean(toggles[id])
}

return [toggleDummy, isSet] as [typeof toggleDummy, typeof isSet]
}
82 changes: 61 additions & 21 deletions packages/demo-web/src/material-ui/component/MuiMainDummy.tsx
Expand Up @@ -2,37 +2,77 @@ import React from 'react'
import Paper from '@mui/material/Paper'
import Button from '@mui/material/Button'
import { MuiSchemaDebug } from './MuiSchemaDebug'
import { MainDummy } from '../../component/MainDummy'
import { UISchemaMap } from '@ui-schema/json-schema/Definitions'
import { createEmptyStore, UIStoreProvider } from '@ui-schema/react/UIStore'
import Grid from '@mui/material/Grid'
import { List } from 'immutable'
import { StoreKeys } from '@ui-schema/system/ValueStore'
import { browserT } from '../../t'
import { isInvalid } from '@ui-schema/react/ValidityReporter'
import { storeUpdater } from '@ui-schema/react/storeUpdater'
import { memo } from '@ui-schema/react/Utils/memo'
import { WidgetEngine } from '@ui-schema/react/WidgetEngine'

interface MainDummyProps {
schema: UISchemaMap
}

const WidgetEngineMemo = memo(WidgetEngine)

const MainDummy: React.FC<MainDummyProps> = ({schema}) => {
const [showValidity, setShowValidity] = React.useState(false)
const [store, setStore] = React.useState(() => createEmptyStore(schema.get('type')))

const onChange = React.useCallback((actions) => setStore(storeUpdater(actions)), [setStore])

return <UIStoreProvider
store={store}
onChange={onChange}
showValidity={showValidity}
//doNotDefault
>
<Paper
sx={{
p: 2,
display: 'flex',
overflow: 'auto',
flexDirection: 'column',
}}
>
{/*<GridStack isRoot schema={schema}/>*/}
<Grid container spacing={2}>
<WidgetEngineMemo
storeKeys={List([]) as StoreKeys}
schemaKeys={List([]) as StoreKeys}
schema={schema}
parentSchema={undefined}
required={false}
t={browserT}
isVirtual={false}
noGrid={false}
/>
</Grid>

<Button onClick={() => setShowValidity(!showValidity)}>{showValidity ? 'hide ' : ''}validity</Button>
{isInvalid(store.getValidity()) ? 'invalid' : 'valid'}
</Paper>

<MuiSchemaDebug setSchema={undefined} schema={schema}/>
</UIStoreProvider>

}

export const DummyRenderer: React.FC<{
id: string
schema: any
toggleDummy?: (id: string) => void
getDummy?: (id: string) => boolean
variant?: 'outlined' | 'elevation'
open?: boolean
stylePaper?: React.CSSProperties
}> = ({id, schema, toggleDummy, getDummy, variant, open = false, stylePaper = {}}) => <React.Fragment>
}> = ({id, schema, toggleDummy, getDummy, open = false}) => <React.Fragment>
{open || !toggleDummy ? null :
<Button style={{marginBottom: 12}} onClick={() => toggleDummy(id)} variant={(getDummy && getDummy(id) ? 'contained' : 'outlined')}>
{id.replace(/([A-Z0-9])/g, ' $1').replace(/^./, str => str.toUpperCase())}
</Button>}
{(getDummy && getDummy(id)) || open || !toggleDummy ?
<Paper
style={stylePaper}
// outlined or elevation
variant={variant}
sx={{
p: 2,
display: 'flex',
overflow: 'auto',
flexDirection: 'column',
}}
>
<MainDummy
schema={schema}
Debugger={MuiSchemaDebug}
Button={Button}
/>
</Paper> : null}
<MainDummy schema={schema}/> : null}
</React.Fragment>
78 changes: 77 additions & 1 deletion packages/demo-web/src/material-ui/material-ui.tsx
Expand Up @@ -37,6 +37,18 @@ import { getValidators } from '@ui-schema/json-schema/getValidators'
import { memo } from '@ui-schema/react/Utils/memo'
import { SchemaTypesType } from '@ui-schema/system/CommonTypings'
import { SchemaValidatorContext } from '@ui-schema/system/SchemaPluginStack'
import { CombiningHandler, ConditionalHandler, DefaultHandler, DependentHandler, ReferencingHandler } from '@ui-schema/react-json-schema'
import { DummyRenderer } from './component/MuiMainDummy'
import { schemaDemoReferencing, schemaDemoReferencingNetwork, schemaDemoReferencingNetworkB } from '../schemas/demoReferencing'
import { useToggle } from '../component/useToggle'
import { FormGroup } from '@ui-schema/ds-material/Widgets'
import { schemaNumberSlider } from '../schemas/demoNumberSlider'
import { schemaLists } from '../schemas/demoLists'
import { schemaWCombining } from '../schemas/demoCombining'
import { schemaWConditional, schemaWConditional1, schemaWConditional2 } from '../schemas/demoConditional'
import { schemaWDep1, schemaWDep2 } from '../schemas/demoDependencies'
import { schemaGrid } from '../schemas/demoGrid'
import { schemaNull, schemaSimBoolean, schemaSimCheck, schemaSimInteger, schemaSimNumber, schemaSimRadio, schemaSimSelect, schemaSimString } from '../schemas/demoSimples'

export type CustomComponents = {
// InfoRenderer?: ReactLeafDefaultNodeType<InfoRendererProps>
Expand Down Expand Up @@ -65,6 +77,7 @@ export const renderMapping: NextMuiWidgetsBinding<

// the `DemoRenderer` below uses `custom` widgets as is to access `leafs`
Text: TextRenderer,
FormGroup: FormGroup,
},
components: {
ErrorFallback: ErrorFallback,
Expand Down Expand Up @@ -156,6 +169,7 @@ function DemoRenderer<P extends DecoratorPropsNext & WidgetProps & WithValue & S
const schemaType = schema?.get('type') as SchemaTypesType | undefined
const schemaWidget = schema?.get('widget')
// console.log('schemaType', schemaType, schemaWidget, renderMap.leafs)
// todo: for usage in e.g. `FormGroup` the matcher should be in the props or renderMap
const getWidget = (): React.ComponentType<Omit<P, keyof DecoratorPropsNext> & DemoRendererProps> => {
let matching: string | undefined
if (typeof schemaWidget === 'string') {
Expand Down Expand Up @@ -212,13 +226,20 @@ const deco = new ReactDeco<
schemaPlugins={schemaPlugins}
/>
})
.use(ReferencingHandler)
.use(SchemaGridHandler)
.use(ExtractStorePlugin)
.use(memo(SchemaPluginsAdapter) as typeof SchemaPluginsAdapter)
.use(memo(CombiningHandler) as typeof CombiningHandler)
.use(DefaultHandler)
.use(DependentHandler)
.use(ConditionalHandler)
.use(SchemaPluginsAdapter)
.use(ValidityReporter)
.use(DemoRenderer)

export default function MaterialDemo() {
const [toggle, getToggle] = useToggle()

return <AppTheme>
{/* todo make the typing stricter and easier (check tactic-ui comments) */}
{/*<WidgetsProvider<NextMuiWidgetsBinding<{}, { renderMap: LeafsRenderMapping<{}, MuiComponentsBinding> }, typeof renderMapping.components>['leafs'], typeof renderMapping.components, typeof deco>*/}
Expand All @@ -233,6 +254,61 @@ export default function MaterialDemo() {
<Grid item xs={12}>
<MainStore/>
</Grid>
<Grid item xs={12}>
<DummyRenderer
id={'schemaReferencingNetwork'} schema={schemaDemoReferencingNetwork}
toggleDummy={toggle} getDummy={getToggle}
/>
</Grid>

<Grid item xs={12}>
<DummyRenderer
id={'schemaReferencingNetworkB'} schema={schemaDemoReferencingNetworkB}
toggleDummy={toggle} getDummy={getToggle}
/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaReferencing'} schema={schemaDemoReferencing} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaNumberSlider'} schema={schemaNumberSlider} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaLists'} schema={schemaLists} toggleDummy={toggle} getDummy={getToggle} open/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaWCombining'} schema={schemaWCombining} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaWConditional'} schema={schemaWConditional} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaWConditional1'} schema={schemaWConditional1} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaWConditional2'} schema={schemaWConditional2} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaWDep1'} schema={schemaWDep1} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaWDep2'} schema={schemaWDep2} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaGrid'} schema={schemaGrid(12)} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaSimString'} schema={schemaSimString} toggleDummy={toggle} getDummy={getToggle}/>
<DummyRenderer id={'schemaSimBoolean'} schema={schemaSimBoolean} toggleDummy={toggle} getDummy={getToggle}/>
<DummyRenderer id={'schemaSimCheck'} schema={schemaSimCheck} toggleDummy={toggle} getDummy={getToggle}/>
<DummyRenderer id={'schemaSimNumber'} schema={schemaSimNumber} toggleDummy={toggle} getDummy={getToggle}/>
<DummyRenderer id={'schemaSimInteger'} schema={schemaSimInteger} toggleDummy={toggle} getDummy={getToggle}/>
<DummyRenderer id={'schemaSimRadio'} schema={schemaSimRadio} toggleDummy={toggle} getDummy={getToggle}/>
<DummyRenderer id={'schemaSimSelect'} schema={schemaSimSelect} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
<Grid item xs={12}>
<DummyRenderer id={'schemaNull'} schema={schemaNull} toggleDummy={toggle} getDummy={getToggle}/>
</Grid>
</Dashboard>
</UIApiProvider>
</UIMetaProvider>
Expand Down
67 changes: 36 additions & 31 deletions packages/ds-material/src/Widgets/FormGroup/FormGroup.tsx
Expand Up @@ -3,43 +3,48 @@ import FormLabel from '@mui/material/FormLabel'
import FormControl from '@mui/material/FormControl'
import MuiFormGroup from '@mui/material/FormGroup'
import { useTheme } from '@mui/material/styles'
import { extractValue, WithValue } from '@ui-schema/react/UIStore'
import { extractValue } from '@ui-schema/react/UIStore'
import { memo } from '@ui-schema/react/Utils/memo'
import { WidgetProps } from '@ui-schema/react/Widgets'
import { TranslateTitle } from '@ui-schema/react/TranslateTitle'
import { MuiWidgetsBinding } from '@ui-schema/ds-material/WidgetsBinding'
import { SchemaValidatorContext } from '@ui-schema/system/SchemaPluginStack'
import { LeafsRenderMapping } from '@tactic-ui/react/LeafsEngine'

export const FormGroupBase: React.ComponentType<WidgetProps<MuiWidgetsBinding> & WithValue> = (props) => {
const {storeKeys, widgets} = props
const {WidgetRenderer} = widgets
const {spacing} = useTheme()
let {schema} = props
// deleting the `widget` to directly use `WidgetEngine` for nesting
// with `widget` it would lead to an endless loop
// using e.g. default `object` renderer then
// @ts-ignore
schema = schema.delete('widget')
return <FormControl
component="fieldset"
style={{
display: 'block',
marginBottom: spacing(1),
}}
>
<FormLabel component="legend">
<TranslateTitle schema={schema} storeKeys={storeKeys}/>
</FormLabel>
<MuiFormGroup
export const FormGroupBase =
<P extends WidgetProps & SchemaValidatorContext & { renderMap: LeafsRenderMapping<{}, {}> }>(props: P): React.ReactElement<P> => {
const {storeKeys, renderMap} = props
const {spacing} = useTheme()
let {schema} = props
// deleting the `widget` to directly use `WidgetEngine` for nesting
// with `widget` it would lead to an endless loop
// using e.g. default `object` renderer then
// @ts-ignore
schema = schema.delete('widget')

const Widget = schema.get('type') ? renderMap.leafs['type:' + schema.get('type')] : undefined

return <FormControl
component="fieldset"
style={{
marginTop: spacing(1),
display: 'block',
marginBottom: spacing(1),
}}
>
{/* @ts-ignore */}
<WidgetRenderer {...props} schema={schema}/>
</MuiFormGroup>
{/*<FormHelperText>Be careful</FormHelperText>*/}
</FormControl>
}
<FormLabel component="legend">
<TranslateTitle schema={schema} storeKeys={storeKeys}/>
</FormLabel>
<MuiFormGroup
style={{
marginTop: spacing(1),
marginBottom: spacing(1),
}}
>
{/* todo: re-use the next widget matcher */}
{/* @ts-ignore */}
{Widget ? <Widget {...props} schema={schema}/> : '-'}
</MuiFormGroup>
{/*<FormHelperText>Be careful</FormHelperText>*/}
</FormControl>
}

export const FormGroup = extractValue(memo(FormGroupBase)) as <P extends WidgetProps<MuiWidgetsBinding>>(props: P) => React.ReactElement
export const FormGroup = extractValue(memo(FormGroupBase)) as typeof FormGroupBase
1 change: 0 additions & 1 deletion packages/ds-material/src/WidgetsDefault/plugins/index.ts

This file was deleted.

33 changes: 0 additions & 33 deletions packages/ds-material/src/WidgetsDefault/plugins/plugins.ts

This file was deleted.

@@ -1,12 +1,12 @@
import React from 'react'
import { getNextPlugin, WidgetPluginProps } from '@ui-schema/react/WidgetEngine'
import { useSchemaCombine } from '@ui-schema/react-json-schema/CombiningHandler'
import { WithValue } from '@ui-schema/react/UIStore'
import { WidgetProps } from '@ui-schema/react/Widgets'
import { DecoratorPropsNext } from '@tactic-ui/react/Deco'

export const CombiningHandler: React.FC<WidgetPluginProps & Partial<WithValue>> = (props) => {
const {schema: baseSchema, value, currentPluginIndex} = props
export const CombiningHandler = <P extends WidgetProps & DecoratorPropsNext & WithValue>(props: P): React.ReactElement<P> => {
const {schema: baseSchema, value} = props
const schema = useSchemaCombine(baseSchema, value)
const next = currentPluginIndex + 1
const Plugin = getNextPlugin(next, props.widgets)
return <Plugin {...props} currentPluginIndex={next} schema={schema}/>
const Next = props.next(props.decoIndex + 1)
return <Next {...props} decoIndex={props.decoIndex + 1} schema={schema}/>
}
@@ -1,8 +1,10 @@
import React from 'react'
import { NextPluginRendererMemo, WidgetPluginProps } from '@ui-schema/react/WidgetEngine'
import { handleIfElseThen } from './handleIfElseThen'
import { WidgetProps } from '@ui-schema/react/Widgets'
import { DecoratorPropsNext } from '@tactic-ui/react/Deco'
import { WithValue } from '@ui-schema/react/UIStore'

export const ConditionalHandler: React.FC<WidgetPluginProps> = (props) => {
export const ConditionalHandler = <P extends WidgetProps & DecoratorPropsNext & WithValue>(props: P): React.ReactElement<P> => {
const {value} = props
let {schema} = props

Expand All @@ -12,5 +14,7 @@ export const ConditionalHandler: React.FC<WidgetPluginProps> = (props) => {
schema = handleIfElseThen(schema, value, schema)
}

return <NextPluginRendererMemo {...props} schema={schema}/>
const Next = props.next(props.decoIndex + 1)

return <Next {...props} schema={schema} decoIndex={props.decoIndex + 1}/>
}

0 comments on commit 05328af

Please sign in to comment.