React Form + UI generator for any design system, based on JSON-Schema, easy creation of complex custom widgets.
JSON Schema form + UI generator for any design system, first-class support for Material UI React, easily create own widgets and plugins.
Develop your next React app faster, with less code duplications - and without wasting time to implement validations.
Additional Material-UI Widgets:
@ui-schema/material-pickers
@ui-schema/material-code
react-color
picker: @ui-schema/material-color
react-colorful
picker: @ui-schema/material-colorful
react-dnd
: @ui-schema/material-dnd
@ui-schema/material-editorjs
@ui-schema/material-slate
Additional Packages, not only for UI Schema:
🚀 Demo: UI Schema + Material Design + Create React App: Demo Source
Use JSON Schema to validate data and automatically create UIs with it - UI-Schema makes it easy to write widgets based on schema structures, use custom UI keywords to make it look great!
t
prop (Translator), Trans
component)t
keyword)tt
/ttEnum
keyword)PluginStack
hidden
keyword)🔥 Professional service & support available, reach out now!
Design-System and Widgets Overview
This project adheres to semver, until 1.0.0
and beginning with 0.1.0
: all 0.x.0
releases are like MAJOR releases and all 0.0.x
like MINOR or PATCH, modules below 0.1.0
should be considered experimental.
Get the latest version - or help build it:
First time? Take the quick-start or take a look into the MUI demo repos: create-react-app & JS (simple) or create-react-app & Typescript (advanced).
Example setup of a renderer, followed by a simple text widget.
Instead of using UIRootRenderer
it’s also possible to use full custom rendering with e.g. ObjectGroup.
import React from 'react';
// Import Schema UI Provider and Render engine
import {isInvalid} from '@ui-schema/ui-schema/ValidityReporter';
import {createOrderedMap} from '@ui-schema/ui-schema/Utils/createMap';
import {UIStoreProvider, createStore} from '@ui-schema/ui-schema/UIStore';
import {storeUpdater} from '@ui-schema/ui-schema/storeUpdater';
import {UIMetaProvider, useUIMeta} from '@ui-schema/ui-schema/UIMeta';
// new in `0.4.0-alpha.1`:
// import {injectPluginStack} from '@ui-schema/ui-schema/applyPluginStack';
// deprecated since `0.4.0-alpha.1`:
import {UIRootRenderer} from '@ui-schema/ui-schema/UIRootRenderer';
// basic in-schema translator / `t` keyword support
import {relTranslator} from '@ui-schema/ui-schema/Translate/relT';
// Get the widgets binding for your design-system
import {widgets} from '@ui-schema/ds-material/widgetsBinding';
// new in `0.4.0-alpha.1`:
// import {GridContainer} from '@ui-schema/ds-material/GridContainer';
// could be fetched from some API or bundled with the app
const schemaBase = {
type: 'object',
properties: {
country: {
type: 'string',
widget: 'Select',
enum: [
'usa',
'canada',
'eu'
],
default: 'eu',
tt: 'upper'
},
name: {
type: 'string',
maxLength: 20,
}
},
required: [
'country',
'name',
],
};
// or fetch from API
const data = {};
// for `>=0.4.0-alpha.1`:
// const GridStack = injectPluginStack(GridContainer)
export const DemoForm = () => {
// optional state for display errors/validity
const [showValidity, setShowValidity] = React.useState(false);
// needed variables and setters for the render engine, create wherever you like
const [store, setStore] = React.useState(() => createStore(createOrderedMap(data)));
const [schema/*, setSchema*/] = React.useState(() => createOrderedMap(schemaBase));
// `useUIMeta` can be used safely, without performance impact (`useUI` has a performance impact)
const {widgets, t} = useUIMeta()
const onChange = React.useCallback((actions) => {
setStore(storeUpdater(actions))
}, [setStore])
return <>
<UIStoreProvider
store={store}
onChange={onChange}
showValidity={showValidity}
>
{/*
* for `>=0.4.0-alpha.1`:
*/}
{/*<GridStack isRoot schema={schema}/>*}
{/*
* deprecated since `0.4.0-alpha.1`:
*/}
<UIRootRenderer schema={schema}/>
</UIStoreProvider>
<button
/* show the validity only at submit (or pass `true` to `showValidity`) */
onClick={() =>
isInvalid(store.getValidity()) ?
setShowValidity(true) :
console.log('doingSomeAction:', store.valuesToJS())
}
>send!
</button>
</>
};
export default function App() {
return <UIMetaProvider
widgets={widgets}
t={relTranslator}
// never pass down functions like this - always use e.g. `React.useCallback`, check performance docs for more
//t={(text, context, schema) => {/* add translations */}}
>
{/*
* somewhere in `YourRouterAndStuff` are your custom forms,
* it's possible to nest `UIMetaProvider` if you need to have different widgets,
* e.g. depending on some lazy loaded component tree
*/}
<YourRouterAndStuff/>
</UIMetaProvider>
}
Easily create new widgets, this is all for a simple text (type=string
) widget:
import React from 'react';
import { TransTitle, WidgetProps, WithScalarValue } from '@ui-schema/ui-schema';
const Widget = (
{
value, storeKeys, onChange,
required, schema,
errors, valid,
...props
}: WidgetProps & WithScalarValue,
) => {
return <>
<label><TransTitle schema={schema} storeKeys={storeKeys}/></label>
<input
type={'text'}
required={required}
value={value || ''}
onChange={(e) => {
onChange({
storeKeys,
scopes: ['value'],
// or use another StoreAction like `update`
type: 'set',
data: {
value: e.target.value,
//internalValue: undefined
//valid: undefined
},
schema,
required,
})
}}
/>
</>
}
See CONTRIBUTING.md.
This project is free software distributed under the MIT License.
See: LICENSE.
© 2024 bemit UG (haftungsbeschränkt)
The icons in the badges of the readme’s are either from simpleicons or are licensed otherwise:
Created by Michael Becker