#
tokens: 47793/50000 4/1152 files (page 29/35)
lines: off (toggle) GitHub
raw markdown copy
This is page 29 of 35. Use http://codebase.md/alibaba/formily?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .all-contributorsrc
├── .codecov.yml
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows
│       ├── check-pr-title.yml
│       ├── ci.yml
│       ├── commitlint.yml
│       ├── issue-open-check.yml
│       ├── package-size.yml
│       └── pr-welcome.yml
├── .gitignore
├── .prettierrc.js
├── .umirc.js
├── .vscode
│   └── cspell.json
├── .yarnrc
├── CHANGELOG.md
├── commitlint.config.js
├── devtools
│   ├── .eslintrc
│   └── chrome-extension
│       ├── .npmignore
│       ├── assets
│       │   └── img
│       │       ├── loading.svg
│       │       └── logo
│       │           ├── 128x128.png
│       │           ├── 16x16.png
│       │           ├── 38x38.png
│       │           ├── 48x48.png
│       │           ├── error.png
│       │           ├── gray.png
│       │           └── scalable.png
│       ├── config
│       │   ├── webpack.base.ts
│       │   ├── webpack.dev.ts
│       │   └── webpack.prod.ts
│       ├── LICENSE.md
│       ├── package.json
│       ├── src
│       │   ├── app
│       │   │   ├── components
│       │   │   │   ├── FieldTree.tsx
│       │   │   │   ├── filter.ts
│       │   │   │   ├── LeftPanel.tsx
│       │   │   │   ├── RightPanel.tsx
│       │   │   │   ├── SearchBox.tsx
│       │   │   │   └── Tabs.tsx
│       │   │   ├── demo.tsx
│       │   │   └── index.tsx
│       │   └── extension
│       │       ├── backend.ts
│       │       ├── background.ts
│       │       ├── content.ts
│       │       ├── devpanel.tsx
│       │       ├── devtools.tsx
│       │       ├── inject.ts
│       │       ├── manifest.json
│       │       ├── popup.tsx
│       │       └── views
│       │           ├── devpanel.ejs
│       │           ├── devtools.ejs
│       │           └── popup.ejs
│       ├── tsconfig.build.json
│       └── tsconfig.json
├── docs
│   ├── functions
│   │   ├── contributors.ts
│   │   └── npm-search.ts
│   ├── guide
│   │   ├── advanced
│   │   │   ├── async.md
│   │   │   ├── async.zh-CN.md
│   │   │   ├── build.md
│   │   │   ├── build.zh-CN.md
│   │   │   ├── business-logic.md
│   │   │   ├── business-logic.zh-CN.md
│   │   │   ├── calculator.md
│   │   │   ├── calculator.zh-CN.md
│   │   │   ├── controlled.md
│   │   │   ├── controlled.zh-CN.md
│   │   │   ├── custom.md
│   │   │   ├── custom.zh-CN.md
│   │   │   ├── destructor.md
│   │   │   ├── destructor.zh-CN.md
│   │   │   ├── input.less
│   │   │   ├── layout.md
│   │   │   ├── layout.zh-CN.md
│   │   │   ├── linkages.md
│   │   │   ├── linkages.zh-CN.md
│   │   │   ├── validate.md
│   │   │   └── validate.zh-CN.md
│   │   ├── contribution.md
│   │   ├── contribution.zh-CN.md
│   │   ├── form-builder.md
│   │   ├── form-builder.zh-CN.md
│   │   ├── index.md
│   │   ├── index.zh-CN.md
│   │   ├── issue-helper.md
│   │   ├── issue-helper.zh-CN.md
│   │   ├── learn-formily.md
│   │   ├── learn-formily.zh-CN.md
│   │   ├── quick-start.md
│   │   ├── quick-start.zh-CN.md
│   │   ├── scenes
│   │   │   ├── dialog-drawer.md
│   │   │   ├── dialog-drawer.zh-CN.md
│   │   │   ├── edit-detail.md
│   │   │   ├── edit-detail.zh-CN.md
│   │   │   ├── index.less
│   │   │   ├── login-register.md
│   │   │   ├── login-register.zh-CN.md
│   │   │   ├── more.md
│   │   │   ├── more.zh-CN.md
│   │   │   ├── query-list.md
│   │   │   ├── query-list.zh-CN.md
│   │   │   ├── step-form.md
│   │   │   ├── step-form.zh-CN.md
│   │   │   ├── tab-form.md
│   │   │   ├── tab-form.zh-CN.md
│   │   │   └── VerifyCode.tsx
│   │   ├── upgrade.md
│   │   └── upgrade.zh-CN.md
│   ├── index.md
│   ├── index.zh-CN.md
│   └── site
│       ├── Contributors.less
│       ├── Contributors.tsx
│       ├── QrCode.less
│       ├── QrCode.tsx
│       ├── Section.less
│       ├── Section.tsx
│       └── styles.less
├── global.config.ts
├── jest.config.js
├── lerna.json
├── LICENSE.md
├── package.json
├── packages
│   ├── .eslintrc
│   ├── antd
│   │   ├── __tests__
│   │   │   ├── moment.spec.ts
│   │   │   └── sideEffects.spec.ts
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── build-style.ts
│   │   ├── create-style.ts
│   │   ├── docs
│   │   │   ├── components
│   │   │   │   ├── ArrayCards.md
│   │   │   │   ├── ArrayCards.zh-CN.md
│   │   │   │   ├── ArrayCollapse.md
│   │   │   │   ├── ArrayCollapse.zh-CN.md
│   │   │   │   ├── ArrayItems.md
│   │   │   │   ├── ArrayItems.zh-CN.md
│   │   │   │   ├── ArrayTable.md
│   │   │   │   ├── ArrayTable.zh-CN.md
│   │   │   │   ├── ArrayTabs.md
│   │   │   │   ├── ArrayTabs.zh-CN.md
│   │   │   │   ├── Cascader.md
│   │   │   │   ├── Cascader.zh-CN.md
│   │   │   │   ├── Checkbox.md
│   │   │   │   ├── Checkbox.zh-CN.md
│   │   │   │   ├── DatePicker.md
│   │   │   │   ├── DatePicker.zh-CN.md
│   │   │   │   ├── Editable.md
│   │   │   │   ├── Editable.zh-CN.md
│   │   │   │   ├── Form.md
│   │   │   │   ├── Form.zh-CN.md
│   │   │   │   ├── FormButtonGroup.md
│   │   │   │   ├── FormButtonGroup.zh-CN.md
│   │   │   │   ├── FormCollapse.md
│   │   │   │   ├── FormCollapse.zh-CN.md
│   │   │   │   ├── FormDialog.md
│   │   │   │   ├── FormDialog.zh-CN.md
│   │   │   │   ├── FormDrawer.md
│   │   │   │   ├── FormDrawer.zh-CN.md
│   │   │   │   ├── FormGrid.md
│   │   │   │   ├── FormGrid.zh-CN.md
│   │   │   │   ├── FormItem.md
│   │   │   │   ├── FormItem.zh-CN.md
│   │   │   │   ├── FormLayout.md
│   │   │   │   ├── FormLayout.zh-CN.md
│   │   │   │   ├── FormStep.md
│   │   │   │   ├── FormStep.zh-CN.md
│   │   │   │   ├── FormTab.md
│   │   │   │   ├── FormTab.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   ├── index.zh-CN.md
│   │   │   │   ├── Input.md
│   │   │   │   ├── Input.zh-CN.md
│   │   │   │   ├── NumberPicker.md
│   │   │   │   ├── NumberPicker.zh-CN.md
│   │   │   │   ├── Password.md
│   │   │   │   ├── Password.zh-CN.md
│   │   │   │   ├── PreviewText.md
│   │   │   │   ├── PreviewText.zh-CN.md
│   │   │   │   ├── Radio.md
│   │   │   │   ├── Radio.zh-CN.md
│   │   │   │   ├── Reset.md
│   │   │   │   ├── Reset.zh-CN.md
│   │   │   │   ├── Select.md
│   │   │   │   ├── Select.zh-CN.md
│   │   │   │   ├── SelectTable.md
│   │   │   │   ├── SelectTable.zh-CN.md
│   │   │   │   ├── Space.md
│   │   │   │   ├── Space.zh-CN.md
│   │   │   │   ├── Submit.md
│   │   │   │   ├── Submit.zh-CN.md
│   │   │   │   ├── Switch.md
│   │   │   │   ├── Switch.zh-CN.md
│   │   │   │   ├── TimePicker.md
│   │   │   │   ├── TimePicker.zh-CN.md
│   │   │   │   ├── Transfer.md
│   │   │   │   ├── Transfer.zh-CN.md
│   │   │   │   ├── TreeSelect.md
│   │   │   │   ├── TreeSelect.zh-CN.md
│   │   │   │   ├── Upload.md
│   │   │   │   └── Upload.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __builtins__
│   │   │   │   ├── hooks
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useClickAway.ts
│   │   │   │   │   └── usePrefixCls.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── loading.ts
│   │   │   │   ├── moment.ts
│   │   │   │   ├── pickDataProps.ts
│   │   │   │   ├── portal.tsx
│   │   │   │   ├── render.ts
│   │   │   │   └── sort.tsx
│   │   │   ├── array-base
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-cards
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-items
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-tabs
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── cascader
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── checkbox
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── date-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── editable
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-button-group
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-dialog
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-drawer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-grid
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-item
│   │   │   │   ├── animation.less
│   │   │   │   ├── grid.less
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-layout
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   ├── style.ts
│   │   │   │   └── useResponsiveFormLayout.ts
│   │   │   ├── form-step
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-tab
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── index.ts
│   │   │   ├── input
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── number-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── password
│   │   │   │   ├── index.tsx
│   │   │   │   ├── PasswordStrength.tsx
│   │   │   │   └── style.ts
│   │   │   ├── preview-text
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── radio
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── reset
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   ├── style.ts
│   │   │   │   ├── useCheckSlackly.tsx
│   │   │   │   ├── useFilterOptions.tsx
│   │   │   │   ├── useFlatOptions.tsx
│   │   │   │   ├── useSize.tsx
│   │   │   │   ├── useTitleAddon.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── space
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── style.less
│   │   │   ├── style.ts
│   │   │   ├── submit
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── switch
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── time-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── transfer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── tree-select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   └── upload
│   │   │       ├── index.tsx
│   │   │       ├── placeholder.ts
│   │   │       └── style.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── benchmark
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   └── index.tsx
│   │   ├── template.ejs
│   │   ├── tsconfig.build.json
│   │   ├── tsconfig.json
│   │   ├── webpack.base.ts
│   │   ├── webpack.dev.ts
│   │   └── webpack.prod.ts
│   ├── core
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── entry
│   │   │   │   │   ├── ActionResponse.less
│   │   │   │   │   ├── ActionResponse.tsx
│   │   │   │   │   ├── createForm.md
│   │   │   │   │   ├── createForm.zh-CN.md
│   │   │   │   │   ├── FieldEffectHooks.md
│   │   │   │   │   ├── FieldEffectHooks.zh-CN.md
│   │   │   │   │   ├── FormChecker.md
│   │   │   │   │   ├── FormChecker.zh-CN.md
│   │   │   │   │   ├── FormEffectHooks.md
│   │   │   │   │   ├── FormEffectHooks.zh-CN.md
│   │   │   │   │   ├── FormHooksAPI.md
│   │   │   │   │   ├── FormHooksAPI.zh-CN.md
│   │   │   │   │   ├── FormPath.md
│   │   │   │   │   ├── FormPath.zh-CN.md
│   │   │   │   │   ├── FormValidatorRegistry.md
│   │   │   │   │   └── FormValidatorRegistry.zh-CN.md
│   │   │   │   └── models
│   │   │   │       ├── ArrayField.md
│   │   │   │       ├── ArrayField.zh-CN.md
│   │   │   │       ├── Field.md
│   │   │   │       ├── Field.zh-CN.md
│   │   │   │       ├── Form.md
│   │   │   │       ├── Form.zh-CN.md
│   │   │   │       ├── ObjectField.md
│   │   │   │       ├── ObjectField.zh-CN.md
│   │   │   │       ├── Query.md
│   │   │   │       ├── Query.zh-CN.md
│   │   │   │       ├── VoidField.md
│   │   │   │       └── VoidField.zh-CN.md
│   │   │   ├── guide
│   │   │   │   ├── architecture.md
│   │   │   │   ├── architecture.zh-CN.md
│   │   │   │   ├── field.md
│   │   │   │   ├── field.zh-CN.md
│   │   │   │   ├── form.md
│   │   │   │   ├── form.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   ├── index.zh-CN.md
│   │   │   │   ├── mvvm.md
│   │   │   │   ├── mvvm.zh-CN.md
│   │   │   │   ├── values.md
│   │   │   │   └── values.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── array.spec.ts
│   │   │   │   ├── effects.spec.ts
│   │   │   │   ├── externals.spec.ts
│   │   │   │   ├── field.spec.ts
│   │   │   │   ├── form.spec.ts
│   │   │   │   ├── graph.spec.ts
│   │   │   │   ├── heart.spec.ts
│   │   │   │   ├── internals.spec.ts
│   │   │   │   ├── lifecycle.spec.ts
│   │   │   │   ├── object.spec.ts
│   │   │   │   ├── shared.ts
│   │   │   │   └── void.spec.ts
│   │   │   ├── effects
│   │   │   │   ├── index.ts
│   │   │   │   ├── onFieldEffects.ts
│   │   │   │   └── onFormEffects.ts
│   │   │   ├── global.d.ts
│   │   │   ├── index.ts
│   │   │   ├── models
│   │   │   │   ├── ArrayField.ts
│   │   │   │   ├── BaseField.ts
│   │   │   │   ├── Field.ts
│   │   │   │   ├── Form.ts
│   │   │   │   ├── Graph.ts
│   │   │   │   ├── Heart.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── LifeCycle.ts
│   │   │   │   ├── ObjectField.ts
│   │   │   │   ├── Query.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── VoidField.ts
│   │   │   ├── shared
│   │   │   │   ├── checkers.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── effective.ts
│   │   │   │   ├── externals.ts
│   │   │   │   └── internals.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── element
│   │   ├── .npmignore
│   │   ├── build-style.ts
│   │   ├── create-style.ts
│   │   ├── docs
│   │   │   ├── .vuepress
│   │   │   │   ├── components
│   │   │   │   │   ├── createCodeSandBox.js
│   │   │   │   │   ├── dumi-previewer.vue
│   │   │   │   │   └── highlight.js
│   │   │   │   ├── config.js
│   │   │   │   ├── enhanceApp.js
│   │   │   │   ├── styles
│   │   │   │   │   └── index.styl
│   │   │   │   └── util.js
│   │   │   ├── demos
│   │   │   │   ├── guide
│   │   │   │   │   ├── array-cards
│   │   │   │   │   │   ├── effects-json-schema.vue
│   │   │   │   │   │   ├── effects-markup-schema.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-collapse
│   │   │   │   │   │   ├── effects-json-schema.vue
│   │   │   │   │   │   ├── effects-markup-schema.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-items
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-table
│   │   │   │   │   │   ├── effects-json-schema.vue
│   │   │   │   │   │   ├── effects-markup-schema.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-tabs
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── cascader
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── checkbox
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── date-picker
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── editable
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-button-group.vue
│   │   │   │   │   ├── form-collapse
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── form-dialog
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-drawer
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-grid
│   │   │   │   │   │   ├── form.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── native.vue
│   │   │   │   │   ├── form-item
│   │   │   │   │   │   ├── bordered-none.vue
│   │   │   │   │   │   ├── common.vue
│   │   │   │   │   │   ├── feedback.vue
│   │   │   │   │   │   ├── inset.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   ├── size.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-layout
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-step
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── form-tab
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── form.vue
│   │   │   │   │   ├── input
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── input-number
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── password
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── preview-text
│   │   │   │   │   │   ├── base.vue
│   │   │   │   │   │   └── extend.vue
│   │   │   │   │   ├── radio
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── reset
│   │   │   │   │   │   ├── base.vue
│   │   │   │   │   │   ├── force.vue
│   │   │   │   │   │   └── validate.vue
│   │   │   │   │   ├── select
│   │   │   │   │   │   ├── json-schema-async.vue
│   │   │   │   │   │   ├── json-schema-sync.vue
│   │   │   │   │   │   ├── markup-schema-async-search.vue
│   │   │   │   │   │   ├── markup-schema-async.vue
│   │   │   │   │   │   ├── markup-schema-sync.vue
│   │   │   │   │   │   ├── template-async.vue
│   │   │   │   │   │   └── template-sync.vue
│   │   │   │   │   ├── space
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── submit
│   │   │   │   │   │   ├── base.vue
│   │   │   │   │   │   └── loading.vue
│   │   │   │   │   ├── switch
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── time-picker
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── transfer
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   └── upload
│   │   │   │   │       ├── json-schema.vue
│   │   │   │   │       ├── markup-schema.vue
│   │   │   │   │       └── template.vue
│   │   │   │   └── index.vue
│   │   │   ├── guide
│   │   │   │   ├── array-cards.md
│   │   │   │   ├── array-collapse.md
│   │   │   │   ├── array-items.md
│   │   │   │   ├── array-table.md
│   │   │   │   ├── array-tabs.md
│   │   │   │   ├── cascader.md
│   │   │   │   ├── checkbox.md
│   │   │   │   ├── date-picker.md
│   │   │   │   ├── editable.md
│   │   │   │   ├── form-button-group.md
│   │   │   │   ├── form-collapse.md
│   │   │   │   ├── form-dialog.md
│   │   │   │   ├── form-drawer.md
│   │   │   │   ├── form-grid.md
│   │   │   │   ├── form-item.md
│   │   │   │   ├── form-layout.md
│   │   │   │   ├── form-step.md
│   │   │   │   ├── form-tab.md
│   │   │   │   ├── form.md
│   │   │   │   ├── index.md
│   │   │   │   ├── input-number.md
│   │   │   │   ├── input.md
│   │   │   │   ├── password.md
│   │   │   │   ├── preview-text.md
│   │   │   │   ├── radio.md
│   │   │   │   ├── reset.md
│   │   │   │   ├── select.md
│   │   │   │   ├── space.md
│   │   │   │   ├── submit.md
│   │   │   │   ├── switch.md
│   │   │   │   ├── time-picker.md
│   │   │   │   ├── transfer.md
│   │   │   │   └── upload.md
│   │   │   └── README.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __builtins__
│   │   │   │   ├── configs
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── shared
│   │   │   │   │   ├── create-context.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── loading.ts
│   │   │   │   │   ├── portal.ts
│   │   │   │   │   ├── resolve-component.ts
│   │   │   │   │   ├── transform-component.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   └── styles
│   │   │   │       └── common.scss
│   │   │   ├── array-base
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-cards
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-collapse
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-items
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-table
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-tabs
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── cascader
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── checkbox
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── date-picker
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── editable
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── el-form
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── el-form-item
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── form
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-button-group
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-collapse
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-dialog
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── form-drawer
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-grid
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-item
│   │   │   │   ├── animation.scss
│   │   │   │   ├── grid.scss
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   ├── style.ts
│   │   │   │   └── var.scss
│   │   │   ├── form-layout
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   ├── style.ts
│   │   │   │   └── useResponsiveFormLayout.ts
│   │   │   ├── form-step
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── form-tab
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── index.ts
│   │   │   ├── input
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── input-number
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── password
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── preview-text
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── radio
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── reset
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── select
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── space
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── style.ts
│   │   │   ├── submit
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── switch
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── time-picker
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── transfer
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   └── upload
│   │   │       ├── index.ts
│   │   │       └── style.ts
│   │   ├── transformer.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── grid
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── index.ts
│   │   │   └── observer.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── json-schema
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── __snapshots__
│   │   │   │   │   └── schema.spec.ts.snap
│   │   │   │   ├── compiler.spec.ts
│   │   │   │   ├── patches.spec.ts
│   │   │   │   ├── schema.spec.ts
│   │   │   │   ├── server-validate.spec.ts
│   │   │   │   ├── shared.spec.ts
│   │   │   │   ├── transformer.spec.ts
│   │   │   │   └── traverse.spec.ts
│   │   │   ├── compiler.ts
│   │   │   ├── global.d.ts
│   │   │   ├── index.ts
│   │   │   ├── patches.ts
│   │   │   ├── polyfills
│   │   │   │   ├── index.ts
│   │   │   │   └── SPECIFICATION_1_0.ts
│   │   │   ├── schema.ts
│   │   │   ├── shared.ts
│   │   │   ├── transformer.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── next
│   │   ├── __tests__
│   │   │   ├── moment.spec.ts
│   │   │   └── sideEffects.spec.ts
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── build-style.ts
│   │   ├── create-style.ts
│   │   ├── docs
│   │   │   ├── components
│   │   │   │   ├── ArrayCards.md
│   │   │   │   ├── ArrayCards.zh-CN.md
│   │   │   │   ├── ArrayCollapse.md
│   │   │   │   ├── ArrayCollapse.zh-CN.md
│   │   │   │   ├── ArrayItems.md
│   │   │   │   ├── ArrayItems.zh-CN.md
│   │   │   │   ├── ArrayTable.md
│   │   │   │   ├── ArrayTable.zh-CN.md
│   │   │   │   ├── Cascader.md
│   │   │   │   ├── Cascader.zh-CN.md
│   │   │   │   ├── Checkbox.md
│   │   │   │   ├── Checkbox.zh-CN.md
│   │   │   │   ├── DatePicker.md
│   │   │   │   ├── DatePicker.zh-CN.md
│   │   │   │   ├── DatePicker2.md
│   │   │   │   ├── DatePicker2.zh-CN.md
│   │   │   │   ├── Editable.md
│   │   │   │   ├── Editable.zh-CN.md
│   │   │   │   ├── Form.md
│   │   │   │   ├── Form.zh-CN.md
│   │   │   │   ├── FormButtonGroup.md
│   │   │   │   ├── FormButtonGroup.zh-CN.md
│   │   │   │   ├── FormCollapse.md
│   │   │   │   ├── FormCollapse.zh-CN.md
│   │   │   │   ├── FormDialog.md
│   │   │   │   ├── FormDialog.zh-CN.md
│   │   │   │   ├── FormDrawer.md
│   │   │   │   ├── FormDrawer.zh-CN.md
│   │   │   │   ├── FormGrid.md
│   │   │   │   ├── FormGrid.zh-CN.md
│   │   │   │   ├── FormItem.md
│   │   │   │   ├── FormItem.zh-CN.md
│   │   │   │   ├── FormLayout.md
│   │   │   │   ├── FormLayout.zh-CN.md
│   │   │   │   ├── FormStep.md
│   │   │   │   ├── FormStep.zh-CN.md
│   │   │   │   ├── FormTab.md
│   │   │   │   ├── FormTab.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   ├── index.zh-CN.md
│   │   │   │   ├── Input.md
│   │   │   │   ├── Input.zh-CN.md
│   │   │   │   ├── NumberPicker.md
│   │   │   │   ├── NumberPicker.zh-CN.md
│   │   │   │   ├── Password.md
│   │   │   │   ├── Password.zh-CN.md
│   │   │   │   ├── PreviewText.md
│   │   │   │   ├── PreviewText.zh-CN.md
│   │   │   │   ├── Radio.md
│   │   │   │   ├── Radio.zh-CN.md
│   │   │   │   ├── Reset.md
│   │   │   │   ├── Reset.zh-CN.md
│   │   │   │   ├── Select.md
│   │   │   │   ├── Select.zh-CN.md
│   │   │   │   ├── SelectTable.md
│   │   │   │   ├── SelectTable.zh-CN.md
│   │   │   │   ├── Space.md
│   │   │   │   ├── Space.zh-CN.md
│   │   │   │   ├── Submit.md
│   │   │   │   ├── Submit.zh-CN.md
│   │   │   │   ├── Switch.md
│   │   │   │   ├── Switch.zh-CN.md
│   │   │   │   ├── TimePicker.md
│   │   │   │   ├── TimePicker.zh-CN.md
│   │   │   │   ├── TimePicker2.md
│   │   │   │   ├── TimePicker2.zh-CN.md
│   │   │   │   ├── Transfer.md
│   │   │   │   ├── Transfer.zh-CN.md
│   │   │   │   ├── TreeSelect.md
│   │   │   │   ├── TreeSelect.zh-CN.md
│   │   │   │   ├── Upload.md
│   │   │   │   └── Upload.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LESENCE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __builtins__
│   │   │   │   ├── empty.tsx
│   │   │   │   ├── hooks
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useClickAway.ts
│   │   │   │   │   └── usePrefixCls.ts
│   │   │   │   ├── icons.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── loading.ts
│   │   │   │   ├── mapSize.ts
│   │   │   │   ├── mapStatus.ts
│   │   │   │   ├── moment.ts
│   │   │   │   ├── pickDataProps.ts
│   │   │   │   ├── portal.tsx
│   │   │   │   ├── render.ts
│   │   │   │   └── toArray.ts
│   │   │   ├── array-base
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-cards
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-items
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── cascader
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── checkbox
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── date-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── date-picker2
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── editable
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-button-group
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-dialog
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-drawer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-grid
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-item
│   │   │   │   ├── animation.scss
│   │   │   │   ├── grid.scss
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   ├── scss
│   │   │   │   │   └── variable.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-layout
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   ├── style.ts
│   │   │   │   └── useResponsiveFormLayout.ts
│   │   │   ├── form-step
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-tab
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── index.ts
│   │   │   ├── input
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── main.scss
│   │   │   ├── number-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── password
│   │   │   │   ├── index.tsx
│   │   │   │   ├── PasswordStrength.tsx
│   │   │   │   └── style.ts
│   │   │   ├── preview-text
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── radio
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── reset
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   ├── style.ts
│   │   │   │   ├── useCheckSlackly.tsx
│   │   │   │   ├── useFilterOptions.tsx
│   │   │   │   ├── useFlatOptions.tsx
│   │   │   │   ├── useSize.tsx
│   │   │   │   ├── useTitleAddon.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── space
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── style.ts
│   │   │   ├── submit
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── switch
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── time-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── time-picker2
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── transfer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── tree-select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   └── upload
│   │   │       ├── index.tsx
│   │   │       ├── main.scss
│   │   │       ├── placeholder.ts
│   │   │       └── style.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── path
│   │   ├── .npmignore
│   │   ├── benchmark.ts
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── accessor.spec.ts
│   │   │   │   ├── basic.spec.ts
│   │   │   │   ├── match.spec.ts
│   │   │   │   ├── parser.spec.ts
│   │   │   │   └── share.spec.ts
│   │   │   ├── contexts.ts
│   │   │   ├── destructor.ts
│   │   │   ├── index.ts
│   │   │   ├── matcher.ts
│   │   │   ├── parser.ts
│   │   │   ├── shared.ts
│   │   │   ├── tokenizer.ts
│   │   │   ├── tokens.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── react
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── components
│   │   │   │   │   ├── ArrayField.md
│   │   │   │   │   ├── ArrayField.zh-CN.md
│   │   │   │   │   ├── ExpressionScope.md
│   │   │   │   │   ├── ExpressionScope.zh-CN.md
│   │   │   │   │   ├── Field.md
│   │   │   │   │   ├── Field.zh-CN.md
│   │   │   │   │   ├── FormConsumer.md
│   │   │   │   │   ├── FormConsumer.zh-CN.md
│   │   │   │   │   ├── FormProvider.md
│   │   │   │   │   ├── FormProvider.zh-CN.md
│   │   │   │   │   ├── ObjectField.md
│   │   │   │   │   ├── ObjectField.zh-CN.md
│   │   │   │   │   ├── RecordScope.md
│   │   │   │   │   ├── RecordScope.zh-CN.md
│   │   │   │   │   ├── RecordsScope.md
│   │   │   │   │   ├── RecordsScope.zh-CN.md
│   │   │   │   │   ├── RecursionField.md
│   │   │   │   │   ├── RecursionField.zh-CN.md
│   │   │   │   │   ├── SchemaField.md
│   │   │   │   │   ├── SchemaField.zh-CN.md
│   │   │   │   │   ├── VoidField.md
│   │   │   │   │   └── VoidField.zh-CN.md
│   │   │   │   ├── hooks
│   │   │   │   │   ├── useExpressionScope.md
│   │   │   │   │   ├── useExpressionScope.zh-CN.md
│   │   │   │   │   ├── useField.md
│   │   │   │   │   ├── useField.zh-CN.md
│   │   │   │   │   ├── useFieldSchema.md
│   │   │   │   │   ├── useFieldSchema.zh-CN.md
│   │   │   │   │   ├── useForm.md
│   │   │   │   │   ├── useForm.zh-CN.md
│   │   │   │   │   ├── useFormEffects.md
│   │   │   │   │   ├── useFormEffects.zh-CN.md
│   │   │   │   │   ├── useParentForm.md
│   │   │   │   │   └── useParentForm.zh-CN.md
│   │   │   │   └── shared
│   │   │   │       ├── connect.md
│   │   │   │       ├── connect.zh-CN.md
│   │   │   │       ├── context.md
│   │   │   │       ├── context.zh-CN.md
│   │   │   │       ├── mapProps.md
│   │   │   │       ├── mapProps.zh-CN.md
│   │   │   │       ├── mapReadPretty.md
│   │   │   │       ├── mapReadPretty.zh-CN.md
│   │   │   │       ├── observer.md
│   │   │   │       ├── observer.zh-CN.md
│   │   │   │       ├── Schema.md
│   │   │   │       └── Schema.zh-CN.md
│   │   │   ├── guide
│   │   │   │   ├── architecture.md
│   │   │   │   ├── architecture.zh-CN.md
│   │   │   │   ├── concept.md
│   │   │   │   ├── concept.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   └── index.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── expression.spec.tsx
│   │   │   │   ├── field.spec.tsx
│   │   │   │   ├── form.spec.tsx
│   │   │   │   ├── schema.json.spec.tsx
│   │   │   │   ├── schema.markup.spec.tsx
│   │   │   │   └── shared.tsx
│   │   │   ├── components
│   │   │   │   ├── ArrayField.tsx
│   │   │   │   ├── ExpressionScope.tsx
│   │   │   │   ├── Field.tsx
│   │   │   │   ├── FormConsumer.tsx
│   │   │   │   ├── FormProvider.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── ObjectField.tsx
│   │   │   │   ├── ReactiveField.tsx
│   │   │   │   ├── RecordScope.tsx
│   │   │   │   ├── RecordsScope.tsx
│   │   │   │   ├── RecursionField.tsx
│   │   │   │   ├── SchemaField.tsx
│   │   │   │   └── VoidField.tsx
│   │   │   ├── global.d.ts
│   │   │   ├── hooks
│   │   │   │   ├── index.ts
│   │   │   │   ├── useAttach.ts
│   │   │   │   ├── useExpressionScope.ts
│   │   │   │   ├── useField.ts
│   │   │   │   ├── useFieldSchema.ts
│   │   │   │   ├── useForm.ts
│   │   │   │   ├── useFormEffects.ts
│   │   │   │   └── useParentForm.ts
│   │   │   ├── index.ts
│   │   │   ├── shared
│   │   │   │   ├── connect.ts
│   │   │   │   ├── context.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── render.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── reactive
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── benchmark.ts
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── action.md
│   │   │   │   ├── action.zh-CN.md
│   │   │   │   ├── autorun.md
│   │   │   │   ├── autorun.zh-CN.md
│   │   │   │   ├── batch.md
│   │   │   │   ├── batch.zh-CN.md
│   │   │   │   ├── define.md
│   │   │   │   ├── define.zh-CN.md
│   │   │   │   ├── hasCollected.md
│   │   │   │   ├── hasCollected.zh-CN.md
│   │   │   │   ├── markObservable.md
│   │   │   │   ├── markObservable.zh-CN.md
│   │   │   │   ├── markRaw.md
│   │   │   │   ├── markRaw.zh-CN.md
│   │   │   │   ├── model.md
│   │   │   │   ├── model.zh-CN.md
│   │   │   │   ├── observable.md
│   │   │   │   ├── observable.zh-CN.md
│   │   │   │   ├── observe.md
│   │   │   │   ├── observe.zh-CN.md
│   │   │   │   ├── raw.md
│   │   │   │   ├── raw.zh-CN.md
│   │   │   │   ├── react
│   │   │   │   │   ├── observer.md
│   │   │   │   │   └── observer.zh-CN.md
│   │   │   │   ├── reaction.md
│   │   │   │   ├── reaction.zh-CN.md
│   │   │   │   ├── toJS.md
│   │   │   │   ├── toJS.zh-CN.md
│   │   │   │   ├── tracker.md
│   │   │   │   ├── tracker.zh-CN.md
│   │   │   │   ├── typeChecker.md
│   │   │   │   ├── typeChecker.zh-CN.md
│   │   │   │   ├── untracked.md
│   │   │   │   ├── untracked.zh-CN.md
│   │   │   │   └── vue
│   │   │   │       ├── observer.md
│   │   │   │       └── observer.zh-CN.md
│   │   │   ├── guide
│   │   │   │   ├── best-practice.md
│   │   │   │   ├── best-practice.zh-CN.md
│   │   │   │   ├── concept.md
│   │   │   │   ├── concept.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   └── index.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── action.spec.ts
│   │   │   │   ├── annotations.spec.ts
│   │   │   │   ├── array.spec.ts
│   │   │   │   ├── autorun.spec.ts
│   │   │   │   ├── batch.spec.ts
│   │   │   │   ├── collections-map.spec.ts
│   │   │   │   ├── collections-set.spec.ts
│   │   │   │   ├── collections-weakmap.spec.ts
│   │   │   │   ├── collections-weakset.spec.ts
│   │   │   │   ├── define.spec.ts
│   │   │   │   ├── externals.spec.ts
│   │   │   │   ├── hasCollected.spec.ts
│   │   │   │   ├── observable.spec.ts
│   │   │   │   ├── observe.spec.ts
│   │   │   │   ├── tracker.spec.ts
│   │   │   │   └── untracked.spec.ts
│   │   │   ├── action.ts
│   │   │   ├── annotations
│   │   │   │   ├── box.ts
│   │   │   │   ├── computed.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── observable.ts
│   │   │   │   ├── ref.ts
│   │   │   │   └── shallow.ts
│   │   │   ├── array.ts
│   │   │   ├── autorun.ts
│   │   │   ├── batch.ts
│   │   │   ├── checkers.ts
│   │   │   ├── environment.ts
│   │   │   ├── externals.ts
│   │   │   ├── global.d.ts
│   │   │   ├── handlers.ts
│   │   │   ├── index.ts
│   │   │   ├── internals.ts
│   │   │   ├── model.ts
│   │   │   ├── observable.ts
│   │   │   ├── observe.ts
│   │   │   ├── reaction.ts
│   │   │   ├── tracker.ts
│   │   │   ├── tree.ts
│   │   │   ├── types.ts
│   │   │   └── untracked.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── reactive-react
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── hooks
│   │   │   │   ├── index.ts
│   │   │   │   ├── useCompatEffect.ts
│   │   │   │   ├── useCompatFactory.ts
│   │   │   │   ├── useDidUpdate.ts
│   │   │   │   ├── useForceUpdate.ts
│   │   │   │   ├── useLayoutEffect.ts
│   │   │   │   └── useObserver.ts
│   │   │   ├── index.ts
│   │   │   ├── observer.ts
│   │   │   ├── shared
│   │   │   │   ├── gc.ts
│   │   │   │   ├── global.ts
│   │   │   │   ├── immediate.ts
│   │   │   │   └── index.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── reactive-test-cases-for-react18
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── index.js
│   │   │   └── MySlowList.js
│   │   ├── template.ejs
│   │   ├── tsconfig.build.json
│   │   ├── tsconfig.json
│   │   ├── webpack.base.ts
│   │   ├── webpack.dev.ts
│   │   └── webpack.prod.ts
│   ├── reactive-vue
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   └── observer.spec.ts
│   │   │   ├── hooks
│   │   │   │   ├── index.ts
│   │   │   │   └── useObserver.ts
│   │   │   ├── index.ts
│   │   │   ├── observer
│   │   │   │   ├── collectData.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── observerInVue2.ts
│   │   │   │   └── observerInVue3.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── shared
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   └── index.spec.ts
│   │   │   ├── array.ts
│   │   │   ├── case.ts
│   │   │   ├── checkers.ts
│   │   │   ├── clone.ts
│   │   │   ├── compare.ts
│   │   │   ├── defaults.ts
│   │   │   ├── deprecate.ts
│   │   │   ├── global.ts
│   │   │   ├── index.ts
│   │   │   ├── instanceof.ts
│   │   │   ├── isEmpty.ts
│   │   │   ├── merge.ts
│   │   │   ├── middleware.ts
│   │   │   ├── path.ts
│   │   │   ├── string.ts
│   │   │   ├── subscribable.ts
│   │   │   └── uid.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── validator
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── parser.spec.ts
│   │   │   │   ├── registry.spec.ts
│   │   │   │   └── validator.spec.ts
│   │   │   ├── formats.ts
│   │   │   ├── index.ts
│   │   │   ├── locale.ts
│   │   │   ├── parser.ts
│   │   │   ├── registry.ts
│   │   │   ├── rules.ts
│   │   │   ├── template.ts
│   │   │   ├── types.ts
│   │   │   └── validator.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   └── vue
│       ├── .npmignore
│       ├── bin
│       │   ├── formily-vue-fix.js
│       │   └── formily-vue-switch.js
│       ├── docs
│       │   ├── .vuepress
│       │   │   ├── components
│       │   │   │   ├── createCodeSandBox.js
│       │   │   │   ├── dumi-previewer.vue
│       │   │   │   └── highlight.js
│       │   │   ├── config.js
│       │   │   ├── enhanceApp.js
│       │   │   └── styles
│       │   │       └── index.styl
│       │   ├── api
│       │   │   ├── components
│       │   │   │   ├── array-field.md
│       │   │   │   ├── expression-scope.md
│       │   │   │   ├── field.md
│       │   │   │   ├── form-consumer.md
│       │   │   │   ├── form-provider.md
│       │   │   │   ├── object-field.md
│       │   │   │   ├── recursion-field-with-component.md
│       │   │   │   ├── recursion-field.md
│       │   │   │   ├── schema-field-with-schema.md
│       │   │   │   ├── schema-field.md
│       │   │   │   └── void-field.md
│       │   │   ├── hooks
│       │   │   │   ├── use-field-schema.md
│       │   │   │   ├── use-field.md
│       │   │   │   ├── use-form-effects.md
│       │   │   │   ├── use-form.md
│       │   │   │   └── use-parent-form.md
│       │   │   └── shared
│       │   │       ├── connect.md
│       │   │       ├── injections.md
│       │   │       ├── map-props.md
│       │   │       ├── map-read-pretty.md
│       │   │       ├── observer.md
│       │   │       └── schema.md
│       │   ├── demos
│       │   │   ├── api
│       │   │   │   ├── components
│       │   │   │   │   ├── array-field.vue
│       │   │   │   │   ├── expression-scope.vue
│       │   │   │   │   ├── field.vue
│       │   │   │   │   ├── form-consumer.vue
│       │   │   │   │   ├── form-provider.vue
│       │   │   │   │   ├── object-field.vue
│       │   │   │   │   ├── recursion-field-with-component.vue
│       │   │   │   │   ├── recursion-field.vue
│       │   │   │   │   ├── schema-field-with-schema.vue
│       │   │   │   │   ├── schema-field.vue
│       │   │   │   │   └── void-field.vue
│       │   │   │   ├── hooks
│       │   │   │   │   ├── use-field-schema.vue
│       │   │   │   │   ├── use-field.vue
│       │   │   │   │   ├── use-form-effects.vue
│       │   │   │   │   ├── use-form.vue
│       │   │   │   │   └── use-parent-form.vue
│       │   │   │   └── shared
│       │   │   │       ├── connect.vue
│       │   │   │       ├── map-props.vue
│       │   │   │       ├── map-read-pretty.vue
│       │   │   │       └── observer.vue
│       │   │   ├── index.vue
│       │   │   └── questions
│       │   │       ├── default-slot.vue
│       │   │       ├── events.vue
│       │   │       ├── named-slot.vue
│       │   │       └── scoped-slot.vue
│       │   ├── guide
│       │   │   ├── architecture.md
│       │   │   ├── concept.md
│       │   │   └── README.md
│       │   ├── questions
│       │   │   └── README.md
│       │   └── README.md
│       ├── package.json
│       ├── README.md
│       ├── rollup.config.js
│       ├── scripts
│       │   ├── postinstall.js
│       │   ├── switch-cli.js
│       │   └── utils.js
│       ├── src
│       │   ├── __tests__
│       │   │   ├── expression.scope.spec.ts
│       │   │   ├── field.spec.ts
│       │   │   ├── form.spec.ts
│       │   │   ├── schema.json.spec.ts
│       │   │   ├── schema.markup.spec.ts
│       │   │   ├── shared.spec.ts
│       │   │   └── utils.spec.ts
│       │   ├── components
│       │   │   ├── ArrayField.ts
│       │   │   ├── ExpressionScope.ts
│       │   │   ├── Field.ts
│       │   │   ├── FormConsumer.ts
│       │   │   ├── FormProvider.ts
│       │   │   ├── index.ts
│       │   │   ├── ObjectField.ts
│       │   │   ├── ReactiveField.ts
│       │   │   ├── RecursionField.ts
│       │   │   ├── SchemaField.ts
│       │   │   └── VoidField.ts
│       │   ├── global.d.ts
│       │   ├── hooks
│       │   │   ├── index.ts
│       │   │   ├── useAttach.ts
│       │   │   ├── useField.ts
│       │   │   ├── useFieldSchema.ts
│       │   │   ├── useForm.ts
│       │   │   ├── useFormEffects.ts
│       │   │   ├── useInjectionCleaner.ts
│       │   │   └── useParentForm.ts
│       │   ├── index.ts
│       │   ├── shared
│       │   │   ├── connect.ts
│       │   │   ├── context.ts
│       │   │   ├── createForm.ts
│       │   │   ├── fragment.ts
│       │   │   ├── h.ts
│       │   │   └── index.ts
│       │   ├── types
│       │   │   └── index.ts
│       │   ├── utils
│       │   │   ├── formatVNodeData.ts
│       │   │   ├── getFieldProps.ts
│       │   │   ├── getRawComponent.ts
│       │   │   └── resolveSchemaProps.ts
│       │   └── vue2-components.ts
│       ├── tsconfig.build.json
│       ├── tsconfig.json
│       └── tsconfig.types.json
├── README.md
├── README.zh-cn.md
├── scripts
│   ├── build-style
│   │   ├── buildAllStyles.ts
│   │   ├── copy.ts
│   │   ├── helper.ts
│   │   └── index.ts
│   └── rollup.base.js
├── tsconfig.build.json
├── tsconfig.jest.json
├── tsconfig.json
└── yarn.lock
```

# Files

--------------------------------------------------------------------------------
/packages/core/src/shared/internals.ts:
--------------------------------------------------------------------------------

```typescript
import {
  FormPath,
  FormPathPattern,
  each,
  pascalCase,
  isFn,
  isValid,
  isUndef,
  isEmpty,
  isPlainObj,
  isNumberLike,
  clone,
  toArr,
} from '@formily/shared'
import {
  ValidatorTriggerType,
  validate,
  parseValidatorDescriptions,
} from '@formily/validator'
import {
  autorun,
  batch,
  contains,
  toJS,
  isObservable,
  DataChange,
  reaction,
  untracked,
} from '@formily/reactive'
import { Field, ArrayField, Form, ObjectField } from '../models'
import {
  ISpliceArrayStateProps,
  IExchangeArrayStateProps,
  IFieldResetOptions,
  ISearchFeedback,
  IFieldFeedback,
  INodePatch,
  GeneralField,
  IFormFeedback,
  LifeCycleTypes,
  FieldMatchPattern,
  FieldFeedbackTypes,
} from '../types'
import {
  isArrayField,
  isObjectField,
  isGeneralField,
  isDataField,
  isForm,
  isQuery,
  isVoidField,
} from './externals'
import {
  RESPONSE_REQUEST_DURATION,
  ReservedProperties,
  MutuallyExclusiveProperties,
  NumberIndexReg,
  GlobalState,
  ReadOnlyProperties,
} from './constants'
import { BaseField } from '../models/BaseField'

