UI-Schema for React
JSON-Schema form + ui generator for any design system, first-class support for Material UI React.
-
Additional Material-UI Widgets:
⚠️ Work in progress!UI-Schema is an extract and rewrite of the form-generator logic used internally by our admin panel.
The fundamentals are working, but a lot of JSON-schema stuff, code testing and widgets needs to be done.
Schema
JSON-Schema included keywords are used to describe the data and create the UI based on the data-schema and special UI keywords. A data-schema with integrated ui-schema enforces the consistency of the UX across different apps and devices.
Features
- add any design-system and custom widget
- translation of widgets
- with any library
- (optional) integrated translation library
- include translation in schema
- single or multi-language
- modular core
- add own validator plugins
- add own schema-driven plugins
- use what you need
- performance optimized, only updates HTML which must re-render, perfect for big schemas
- supports code-splitting (with custom widget mappings, lazy-loading widgets)
- includes helper functions for store handling
- conditional and combining schemas
- easy nesting of editor for object/array widgets
- supports JSON-Schema 2019-09 / draft-8
Design-System and Widgets Overview
Basic Example
This example shows the available props.
First time? Take the quick-start or take a look into the create-react-app UI-Schema example.
import React from "react";
// Import Schema-Editor
import {
SchemaEditor,
isInvalid,
createOrderedMap, createStore,
createMap, createEmptyStore,
updateValue
} from "@ui-schema/ui-schema";
// Get the widgets binding for your design-system
import {widgets} from "@ui-schema/ds-material";
// 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"
},
name: {
type: "string",
maxLength: 20,
}
},
required: [
"country",
"name",
],
};
const data = {};
const Editor = () => {
// optional state for display errors/validity
const [showValidity, setShowValidity] = React.useState(false);
// needed variables and setters for the SchemaEditor, create wherever you like
const [store, setStore] = React.useState(() => createStore(createOrderedMap(data)));
const [schema/*, setSchema*/] = React.useState(() => createOrderedMap(schemaBase));
return <React.Fragment>
<SchemaEditor
schema={schema}
store={store}
onChange={setStore}
showValidity={showValidity}
widgets={widgets}
t={(text, context, schema) => {/* add translations */}}
{/*
* or custom onChange, e.g. save-on-update:
* - handler gets the previous store
* - returns updated store
*/}
onChange={handler => setStore(data => handler(data))}
>
{/* (optional) add components which use the context of the Editor here */}
</SchemaEditor>
<button
{/* show the validity only at submit (or pass `true` to `showValidity`) */}
onClick={() =>
isInvalid(store.getValidity()) ?
setShowValidity(true) :
doingSomeAction()
}
>send!</button>
</React.Fragment>
};
export {Editor}
Contributing
- Fork/Clone Repository
- Install root dev-dependencies (like lerna, webpack):
npm i
- Start dev-server:
npm start
(will clean-dist + symlink-es-modules + init & hoist packages + starting demo app) - Open browser on localhost:4200
- Explore packages
- Code -> Commit -> Pull Request -> Being Awesome!
Changes from any package are reflected inside the demo/docs package.
- Start Documentation:
npm run docs
(needs running demo server)- see localhost:4201
- write in packages/docs/src/content/docs
- or: starting Demo + Docs (after having initialized, hoisted it manually):
npm run serve
Commands:
- Build:
npm run build
- Clean node_modules and build dirs:
npm run clean
- Clean build dirs:
npm run clean-dist
- Add new node_module to one package:
lerna add <npm-package-name> --scope=@ui-schema/demo [--dev] [--peer]
, without--scope
in all packages - Do not change package.json of packages manually, and if Bootstrap lerna:
npm run bootstrap
- Add new package
lerna create <name>
and follow on screen, e.g.:lerna create material-pickers
add package name@ui-schema/material-picker
, creates folder./packages/material-pickers
Publish, for main-repo only:
- Currently manually
lerna version <semver> --no-git-tag-version
is needed- like
lerna version 0.0.2 --no-git-tag-version
, see docs
- like
- Then tag the commit with the same version
- Push, CI will publish to npm using
npm run release -- --yes
- this leads to:
lerna publish from-package --no-git-reset --yes
- this leads to:
- todo: automate version bump by git-tags w/ publish, and switch to independent lerna versioning
Templates for monorepo packages:
License
This project is free software distributed under the MIT License.
See: LICENSE.
© 2020 bemit UG (haftungsbeschränkt)
License Icons
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
Contributors
By committing your code/creating a pull request to this repository you agree to release the code under the MIT License attached to the repository.
Created by Michael Becker