330 lines
6.3 KiB
Markdown
330 lines
6.3 KiB
Markdown
|
# What is UI Schema?
|
||
|
|
||
|
A protocol for describing front-end components, based on Formily Schema 2.0, JSON Schema-like style.
|
||
|
|
||
|
```ts
|
||
|
interface ISchema {
|
||
|
type: 'void' | 'string' | 'number' | 'object' | 'array';
|
||
|
name?: string;
|
||
|
title?: any;
|
||
|
// wrapper component
|
||
|
['x-decorator']? : string;
|
||
|
// Wrapper component properties
|
||
|
['x-decorator-props']? : any;
|
||
|
// component
|
||
|
['x-component']? : string;
|
||
|
// Component properties
|
||
|
['x-component-props']? : any;
|
||
|
// display state, default is 'visible'
|
||
|
['x-display']? : 'none' | 'hidden' | 'visible';
|
||
|
// child node of the component, simply use
|
||
|
['x-content']? : any;
|
||
|
// children node schema
|
||
|
properties?: Record<string, ISchema>;
|
||
|
|
||
|
// The following is used only for field components
|
||
|
|
||
|
// field linkage
|
||
|
['x-reactions']? : SchemaReactions;
|
||
|
// Field UI interaction mode, default is 'editable'
|
||
|
['x-pattern']? : 'editable' | 'disabled' | 'readPretty';
|
||
|
// Field validation
|
||
|
['x-validator']? : Validator;
|
||
|
// default data
|
||
|
default: ? :any;
|
||
|
|
||
|
// Designer related
|
||
|
|
||
|
// Designer component (toolbar), including: drag and drop to move, insert new nodes, modify parameters, remove, etc.
|
||
|
['x-designer']? : any;
|
||
|
// Initializer component (toolbar), determines what can be inserted inside the current schema
|
||
|
['x-initializer']? : any;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## The simplest component
|
||
|
|
||
|
All native html tags can be converted to schema writing. For example
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
'x-component': 'h1',
|
||
|
'x-content': 'Hello, world!
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX examples
|
||
|
|
||
|
```tsx | pure
|
||
|
<h1>Hello, world!</h1>
|
||
|
```
|
||
|
|
||
|
## children components can be written in properties
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
'x-component': 'input',
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
<input name={'title'} />
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
## The clever use of Decorator
|
||
|
|
||
|
The combination of decorator + component allows you to put two components in a single schema node, reducing the complexity of the schema structure and increasing the reusability of the components.
|
||
|
|
||
|
For example, in a form scenario, you can combine a FormItem component with any field component, where the FormItem is the Decorator.
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
['x-component']: 'div',
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
'x-decorator': 'FormItem',
|
||
|
'x-component': 'Input',
|
||
|
},
|
||
|
content: {
|
||
|
type: 'string',
|
||
|
'x-decorator': 'FormItem',
|
||
|
'x-component': 'Input.TextArea',
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div>
|
||
|
<FormItem>
|
||
|
<Input name={'title'} />
|
||
|
</FormItem>
|
||
|
<FormItem>
|
||
|
<Input.TextArea name={'content'} />
|
||
|
</FormItem>
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
It is also possible to provide a CardItem component that wraps all blocks, so that all blocks are Card wrapped.
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
['x-component']: 'div',
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
'x-decorator': 'CardItem',
|
||
|
'x-component': 'Table',
|
||
|
},
|
||
|
content: {
|
||
|
type: 'string',
|
||
|
'x-decorator': 'CardItem',
|
||
|
'x-component': 'Kanban',
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div>
|
||
|
<CardItem>
|
||
|
<Table />
|
||
|
</CardItem>
|
||
|
<CardItem>
|
||
|
<Kanban />
|
||
|
</CardItem>
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
## Display state of the component
|
||
|
|
||
|
- `'x-display': 'visible'`: the component is displayed
|
||
|
- `'x-display': 'hidden'`: component is hidden, data is not hidden
|
||
|
- `'x-display': 'none'`: component is hidden, data is also hidden
|
||
|
|
||
|
### `'x-display': 'visible'`
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
'x-component': 'input',
|
||
|
'x-display': 'visible'
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
<input name={'title'} />
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
### `'x-display': 'hidden'`
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
'x-component': 'input',
|
||
|
'x-display': 'hidden'
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
{/* The input component is not output here, the corresponding field model with name=title still exists */}
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
### `'x-display': 'none'`
|
||
|
|
||
|
```ts
|
||
|
{
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
'x-component': 'input',
|
||
|
'x-display': 'none'
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
{/* The input component is not output here, and the corresponding field model with name=title does not exist anymore */}
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
## Display modes for components
|
||
|
|
||
|
For field components, there are three display modes:
|
||
|
|
||
|
- `'x-pattern': 'editable'` Editable
|
||
|
- `'x-pattern': 'disabled'` Non-editable
|
||
|
- `'x-pattern': 'readPretty'` Friendly reading
|
||
|
|
||
|
As in the case of the `<SingleText />` component, the editable and disabled modes are `<input />` and the readPretty mode is `<div />`.
|
||
|
|
||
|
### `'x-pattern': 'editable'`
|
||
|
|
||
|
```ts
|
||
|
const schema = {
|
||
|
name: 'test',
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
default: 'Hello',
|
||
|
'x-component': 'SingleText',
|
||
|
'x-pattern': 'editable'
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
<input name={'title'} value={'Hello'} />
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
### `'x-pattern': 'disabled'`
|
||
|
|
||
|
```ts
|
||
|
const schema = {
|
||
|
name: 'test',
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
default: 'Hello',
|
||
|
'x-component': 'SingleText',
|
||
|
'x-pattern': 'disabled'
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
<input name={'title'} value={'Hello'} disabled />
|
||
|
</div>
|
||
|
```
|
||
|
|
||
|
### `'x-pattern': 'readPretty'`
|
||
|
|
||
|
```ts
|
||
|
const schema = {
|
||
|
name: 'test',
|
||
|
type: 'void',
|
||
|
'x-component': 'div',
|
||
|
'x-component-props': { className: 'form-item' },
|
||
|
properties: {
|
||
|
title: {
|
||
|
type: 'string',
|
||
|
default: 'Hello',
|
||
|
'x-component': 'SingleText',
|
||
|
'x-pattern': 'readPretty',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
```
|
||
|
|
||
|
JSX is equivalent to
|
||
|
|
||
|
```tsx | pure
|
||
|
<div className={'form-item'}>
|
||
|
<div>Hello</div>
|
||
|
</div>
|
||
|
```
|