const hasOwnProperty = Object.prototype.hasOwnProperty

const notify = (
  target: Form | Field,
  formType: LifeCycleTypes,
  fieldType: LifeCycleTypes
) => {
  if (isForm(target)) {
    target.notify(formType)
  } else {
    target.notify(fieldType)
  }
}

export const isHTMLInputEvent = (event: any, stopPropagation = true) => {
  if (event?.target) {
    if (
      typeof event.target === 'object' &&
      ('value' in event.target || 'checked' in event.target)
    )
      return true
    if (stopPropagation) event.stopPropagation?.()
  }
  return false
}

export const getValuesFromEvent = (args: any[]) => {
  return args.map((event) => {
    if (event?.target) {
      if (isValid(event.target.value)) return event.target.value
      if (isValid(event.target.checked)) return event.target.checked
      return
    }
    return event
  })
}

export const getTypedDefaultValue = (field: Field) => {
  if (isArrayField(field)) return []
  if (isObjectField(field)) return {}
}

export const buildFieldPath = (field: GeneralField) => {
  return buildDataPath(field.form.fields, field.address)
}

export const buildDataPath = (
  fields: Record<string, GeneralField>,
  pattern: FormPath
) => {
  let prevArray = false
  const segments = pattern.segments
  const path = segments.reduce((path: string[], key: string, index: number) => {
    const currentPath = path.concat(key)
    const currentAddress = segments.slice(0, index + 1)
    const current = fields[currentAddress.join('.')]
    if (prevArray) {
      if (!isVoidField(current)) {
        prevArray = false
      }
      return path
    }
    if (index >= segments.length - 1) {
      return currentPath
    }
    if (isVoidField(current)) {
      const parentAddress = segments.slice(0, index)
      const parent = fields[parentAddress.join('.')]
      if (isArrayField(parent) && isNumberLike(key)) {
        prevArray = true
        return currentPath
      }
      return path
    } else {
      prevArray = false
    }
    return currentPath
  }, [])
  return new FormPath(path)
}

