diff --git a/packages/demo-web/src/component/useToggle.ts b/packages/demo-web/src/component/useToggle.ts new file mode 100644 index 00000000..7c9e93d6 --- /dev/null +++ b/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] +} diff --git a/packages/demo-web/src/material-ui/component/MuiMainDummy.tsx b/packages/demo-web/src/material-ui/component/MuiMainDummy.tsx index 21e8c399..b23db765 100644 --- a/packages/demo-web/src/material-ui/component/MuiMainDummy.tsx +++ b/packages/demo-web/src/material-ui/component/MuiMainDummy.tsx @@ -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 = ({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 + + {/**/} + + + + + + {isInvalid(store.getValidity()) ? 'invalid' : 'valid'} + + + + + +} 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 = {}}) => +}> = ({id, schema, toggleDummy, getDummy, open = false}) => {open || !toggleDummy ? null : } {(getDummy && getDummy(id)) || open || !toggleDummy ? - - - : null} + : null} diff --git a/packages/demo-web/src/material-ui/material-ui.tsx b/packages/demo-web/src/material-ui/material-ui.tsx index 4a774173..75f1c91d 100644 --- a/packages/demo-web/src/material-ui/material-ui.tsx +++ b/packages/demo-web/src/material-ui/material-ui.tsx @@ -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 @@ -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, @@ -156,6 +169,7 @@ function DemoRenderer

