diff --git a/src/js/component/form.jsx b/src/js/component/form.jsx index 5fb1e63..0e9f87f 100644 --- a/src/js/component/form.jsx +++ b/src/js/component/form.jsx @@ -9,86 +9,53 @@ import MultilineTextControl, { multilineTextControlTester } from "../renderers/M import ColorPaletteTextControl, { colorPaletteControlTester } from "../renderers/ColorPaletteControl"; import BooleanToggleControl, { booleanToggleControlTester } from "../renderers/BooleanToggleControl"; import BooleanCheckboxControl, { booleanCheckboxControlTester } from "../renderers/BooleanCheckboxControl"; +import GutenbergNavigatorlLayoutRenderer, { gutenbergNavigatorLayoutTester } from "../renderers/NavigatorLayout"; const schema = { type: "object", properties: { - textControl: { - type: "string", - label: "Text Control Label", - description: "Text Control displays a 'string' Control" - }, - multilineTextControl: { - type: "string", - label: "Muliline Text Control Label", - description: "Multiline Text Control displays a 'string' Control supports multiline" - }, - colorPaletteControl: { - type: "string", - label: "Color Palette Control Label", - description: "Color Picker with predefine palette" - }, - booleanToggleControl: { - type: "boolean", - label: "Boolean Toggle Control Label", - description: "Boolean Control with Toggle Renderer" + address: { + type: 'object', + properties: { + street_address: { type: 'string' }, + city: { type: 'string' }, + state: { type: 'string' }, + user: { + type: 'object', + properties: { + name: { type: 'string' }, + mail: { type: 'string' }, + } + } + } }, - booleanCheckboxControl: { - type: "boolean", - label: "Boolean Checkbox Control Label", - description: "Boolean Control with Checkbox Renderer" + business: { + type: 'object', + properties: { + job: { type: 'string' } + } } }, }; const uischema = { - type: "VerticalLayout", + type: "NavigatorLayout", elements: [ { - type: "Control", - scope: "#/properties/textControl", - }, - { - type: "Control", - scope: "#/properties/multilineTextControl", - options: { - multi: true, - }, - }, - { - type: "Control", - scope: "#/properties/colorPaletteControl", - options: { - format: 'color', - colors:[ - { - color: '#f00', - name: 'Red' - }, - { - color: '#fff', - name: 'White' - }, - { - color: '#00f', - name: 'Blue' - } - ] - }, - }, - { - type: "Control", - scope: "#/properties/booleanToggleControl", - options: { - toggle: true - } - }, - { - type: "Control", - scope: "#/properties/booleanCheckboxControl", + type: 'VerticalLayout', + elements: [ + { + type: 'Control', + scope: '#/properties/address', + }, + { + type: 'Control', + scope: '#/properties/business', + } + ], } ], -}; +} const initialData = {}; @@ -100,7 +67,8 @@ const renderers = [ { tester: multilineTextControlTester, renderer: MultilineTextControl }, { tester: colorPaletteControlTester, renderer: ColorPaletteTextControl }, { tester: booleanToggleControlTester, renderer: BooleanToggleControl}, - { tester: booleanCheckboxControlTester, renderer: BooleanCheckboxControl} + { tester: booleanCheckboxControlTester, renderer: BooleanCheckboxControl}, + { tester: gutenbergNavigatorLayoutTester, renderer: GutenbergNavigatorlLayoutRenderer} ]; export default function App() { diff --git a/src/js/renderers/NavigatorLayout.js b/src/js/renderers/NavigatorLayout.js new file mode 100644 index 0000000..8f94b27 --- /dev/null +++ b/src/js/renderers/NavigatorLayout.js @@ -0,0 +1,115 @@ +import React from "react" +import { rankWith, uiTypeIs } from "@jsonforms/core" +import { MaterialLayoutRenderer } from "./NavigatorRenderer" +import { + JsonFormsDispatch, + withJsonFormsLayoutProps +} from "@jsonforms/react" + +import { + __experimentalNavigatorProvider as NavigatorProvider, + __experimentalNavigatorScreen as NavigatorScreen, + __experimentalNavigatorButton as NavigatorButton, + __experimentalNavigatorToParentButton as NavigatorToParentButton, +} from '@wordpress/components'; + +/** + * Default tester for a vertical layout. + * @type {RankedTester} + */ +export const gutenbergNavigatorLayoutTester = rankWith( + 2, + uiTypeIs("NavigatorLayout") +) + +export const GutenbergNavigatorlLayoutRenderer = ({ + uischema, + schema, + path, + enabled, + visible, + renderers, + cells +}) => { + // nit: move this method into seperate file + /* + * Recursive method to get all the `object` type property and return them as { path, key } + * Note: so far the method skips the root node, and only looking inside the `properties` prop + */ + const getObjectProperties = (obj, parentPath = '') => { + const result = []; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const path = parentPath ? `${parentPath}/${key}` : `/${key}`; + // Convert the slash-string into dot-string, eg: /address/user - address.user + const dotPath = path.replace(/^\//, '').replace(/\//g, '.'); + const prop = obj[key]; + + if (prop.type === 'object') { + result.push({ path, key, dotPath }); + result.push(...getObjectProperties(prop.properties, path)); + } + } + } + + return result; + }; + + const navigatableProps = getObjectProperties(schema.properties); + + // The navigatorLayout should be the root layout + const navigatorLayout = uischema + + const childProps = { + elements: navigatorLayout.elements, + schema, + path, + enabled, + direction: "column", + visible + } + + return ( + <> + {/* */} + + + This is the home screen. + {navigatableProps.filter((({dotPath}) => dotPath.split(".").length < 2 )).map(({path, key, dotPath}, index) => ( + + Go to {key} screen. {dotPath} + + ))} + + + {navigatableProps.map(({path, key, dotPath}, index) => ( + + This is the {key} screen. {dotPath} + + Go back + + + Go to home + + + + ))} + + + > + ) +} + +export default withJsonFormsLayoutProps(GutenbergNavigatorlLayoutRenderer) diff --git a/src/js/renderers/NavigatorRenderer.js b/src/js/renderers/NavigatorRenderer.js new file mode 100644 index 0000000..9a509ce --- /dev/null +++ b/src/js/renderers/NavigatorRenderer.js @@ -0,0 +1,74 @@ +import isEmpty from "lodash/isEmpty" +import React from "react" +import { getAjv } from "@jsonforms/core" +import { JsonFormsDispatch, useJsonForms } from "@jsonforms/react" +import { Grid, Hidden } from "@mui/material" + +export const renderLayoutElements = ( + elements, + schema, + path, + enabled, + renderers, + cells +) => { + return elements.map((child, index) => ( + + + + )) +} + +const MaterialLayoutRendererComponent = ({ + visible, + elements, + schema, + path, + enabled, + direction, + renderers, + cells +}) => { + if (isEmpty(elements)) { + return null + } else { + return ( + + + {renderLayoutElements( + elements, + schema, + path, + enabled, + renderers, + cells + )} + + + ) + } +} +export const MaterialLayoutRenderer = React.memo( + MaterialLayoutRendererComponent +) + +// TODO fix @typescript-eslint/ban-types +// eslint-disable-next-line @typescript-eslint/ban-types +export const withAjvProps = Component => + function WithAjvProps(props) { + const ctx = useJsonForms() + const ajv = getAjv({ jsonforms: { ...ctx } }) + + return + }
This is the home screen.
Go to {key} screen. {dotPath}
This is the {key} screen. {dotPath}
Go to home