export const locateNode = (field: GeneralField, address: FormPathPattern) => {
  field.address = FormPath.parse(address)
  field.path = buildFieldPath(field)
  field.form.indexes[field.path.toString()] = field.address.toString()
  return field
}

export const patchFieldStates = (
  target: Record<string, GeneralField>,
  patches: INodePatch<GeneralField>[]
) => {
  patches.forEach(({ type, address, oldAddress, payload }) => {
    if (type === 'remove') {
      destroy(target, address, false)
    } else if (type === 'update') {
      if (payload) {
        target[address] = payload
        if (target[oldAddress] === payload) {
          target[oldAddress] = undefined
        }
      }
      if (address && payload) {
        locateNode(payload, address)
      }
    }
  })
}

export const destroy = (
  target: Record<string, GeneralField>,
  address: string,
  forceClear = true
) => {
  const field = target[address]
  field?.dispose()
  if (isDataField(field) && forceClear) {
    const form = field.form
    const path = field.path
    form.deleteValuesIn(path)
    form.deleteInitialValuesIn(path)
  }
  delete target[address]
}

export const patchFormValues = (
  form: Form,
  path: Array<string | number>,
  source: any
) => {
  const update = (path: Array<string | number>, source: any) => {
    if (path.length) {
      form.setValuesIn(path, clone(source))
    } else {
      Object.assign(form.values, clone(source))
    }
  }

  const patch = (source: any, path: Array<string | number> = []) => {
    const targetValue = form.getValuesIn(path)
    const targetField = form.query(path).take()
    const isUnVoidField = targetField && !isVoidField(targetField)

    if (isUnVoidField && targetField.display === 'none') {
      targetField.caches.value = clone(source)
      return
    }

    if (allowAssignDefaultValue(targetValue, source)) {
      update(path, source)
    } else {
      if (isEmpty(source)) return
      if (GlobalState.initializing) return
      if (isPlainObj(targetValue) && isPlainObj(source)) {
        each(source, (value, key) => {
          patch(value, path.concat(key))
        })
      } else {
        if (targetField) {
          if (isUnVoidField && !targetField.selfModified) {
            update(path, source)
          }
        } else if (form.initialized) {
          update(path, source)
        }
      }
    }
  }
  patch(source, path)
}

