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:
- Date-Time Picker:
@ui-schema/material-pickers
- Codemirror as Material Input:
@ui-schema/material-code
react-color
picker:@ui-schema/material-color
react-colorful
picker:@ui-schema/material-colorful
- 🚧 Drag 'n Drop with
react-dnd
:@ui-schema/material-dnd
- 🚧 EditorJS as Material TextField:
@ui-schema/material-editorjs
- 🚧 SlateJS as Material TextField:
@ui-schema/material-slate
- Date-Time Picker:
-
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!
- add any design-system or custom widget
- easily create isolated and atomic widgets, with autowired data and validations
- customize design system behaviour with e.g. widget compositions
- easy binding of own design systems and custom widgets
- easily add advanced features like read-or-write mode
- auto-rendering by data & schema or full-custom forms with autowired widgets
- flexible translation of widgets
- with any library (
t
prop (Translator),Trans
component) - in-schema translations (
t
keyword) - label text transforms (
tt
/ttEnum
keyword) - single or multi-language
- for labels, titles, errors, icons...
- (optional) tiny integrated translation library
- (optional) translation dictionaries
- with any library (
- modular, extensible and slim core
- add own plugins
- add own validators
- add own base renderers
- add own widget matchers & render strategies
- use what you need
- performance optimized, only updates HTML which must re-render, perfect for big schemas
- code-splitting, with custom widget mappings / lazy-loading widgets
- includes helper functions for store and immutable handling
- easy nesting for custom object/array widgets with
PluginStack
- validate hidden/auto-generated values, virtualize schema levels (
hidden
keyword) - handle store update from anywhere and however you want
- extensive documentations of core, widgets
- typed components and definitions for JSON Schema and UI Schema
- complex conditionals schemas
- loading / referencing schemas by URL, connect any API or e.g. babel dynamic loading instead
- definitions and JSON-Pointer references in schemas
- JSON Schema extension: UI Schema, change design and even behaviour of widgets
- JSON Schema versions supported: Draft 2019-09 / Draft-08, Draft-07, Draft-06, Draft-04
🔥 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:
- latest releases (GitHub release notes)
- update and migration notes (docs page)
- current roadmap (GitHub discussion)
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.
© 2022 bemit UG (haftungsbeschränkt)
The icons in the badges of the readme's are either from simpleicons or are licensed otherwise:
- Play Icon © Chanut is Industries, CC BY 3.0
- Experiment Icon © Ardiansyah Ardi, CC BY 3.0
- Doc Icons © PICOL, CC BY 3.0
Created by Michael Becker