& DemoRendererProps> => { let matching: string | undefined if (typeof schemaWidget === 'string') { @@ -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 {/* todo make the typing stricter and easier (check tactic-ui comments) */} {/* }, typeof renderMapping.components>['leafs'], typeof renderMapping.components, typeof deco>*/} @@ -233,6 +254,61 @@ export default function MaterialDemo() { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ds-material/src/Widgets/FormGroup/FormGroup.tsx b/packages/ds-material/src/Widgets/FormGroup/FormGroup.tsx index 3a630e97..cc992691 100644 --- a/packages/ds-material/src/Widgets/FormGroup/FormGroup.tsx +++ b/packages/ds-material/src/Widgets/FormGroup/FormGroup.tsx @@ -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 & 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 - - - - }>(props: P): React.ReactElement

=> { + 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 - {/* @ts-ignore */} - - - {/*Be careful*/} - -} + + + + + {/* todo: re-use the next widget matcher */} + {/* @ts-ignore */} + {Widget ? : '-'} + + {/*Be careful*/} + + } -export const FormGroup = extractValue(memo(FormGroupBase)) as

>(props: P) => React.ReactElement +export const FormGroup = extractValue(memo(FormGroupBase)) as typeof FormGroupBase diff --git a/packages/ds-material/src/WidgetsDefault/plugins/index.ts b/packages/ds-material/src/WidgetsDefault/plugins/index.ts deleted file mode 100644 index f9c03499..00000000 --- a/packages/ds-material/src/WidgetsDefault/plugins/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './plugins' diff --git a/packages/ds-material/src/WidgetsDefault/plugins/plugins.ts b/packages/ds-material/src/WidgetsDefault/plugins/plugins.ts deleted file mode 100644 index 52d7bd08..00000000 --- a/packages/ds-material/src/WidgetsDefault/plugins/plugins.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { SchemaGridHandler } from '@ui-schema/ds-material/Grid' -import { WidgetPluginType } from '@ui-schema/react/WidgetEngine' -import { DefaultHandler } from '@ui-schema/react-json-schema/DefaultHandler' -import { CombiningHandler } from '@ui-schema/react-json-schema/CombiningHandler' -import { ConditionalHandler } from '@ui-schema/react-json-schema/ConditionalHandler' -import { DependentHandler } from '@ui-schema/react-json-schema/DependentHandler' -import { ReferencingHandler } from '@ui-schema/react-json-schema/ReferencingHandler' -import { SchemaPluginsAdapter } from '@ui-schema/react/SchemaPluginsAdapter' -import { ValidityReporter } from '@ui-schema/react/ValidityReporter' -import { getValidators } from '@ui-schema/json-schema/getValidators' -import { SchemaPlugin } from '@ui-schema/system/SchemaPlugin' - -export const plugins = (): { - widgetPlugins: WidgetPluginType[] - schemaPlugins: SchemaPlugin[] -} => { - const widgetPlugins: WidgetPluginType[] = [ - ReferencingHandler,// must be before AND maybe after combining/conditional? - SchemaGridHandler,// todo: Grid must be after e.g. ConditionalHandler, but why was it this high? wasn't that because of e.g. conditional object grids? - // ExtractStorePlugin, - CombiningHandler, - DefaultHandler, - DependentHandler, - ConditionalHandler, - SchemaPluginsAdapter, - ValidityReporter, - ] - - return { - widgetPlugins, - schemaPlugins: getValidators(), - } -} diff --git a/packages/uis-react-json-schema/src/CombiningHandler/CombiningHandler.tsx b/packages/uis-react-json-schema/src/CombiningHandler/CombiningHandler.tsx index d8ec52a7..b2c9b132 100644 --- a/packages/uis-react-json-schema/src/CombiningHandler/CombiningHandler.tsx +++ b/packages/uis-react-json-schema/src/CombiningHandler/CombiningHandler.tsx @@ -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> = (props) => { - const {schema: baseSchema, value, currentPluginIndex} = props +export const CombiningHandler =

(props: P): React.ReactElement

=> { + const {schema: baseSchema, value} = props const schema = useSchemaCombine(baseSchema, value) - const next = currentPluginIndex + 1 - const Plugin = getNextPlugin(next, props.widgets) - return + const Next = props.next(props.decoIndex + 1) + return } diff --git a/packages/uis-react-json-schema/src/ConditionalHandler/ConditionalHandler.tsx b/packages/uis-react-json-schema/src/ConditionalHandler/ConditionalHandler.tsx index 4f388a1f..65ddbaa5 100644 --- a/packages/uis-react-json-schema/src/ConditionalHandler/ConditionalHandler.tsx +++ b/packages/uis-react-json-schema/src/ConditionalHandler/ConditionalHandler.tsx @@ -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 = (props) => { +export const ConditionalHandler =

(props: P): React.ReactElement

=> { const {value} = props let {schema} = props @@ -12,5 +14,7 @@ export const ConditionalHandler: React.FC = (props) => { schema = handleIfElseThen(schema, value, schema) } - return + const Next = props.next(props.decoIndex + 1) + + return } diff --git a/packages/uis-react-json-schema/src/DefaultHandler/DefaultHandler.tsx b/packages/uis-react-json-schema/src/DefaultHandler/DefaultHandler.tsx index 984a1447..4b3be2bb 100644 --- a/packages/uis-react-json-schema/src/DefaultHandler/DefaultHandler.tsx +++ b/packages/uis-react-json-schema/src/DefaultHandler/DefaultHandler.tsx @@ -1,16 +1,16 @@ import React from 'react' import { Map } from 'immutable' -import { getNextPlugin, WidgetPluginProps } from '@ui-schema/react/WidgetEngine' +import { WidgetProps } from '@ui-schema/react/Widgets' +import { DecoratorPropsNext } from '@tactic-ui/react/Deco' +import { WithValue } from '@ui-schema/react/UIStore' export interface DefaultHandlerProps { doNotDefault?: boolean readOnly?: boolean } -export const DefaultHandler: React.FC = (props) => { - const {schema, currentPluginIndex, doNotDefault, readOnly} = props - const next = currentPluginIndex + 1 - const Plugin = getNextPlugin(next, props.widgets) +export const DefaultHandler =

(props: P & DefaultHandlerProps): React.ReactElement

=> { + const {schema, doNotDefault, readOnly} = props const defaultVal = schema.get('default') @@ -51,6 +51,7 @@ export const DefaultHandler: React.FC = nextValue = defaultVal } - return + const Next = props.next(props.decoIndex + 1) + return } diff --git a/packages/uis-react-json-schema/src/DependentHandler/DependentHandler.tsx b/packages/uis-react-json-schema/src/DependentHandler/DependentHandler.tsx index b1c0b3eb..f684efc5 100644 --- a/packages/uis-react-json-schema/src/DependentHandler/DependentHandler.tsx +++ b/packages/uis-react-json-schema/src/DependentHandler/DependentHandler.tsx @@ -1,15 +1,20 @@ import React from 'react' -import { getNextPlugin, NextPluginRendererMemo, WidgetPluginProps } from '@ui-schema/react/WidgetEngine' import { useUIStore } from '@ui-schema/react/UIStore' import { mergeSchema } from '@ui-schema/system/Utils/mergeSchema' import { List, Map } from 'immutable' import { UISchemaMap } from '@ui-schema/json-schema/Definitions' +import { WidgetProps } from '@ui-schema/react/Widgets' +import { DecoratorPropsNext } from '@tactic-ui/react/Deco' -const DependentRenderer: React.FC | UISchemaMap dependentSchemas?: UISchemaMap dependentRequired?: List -}> = ({dependencies, dependentSchemas, dependentRequired, ...props}) => { +} + +const DependentRenderer =

( + {dependencies, dependentSchemas, dependentRequired, ...props}: P & DependentRendererProps +) => { const {schema, storeKeys} = props const {store} = useUIStore() @@ -54,18 +59,18 @@ const DependentRenderer: React.FC + const Next = props.next(props.decoIndex + 1) + return } -export const DependentHandler: React.FC = (props) => { - const {schema, currentPluginIndex} = props - const next = currentPluginIndex + 1 - const Plugin = getNextPlugin(next, props.widgets) +export const DependentHandler =

(props: P): React.ReactElement

=> { + const {schema} = props const dependencies = schema.get('dependencies') const dependentSchemas = schema.get('dependentSchemas') const dependentRequired = schema.get('dependentRequired') + const Next = props.next(props.decoIndex + 1) return dependencies || dependentSchemas || dependentRequired ? = (props) => { dependentRequired={dependentRequired} {...props} /> : - + } diff --git a/packages/uis-react-json-schema/src/InheritKeywords/InheritKeywords.ts b/packages/uis-react-json-schema/src/InheritKeywords/InheritKeywords.ts index 532406ad..1af17171 100644 --- a/packages/uis-react-json-schema/src/InheritKeywords/InheritKeywords.ts +++ b/packages/uis-react-json-schema/src/InheritKeywords/InheritKeywords.ts @@ -1,9 +1,9 @@ -import { PluginSimple } from '@ui-schema/ui-schema/PluginSimpleStack' +import { SchemaPlugin } from '@ui-schema/system/SchemaPlugin' export const InheritKeywords = ( keywords: (string | (string[]))[], - should?: PluginSimple['should'], -): PluginSimple => ({ + should?: SchemaPlugin['should'], +): SchemaPlugin => ({ should: should, handle: ({parentSchema, schema}: any) => { let newSchema = schema diff --git a/packages/uis-react-json-schema/src/InjectSplitSchemaPlugin/InjectSplitSchemaPlugin.tsx b/packages/uis-react-json-schema/src/InjectSplitSchemaPlugin/InjectSplitSchemaPlugin.tsx index 4a451528..a9ca7a0c 100644 --- a/packages/uis-react-json-schema/src/InjectSplitSchemaPlugin/InjectSplitSchemaPlugin.tsx +++ b/packages/uis-react-json-schema/src/InjectSplitSchemaPlugin/InjectSplitSchemaPlugin.tsx @@ -1,9 +1,11 @@ import React from 'react' import { Map } from 'immutable' -import { getNextPlugin, WidgetPluginProps } from '@ui-schema/react/WidgetEngine' import { useSchemaRoot } from '@ui-schema/react-json-schema/SchemaRootProvider' import { UISchemaMap } from '@ui-schema/json-schema/Definitions' import { escapePointer } from '@ui-schema/json-pointer/escapePointer' +import { WidgetProps } from '@ui-schema/react/Widgets' +import { WithValue } from '@ui-schema/react/UIStore' +import { DecoratorPropsNext } from '@tactic-ui/react/Deco' export interface InjectSplitSchemaRootContext { schemaStyle?: UISchemaMap @@ -14,14 +16,11 @@ export interface InjectSplitSchemaRootContext { * @param props * @constructor */ -export const InjectSplitSchemaPlugin: React.ComponentType = (props) => { +export const InjectSplitSchemaPlugin =

(props: P): React.ReactElement

=> { const { schema, storeKeys, - currentPluginIndex, } = props const {schemaStyle} = useSchemaRoot() - const next = currentPluginIndex + 1 - const Plugin = getNextPlugin(next, props.widgets) const pointer = storeKeys.size > 0 ? '/' + storeKeys.map(k => escapePointer(String(k))).join('/') : '' const schemaStyleLevel = schemaStyle?.get(pointer) as Map | undefined @@ -38,10 +37,10 @@ export const InjectSplitSchemaPlugin: React.ComponentType = ( .delete('anyOf') .delete('required') } - // @ts-ignore - return } diff --git a/packages/uis-react-json-schema/src/ObjectRenderer/ObjectRenderer.tsx b/packages/uis-react-json-schema/src/ObjectRenderer/ObjectRenderer.tsx index 9ddc12ab..9488d616 100644 --- a/packages/uis-react-json-schema/src/ObjectRenderer/ObjectRenderer.tsx +++ b/packages/uis-react-json-schema/src/ObjectRenderer/ObjectRenderer.tsx @@ -3,6 +3,7 @@ import { memo } from '@ui-schema/react/Utils/memo' import { WidgetEngine } from '@ui-schema/react/WidgetEngine' import { LeafsRenderMapping } from '@tactic-ui/react/LeafsEngine' import { GroupRendererProps, WidgetProps } from '@ui-schema/react/Widgets' +import { SchemaValidatorContext } from '@ui-schema/system/SchemaPluginStack' export interface ObjectRendererProps extends WidgetProps { noGrid?: GroupRendererProps['noGrid'] @@ -10,7 +11,7 @@ export interface ObjectRendererProps extends WidgetProps { const WidgetEngineMemo = memo(WidgetEngine) -const ObjectRendererBase =

> }> }>( +const ObjectRendererBase =

> }> }>( { schema, storeKeys, schemaKeys, // for performance reasons, not pushing errors deeper diff --git a/packages/uis-react-json-schema/src/ReferencingHandler/ReferencingHandler.tsx b/packages/uis-react-json-schema/src/ReferencingHandler/ReferencingHandler.tsx index 6a971dab..cae2ad99 100644 --- a/packages/uis-react-json-schema/src/ReferencingHandler/ReferencingHandler.tsx +++ b/packages/uis-react-json-schema/src/ReferencingHandler/ReferencingHandler.tsx @@ -5,10 +5,17 @@ import { isRootSchema, useSchemaRoot, } from '@ui-schema/react-json-schema/SchemaRootProvider' import { useSchemaRef } from '@ui-schema/react-json-schema/ReferencingHandler' -import { NextPluginRendererMemo, WidgetPluginProps } from '@ui-schema/react/WidgetEngine' import { getSchemaId } from '@ui-schema/system/Utils/getSchema' +import { DecoratorPropsNext } from '@tactic-ui/react/Deco' +import { WidgetProps } from '@ui-schema/react/Widgets' -export const ReferencingHandler: React.FC = ({rootContext, ...props}) => { +export interface ReferencingHandlerProps { + rootContext?: { [k: string]: any } +} + +export const ReferencingHandler =

( + {rootContext, ...props}: P & ReferencingHandlerProps, +): React.ReactElement

=> { const {schema: baseSchema, isVirtual} = props const {schema: maybeRootSchema, definitions: maybeDefinitions, ...nestedRootProps} = useSchemaRoot() const isRoot = Boolean(isRootSchema(baseSchema) || rootContext || baseSchema.get('definitions') || baseSchema.get('$defs')) @@ -17,13 +24,15 @@ export const ReferencingHandler: React.FC 0 ? isVirtual ? null : : isRoot ? - + : - + ) as unknown as React.ReactElement } diff --git a/packages/uis-react-json-schema/src/SortPlugin/SortPlugin.ts b/packages/uis-react-json-schema/src/SortPlugin/SortPlugin.ts index 9729a96b..b1a7b6fb 100644 --- a/packages/uis-react-json-schema/src/SortPlugin/SortPlugin.ts +++ b/packages/uis-react-json-schema/src/SortPlugin/SortPlugin.ts @@ -1,7 +1,7 @@ import { OrderedMap, List } from 'immutable' -import { PluginSimple } from '@ui-schema/ui-schema/PluginSimpleStack' +import { SchemaPlugin } from '@ui-schema/system/SchemaPlugin' -export const SortPlugin: PluginSimple = { +export const SortPlugin: SchemaPlugin = { handle: ({schema}: any) => { const sortOrder = schema?.get('sortOrder') as List if(!sortOrder) return {}