export const matchFeedback = (
  search?: ISearchFeedback,
  feedback?: IFormFeedback
) => {
  if (!search || !feedback) return false
  if (search.type && search.type !== feedback.type) return false
  if (search.code && search.code !== feedback.code) return false
  if (search.path && feedback.path) {
    if (!FormPath.parse(search.path).match(feedback.path)) return false
  }
  if (search.address && feedback.address) {
    if (!FormPath.parse(search.address).match(feedback.address)) return false
  }
  if (search.triggerType && search.triggerType !== feedback.triggerType)
    return false
  return true
}

export const queryFeedbacks = (field: Field, search?: ISearchFeedback) => {
  return field.feedbacks.filter((feedback) => {
    if (!feedback.messages?.length) return false
    return matchFeedback(search, {
      ...feedback,
      address: field.address?.toString(),
      path: field.path?.toString(),
    })
  })
}

export const queryFeedbackMessages = (
  field: Field,
  search: ISearchFeedback
) => {
  if (!field.feedbacks.length) return []
  return queryFeedbacks(field, search).reduce(
    (buf, info) => (isEmpty(info.messages) ? buf : buf.concat(info.messages)),
    []
  )
}

export const updateFeedback = (field: Field, feedback?: IFieldFeedback) => {
  if (!feedback) return
  return batch(() => {
    if (!field.feedbacks.length) {
      if (!feedback.messages?.length) {
        return
      }
      field.feedbacks = [feedback]
    } else {
      const searched = queryFeedbacks(field, feedback)
      if (searched.length) {
        field.feedbacks = field.feedbacks.reduce((buf, item) => {
          if (searched.includes(item)) {
            if (feedback.messages?.length) {
              item.messages = feedback.messages
              return buf.concat(item)
            } else {
              return buf
            }
          } else {
            return buf.concat(item)
          }
        }, [])
        return
      } else if (feedback.messages?.length) {
        field.feedbacks = field.feedbacks.concat(feedback)
      }
    }
  })
}

export const validateToFeedbacks = async (
  field: Field,
  triggerType: ValidatorTriggerType = 'onInput'
) => {
  const results = await validate(field.value, field.validator, {
    triggerType,
    validateFirst: field.props.validateFirst ?? field.form.props.validateFirst,
    context: { field, form: field.form },
  })

  batch(() => {
    each(results, (messages, type: FieldFeedbackTypes) => {
      field.setFeedback({
        triggerType,
        type,
        code: pascalCase(`validate-${type}`),
        messages: messages,
      })
    })
  })
  return results
}

export const setValidatorRule = (field: Field, name: string, value: any) => {
  if (!isValid(value)) return
  const validators = parseValidatorDescriptions(field.validator)
  const hasRule = validators.some((desc) => name in desc)
  const rule = {
    [name]: value,
  }
  if (hasRule) {
    field.validator = validators.map((desc: any) => {
      if (isPlainObj(desc) && hasOwnProperty.call(desc, name)) {
        desc[name] = value
        return desc
      }
      return desc
    })
  } else {
    if (name === 'required') {
      field.validator = [rule].concat(validators)
    } else {
      field.validator = validators.concat(rule)
    }
  }
}

export const spliceArrayState = (
  field: ArrayField,
  props?: ISpliceArrayStateProps
) => {
  const { startIndex, deleteCount, insertCount } = {
    startIndex: 0,
    deleteCount: 0,
    insertCount: 0,
    ...props,
  }
  const address = field.address.toString()
  const addrLength = address.length
  const form = field.form
  const fields = form.fields
  const fieldPatches: INodePatch<GeneralField>[] = []
  const offset = insertCount - deleteCount
  const isArrayChildren = (identifier: string) => {
    return identifier.indexOf(address) === 0 && identifier.length > addrLength
  }
  const isAfterNode = (identifier: string) => {
    const afterStr = identifier.substring(addrLength)
    const number = afterStr.match(NumberIndexReg)?.[1]
    if (number === undefined) return false
    const index = Number(number)
    return index > startIndex + deleteCount - 1
  }
  const isInsertNode = (identifier: string) => {
    const afterStr = identifier.substring(addrLength)
    const number = afterStr.match(NumberIndexReg)?.[1]
    if (number === undefined) return false
    const index = Number(number)
    return index >= startIndex && index < startIndex + insertCount
  }
  const isDeleteNode = (identifier: string) => {
    const preStr = identifier.substring(0, addrLength)
    const afterStr = identifier.substring(addrLength)
    const number = afterStr.match(NumberIndexReg)?.[1]
    if (number === undefined) return false
    const index = Number(number)
    return (
      (index > startIndex &&
        !fields[
          `${preStr}${afterStr.replace(/^\.\d+/, `.${index + deleteCount}`)}`
        ]) ||
      index === startIndex
    )
  }
  const moveIndex = (identifier: string) => {
    if (offset === 0) return identifier
    const preStr = identifier.substring(0, addrLength)
    const afterStr = identifier.substring(addrLength)
    const number = afterStr.match(NumberIndexReg)?.[1]
    if (number === undefined) return identifier
    const index = Number(number) + offset
    return `${preStr}${afterStr.replace(/^\.\d+/, `.${index}`)}`
  }

  batch(() => {
    each(fields, (field, identifier) => {
      if (isArrayChildren(identifier)) {
        if (isAfterNode(identifier)) {
          const newIdentifier = moveIndex(identifier)
          fieldPatches.push({
            type: 'update',
            address: newIdentifier,
            oldAddress: identifier,
            payload: field,
          })
        }
        if (isInsertNode(identifier) || isDeleteNode(identifier)) {
          fieldPatches.push({ type: 'remove', address: identifier })
        }
      }
    })
    patchFieldStates(fields, fieldPatches)
  })
  field.form.notify(LifeCycleTypes.ON_FORM_GRAPH_CHANGE)
}

export const exchangeArrayState = (
  field: ArrayField,
  props: IExchangeArrayStateProps
) => {
  const { fromIndex, toIndex } = {
    fromIndex: 0,
    toIndex: 0,
    ...props,
  }
  const address = field.address.toString()
  const fields = field.form.fields
  const addrLength = address.length
  const fieldPatches: INodePatch<GeneralField>[] = []
  const isArrayChildren = (identifier: string) => {
    return identifier.indexOf(address) === 0 && identifier.length > addrLength
  }

  const isDown = fromIndex < toIndex

  const isMoveNode = (identifier: string) => {
    const afterStr = identifier.slice(address.length)
    const number = afterStr.match(NumberIndexReg)?.[1]
    if (number === undefined) return false
    const index = Number(number)
    return isDown
      ? index > fromIndex && index <= toIndex
      : index < fromIndex && index >= toIndex
  }

  const isFromNode = (identifier: string) => {
    const afterStr = identifier.substring(addrLength)
    const number = afterStr.match(NumberIndexReg)?.[1]
    if (number === undefined) return false
    const index = Number(number)
    return index === fromIndex
  }

  const moveIndex = (identifier: string) => {
    const preStr = identifier.substring(0, addrLength)
    const afterStr = identifier.substring(addrLength)
    const number = afterStr.match(NumberIndexReg)[1]
    const current = Number(number)
    let index = current
    if (index === fromIndex) {
      index = toIndex
    } else {
      index += isDown ? -1 : 1
    }

    return `${preStr}${afterStr.replace(/^\.\d+/, `.${index}`)}`
  }

  batch(() => {
    each(fields, (field, identifier) => {
      if (isArrayChildren(identifier)) {
        if (isMoveNode(identifier) || isFromNode(identifier)) {
          const newIdentifier = moveIndex(identifier)
          fieldPatches.push({
            type: 'update',
            address: newIdentifier,
            oldAddress: identifier,
            payload: field,
          })
          if (!fields[newIdentifier]) {
            fieldPatches.push({
              type: 'remove',
              address: identifier,
            })
          }
        }
      }
    })
    patchFieldStates(fields, fieldPatches)
  })
  field.form.notify(LifeCycleTypes.ON_FORM_GRAPH_CHANGE)
}

export const cleanupArrayChildren = (field: ArrayField, start: number) => {
  const address = field.address.toString()
  const fields = field.form.fields

  const isArrayChildren = (identifier: string) => {
    return (
      identifier.indexOf(address) === 0 && identifier.length > address.length
    )
  }

  const isNeedCleanup = (identifier: string) => {
    const afterStr = identifier.slice(address.length)
    const numStr = afterStr.match(NumberIndexReg)?.[1]
    if (numStr === undefined) return false
    const index = Number(numStr)
    return index >= start
  }

  batch(() => {
    each(fields, (field, identifier) => {
      if (isArrayChildren(identifier) && isNeedCleanup(identifier)) {
        field.destroy()
      }
    })
  })
}

export const cleanupObjectChildren = (field: ObjectField, keys: string[]) => {
  if (keys.length === 0) return
  const address = field.address.toString()
  const fields = field.form.fields

  const isObjectChildren = (identifier: string) => {
    return (
      identifier.indexOf(address) === 0 && identifier.length > address.length
    )
  }

  const isNeedCleanup = (identifier: string) => {
    const afterStr = identifier.slice(address.length)
    const key = afterStr.match(/^\.([^.]+)/)?.[1]
    if (key === undefined) return false
    return keys.includes(key)
  }

  batch(() => {
    each(fields, (field, identifier) => {
      if (isObjectChildren(identifier) && isNeedCleanup(identifier)) {
        field.destroy()
      }
    })
  })
}

export const initFieldUpdate = batch.scope.bound((field: GeneralField) => {
  const form = field.form
  const updates = FormPath.ensureIn(form, 'requests.updates', [])
  const indexes = FormPath.ensureIn(form, 'requests.updateIndexes', {})
  for (let index = 0; index < updates.length; index++) {
    const { pattern, callbacks } = updates[index]
    let removed = false
    if (field.match(pattern)) {
      callbacks.forEach((callback) => {
        field.setState(callback)
      })
      if (!pattern.isWildMatchPattern && !pattern.isMatchPattern) {
        updates.splice(index--, 1)
        removed = true
      }
    }
    if (!removed) {
      indexes[pattern.toString()] = index
    } else {
      delete indexes[pattern.toString()]
    }
  }
})

export const subscribeUpdate = (
  form: Form,
  pattern: FormPath,
  callback: (...args: any[]) => void
) => {
  const updates = FormPath.ensureIn(form, 'requests.updates', [])
  const indexes = FormPath.ensureIn(form, 'requests.updateIndexes', {})
  const id = pattern.toString()
  const current = indexes[id]
  if (isValid(current)) {
    if (
      updates[current] &&
      !updates[current].callbacks.some((fn: any) =>
        fn.toString() === callback.toString() ? fn === callback : false
      )
    ) {
      updates[current].callbacks.push(callback)
    }
  } else {
    indexes[id] = updates.length
    updates.push({
      pattern,
      callbacks: [callback],
    })
  }
}

export const deserialize = (model: any, setter: any) => {
  if (!model) return
  if (isFn(setter)) {
    setter(model)
  } else {
    for (let key in setter) {
      if (!hasOwnProperty.call(setter, key)) continue
      if (ReadOnlyProperties[key] || ReservedProperties[key]) continue
      const MutuallyExclusiveKey = MutuallyExclusiveProperties[key]
      if (
        MutuallyExclusiveKey &&
        hasOwnProperty.call(setter, MutuallyExclusiveKey) &&
        !isValid(setter[MutuallyExclusiveKey])
      )
        continue
      const value = setter[key]
      if (isFn(value)) continue
      model[key] = value
    }
  }
  return model
}

export const serialize = (model: any, getter?: any) => {
  if (isFn(getter)) {
    return getter(model)
  } else {
    const results = {}
    for (let key in model) {
      if (!hasOwnProperty.call(model, key)) continue
      if (ReservedProperties[key]) continue
      if (key === 'address' || key === 'path') {
        results[key] = model[key].toString()
        continue
      }
      const value = model[key]
      if (isFn(value)) continue
      results[key] = toJS(value)
    }
    return results
  }
}

export const createChildrenFeedbackFilter = (field: Field) => {
  const identifier = field.address?.toString()
  return ({ address }: IFormFeedback) => {
    return address === identifier || address.indexOf(identifier + '.') === 0
  }
}

export const createStateSetter = (model: any) => {
  return batch.bound((setter?: any) => deserialize(model, setter))
}

export const createStateGetter = (model: any) => {
  return (getter?: any) => serialize(model, getter)
}

export const createBatchStateSetter = (form: Form) => {
  return batch.bound((pattern: FieldMatchPattern, payload?: any) => {
    if (isQuery(pattern)) {
      pattern.forEach((field) => {
        field.setState(payload)
      })
    } else if (isGeneralField(pattern)) {
      pattern.setState(payload)
    } else {
      let matchCount = 0,
        path = FormPath.parse(pattern)
      form.query(path).forEach((field) => {
        field.setState(payload)
        matchCount++
      })

      if (matchCount === 0 || path.isWildMatchPattern) {
        subscribeUpdate(form, path, payload)
      }
    }
  })
}

export const createBatchStateGetter = (form: Form) => {
  return (pattern: FieldMatchPattern, payload?: any) => {
    if (isQuery(pattern)) {
      return pattern.take(payload)
    } else if (isGeneralField(pattern)) {
      return (pattern as any).getState(payload)
    } else {
      return form.query(pattern).take((field: any) => {
        return field.getState(payload)
      })
    }
  }
}

export const triggerFormInitialValuesChange = (
  form: Form,
  change: DataChange
) => {
  if (Array.isArray(change.object) && change.key === 'length') return
  if (
    contains(form.initialValues, change.object) ||
    form.initialValues === change.value
  ) {
    if (change.type === 'add' || change.type === 'set') {
      patchFormValues(form, change.path.slice(1), change.value)
    }
    if (form.initialized) {
      form.notify(LifeCycleTypes.ON_FORM_INITIAL_VALUES_CHANGE)
    }
  }
}

export const triggerFormValuesChange = (form: Form, change: DataChange) => {
  if (Array.isArray(change.object) && change.key === 'length') return
  if (
    (contains(form.values, change.object) || form.values === change.value) &&
    form.initialized
  ) {
    form.notify(LifeCycleTypes.ON_FORM_VALUES_CHANGE)
  }
}

export const setValidating = (target: Form | Field, validating: boolean) => {
  clearTimeout(target.requests.validate)
  if (validating) {
    target.requests.validate = setTimeout(() => {
      batch(() => {
        target.validating = validating
        notify(
          target,
          LifeCycleTypes.ON_FORM_VALIDATING,
          LifeCycleTypes.ON_FIELD_VALIDATING
        )
      })
    }, RESPONSE_REQUEST_DURATION)
    notify(
      target,
      LifeCycleTypes.ON_FORM_VALIDATE_START,
      LifeCycleTypes.ON_FIELD_VALIDATE_START
    )
  } else {
    if (target.validating !== validating) {
      target.validating = validating
    }
    notify(
      target,
      LifeCycleTypes.ON_FORM_VALIDATE_END,
      LifeCycleTypes.ON_FIELD_VALIDATE_END
    )
  }
}

export const setSubmitting = (target: Form | Field, submitting: boolean) => {
  clearTimeout(target.requests.submit)
  if (submitting) {
    target.requests.submit = setTimeout(() => {
      batch(() => {
        target.submitting = submitting
        notify(
          target,
          LifeCycleTypes.ON_FORM_SUBMITTING,
          LifeCycleTypes.ON_FIELD_SUBMITTING
        )
      })
    }, RESPONSE_REQUEST_DURATION)
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_START,
      LifeCycleTypes.ON_FIELD_SUBMIT_START
    )
  } else {
    if (target.submitting !== submitting) {
      target.submitting = submitting
    }
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_END,
      LifeCycleTypes.ON_FIELD_SUBMIT_END
    )
  }
}

export const setLoading = (target: Form | Field, loading: boolean) => {
  clearTimeout(target.requests.loading)
  if (loading) {
    target.requests.loading = setTimeout(() => {
      batch(() => {
        target.loading = loading
        notify(
          target,
          LifeCycleTypes.ON_FORM_LOADING,
          LifeCycleTypes.ON_FIELD_LOADING
        )
      })
    }, RESPONSE_REQUEST_DURATION)
  } else if (target.loading !== loading) {
    target.loading = loading
  }
}

export const batchSubmit = async <T>(
  target: Form | Field,
  onSubmit?: (values: any) => Promise<T> | void
): Promise<T> => {
  const getValues = (target: Form | Field) => {
    if (isForm(target)) {
      return toJS(target.values)
    }
    return toJS(target.value)
  }
  target.setSubmitting(true)
  try {
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_START,
      LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_START
    )
    await target.validate()
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_SUCCESS,
      LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_SUCCESS
    )
  } catch (e) {
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_FAILED,
      LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_FAILED
    )
  }
  notify(
    target,
    LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_END,
    LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_END
  )
  let results: any
  try {
    if (target.invalid) {
      throw target.errors
    }
    if (isFn(onSubmit)) {
      results = await onSubmit(getValues(target))
    } else {
      results = getValues(target)
    }
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_SUCCESS,
      LifeCycleTypes.ON_FIELD_SUBMIT_SUCCESS
    )
  } catch (e) {
    target.setSubmitting(false)
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT_FAILED,
      LifeCycleTypes.ON_FIELD_SUBMIT_FAILED
    )
    notify(
      target,
      LifeCycleTypes.ON_FORM_SUBMIT,
      LifeCycleTypes.ON_FIELD_SUBMIT
    )
    throw e
  }
  target.setSubmitting(false)
  notify(target, LifeCycleTypes.ON_FORM_SUBMIT, LifeCycleTypes.ON_FIELD_SUBMIT)
  return results
}

const shouldValidate = (field: Field) => {
  const validatePattern = field.props.validatePattern ??
    field.form.props.validatePattern ?? ['editable']
  const validateDisplay = field.props.validateDisplay ??
    field.form.props.validateDisplay ?? ['visible']
  return (
    validatePattern.includes(field.pattern) &&
    validateDisplay.includes(field.display)
  )
}

export const batchValidate = async (
  target: Form | Field,
  pattern: FormPathPattern,
  triggerType?: ValidatorTriggerType
) => {
  if (isForm(target)) target.setValidating(true)
  else {
    if (!shouldValidate(target)) return
  }
  const tasks = []
  target.query(pattern).forEach((field) => {
    if (!isVoidField(field)) {
      tasks.push(validateSelf(field, triggerType, field === target))
    }
  })
  await Promise.all(tasks)
  if (isForm(target)) target.setValidating(false)
  if (target.invalid) {
    notify(
      target,
      LifeCycleTypes.ON_FORM_VALIDATE_FAILED,
      LifeCycleTypes.ON_FIELD_VALIDATE_FAILED
    )
    throw target.errors
  }
  notify(
    target,
    LifeCycleTypes.ON_FORM_VALIDATE_SUCCESS,
    LifeCycleTypes.ON_FIELD_VALIDATE_SUCCESS
  )
}

export const batchReset = async (
  target: Form | Field,
  pattern: FormPathPattern,
  options?: IFieldResetOptions
) => {
  const tasks = []
  target.query(pattern).forEach((field) => {
    if (!isVoidField(field)) {
      tasks.push(resetSelf(field, options, target === field))
    }
  })
  if (isForm(target)) {
    target.modified = false
  }
  notify(target, LifeCycleTypes.ON_FORM_RESET, LifeCycleTypes.ON_FIELD_RESET)
  await Promise.all(tasks)
}

export const validateSelf = batch.bound(
  async (target: Field, triggerType?: ValidatorTriggerType, noEmit = false) => {
    const start = () => {
      setValidating(target, true)
    }
    const end = () => {
      setValidating(target, false)
      if (noEmit) return
      if (target.selfValid) {
        target.notify(LifeCycleTypes.ON_FIELD_VALIDATE_SUCCESS)
      } else {
        target.notify(LifeCycleTypes.ON_FIELD_VALIDATE_FAILED)
      }
    }

    if (!shouldValidate(target)) return {}
    start()
    if (!triggerType) {
      const allTriggerTypes = parseValidatorDescriptions(
        target.validator
      ).reduce(
        (types, desc) =>
          types.indexOf(desc.triggerType) > -1
            ? types
            : types.concat(desc.triggerType),
        []
      )
      const results = {}
      for (let i = 0; i < allTriggerTypes.length; i++) {
        const payload = await validateToFeedbacks(target, allTriggerTypes[i])
        each(payload, (result, key) => {
          results[key] = results[key] || []
          results[key] = results[key].concat(result)
        })
      }
      end()
      return results
    }
    const results = await validateToFeedbacks(target, triggerType)
    end()
    return results
  }
)

export const resetSelf = batch.bound(
  async (target: Field, options?: IFieldResetOptions, noEmit = false) => {
    const typedDefaultValue = getTypedDefaultValue(target)
    target.modified = false
    target.selfModified = false
    target.visited = false
    target.feedbacks = []
    target.inputValue = typedDefaultValue
    target.inputValues = []
    target.caches = {}
    if (!isUndef(target.value)) {
      if (options?.forceClear) {
        target.value = typedDefaultValue
      } else {
        const initialValue = target.initialValue
        target.value = toJS(
          !isUndef(initialValue) ? initialValue : typedDefaultValue
        )
      }
    }
    if (!noEmit) {
      target.notify(LifeCycleTypes.ON_FIELD_RESET)
    }
    if (options?.validate) {
      return await validateSelf(target)
    }
  }
)

export const modifySelf = (target: Field) => {
  if (target.selfModified) return
  target.selfModified = true
  target.modified = true
  let parent = target.parent
  while (parent) {
    if (isDataField(parent)) {
      if (parent.modified) return
      parent.modified = true
    }
    parent = parent.parent
  }
  target.form.modified = true
}

export const getValidFormValues = (values: any) => {
  if (isObservable(values)) return values
  return clone(values || {})
}

export const getValidFieldDefaultValue = (value: any, initialValue: any) => {
  if (allowAssignDefaultValue(value, initialValue)) return clone(initialValue)
  return value
}

export const allowAssignDefaultValue = (target: any, source: any) => {
  const isValidTarget = !isUndef(target)
  const isValidSource = !isUndef(source)
  if (!isValidTarget) {
    return isValidSource
  }

  if (typeof target === typeof source) {
    if (target === '') return false
    if (target === 0) return false
  }

  const isEmptyTarget = target !== null && isEmpty(target, true)
  const isEmptySource = source !== null && isEmpty(source, true)
  if (isEmptyTarget) {
    return !isEmptySource
  }
  return false
}

export const createReactions = (field: GeneralField) => {
  const reactions = toArr(field.props.reactions)
  field.form.addEffects(field, () => {
    reactions.forEach((reaction) => {
      if (isFn(reaction)) {
        field.disposers.push(
          autorun(
            batch.scope.bound(() => {
              if (field.destroyed) return
              reaction(field)
            })
          )
        )
      }
    })
  })
}

export const createReaction = <T>(
  tracker: () => T,
  scheduler?: (value: T) => void
) => {
  return reaction(tracker, untracked.bound(scheduler))
}

export const initializeStart = () => {
  GlobalState.initializing = true
}

export const initializeEnd = () => {
  batch.endpoint(() => {
    GlobalState.initializing = false
  })
}

export const getArrayParent = (field: BaseField, index = field.index) => {
  if (index > -1) {
    let parent: any = field.parent
    while (parent) {
      if (isArrayField(parent)) return parent
      if (parent === field.form) return
      parent = parent.parent
    }
  }
}

export const getObjectParent = (field: BaseField) => {
  let parent: any = field.parent
  while (parent) {
    if (isArrayField(parent)) return
    if (isObjectField(parent)) return parent
    if (parent === field.form) return
    parent = parent.parent
  }
}

```

--------------------------------------------------------------------------------
/packages/vue/src/__tests__/schema.json.spec.ts:
--------------------------------------------------------------------------------

```typescript
import { createForm, Field } from '@formily/core'
import { observer } from '@formily/reactive-vue'
import { Schema } from '@formily/json-schema'
import { fireEvent, render, waitFor } from '@testing-library/vue'
import { mount } from '@vue/test-utils'
import Vue, { FunctionalComponentOptions } from 'vue'
import {
  FormProvider,
  createSchemaField,
  RecursionField,
} from '../vue2-components'
import { connect, mapProps, mapReadPretty, useField, useFieldSchema } from '../'
import { defineComponent, h } from 'vue-demi'

Vue.component('FormProvider', FormProvider)

const Input: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h('input', {
      class: 'input',
      attrs: {
        value: context.props.value,
        'data-testid': 'input',
      },
      on: {
        input: context.listeners.change,
      },
    })
  },
}

const Input2: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h('input', {
      class: 'input2',
      attrs: {
        value: context.props.value,
        'data-testid': 'input2',
      },
      on: {
        input: context.listeners.change,
      },
    })
  },
}

const FormItem: FunctionalComponentOptions = {
  functional: true,
  render(h, { props, slots, data }) {
    return h(
      'div',
      {
        ...data,
        style: {
          width: '300px',
          height: '30px',
          background: 'yellow',
        },
        attrs: {
          'data-testid': 'formitem',
          ...data.attrs,
        },
      },
      [props.label || 'unknown ', slots().default]
    )
  },
}

const ArrayItems = observer(
  defineComponent({
    setup() {
      const fieldRef = useField<Field>()
      const schemaRef = useFieldSchema()

      return () => {
        const field = fieldRef.value
        const schema = schemaRef.value
        const items = field.value?.map?.((item, index) => {
          return h(RecursionField, {
            props: { schema: schema.items, name: index },
          })
        })
        return h('div', { attrs: { 'data-testid': 'array-items' } }, [items])
      }
    },
  })
)

const Previewer: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h(
      'div',
      {
        attrs: {
          'data-testid': 'previewer',
        },
      },
      context.children
    )
  },
}

const Previewer2: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h(
      'div',
      {
        attrs: {
          'data-testid': 'previewer2',
        },
      },
      [context.scopedSlots.content({})]
    )
  },
}

const Previewer3: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h(
      'div',
      {
        attrs: {
          'data-testid': 'previewer3',
        },
      },
      [
        context.scopedSlots.default({
          slotProp: '123',
        }),
      ]
    )
  },
}

const Previewer4: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h(
      'div',
      {
        attrs: {
          'data-testid': 'previewer4',
        },
      },
      [
        context.scopedSlots.content({
          slotProp: '123',
        }),
      ]
    )
  },
}

const Previewer5: FunctionalComponentOptions = {
  functional: true,
  render(h, context) {
    return h(
      'div',
      {
        attrs: {
          'data-testid': 'previewer5',
        },
      },
      context.slots()?.append
    )
  },
}

describe('json schema field', () => {
  test('string field', () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Input,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            default: '123',
            'x-component': 'Input',
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeVisible()
    expect(queryByTestId('input').getAttribute('value')).toEqual('123')
  })

  test('object field', () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Input,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'object',
            properties: {
              string: {
                type: 'string',
                'x-component': 'Input',
              },
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeVisible()
  })
})

describe('x-content', () => {
  test('default slot', () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Previewer,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer',
            'x-content': '123',
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer')).toBeVisible()
    expect(queryByTestId('previewer').textContent).toEqual('123')
  })

  test('default slot with component', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer',
            'x-content': Content,
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer')).toBeVisible()
    expect(queryByTestId('previewer').textContent).toEqual('123')
  })

  test('default slot with name default', () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Previewer,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer',
            'x-content': {
              default: '123',
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer')).toBeVisible()
    expect(queryByTestId('previewer').textContent).toEqual('123')
  })

  test('default slot with name default and component', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer',
            'x-content': {
              default: Content,
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer')).toBeVisible()
    expect(queryByTestId('previewer').textContent).toEqual('123')
  })

  test('named slot', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer2,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer2',
            'x-content': {
              content: Content,
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer2')).toBeVisible()
    expect(queryByTestId('previewer2').textContent).toEqual('123')
  })

  test('named slot with scope', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer2,
      },
      scope: {
        Content,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer2',
            'x-content': {
              content: '{{Content}}',
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer2')).toBeVisible()
    expect(queryByTestId('previewer2').textContent).toEqual('123')
  })

  test('named slot in void field', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer2,
      },
      scope: {
        Content,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'void',
            'x-component': 'Previewer2',
            'x-content': {
              content: '{{Content}}',
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer2')).toBeVisible()
    expect(queryByTestId('previewer2').textContent).toEqual('123')
  })

  test('scoped slot', () => {
    const form = createForm()
    const Content = {
      functional: true,
      render(h, context) {
        return h('span', context.props.slotProp)
      },
    }

    const { SchemaField } = createSchemaField({
      components: {
        Previewer3,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer3',
            'x-content': Content,
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer3')).toBeVisible()
    expect(queryByTestId('previewer3').textContent).toEqual('123')
  })

  test('scoped slot with scope', () => {
    const form = createForm()
    const Content = {
      functional: true,
      render(h, context) {
        return h('span', context.props.slotProp)
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer3,
      },
      scope: {
        Content,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer3',
            'x-content': '{{Content}}',
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer3')).toBeVisible()
    expect(queryByTestId('previewer3').textContent).toEqual('123')
  })

  test('scoped slot with name default', () => {
    const form = createForm()
    const Content = {
      functional: true,
      render(h, context) {
        return h('span', context.props.slotProp)
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer3,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer3',
            'x-content': {
              default: Content,
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer3')).toBeVisible()
    expect(queryByTestId('previewer3').textContent).toEqual('123')
  })

  test('scoped slot with name other', () => {
    const form = createForm()
    const Content = {
      functional: true,
      render(h, context) {
        return h('span', context.props.slotProp)
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer4,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer4',
            'x-content': {
              content: Content,
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer4')).toBeVisible()
    expect(queryByTestId('previewer4').textContent).toEqual('123')
  })

  test('scoped slot with connect', () => {
    const form = createForm()
    const ConnectedComponent = connect(
      defineComponent({
        render(h) {
          return h(
            'div',
            {
              attrs: {
                'data-testid': 'ConnectedComponent',
              },
            },
            [
              this.$scopedSlots.default({
                slotProp: '123',
              }),
            ]
          )
        },
      }),
      mapProps((props, field) => {
        return {
          ...props,
        }
      })
    )

    const scopeSlotComponent = {
      functional: true,
      render(h, context) {
        return h('span', context.props.slotProp)
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        ConnectedComponent,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            name: 'ConnectedComponent',
            'x-component': 'ConnectedComponent',
            'x-content': {
              default: scopeSlotComponent,
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('ConnectedComponent')).toBeVisible()
    expect(queryByTestId('ConnectedComponent').textContent).toEqual('123')
  })

  test('scoped slot with connect and readPretty', () => {
    const form = createForm()

    const ConnectedWithMapReadPretty = connect(
      defineComponent({
        render(h) {
          return h(
            'div',
            {
              attrs: {
                'data-testid': 'ConnectedWithMapReadPretty',
              },
            },
            [
              this.$scopedSlots.withMapReadPretty({
                slotProp: '123',
              }),
            ]
          )
        },
      }),
      mapProps((props, field) => {
        return {
          ...props,
        }
      }),
      mapReadPretty({
        render(h) {
          return h('div', 'read pretty')
        },
      })
    )

    const scopeSlotComponent = {
      functional: true,
      render(h, context) {
        return h('span', context.props.slotProp)
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        ConnectedWithMapReadPretty,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            name: 'ConnectedWithMapReadPretty',
            'x-component': 'ConnectedWithMapReadPretty',
            'x-content': {
              withMapReadPretty: scopeSlotComponent,
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('ConnectedWithMapReadPretty')).toBeVisible()
    expect(queryByTestId('ConnectedWithMapReadPretty').textContent).toEqual(
      '123'
    )
  })

  test('slot compitible', () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Previewer5,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Previewer5',
            'x-content': {
              append: '123',
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer5')).toBeVisible()
    expect(queryByTestId('previewer5').textContent).toEqual('123')
  })

  test('wrong x-content will be ignore', () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Previewer,
      },
    })
    const { queryAllByTestId, container } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'object',
            properties: {
              input1: {
                type: 'string',
                'x-component': 'Previewer',
                'x-content': {
                  default: {
                    someAttr: '123',
                  },
                },
              },
              input2: {
                type: 'string',
                'x-component': 'Previewer',
                'x-content': {
                  default: null,
                },
              },
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    queryAllByTestId('previewer').forEach((el) => expect(el).toBeVisible())
    queryAllByTestId('previewer').forEach((el) =>
      expect(el.textContent).toEqual('')
    )
  })
})

describe('x-slot', () => {
  test('x-slot works in void field properties', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer4,
        Content,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'void',
            'x-component': 'Previewer4',
            properties: {
              content: {
                type: 'void',
                'x-component': 'Content',
                'x-slot': 'content',
              },
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer4')).toBeVisible()
    expect(queryByTestId('previewer4').textContent).toEqual('123')
  })
  test('x-slot works in object field properties', () => {
    const form = createForm()
    const Content = {
      render(h) {
        return h('span', '123')
      },
    }
    const { SchemaField } = createSchemaField({
      components: {
        Previewer4,
        Content,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'object',
            'x-component': 'Previewer4',
            properties: {
              content: {
                type: 'void',
                'x-component': 'Content',
                'x-slot': 'content',
              },
            },
          }),
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          name="string"
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('previewer4')).toBeVisible()
    expect(queryByTestId('previewer4').textContent).toEqual('123')
  })
})

describe('scope', () => {
  test('scope in <SchemaField> prop', async () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        Input2,
        Previewer,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: {
            type: 'object',
            properties: {
              input1: {
                type: 'string',
                'x-component': 'Input',
                'x-reactions': {
                  target: 'input2',
                  fulfill: {
                    state: {
                      value: '{{ test }}',
                    },
                  },
                },
              },
              input2: {
                type: 'string',
                'x-component': 'Input2',
              },
            },
          },
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          :schema="schema"
          :scope="{
            test: '123'
          }"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('input2').getAttribute('value')).toEqual('123')
  })

  test('scope in options of createSchemaField', async () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        Input2,
        Previewer,
      },
      scope: {
        test: '123',
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: {
            type: 'object',
            properties: {
              input1: {
                type: 'string',
                'x-component': 'Input',
                'x-reactions': {
                  target: 'input2',
                  fulfill: {
                    state: {
                      value: '{{ test }}',
                    },
                  },
                },
              },
              input2: {
                type: 'string',
                'x-component': 'Input2',
              },
            },
          },
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField
          :schema="schema"
        />
      </FormProvider>`,
    })
    expect(queryByTestId('input2').getAttribute('value')).toEqual('123')
  })
})

describe('expression', () => {
  test('expression x-visible', async () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        Input2,
        Previewer,
      },
    })

    const wrapper = mount(
      {
        components: { SchemaField },
        data() {
          return {
            form,
            schema: {
              type: 'object',
              properties: {
                input: {
                  type: 'string',
                  'x-component': 'Input',
                },
                input2: {
                  type: 'string',
                  'x-component': 'Input2',
                  'x-visible': '{{$form.values.input === "123"}}',
                },
              },
            },
          }
        },
        template: `<FormProvider :form="form">
        <SchemaField
          :schema="schema"
        />
      </FormProvider>`,
      },
      {
        attachToDocument: true,
      }
    )

    expect(wrapper.find('.input').exists()).toBeTruthy()
    expect(wrapper.find('.input2').exists()).not.toBeTruthy()

    form.values.input = '123'
    await waitFor(() => expect(wrapper.find('.input2').exists()).toBeTruthy())
    wrapper.destroy()
  })

  test('expression x-value', async () => {
    const form = createForm({
      values: {
        input: 1,
      },
    })
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        Input2,
        Previewer,
      },
    })

    const wrapper = mount(
      {
        components: { SchemaField },
        data() {
          return {
            form,
            schema: {
              type: 'object',
              properties: {
                input: {
                  type: 'string',
                  'x-component': 'Input',
                },
                input2: {
                  type: 'string',
                  'x-component': 'Input2',
                  'x-value': '{{$form.values.input * 10}}',
                },
              },
            },
          }
        },
        template: `<FormProvider :form="form">
        <SchemaField
          :schema="schema"
        />
      </FormProvider>`,
      },
      { attachToDocument: true }
    )

    expect(wrapper.find('.input2').attributes().value).toEqual('10')
    form.values.input = 10
    await waitFor(() =>
      expect(wrapper.find('.input2').attributes().value).toEqual('100')
    )
    wrapper.destroy()
  })
})

describe('schema controlled', () => {
  test('view update correctly when schema changed', async () => {
    const form = createForm({})
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        Input2,
      },
    })
    const component = defineComponent({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: {
            type: 'object',
            properties: {
              input: {
                type: 'string',
                'x-component': 'Input',
              },
              input2: {
                type: 'string',
                'x-component': 'Input2',
              },
            },
          },
        }
      },
      methods: {
        changeSchema() {
          this.schema = {
            type: 'object',
            properties: {
              input2: {
                type: 'string',
                'x-component': 'Input2',
              },
            },
          }
        },
      },
      template: `<FormProvider :form="form">
          <SchemaField
            :schema="schema"
          />
          <button @click="changeSchema()">changeSchema</button>
        </FormProvider>`,
    })
    const { queryByTestId, getByText } = render(component)

    expect(queryByTestId('input')).toBeVisible()
    expect(queryByTestId('input2')).toBeVisible()
    getByText('changeSchema').click()
    await waitFor(() => {
      expect(queryByTestId('input2')).toBeVisible()
      expect(queryByTestId('input')).toBeNull()
    })
  })
  test('view updated correctly with schema fragment changed', async () => {
    const form = createForm({})
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        Input2,
        ArrayItems,
      },
    })
    const frag1 = {
      type: 'object',
      properties: {
        input1: {
          type: 'string',
          'x-component': 'Input',
        },
      },
    }
    const frag2 = {
      type: 'array',
      'x-component': 'ArrayItems',
      items: {
        type: 'object',
        properties: {
          input2: {
            type: 'string',
            'x-component': 'Input2',
          },
        },
      },
    }
    const component = defineComponent({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: {
            type: 'object',
            properties: {
              input: frag1,
            },
          },
        }
      },
      methods: {
        changeSchema() {
          this.form.clearFormGraph('input')
          this.form.deleteValuesIn('input')
          this.schema = {
            type: 'object',
            properties: {
              input: frag2,
            },
          }
        },
      },
      template: `<FormProvider :form="form">
          <SchemaField
            :schema="schema"
          />
          <button @click="changeSchema()">changeSchema</button>
        </FormProvider>`,
    })
    const { queryByTestId, getByText } = render(component)

    expect(queryByTestId('input')).toBeVisible()
    expect(queryByTestId('array-items')).toBeNull()
    getByText('changeSchema').click()
    await waitFor(() => {
      expect(queryByTestId('input')).toBeNull()
      expect(queryByTestId('array-items')).toBeVisible()
    })
  })
})

describe('x-decorator', () => {
  test('x-decorator-props', async () => {
    const form = createForm()
    const { SchemaField } = createSchemaField({
      components: {
        Input,
        FormItem,
      },
    })

    const atBlurFn = jest.fn()
    const onClickFn = jest.fn()
    const atClickFn = jest.fn()
    const { queryByTestId, getByText } = render({
      components: { SchemaField },
      data() {
        return {
          form,
          schema: new Schema({
            type: 'string',
            'x-component': 'Input',
            'x-component-props': {
              '@blur': function atBlur() {
                atBlurFn()
              },
            },
            'x-decorator': 'FormItem',
            'x-decorator-props': {
              label: 'Label ',
              onClick: function onClick() {
                onClickFn()
              },
              '@click': function atClick() {
                atClickFn()
              },
            },
          }),
        }
      },
      template: `
        <FormProvider :form="form">
          <SchemaField
            name="string"
            :schema="schema"
          />
        </FormProvider>`,
    })
    expect(queryByTestId('formitem')).toBeVisible()
    await fireEvent.click(getByText('Label'))
    expect(atClickFn).toBeCalledTimes(1)
    expect(onClickFn).toBeCalledTimes(0)
  })
})

```

--------------------------------------------------------------------------------
/packages/antd/docs/components/FormItem.zh-CN.md:
--------------------------------------------------------------------------------

```markdown
# FormItem

> 全新的 FormItem 组件,相比于 Antd 的 FormItem,它支持的功能更多,同时它的定位是纯样式组件,不管理表单状态,所以也会更轻量,更方便定制

## Markup Schema 案例

```tsx
import React from 'react'
import { Input, Select, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        x-decorator="FormItem"
        x-component="Input"
        required
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    input: {
      type: 'string',
      title: '输入框',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="input"
      title="输入框"
      required
      decorator={[FormItem]}
      component={[
        Input,
        {
          style: {
            width: 240,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 常用属性案例

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'label为空时的展示' }}
        />
        <SchemaField.String
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
          }}
        />
        <SchemaField.String
          title=""
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
          }}
        />
        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '冒号' }}
        />
        <SchemaField.String
          title="默认"
          x-decorator="FormItem"
          x-component="Input"
        />
        <SchemaField.String
          title="无冒号(colon=false)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            colon: false,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '固定宽度设置' }}
        />
        <SchemaField.String
          title="固定label宽度(labelWidth)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
          }}
        />
        <SchemaField.String
          title="固定label宽度(labelWidth)溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出溢出"
          description="描述描述"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            tooltip: '提示提示',
            tooltipLayout: 'text',
          }}
        />
        <SchemaField.String
          title="固定label宽度(labelWidth)换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行换行"
          description="描述描述"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            labelWrap: true,
            tooltip: '提示提示',
          }}
        />
        <SchemaField.String
          title="固定内容宽度(wrapperWidth)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            wrapperWidth: 300,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '对齐方式设置' }}
        />
        <SchemaField.String
          title="label左对齐(labelAlign=left)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            labelAlign: 'left',
          }}
        />
        <SchemaField.String
          title="label右对齐(labelAlign=right默认)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            labelAlign: 'right',
          }}
        />

        <SchemaField.String
          title="内容左对齐(wrapperAlign=left默认)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            wrapperWidth: 240,
            wrapperAlign: 'left',
          }}
        />
        <SchemaField.String
          title="内容右对齐(wrapperAlign=right)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            wrapperWidth: 240,
            wrapperAlign: 'right',
          }}
        />

        <SchemaField.String
          title="tooltip"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            tooltip: 'tooltip',
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '是否撑满' }}
        />

        <SchemaField.String
          title="默认不撑满(fullness=false)"
          x-decorator="FormItem"
          x-component="Select"
        />
        <SchemaField.String
          title="撑满(fullness=true)"
          x-decorator="FormItem"
          x-component="Select"
          x-decorator-props={{
            fullness: true,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '辅助信息' }}
        />

        <SchemaField.String
          title="必填星号"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            asterisk: true,
            labelCol: 6,
            wrapperCol: 10,
          }}
        />

        <SchemaField.String
          title="前缀"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            addonBefore: 'addonBefore',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />
        <SchemaField.String
          title="后缀"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            addonAfter: 'addonAfter',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />

        <SchemaField.String
          title="帮助信息feedbackText"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackText: 'feedbackText',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />

        <SchemaField.String
          title="额外信息extra"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackText: 'feedbackText',
            extra: 'extra',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />
      </SchemaField>
    </FormProvider>
  )
}
```

## 必填样式

```tsx
import React, { useState } from 'react'
import { Input, FormItem, FormLayout } from '@formily/antd'
import { Radio, ConfigProvider } from 'antd'
import zhCN from 'antd/es/locale/zh_CN'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => {
  const [requiredMark, setRequiredMark] = useState(true)
  return (
    <ConfigProvider locale={zhCN}>
      <p>
        Required Mark:
        <Radio.Group
          value={requiredMark}
          onChange={(e) => setRequiredMark(e.target.value)}
        >
          <Radio.Button value="optional">optional</Radio.Button>
          <Radio.Button value={true}>true</Radio.Button>
          <Radio.Button value={false}>false</Radio.Button>
        </Radio.Group>
      </p>
      <FormProvider form={form}>
        <FormLayout requiredMark={requiredMark}>
          <SchemaField>
            <SchemaField.String
              title="我是必填项"
              required
              x-decorator="FormItem"
              x-component="Input"
            />
            <SchemaField.String
              title="我是选填项"
              x-decorator="FormItem"
              x-component="Input"
            />
            <SchemaField.String
              default="字段不可编辑时,始终隐藏必填/选填标识"
              x-editable={false}
              x-decorator="FormItem"
              x-component="Input"
            />
            <SchemaField.String
              title="我是必填项"
              required
              default="不可编辑"
              x-editable={false}
              x-decorator="FormItem"
              x-component="Input"
            />
            <SchemaField.String
              title="我是选填项"
              default="不可编辑"
              x-editable={false}
              x-decorator="FormItem"
              x-component="Input"
            />
          </SchemaField>
        </FormLayout>
      </FormProvider>
    </ConfigProvider>
  )
}
```

## 无边框案例

设置去除组件边框

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="input"
          title="Input"
          x-decorator="FormItem"
          x-component="Input"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="Cascader"
          title="Cascader"
          x-decorator="FormItem"
          x-component="Cascader"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="DatePicker"
          title="DatePicker"
          x-decorator="FormItem"
          x-component="DatePicker"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="NumberPicker"
          title="NumberPicker"
          x-decorator="FormItem"
          x-component="NumberPicker"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="TreeSelect"
          title="TreeSelect"
          x-decorator="FormItem"
          x-component="TreeSelect"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.Boolean
          name="Switch"
          title="Switch"
          x-decorator="FormItem"
          x-component="Switch"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
      </SchemaField>
    </FormProvider>
  )
}
```

## 内嵌模式案例

设置表单组件为内嵌模式

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="input"
          title="Input"
          x-decorator="FormItem"
          x-component="Input"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="Cascader"
          title="Cascader"
          x-decorator="FormItem"
          x-component="Cascader"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="DatePicker"
          title="DatePicker"
          x-decorator="FormItem"
          x-component="DatePicker"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="NumberPicker"
          title="NumberPicker"
          x-decorator="FormItem"
          x-component="NumberPicker"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="TreeSelect"
          title="TreeSelect"
          x-decorator="FormItem"
          x-component="TreeSelect"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.Boolean
          name="Switch"
          title="Switch"
          x-decorator="FormItem"
          x-component="Switch"
          required
          x-decorator-props={{
            inset: false,
          }}
        />
      </SchemaField>
    </FormProvider>
  )
}
```

## 反馈信息定制案例

可通过 `feedbackIcon` 传入指定反馈的按钮

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  TimePicker,
  FormItem,
  FormLayout,
  NumberPicker,
  Switch,
} from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { CheckCircleFilled, LoadingOutlined } from '@ant-design/icons'
const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    TimePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
    FormLayout,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          title="错误状态(feedbackStatus=error)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'error',
          }}
        />

        <SchemaField.String
          title="警告状态(feedbackStatus=warning)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'warning',
          }}
        />

        <SchemaField.String
          title="成功状态(feedbackStatus=success)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'success',
            feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
          }}
        />

        <SchemaField.String
          title="加载状态(feedbackStatus=pending)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'pending',
            feedbackIcon: <LoadingOutlined style={{ color: '#1890ff' }} />,
          }}
        />

        <SchemaField.String
          title="禁用错误状态边框样式(feedbackStatus=error)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            enableOutlineFeedback: false,
            feedbackStatus: 'error',
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '反馈信息的布局' }}
        />

        <SchemaField.String
          title="紧凑模式required"
          x-decorator="FormItem"
          x-component="Input"
          required
          x-decorator-props={{
            feedbackLayout: 'terse',
          }}
        />

        <SchemaField.String
          title="紧凑模式有feedback(feedbackLayout=terse)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'error',
            feedbackText: 'error message',
            feedbackLayout: 'terse',
          }}
        />

        <SchemaField.String
          title="紧凑模式无feedback(feedbackLayout=terse)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackLayout: 'terse',
          }}
        />

        <SchemaField.String
          title="松散模式(feedbackLayout=loose)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'error',
            feedbackText: 'error message',
            feedbackLayout: 'loose',
          }}
        />

        <SchemaField.String
          title="弹出模式(feedbackLayout=popover)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'warning',
            feedbackText: 'warning message',
            feedbackLayout: 'popover',
          }}
        />

        <SchemaField.String
          title="弹出模式(feedbackLayout=popover)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'error',
            feedbackText: 'error message',
            feedbackLayout: 'popover',
          }}
        />
        <SchemaField.String
          title="弹出模式(feedbackLayout=popover)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'success',
            feedbackText: 'success message',
            feedbackLayout: 'popover',
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: '组件的适配情况' }}
        />
        <SchemaField.Void
          x-component="FormLayout"
          x-component-props={{ layout: 'vertical' }}
        >
          <SchemaField.String
            title="Select"
            x-decorator="FormItem"
            x-component="Select"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />

          <SchemaField.String
            title="DatePicker"
            x-decorator="FormItem"
            x-component="DatePicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.RangePicker"
            x-decorator="FormItem"
            x-component="DatePicker.RangePicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.YearPicker"
            x-decorator="FormItem"
            x-component="DatePicker.YearPicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.MonthPicker"
            x-decorator="FormItem"
            x-component="DatePicker.MonthPicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.TimePicker"
            x-decorator="FormItem"
            x-component="TimePicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="NumberPicker"
            x-decorator="FormItem"
            x-component="NumberPicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />

          <SchemaField.String
            title="TreeSelect"
            x-decorator="FormItem"
            x-component="TreeSelect"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />

          <SchemaField.String
            title="Cascader"
            x-decorator="FormItem"
            x-component="Cascader"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
        </SchemaField.Void>
      </SchemaField>
    </FormProvider>
  )
}
```

## 尺寸控制案例

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/antd'
import { createForm, onFieldChange } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Div = (props) => <div {...props} />

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Div,
  },
})

const form = createForm({
  values: {
    size: 'default',
  },
  effects: () => {
    onFieldChange('size', ['value'], (field, form) => {
      form.setFieldState('sizeWrap.*', (state) => {
        if (state.decorator[1]) {
          state.decorator[1].size = field.value
        }
      })
    })
  },
})

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="size"
          title="Radio.Group"
          x-decorator="FormItem"
          x-component="Radio.Group"
          enum={[
            { value: 'small', label: 'Small' },
            { value: 'default', label: 'Default' },
            { value: 'large', label: 'Large' },
          ]}
        />
        <SchemaField.Void name="sizeWrap" x-component="Div">
          <SchemaField.String
            name="input"
            title="Input"
            x-decorator="FormItem"
            x-component="Input"
            required
          />
          <SchemaField.String
            name="select1"
            title="Multiple Select"
            x-decorator="FormItem"
            x-component="Select"
            enum={[
              {
                label: '选项1',
                value: 1,
              },
              {
                label: '选项2',
                value: 2,
              },
            ]}
            x-component-props={{
              mode: 'multiple',
              placeholder: '请选择',
            }}
            required
          />
          <SchemaField.String
            name="select2"
            title="Select"
            x-decorator="FormItem"
            x-component="Select"
            enum={[
              {
                label: '选项1',
                value: 1,
              },
              {
                label: '选项2',
                value: 2,
              },
            ]}
            x-component-props={{
              placeholder: '请选择',
            }}
            required
          />
          <SchemaField.String
            name="Cascader"
            title="Cascader"
            x-decorator="FormItem"
            x-component="Cascader"
            required
          />
          <SchemaField.String
            name="DatePicker"
            title="DatePicker"
            x-decorator="FormItem"
            x-component="DatePicker"
            required
          />
          <SchemaField.String
            name="NumberPicker"
            title="NumberPicker"
            x-decorator="FormItem"
            x-component="NumberPicker"
            required
          />
          <SchemaField.String
            name="TreeSelect"
            title="TreeSelect"
            x-decorator="FormItem"
            x-component="TreeSelect"
            required
          />
          <SchemaField.Boolean
            name="Switch"
            title="Switch"
            x-decorator="FormItem"
            x-component="Switch"
            required
          />
        </SchemaField.Void>
      </SchemaField>
    </FormProvider>
  )
}
```

## API

### FormItem

| 属性名                | 类型                                                   | 描述                                                                | 默认值              |
| --------------------- | ------------------------------------------------------ | ------------------------------------------------------------------- | ------------------- |
| label                 | ReactNode                                              | 标签                                                                | -                   |
| style                 | CSSProperties                                          | 样式                                                                | -                   |
| labelStyle            | CSSProperties                                          | 标签样式                                                            | -                   |
| wrapperStyle          | CSSProperties                                          | 组件容器样式                                                        | -                   |
| className             | string                                                 | 组件样式类名                                                        | -                   |
| colon                 | boolean                                                | 冒号                                                                | true                |
| tooltip               | ReactNode                                              | 问号提示                                                            | -                   |
| tooltipLayout         | `"icon" \| "text"`                                     | 问号提示布局                                                        | `"icon"`            |
| tooltipIcon           | ReactNode                                              | 问号提示图标                                                        | `?`                 |
| labelAlign            | `"left"` \| `"right"`                                  | 标签文本对齐方式                                                    | `"right"`           |
| labelWrap             | boolean                                                | 标签换⾏,否则出现省略号,hover 有 tooltip                          | false               |
| labelWidth            | `number \| string`                                     | 标签固定宽度                                                        | -                   |
| wrapperWidth          | `number \| string`                                     | 内容固定宽度                                                        | -                   |
| labelCol              | number                                                 | 标签⽹格所占列数,和内容列数加起来总和为 24                         | -                   |
| wrapperCol            | number                                                 | 内容⽹格所占列数,和标签列数加起来总和为 24                         | -                   |
| wrapperAlign          | `"left"` \| `"right"`                                  | 内容文本对齐方式⻬                                                  | `"left"`            |
| wrapperWrap           | boolean                                                | 内容换⾏,否则出现省略号,hover 有 tooltip                          | false               |
| fullness              | boolean                                                | 内容撑满                                                            | false               |
| addonBefore           | ReactNode                                              | 前缀内容                                                            | -                   |
| addonAfter            | ReactNode                                              | 后缀内容                                                            | -                   |
| size                  | `"small"` \| `"default"` \| `"large"`                  | 尺⼨                                                                | -                   |
| inset                 | boolean                                                | 是否是内嵌布局                                                      | false               |
| extra                 | ReactNode                                              | 扩展描述⽂案                                                        | -                   |
| feedbackText          | ReactNode                                              | 反馈⽂案                                                            | -                   |
| feedbackLayout        | `"loose"` \| `"terse"` \| `"popover" \| "none"`        | 反馈布局                                                            | -                   |
| feedbackStatus        | `"error"` \| `"warning"` \| `"success"` \| `"pending"` | 反馈布局                                                            | -                   |
| feedbackIcon          | ReactNode                                              | 反馈图标                                                            | -                   |
| enableOutlineFeedback | boolean                                                | 开启异常状态的边框颜色样式,当自定义组件内存在子表单时建议关闭此项  | true                |
| getPopupContainer     | function(triggerNode)                                  | 当 feedbackLayout 为 popover 时,浮层渲染父节点,默认渲染到 body 上 | () => document.body |
| asterisk              | boolean                                                | 星号提醒                                                            | -                   |
| gridSpan              | number                                                 | ⽹格布局占宽                                                        | -                   |
| bordered              | boolean                                                | 是否有边框                                                          | -                   |

### FormItem.BaseItem

纯样式组件,属性与 FormItem 一样,与 Formily Core 不做状态桥接,主要用于一些需要依赖 FormItem 的样式布局能力,但不希望接入 Field 状态的场景

```

--------------------------------------------------------------------------------
/packages/next/docs/components/FormItem.md:
--------------------------------------------------------------------------------

```markdown
# FormItem

> The brand new FormItem component, compared to Fusion Next’s FormItem, it supports more functions. At the same time, it is positioned as a pure style component and does not manage form status, so it will be lighter and more convenient for customization

## Markup Schema example

```tsx
import React from 'react'
import { Input, Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        x-decorator="FormItem"
        x-component="Input"
        required
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JOSN Schema case

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    input: {
      type: 'string',
      title: 'input box',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Pure JSX case

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="input"
      title="input box"
      required
      decorator={[FormItem]}
      component={[
        Input,
        {
          style: {
            width: 240,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Commonly used attribute cases

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'Display when label is empty' }}
        />
        <SchemaField.String
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
          }}
        />
        <SchemaField.String
          title=""
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
          }}
        />
        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'colon' }}
        />
        <SchemaField.String
          title="default"
          x-decorator="FormItem"
          x-component="Input"
        />
        <SchemaField.String
          title="no colon (colon=false)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            colon: false,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'Fixed width settings' }}
        />
        <SchemaField.String
          title="Fixed label width (labelWidth)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
          }}
        />
        <SchemaField.String
          title="Fixed label width (labelWidth) overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow overflow"
          description="description description"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            tooltip: 'Prompt Tip',
            tooltipLayout: 'text',
          }}
        />
        <SchemaField.String
          title="Fixed label width (labelWidth) newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline newline"
          description="description description"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            labelWrap: true,
            tooltip: 'Prompt Tip',
          }}
        />
        <SchemaField.String
          title="fixed content width (wrapperWidth)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            wrapperWidth: 300,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'Alignment settings' }}
        />
        <SchemaField.String
          title="labelLeft Alignment(labelAlign=left)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            labelAlign: 'left',
          }}
        />
        <SchemaField.String
          title="label right alignment (labelAlign=right default)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            labelAlign: 'right',
          }}
        />

        <SchemaField.String
          title="Content left aligned (wrapperAlign=left default)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            wrapperWidth: 240,
            wrapperAlign: 'left',
          }}
        />
        <SchemaField.String
          title="Content align right (wrapperAlign=right)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            labelWidth: 300,
            wrapperWidth: 240,
            wrapperAlign: 'right',
          }}
        />

        <SchemaField.String
          title="tooltip"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            tooltip: 'tooltip',
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'Is it full?' }}
        />

        <SchemaField.String
          title="The default is fullness(fullness=true)"
          x-decorator="FormItem"
          x-component="Select"
        />
        <SchemaField.String
          title="Not fullness(fullness=false)"
          x-decorator="FormItem"
          x-component="Select"
          x-decorator-props={{
            fullness: false,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'auxiliary information' }}
        />

        <SchemaField.String
          title="Required asterisk"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            asterisk: true,
            labelCol: 6,
            wrapperCol: 10,
          }}
        />

        <SchemaField.String
          title="prefix"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            addonBefore: 'addonBefore',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />
        <SchemaField.String
          title="suffix"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            addonAfter: 'addonAfter',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />

        <SchemaField.String
          title="Help information feedbackText"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackText: 'feedbackText',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />

        <SchemaField.String
          title="extra information extra"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackText: 'feedbackText',
            extra: 'extra',
            labelCol: 6,
            wrapperCol: 10,
          }}
        />
      </SchemaField>
    </FormProvider>
  )
}
```

## Borderless case

Set to remove the component border

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="input"
          title="Input"
          x-decorator="FormItem"
          x-component="Input"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="Cascader"
          title="Cascader"
          x-decorator="FormItem"
          x-component="Cascader"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="DatePicker"
          title="DatePicker"
          x-decorator="FormItem"
          x-component="DatePicker"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="NumberPicker"
          title="NumberPicker"
          x-decorator="FormItem"
          x-component="NumberPicker"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.String
          name="TreeSelect"
          title="TreeSelect"
          x-decorator="FormItem"
          x-component="TreeSelect"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
        <SchemaField.Boolean
          name="Switch"
          title="Switch"
          x-decorator="FormItem"
          x-component="Switch"
          required
          x-decorator-props={{
            bordered: false,
          }}
        />
      </SchemaField>
    </FormProvider>
  )
}
```

## Embedded mode case

Set the form component to inline mode

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="input"
          title="Input"
          x-decorator="FormItem"
          x-component="Input"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="Select"
          title="Select"
          x-decorator="FormItem"
          x-component="Select"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="Cascader"
          title="Cascader"
          x-decorator="FormItem"
          x-component="Cascader"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="DatePicker"
          title="DatePicker"
          x-decorator="FormItem"
          x-component="DatePicker"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="NumberPicker"
          title="NumberPicker"
          x-decorator="FormItem"
          x-component="NumberPicker"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.String
          name="TreeSelect"
          title="TreeSelect"
          x-decorator="FormItem"
          x-component="TreeSelect"
          required
          x-decorator-props={{
            inset: true,
          }}
        />
        <SchemaField.Boolean
          name="Switch"
          title="Switch"
          x-decorator="FormItem"
          x-component="Switch"
          required
          x-decorator-props={{
            inset: false,
          }}
        />
      </SchemaField>
    </FormProvider>
  )
}
```

## Feedback Customization Case

The button for specifying feedback can be passed in through `feedbackIcon`

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  TimePicker,
  FormItem,
  FormLayout,
  NumberPicker,
  Switch,
} from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { CheckCircleFilled, LoadingOutlined } from '@ant-design/icons'
const Title = (props) => <h3>{props.text}</h3>

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    TimePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Title,
    FormLayout,
  },
})

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          title="error status (feedbackStatus=error)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'error',
          }}
        />

        <SchemaField.String
          title="Warning Status(feedbackStatus=warning)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'warning',
          }}
        />

        <SchemaField.String
          title="Success Status (feedbackStatus=success)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'success',
            feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
          }}
        />

        <SchemaField.String
          title="Loading Status(feedbackStatus=pending)"
          x-decorator="FormItem"
          x-component="Input"
          description="description"
          x-decorator-props={{
            feedbackStatus: 'pending',
            feedbackIcon: <LoadingOutlined style={{ color: '#1890ff' }} />,
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'Layout of feedback information' }}
        />

        <SchemaField.String
          title="Compact mode required"
          x-decorator="FormItem"
          x-component="Input"
          required
          x-decorator-props={{
            feedbackLayout: 'terse',
          }}
        />

        <SchemaField.String
          title="Compact mode has feedback(feedbackLayout=terse)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'error',
            feedbackText: 'error message',
            feedbackLayout: 'terse',
          }}
        />

        <SchemaField.String
          title="Compact mode without feedback(feedbackLayout=terse)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackLayout: 'terse',
          }}
        />

        <SchemaField.String
          title="loose mode (feedbackLayout=loose)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'error',
            feedbackText: 'error message',
            feedbackLayout: 'loose',
          }}
        />

        <SchemaField.String
          title="Popup Mode (feedbackLayout=popover)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'warning',
            feedbackText: 'warning message',
            feedbackLayout: 'popover',
          }}
        />

        <SchemaField.String
          title="Popup Mode (feedbackLayout=popover)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'error',
            feedbackText: 'error message',
            feedbackLayout: 'popover',
          }}
        />
        <SchemaField.String
          title="Popup Mode (feedbackLayout=popover)"
          x-decorator="FormItem"
          x-component="Input"
          x-decorator-props={{
            feedbackStatus: 'success',
            feedbackText: 'success message',
            feedbackLayout: 'popover',
          }}
        />

        <SchemaField.Void
          x-component="Title"
          x-component-props={{ text: 'Component adaptation' }}
        />
        <SchemaField.Void
          x-component="FormLayout"
          x-component-props={{ layout: 'vertical' }}
        >
          <SchemaField.String
            title="Select"
            x-decorator="FormItem"
            x-component="Select"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />

          <SchemaField.String
            title="DatePicker"
            x-decorator="FormItem"
            x-component="DatePicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.RangePicker"
            x-decorator="FormItem"
            x-component="DatePicker.RangePicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.YearPicker"
            x-decorator="FormItem"
            x-component="DatePicker.YearPicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.MonthPicker"
            x-decorator="FormItem"
            x-component="DatePicker.MonthPicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="DatePicker.TimePicker"
            x-decorator="FormItem"
            x-component="TimePicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
          <SchemaField.String
            title="NumberPicker"
            x-decorator="FormItem"
            x-component="NumberPicker"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />

          <SchemaField.String
            title="TreeSelect"
            x-decorator="FormItem"
            x-component="TreeSelect"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />

          <SchemaField.String
            title="Cascader"
            x-decorator="FormItem"
            x-component="Cascader"
            x-decorator-props={{
              feedbackStatus: 'success',
              feedbackIcon: <CheckCircleFilled style={{ color: '#52c41a' }} />,
            }}
          />
        </SchemaField.Void>
      </SchemaField>
    </FormProvider>
  )
}
```

## Size control case

```tsx
import React from 'react'
import {
  Input,
  Radio,
  TreeSelect,
  Cascader,
  Select,
  DatePicker,
  FormItem,
  NumberPicker,
  Switch,
} from '@formily/next'
import { createForm, onFieldChange } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const Div = (props) => <div {...props} />

const SchemaField = createSchemaField({
  components: {
    Input,
    Select,
    Cascader,
    TreeSelect,
    DatePicker,
    NumberPicker,
    Switch,
    Radio,
    FormItem,
    Div,
  },
})

const form = createForm({
  values: {
    size: 'default',
  },
  effects: () => {
    onFieldChange('size', ['value'], (field, form) => {
      form.setFieldState('sizeWrap.*', (state) => {
        if (state.decorator[1]) {
          state.decorator[1].size = field.value
        }
      })
    })
  },
})

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="size"
          title="Radio.Group"
          x-decorator="FormItem"
          x-component="Radio.Group"
          enum={[
            { value: 'small', label: 'Small' },
            { value: 'default', label: 'Default' },
            { value: 'large', label: 'Large' },
          ]}
        />
        <SchemaField.Void name="sizeWrap" x-component="Div">
          <SchemaField.String
            name="input"
            title="Input"
            x-decorator="FormItem"
            x-component="Input"
            required
          />
          <SchemaField.String
            name="Select"
            title="Select"
            x-decorator="FormItem"
            x-component="Select"
            required
          />
          <SchemaField.String
            name="Select"
            title="Select"
            x-decorator="FormItem"
            x-component="Select"
            enum={[
              {
                label: 'Option 1',
                value: 1,
              },
              {
                label: 'Option 2',
                value: 2,
              },
            ]}
            required
          />
          <SchemaField.String
            name="Cascader"
            title="Cascader"
            x-decorator="FormItem"
            x-component="Cascader"
            required
          />
          <SchemaField.String
            name="DatePicker"
            title="DatePicker"
            x-decorator="FormItem"
            x-component="DatePicker"
            required
          />
          <SchemaField.String
            name="NumberPicker"
            title="NumberPicker"
            x-decorator="FormItem"
            x-component="NumberPicker"
            required
          />
          <SchemaField.String
            name="TreeSelect"
            title="TreeSelect"
            x-decorator="FormItem"
            x-component="TreeSelect"
            required
          />
          <SchemaField.Boolean
            name="Switch"
            title="Switch"
            x-decorator="FormItem"
            x-component="Switch"
            required
          />
        </SchemaField.Void>
      </SchemaField>
    </FormProvider>
  )
}
```

## API

### FormItem

| Property name  | Type                                                   | Description                                                                                      | Default value |
| -------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | ------------- |
| label          | ReactNode                                              | label                                                                                            | -             |
| style          | CSSProperties                                          | Style                                                                                            | -             |
| labelStyle     | CSSProperties                                          | Label style                                                                                      | -             |
| wrapperStyle   | CSSProperties                                          | Component container style                                                                        | -             |
| className      | string                                                 | Component style class name                                                                       | -             |
| colon          | boolean                                                | colon                                                                                            | true          |
| tooltip        | ReactNode                                              | Question mark prompt                                                                             | -             |
| tooltipLayout  | `"icon" \| "text"`                                     | Ask the prompt layout                                                                            | `"icon"`      |
| tooltipIcon    | ReactNode                                              | Ask the prompt icon                                                                              | `?`           |
| labelAlign     | `"left"` \| `"right"`                                  | Label text alignment                                                                             | `"right"`     |
| labelWrap      | boolean                                                | Label change, otherwise an ellipsis appears, hover has tooltip                                   | false         |
| labelWidth     | `number \| string`                                     | Label fixed width                                                                                | -             |
| wrapperWidth   | `number \| string`                                     | Content fixed width                                                                              | -             |
| labelCol       | number                                                 | The number of columns occupied by the label grid, and the number of content columns add up to 24 | -             |
| wrapperCol     | number                                                 | The number of columns occupied by the content grid, and the number of label columns add up to 24 | -             |
| wrapperAlign   | `"left"` \| `"right"`                                  | Content text alignment ⻬                                                                        | `"left"`      |
| wrapperWrap    | boolean                                                | Change the content, otherwise an ellipsis appears, and hover has tooltip                         | false         |
| fullness       | boolean                                                | fullness                                                                                         | true          |
| addonBefore    | ReactNode                                              | Prefix content                                                                                   | -             |
| addonAfter     | ReactNode                                              | Suffix content                                                                                   | -             |
| size           | `"small"` \| `"default"` \| `"large"`                  | 尺⼨                                                                                             | -             |
| inset          | boolean                                                | Is it an inline layout                                                                           | false         |
| extra          | ReactNode                                              | Extended description script                                                                      | -             |
| feedbackText   | ReactNode                                              | Feedback Case                                                                                    | -             |
| feedbackLayout | `"loose"` \| `"terse"` \| `"popover" \| "none"`        | Feedback layout                                                                                  | -             |
| feedbackStatus | `"error"` \| `"warning"` \| `"success"` \| `"pending"` | Feedback layout                                                                                  | -             |
| feedbackIcon   | ReactNode                                              | Feedback icon                                                                                    | -             |
| asterisk       | boolean                                                | Asterisk reminder                                                                                | -             |
| gridSpan       | number                                                 | Grid layout occupies width                                                                       | -             |
| bordered       | boolean                                                | Is there a border                                                                                | -             |

### FormItem.BaseItem

Pure style components, the properties are the same as FormItem, and Formily Core does not do state bridging. It is mainly used for scenarios that need to rely on the style layout capabilities of FormItem but do not want to access the Field state.

```
Page 29/35FirstPrevNextLast