#
tokens: 48088/50000 9/1152 files (page 24/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 24 of 52. Use http://codebase.md/alibaba/formily?lines=true&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

--------------------------------------------------------------------------------
/docs/guide/upgrade.md:
--------------------------------------------------------------------------------

```markdown
  1 | # V2 Upgrade Guide
  2 | 
  3 | It is important to mention here that Formily2 is very different from Formily1.x, and there are a lot of Break Changes.
  4 | 
  5 | Therefore, for old users, they basically need to learn again, and V1 and V2 cannot be upgraded smoothly.
  6 | 
  7 | But the original intention of the Formily2 project is to reduce everyone's learning costs, because the old users themselves have a certain understanding of Formily's core ideas. In order to help old users learn Formily2 more quickly, this article will list the core differences between V1 and V2. , and will not list the new capabilities.
  8 | 
  9 | ## Kernel Difference
 10 | 
 11 | > This mainly refers to the difference between @formily/core
 12 | 
 13 | Because Formily1.x users mainly use setFieldState/setFormState and getFieldState/getFormState when using the core APIs, these APIs are retained in V2, but the internal model properties are semantically different. The differences are as follows:
 14 | 
 15 | **modified**
 16 | 
 17 | - V1: Represent whether the field has been changed, in fact, it is of no use, because the initialization of the field means that it has been changed.
 18 | - V2: Indicates whether the field is manually modified, that is, it will be set to true when the component triggers the onChange event.
 19 | 
 20 | **inputed**
 21 | 
 22 | - V1: Represent Whether the field has been manually modified
 23 | - V2: Remove, use modified uniformly
 24 | 
 25 | **pristine**
 26 | 
 27 | - V1:Represent whether the field value is equal to initialValue
 28 | - V2: Remove, user manual judgment, this attribute will cause a lot of dirty checks
 29 | 
 30 | **display**
 31 | 
 32 | - V1: Represent whether the field is displayed, if it is false, the field value will not be removed
 33 | - V2: Represent the field display mode, the value is `"none" | "visible" | "hidden"`
 34 | 
 35 | **touched**
 36 | 
 37 | - V1: Redundant field
 38 | - V2: Remove
 39 | 
 40 | **validating**
 41 | 
 42 | - V1: Whether the representative field is being verified
 43 | - V2: Remove, use validateStatus uniformly
 44 | 
 45 | **effectErrors/effectWarnings**
 46 | 
 47 | - V1: Errors and warnings that represent the manual operation of the user
 48 | - V2: Remove, use feedbacks uniformly
 49 | 
 50 | **ruleErrors/ruleWarnings**
 51 | 
 52 | - V1: Errors and warnings representing the verification operation of the validator
 53 | - V2: Remove, use feedbacks uniformly
 54 | 
 55 | **values**
 56 | 
 57 | - V1: Represent all the parameters returned by the onChange event
 58 | - V2: Remove, use inputValues uniformly
 59 | 
 60 | **rules**
 61 | 
 62 | - V1: Represent verification rules
 63 | - V2: Remove, use validator uniformly, because rules literally means rules, but the meaning of rules is very big, not limited to verification rules
 64 | 
 65 | **props**
 66 | 
 67 | - V1: Represent the extended attributes of the component, and the positioning is very unclear. In the pure JSX scenario, it represents the collection of component attributes and FormItem attributes. In the Schema scenario, it represents the attributes of the Schema field.
 68 | - V2: Remove, use decorator and component uniformly
 69 | 
 70 | **VirtualField**
 71 | 
 72 | - V1: Represents a virtual field
 73 | - V2: Renamed and use [VoidField](https://core.formilyjs.org/api/models/void-field) uniformly
 74 | 
 75 | ## Bridge layer differences
 76 | 
 77 | > This mainly refers to the difference between @formily/react and @formily/react-schema-renderer.
 78 | 
 79 | **createFormActions/createAsyncFormActions**
 80 | 
 81 | - V1 Create a Form operator, you can call the setFieldState/setFormState method.
 82 | - V2 is removed, and the operation status of the Form instance created by [createForm](https://core.formilyjs.org/api/entry/create-form) in @formily/core is used uniformly.
 83 | 
 84 | **Form**
 85 | 
 86 | - V1 will create a Form instance inside, which can control the transfer of values/initialValues attributes, etc.
 87 | - V2 removed, unified use of [FormProvider](https://react.formilyjs.org/api/components/form-provider)
 88 | 
 89 | **SchemaForm**
 90 | 
 91 | - V1 will parse the json-schema protocol internally, create a Form instance, support controlled mode, and render it.
 92 | - V2 is removed, the SchemaField component created by [createSchemaField](https://react.formilyjs.org/api/components/schema-field) is used uniformly, and the controlled mode is not supported.
 93 | 
 94 | **Field**
 95 | 
 96 | - V1 supports controlled mode, which requires the use of render props for component state mapping.
 97 | - V2 does not support controlled mode, you can quickly implement state mapping by passing in the decorator/component property.
 98 | 
 99 | **VirtualField**
100 | 
101 | - V1 supports controlled mode, which requires the use of render props for component state mapping.
102 | - V2 does not support controlled mode, renamed [VoidField](https://react.formilyjs.org/api/components/void-field), and passed in the decorator/component property to quickly implement state mapping.
103 | 
104 | **FieldList**
105 | 
106 | - V1 Represent auto-incremented field control component
107 | - V2 Renamed to [ArrayField](https://react.formilyjs.org/api/components/array-field)
108 | 
109 | **FormSpy**
110 | 
111 | - V1 Monitor all life cycle triggers and re-render
112 | - V2 Remove and use [FormConsumer](https://react.formilyjs.org/api/components/form-consumer)
113 | 
114 | **SchemaMarkupField**
115 | 
116 | - V1 Stands for Schema description label component
117 | - V2 Remove, unified use the description label component created by the [createSchemaField](https://react.formilyjs.org/api/components/schema-field)
118 | 
119 | **useFormQuery**
120 | 
121 | - V1 Fast Hook for realizing form query, supporting middleware mechanism
122 | - V2 Temporarily remove
123 | 
124 | **useForm**
125 | 
126 | - V1 Represents the creation of a Form instance
127 | - V2 Represents the Form instance in the consumption context, if you want to create it, please use [createForm](https://react.formilyjs.org/api/entry/create-form)
128 | 
129 | **useField**
130 | 
131 | - V1 Represents the creation of a Field instance
132 | - V2 Represents the Field instance in the consumption context, if you want to create it, please call [form.createField](https://core.formilyjs.org/api/models/form#createfield)
133 | 
134 | **useVirtualField**
135 | 
136 | - V1 Represents the creation of a VirtualField instance
137 | - V2 Remove, if you want to create, please call [form.createVoidField](https://core.formilyjs.org/api/models/form#createvoidfield)
138 | 
139 | **useFormState**
140 | 
141 | - V1 Form state in consumption context
142 | - V2 Remove, use [useForm](https://react.formilyjs.org/api/hooks/use-form) uniformly
143 | 
144 | **useFieldState**
145 | 
146 | - V1 consume Field status in context
147 | - V2 Remove, use [useField](https://react.formilyjs.org/api/hooks/use-field)
148 | 
149 | **useFormSpy**
150 | 
151 | - V1 Create a lifecycle listener and trigger a re-render
152 | - V2 Remove
153 | 
154 | **useSchemaProps**
155 | 
156 | - V1Cconsume rops of SchemaField in context
157 | - V2 Remove, use [useFieldSchema](https://react.formilyjs.org/api/hooks/use-field-schema) uniformly
158 | 
159 | **connect**
160 | 
161 | - V1 Standard HOC
162 | - V2 The higher-order function is changed to 1st order, and the properties have changed dramatically. See the [connect document](https://react.formilyjs.org/api/shared/connect) for details
163 | 
164 | **registerFormField/registerVirtaulBox/registerFormComponent/registerFormItemComponent**
165 | 
166 | - V1 Globally registered components
167 | - V2 Remove, global registration is no longer supported
168 | 
169 | **FormEffectHooks**
170 | 
171 | - V1 RxJS lifecycle hook
172 | - V2 Remove, export from @formily/core uniformly, and will not return RxJS Observable object
173 | 
174 | **effects**
175 | 
176 | - V1 Support callback function`$` selector
177 | - V2 Remove`$`selector
178 | 
179 | ## Protocol layer differences
180 | 
181 | > This mainly refers to the difference in the JSON Schema protocol
182 | 
183 | **editable**
184 | 
185 | - V1 is directly in the Schema description, indicating whether the field can be edited
186 | - V2 Renamed x-editable
187 | 
188 | **visible**
189 | 
190 | - V1 Indicates whether the field is displayed
191 | - V2 Renamed x-visible
192 | 
193 | **display**
194 | 
195 | - V1 Represent whether the field is displayed or not, if it is false, it represents the hidden behavior without deleting the value
196 | - V2 Renamed x-display, which represents the field display mode, and the value is`"none" | "visible" | "hidden"`
197 | 
198 | **triggerType**
199 | 
200 | - V1 Represent the field verification timing
201 | - V2 Remove, please use`x-validator:[{triggerType:"onBlur",validator:()=>...}]`
202 | 
203 | **x-props**
204 | 
205 | - V1 Represents the FormItem property
206 | - V2 Remove, please use x-decorator-props
207 | 
208 | **x-rules**
209 | 
210 | - V1 Represent field verification rules
211 | - V2 Renamed x-validator
212 | 
213 | **x-linkages**
214 | 
215 | - V1 Represent field linkage
216 | - V2 Remove, use x-reactions uniformly
217 | 
218 | **x-mega-props**
219 | 
220 | - V1 Represent the sub-component properties of the MegaLayout component
221 | - V2 Remove
222 | 
223 | ## Component library differences
224 | 
225 | In Formily 1.x, we mainly use @formily/antd and @formily/antd-components, or @formily/next and @formily/next-components.
226 | 
227 | In V2, we have the following changes:
228 | 
229 | - @formily/antd and @formily/antd-components were merged into @formily/antd, and the directory structure was changed to that of a pure component library.
230 | 
231 | - The internal API of @formily/react @formily/core will no longer be exported.
232 | - Almost all components have been rewritten and cannot be smoothly upgraded.
233 | - Remove styled-components.
234 | 
```

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

```markdown
  1 | # Space
  2 | 
  3 | > Super convenient Flex layout component, can help users quickly realize the layout of any element side by side next to each other
  4 | 
  5 | ## Markup Schema example
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   Input,
 11 |   FormItem,
 12 |   FormLayout,
 13 |   FormButtonGroup,
 14 |   Submit,
 15 |   Space,
 16 | } from '@formily/next'
 17 | import { createForm } from '@formily/core'
 18 | import { FormProvider, createSchemaField } from '@formily/react'
 19 | 
 20 | const SchemaField = createSchemaField({
 21 |   components: {
 22 |     Input,
 23 |     FormItem,
 24 |     Space,
 25 |   },
 26 | })
 27 | 
 28 | const form = createForm()
 29 | 
 30 | export default () => (
 31 |   <FormProvider form={form}>
 32 |     <FormLayout labelCol={6} wrapperCol={16}>
 33 |       <SchemaField>
 34 |         <SchemaField.Void
 35 |           title="name"
 36 |           x-decorator="FormItem"
 37 |           x-decorator-props={{
 38 |             asterisk: true,
 39 |             feedbackLayout: 'none',
 40 |           }}
 41 |           x-component="Space"
 42 |         >
 43 |           <SchemaField.String
 44 |             name="firstName"
 45 |             x-decorator="FormItem"
 46 |             x-component="Input"
 47 |             required
 48 |           />
 49 |           <SchemaField.String
 50 |             name="lastName"
 51 |             x-decorator="FormItem"
 52 |             x-component="Input"
 53 |             x-visible="{{$values.firstName === '123'}}"
 54 |             required
 55 |           />
 56 |           <SchemaField.String
 57 |             name="kk"
 58 |             x-decorator="FormItem"
 59 |             x-component="Input"
 60 |             x-decorator-props={{
 61 |               addonAfter: 'Unit',
 62 |             }}
 63 |             required
 64 |           />
 65 |         </SchemaField.Void>
 66 |         <SchemaField.Void
 67 |           title="Text concatenation"
 68 |           x-decorator="FormItem"
 69 |           x-decorator-props={{
 70 |             asterisk: true,
 71 |             feedbackLayout: 'none',
 72 |           }}
 73 |           x-component="Space"
 74 |         >
 75 |           <SchemaField.String
 76 |             name="aa"
 77 |             x-decorator="FormItem"
 78 |             x-component="Input"
 79 |             x-decorator-props={{
 80 |               addonAfter: 'Unit',
 81 |             }}
 82 |             required
 83 |           />
 84 |           <SchemaField.String
 85 |             name="bb"
 86 |             x-decorator="FormItem"
 87 |             x-component="Input"
 88 |             x-decorator-props={{
 89 |               addonAfter: 'Unit',
 90 |             }}
 91 |             required
 92 |           />
 93 |           <SchemaField.String
 94 |             name="cc"
 95 |             x-decorator="FormItem"
 96 |             x-component="Input"
 97 |             x-decorator-props={{
 98 |               addonAfter: 'Unit',
 99 |             }}
100 |             required
101 |           />
102 |         </SchemaField.Void>
103 |         <SchemaField.String
104 |           name="textarea"
105 |           title="text box"
106 |           x-decorator="FormItem"
107 |           required
108 |           x-component="Input.TextArea"
109 |           x-component-props={{
110 |             style: {
111 |               width: 400,
112 |             },
113 |           }}
114 |         />
115 |       </SchemaField>
116 |       <FormButtonGroup.FormItem>
117 |         <Submit onSubmit={console.log}>Submit</Submit>
118 |       </FormButtonGroup.FormItem>
119 |     </FormLayout>
120 |   </FormProvider>
121 | )
122 | ```
123 | 
124 | ## JSON Schema case
125 | 
126 | ```tsx
127 | import React from 'react'
128 | import {
129 |   Input,
130 |   FormItem,
131 |   FormLayout,
132 |   FormButtonGroup,
133 |   Submit,
134 |   Space,
135 | } from '@formily/next'
136 | import { createForm } from '@formily/core'
137 | import { FormProvider, createSchemaField } from '@formily/react'
138 | 
139 | const SchemaField = createSchemaField({
140 |   components: {
141 |     Input,
142 |     FormItem,
143 |     Space,
144 |   },
145 | })
146 | 
147 | const form = createForm()
148 | 
149 | const schema = {
150 |   type: 'object',
151 |   properties: {
152 |     name: {
153 |       type: 'void',
154 |       title: 'Name',
155 |       'x-decorator': 'FormItem',
156 |       'x-decorator-props': {
157 |         asterisk: true,
158 |         feedbackLayout: 'none',
159 |       },
160 |       'x-component': 'Space',
161 |       properties: {
162 |         firstName: {
163 |           type: 'string',
164 |           'x-decorator': 'FormItem',
165 |           'x-component': 'Input',
166 |           required: true,
167 |         },
168 |         lastName: {
169 |           type: 'string',
170 |           'x-decorator': 'FormItem',
171 |           'x-component': 'Input',
172 |           required: true,
173 |         },
174 |       },
175 |     },
176 |     texts: {
177 |       type: 'void',
178 |       title: 'Text concatenation',
179 |       'x-decorator': 'FormItem',
180 |       'x-decorator-props': {
181 |         asterisk: true,
182 |         feedbackLayout: 'none',
183 |       },
184 |       'x-component': 'Space',
185 |       properties: {
186 |         aa: {
187 |           type: 'string',
188 |           'x-decorator': 'FormItem',
189 |           'x-decorator-props': {
190 |             addonAfter: 'Unit',
191 |           },
192 |           'x-component': 'Input',
193 |           required: true,
194 |         },
195 |         bb: {
196 |           type: 'string',
197 |           'x-decorator': 'FormItem',
198 |           'x-decorator-props': {
199 |             addonAfter: 'Unit',
200 |           },
201 |           'x-component': 'Input',
202 |           required: true,
203 |         },
204 |         cc: {
205 |           type: 'string',
206 |           'x-decorator': 'FormItem',
207 |           'x-decorator-props': {
208 |             addonAfter: 'Unit',
209 |           },
210 |           'x-component': 'Input',
211 |           required: true,
212 |         },
213 |       },
214 |     },
215 | 
216 |     textarea: {
217 |       type: 'string',
218 |       title: 'Text box',
219 |       'x-decorator': 'FormItem',
220 |       'x-component': 'Input.TextArea',
221 |       'x-component-props': {
222 |         style: {
223 |           width: 400,
224 |         },
225 |       },
226 |       required: true,
227 |     },
228 |   },
229 | }
230 | 
231 | export default () => (
232 |   <FormProvider form={form}>
233 |     <FormLayout labelCol={6} wrapperCol={16}>
234 |       <SchemaField schema={schema} />
235 |       <FormButtonGroup.FormItem>
236 |         <Submit onSubmit={console.log}>Submit</Submit>
237 |       </FormButtonGroup.FormItem>
238 |     </FormLayout>
239 |   </FormProvider>
240 | )
241 | ```
242 | 
243 | ## Pure JSX case
244 | 
245 | ```tsx
246 | import React from 'react'
247 | import {
248 |   Input,
249 |   FormItem,
250 |   FormLayout,
251 |   FormButtonGroup,
252 |   Submit,
253 |   Space,
254 | } from '@formily/next'
255 | import { createForm } from '@formily/core'
256 | import { FormProvider, Field, VoidField } from '@formily/react'
257 | 
258 | const form = createForm()
259 | 
260 | export default () => (
261 |   <FormProvider form={form}>
262 |     <FormLayout labelCol={6} wrapperCol={16}>
263 |       <VoidField
264 |         name="name"
265 |         title="name"
266 |         decorator={[
267 |           FormItem,
268 |           {
269 |             asterisk: true,
270 |             feedbackLayout: 'none',
271 |           },
272 |         ]}
273 |         component={[Space]}
274 |       >
275 |         <Field
276 |           name="firstName"
277 |           decorator={[FormItem]}
278 |           component={[Input]}
279 |           required
280 |         />
281 |         <Field
282 |           name="lastName"
283 |           decorator={[FormItem]}
284 |           component={[Input]}
285 |           required
286 |         />
287 |       </VoidField>
288 |       <VoidField
289 |         name="texts"
290 |         title="Text concatenation"
291 |         decorator={[
292 |           FormItem,
293 |           {
294 |             asterisk: true,
295 |             feedbackLayout: 'none',
296 |           },
297 |         ]}
298 |         component={[Space]}
299 |       >
300 |         <Field
301 |           name="aa"
302 |           decorator={[
303 |             FormItem,
304 |             {
305 |               addonAfter: 'Unit',
306 |             },
307 |           ]}
308 |           component={[Input]}
309 |           required
310 |         />
311 |         <Field
312 |           name="bb"
313 |           decorator={[
314 |             FormItem,
315 |             {
316 |               addonAfter: 'Unit',
317 |             },
318 |           ]}
319 |           component={[Input]}
320 |           required
321 |         />
322 |         <Field
323 |           name="cc"
324 |           decorator={[
325 |             FormItem,
326 |             {
327 |               addonAfter: 'Unit',
328 |             },
329 |           ]}
330 |           component={[Input]}
331 |           required
332 |         />
333 |       </VoidField>
334 |       <Field
335 |         name="textarea"
336 |         title="text box"
337 |         decorator={[FormItem]}
338 |         component={[
339 |           Input.TextArea,
340 |           {
341 |             style: {
342 |               width: 400,
343 |             },
344 |           },
345 |         ]}
346 |         required
347 |       />
348 |       <FormButtonGroup.FormItem>
349 |         <Submit onSubmit={console.log}>Submit</Submit>
350 |       </FormButtonGroup.FormItem>
351 |     </FormLayout>
352 |   </FormProvider>
353 | )
354 | ```
355 | 
356 | ## API
357 | 
358 | | Property name | Type                                      | Description     | Default value |
359 | | ------------- | ----------------------------------------- | --------------- | ------------- |
360 | | style         | CSSProperties                             | Style           | -             |
361 | | className     | string                                    | class name      | -             |
362 | | prefix        | string                                    | style prefix    | true          |
363 | | size          | `number \|'small' \|'large' \|'middle'`   | interval size   | 8px           |
364 | | direction     | `'horizontal' \|'vertical'`               | direction       | -             |
365 | | align         | `'start' \|'end' \|'center' \|'baseline'` | align           | `'start'`     |
366 | | wrap          | boolean                                   | Whether to wrap | false         |
367 | 
```

--------------------------------------------------------------------------------
/packages/next/src/form-item/main.scss:
--------------------------------------------------------------------------------

```scss
  1 | @import '~@alifd/next/lib/core/index-noreset.scss';
  2 | @import './scss/variable.scss';
  3 | @import './grid.scss';
  4 | @import './animation.scss';
  5 | 
  6 | .#{$form-item-cls} {
  7 |   display: flex;
  8 |   margin-bottom: $form-item-m-margin-b + 2;
  9 |   position: relative;
 10 |   line-height: $form-element-medium-height;
 11 |   font-size: $form-element-medium-font-size;
 12 | 
 13 |   &-layout-vertical {
 14 |     display: block;
 15 |   }
 16 | 
 17 |   &-label-content {
 18 |     min-height: $form-element-medium-height;
 19 |   }
 20 | 
 21 |   &-control-content-component {
 22 |     line-height: $form-element-medium-height;
 23 |   }
 24 | 
 25 |   &-inset {
 26 |     padding: 0 8px;
 27 |     border: 1px solid $input-border-color;
 28 |     border-radius: $form-element-medium-corner;
 29 |     width: 100%;
 30 | 
 31 |     .#{$css-prefix}input {
 32 |       border: none !important;
 33 |       box-shadow: none !important;
 34 |       outline: none;
 35 |     }
 36 |   }
 37 | 
 38 |   &-bordered-none:not(.#{$form-item-cls}-inset) {
 39 |     .#{$css-prefix}input {
 40 |       border: none !important;
 41 |       box-shadow: none !important;
 42 |       outline: none;
 43 |     }
 44 |   }
 45 | }
 46 | 
 47 | .#{$form-item-cls}-label {
 48 |   position: relative;
 49 |   display: flex;
 50 |   &-content {
 51 |     overflow: hidden;
 52 |     text-overflow: ellipsis;
 53 |     white-space: nowrap;
 54 |   }
 55 | 
 56 |   &-tooltip {
 57 |     cursor: help;
 58 | 
 59 |     .#{$form-item-cls}-colon {
 60 |       display: flex;
 61 |     }
 62 | 
 63 |     * {
 64 |       cursor: help;
 65 |     }
 66 | 
 67 |     &-colon {
 68 |       cursor: help;
 69 |     }
 70 | 
 71 |     label {
 72 |       border-bottom: 1px dashed currentColor;
 73 |     }
 74 |   }
 75 | }
 76 | 
 77 | .#{$form-item-cls}-label label {
 78 |   cursor: text;
 79 |   color: rgba(0, 0, 0, 0.85);
 80 | }
 81 | 
 82 | .#{$form-item-cls}-label-align-left {
 83 |   > .#{$form-item-cls}-label {
 84 |     justify-content: flex-start;
 85 |   }
 86 | }
 87 | 
 88 | .#{$form-item-cls}-label-align-right {
 89 |   > .#{$form-item-cls}-label {
 90 |     justify-content: flex-end;
 91 |   }
 92 | }
 93 | 
 94 | .#{$form-item-cls}-label-wrap {
 95 |   .#{$form-item-cls}-label {
 96 |     label {
 97 |       white-space: pre-line;
 98 |       word-break: break-all;
 99 |     }
100 |   }
101 | }
102 | 
103 | .#{$form-item-cls}-feedback-layout-terse {
104 |   margin-bottom: 8px;
105 | 
106 |   &.#{$form-item-cls}-feedback-has-text:not(.#{$form-item-cls}-inset) {
107 |     margin-bottom: 0;
108 |   }
109 | }
110 | 
111 | .#{$form-item-cls}-feedback-layout-loose {
112 |   margin-bottom: $form-item-m-margin-b + 4;
113 | 
114 |   &.#{$form-item-cls}-feedback-has-text:not(.#{$form-item-cls}-inset) {
115 |     margin-bottom: 0;
116 |   }
117 | }
118 | 
119 | .#{$form-item-cls}-feedback-layout-none {
120 |   margin-bottom: 0px;
121 | 
122 |   &.#{$form-item-cls}-feedback-has-text:not(.#{$form-item-cls}-inset) {
123 |     margin-bottom: 0;
124 |   }
125 | }
126 | 
127 | .#{$form-item-cls}-control {
128 |   flex: 1;
129 |   max-width: 100%;
130 | 
131 |   .#{$form-item-cls}-control-content {
132 |     display: flex;
133 | 
134 |     .#{$form-item-cls}-control-content-component {
135 |       width: 100%;
136 |       min-height: $form-element-medium-height;
137 |       line-height: $form-element-medium-height;
138 | 
139 |       &-has-feedback-icon {
140 |         flex: 1;
141 |         position: relative;
142 |         display: flex;
143 |         align-items: center;
144 | 
145 |         .#{$css-prefix}input {
146 |           height: 100%;
147 |           border: none !important;
148 |           box-shadow: none !important;
149 |           outline: none;
150 | 
151 |           .#{$css-prefix}input-control {
152 |             margin-right: 0;
153 |             padding-right: 0;
154 | 
155 |             .#{$css-prefix}icon {
156 |               display: none;
157 |             }
158 | 
159 |             .#{$css-prefix}input-hint-wrap {
160 |               .#{$css-prefix}icon {
161 |                 display: block;
162 |               }
163 |             }
164 |           }
165 |         }
166 |       }
167 | 
168 |       .#{$css-prefix}range {
169 |         height: 100%;
170 |         padding-left: 2px;
171 |       }
172 | 
173 |       .#{$css-prefix}transfer {
174 |         display: flex;
175 |         align-items: center;
176 |       }
177 |     }
178 | 
179 |     .#{$form-item-cls}-addon-before {
180 |       margin-right: 8px;
181 |       display: inline-flex;
182 |       align-items: center;
183 |       min-height: $form-element-medium-height;
184 |       flex-shrink: 0;
185 |     }
186 | 
187 |     .#{$form-item-cls}-addon-after {
188 |       margin-left: 8px;
189 |       display: inline-flex;
190 |       align-items: center;
191 |       min-height: $form-element-medium-height;
192 |       flex-shrink: 0;
193 |     }
194 |   }
195 | }
196 | 
197 | .#{$form-item-cls}-size-small {
198 |   font-size: $form-element-small-font-size;
199 |   line-height: $form-element-small-height;
200 | 
201 |   .#{$form-item-cls}-label-content {
202 |     min-height: $form-element-small-height;
203 |   }
204 | 
205 |   .#{$form-item-cls}-control-content {
206 |     .#{$form-item-cls}-control-content-component {
207 |       line-height: $form-element-small-height;
208 |       min-height: $form-element-small-height;
209 |     }
210 | 
211 |     .#{$form-item-cls}-addon-before {
212 |       min-height: $form-element-small-height;
213 |     }
214 | 
215 |     .#{$form-item-cls}-addon-after {
216 |       min-height: $form-element-small-height;
217 |     }
218 |   }
219 | 
220 |   &-inset {
221 |     border-radius: $form-element-small-corner;
222 |   }
223 | 
224 |   &.#{$form-item-cls}-feedback-layout-terse {
225 |     margin-bottom: 8px;
226 | 
227 |     &.#{$form-item-cls}-feedback-has-text:not(.#{$form-item-cls}-inset) {
228 |       margin-bottom: 0;
229 |     }
230 |   }
231 | 
232 |   &.#{$form-item-cls}-feedback-layout-loose {
233 |     margin-bottom: $form-item-s-margin-b + 8;
234 | 
235 |     &.#{$form-item-cls}-feedback-has-text:not(.#{$form-item-cls}-inset) {
236 |       margin-bottom: 0;
237 |     }
238 |   }
239 | 
240 |   .#{$form-item-cls}-help,
241 |   .#{$form-item-cls}-extra {
242 |     min-height: $form-element-small-font-size + 2;
243 |   }
244 | 
245 |   .#{$form-item-cls}-control-content {
246 |     min-height: $form-element-small-height;
247 |   }
248 | 
249 |   .#{$form-item-cls}-label > label {
250 |     height: $form-element-small-height;
251 |   }
252 | }
253 | 
254 | .#{$form-item-cls}-size-large {
255 |   font-size: $form-element-large-font-size;
256 |   line-height: $form-element-large-height;
257 | 
258 |   .#{$form-item-cls}-label-content {
259 |     min-height: $form-element-large-height;
260 |   }
261 | 
262 |   .#{$form-item-cls}-control-content {
263 |     .#{$form-item-cls}-control-content-component {
264 |       line-height: $form-element-large-height;
265 |       min-height: $form-element-large-height;
266 |     }
267 | 
268 |     .#{$form-item-cls}-addon-before {
269 |       min-height: $form-element-large-height;
270 |     }
271 | 
272 |     .#{$form-item-cls}-addon-after {
273 |       min-height: $form-element-large-height;
274 |     }
275 |   }
276 | 
277 |   &-inset {
278 |     border-radius: $form-element-large-corner;
279 |   }
280 | 
281 |   .#{$form-item-cls}-help,
282 |   .#{$form-item-cls}-extra {
283 |     min-height: $form-element-large-font-size + 2;
284 |   }
285 | 
286 |   &.#{$form-item-cls}-feedback-layout-loose {
287 |     margin-bottom: $form-item-l-margin-b;
288 | 
289 |     &.#{$form-item-cls}-feedback-has-text:not(.#{$form-item-cls}-inset) {
290 |       margin-bottom: 0;
291 |     }
292 |   }
293 | 
294 |   .#{$form-item-cls}-control-content {
295 |     min-height: $form-element-large-height;
296 |   }
297 | 
298 |   .#{$form-item-cls}-label > label {
299 |     height: $form-element-large-height;
300 |   }
301 | }
302 | 
303 | .#{$form-item-cls}-feedback-layout-popover {
304 |   margin-bottom: 8px;
305 | }
306 | 
307 | .#{$form-item-cls}-label-tooltip-icon {
308 |   margin-left: 4px;
309 |   color: #00000073;
310 |   cursor: pointer;
311 |   max-height: $form-element-medium-height;
312 | }
313 | 
314 | .#{$form-item-cls}-control-align-left {
315 |   .#{$form-item-cls}-control-content {
316 |     justify-content: flex-start;
317 |   }
318 | }
319 | 
320 | .#{$form-item-cls}-control-align-right {
321 |   .#{$form-item-cls}-control-content {
322 |     justify-content: flex-end;
323 |   }
324 | }
325 | 
326 | .#{$form-item-cls}-control-wrap {
327 |   .#{$form-item-cls}-control {
328 |     white-space: pre-line;
329 |   }
330 | }
331 | 
332 | .#{$form-item-cls}-asterisk {
333 |   color: $form-error-color;
334 |   margin-right: 4px;
335 |   display: inline-block;
336 |   font-family: SimSun, sans-serif;
337 | }
338 | 
339 | .#{$form-item-cls}-colon {
340 |   margin-left: 2px;
341 |   margin-right: 8px;
342 | }
343 | 
344 | .#{$form-item-cls}-help,
345 | .#{$form-item-cls}-extra {
346 |   clear: both;
347 |   line-height: $form-item-m-margin-b + 4;
348 |   min-height: $form-item-m-margin-b;
349 |   color: rgba(0, 0, 0, 0.45);
350 |   transition: color 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);
351 |   padding-top: 0px;
352 | }
353 | 
354 | .#{$form-item-cls}-fullness {
355 |   > .#{$form-item-cls}-control {
356 |     > .#{$form-item-cls}-control-content {
357 |       > .#{$form-item-cls}-control-content-component {
358 |         > *:first-child:not(.#{$css-prefix}switch):not(.#{$css-prefix}icon):not(.#{$css-prefix}formily-icon):not(.anticon):not(.#{$css-prefix}btn-text) {
359 |           width: 100%;
360 |         }
361 |       }
362 |     }
363 |   }
364 | }
365 | 
366 | .#{$form-item-cls}-control-content-component-has-feedback-icon {
367 |   border-radius: 2px;
368 |   border: 1px solid $input-border-color;
369 |   transition: all 0.3s;
370 |   touch-action: manipulation;
371 |   outline: none;
372 |   padding-right: 8px;
373 | 
374 |   .#{$css-prefix}input {
375 |     border: none !important;
376 |   }
377 | 
378 |   .#{$css-prefix}range-picker-trigger {
379 |     border: none !important;
380 |   }
381 | 
382 |   .#{$form-item-cls}-feedback-icon {
383 |     display: flex;
384 |     justify-content: center;
385 |     align-items: center;
386 |     margin-right: -2px;
387 |     padding-left: 2px;
388 | 
389 |     .anticon {
390 |       display: inline-block;
391 |       color: inherit;
392 |       font-style: normal;
393 |       font-size: $form-element-medium-font-size;
394 |       line-height: 0;
395 |       text-align: center;
396 |       text-transform: none;
397 |       vertical-align: -0.125em;
398 |       text-rendering: optimizeLegibility;
399 |     }
400 |   }
401 | }
402 | 
403 | .#{$form-item-cls}-error-help {
404 |   color: $form-error-color;
405 | }
406 | 
407 | .#{$form-item-cls}-warning-help {
408 |   color: $form-warning-color;
409 | }
410 | 
411 | .#{$form-item-cls}-success-help {
412 |   color: $form-success-color;
413 | }
414 | 
```

--------------------------------------------------------------------------------
/packages/reactive/src/__tests__/annotations.spec.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { observable, action, model, define } from '../'
  2 | import { autorun, reaction } from '../autorun'
  3 | import { observe } from '../observe'
  4 | import { isObservable } from '../externals'
  5 | import { untracked } from '../untracked'
  6 | import { getObservableMaker } from '../internals'
  7 | 
  8 | test('observable annotation', () => {
  9 |   const obs = observable<any>({
 10 |     aa: 111,
 11 |   })
 12 |   const handler = jest.fn()
 13 |   const handler1 = jest.fn()
 14 |   observe(obs, handler1)
 15 |   reaction(() => {
 16 |     handler(obs.aa)
 17 |   })
 18 |   obs.aa = { bb: { cc: 123 } }
 19 |   obs.aa.bb = 333
 20 |   expect(handler).toBeCalledTimes(2)
 21 |   expect(handler1).toBeCalledTimes(2)
 22 | 
 23 |   const handler2 = jest.fn()
 24 |   const handler3 = jest.fn()
 25 |   const obsAnno = getObservableMaker(observable)({ value: obs })
 26 | 
 27 |   observe(obsAnno, handler2)
 28 |   reaction(() => {
 29 |     handler3(obsAnno.aa)
 30 |   })
 31 |   obsAnno.aa = { bb: { cc: 123 } }
 32 |   obsAnno.aa.bb = 333
 33 |   expect(handler2).toBeCalledTimes(2)
 34 |   expect(handler3).toBeCalledTimes(2)
 35 | })
 36 | 
 37 | test('shallow annotation', () => {
 38 |   const obs = observable.shallow<any>({
 39 |     aa: 111,
 40 |   })
 41 |   const handler = jest.fn()
 42 |   const handler1 = jest.fn()
 43 |   observe(obs, handler1)
 44 |   reaction(() => {
 45 |     handler(obs.aa)
 46 |   })
 47 |   obs.aa = { bb: { cc: 123 } }
 48 |   expect(isObservable(obs)).toBe(true)
 49 |   expect(isObservable(obs.aa)).toBe(false)
 50 |   expect(isObservable(obs.aa.bb)).toBe(false)
 51 |   obs.aa.bb = 333
 52 |   obs.cc = 444
 53 |   expect(handler).toBeCalledTimes(2)
 54 |   expect(handler1).toBeCalledTimes(2)
 55 | })
 56 | 
 57 | test('box annotation', () => {
 58 |   const obs = observable.box(123)
 59 |   const handler = jest.fn()
 60 |   const handler1 = jest.fn()
 61 |   observe(obs, handler1)
 62 |   reaction(() => {
 63 |     handler(obs.get())
 64 |   })
 65 |   const boxValue = 333
 66 |   obs.set(boxValue)
 67 |   expect(handler1).toBeCalledTimes(1)
 68 |   expect(handler1.mock.calls[0][0]).toMatchObject({
 69 |     value: boxValue,
 70 |   })
 71 |   expect(handler).toBeCalledTimes(2)
 72 |   expect(handler.mock.calls[0][0]).toBe(123)
 73 |   expect(handler.mock.calls[1][0]).toBe(boxValue)
 74 | })
 75 | 
 76 | test('ref annotation', () => {
 77 |   const obs = observable.ref(123)
 78 |   const handler = jest.fn()
 79 |   const handler1 = jest.fn()
 80 |   observe(obs, handler1)
 81 |   reaction(() => {
 82 |     handler(obs.value)
 83 |   })
 84 |   obs.value = 333
 85 |   expect(handler).nthCalledWith(1, 123)
 86 |   expect(handler).nthCalledWith(2, 333)
 87 |   expect(handler1).toBeCalledTimes(1)
 88 | })
 89 | 
 90 | test('action annotation', () => {
 91 |   const obs = observable<any>({})
 92 |   const setData = action.bound(() => {
 93 |     obs.aa = 123
 94 |     obs.bb = 321
 95 |   })
 96 |   const handler = jest.fn()
 97 |   reaction(() => {
 98 |     return [obs.aa, obs.bb]
 99 |   }, handler)
100 |   setData()
101 |   expect(handler).toBeCalledTimes(1)
102 |   expect(handler).toBeCalledWith([123, 321], [undefined, undefined])
103 | })
104 | 
105 | test('no action annotation', () => {
106 |   const obs = observable<any>({})
107 |   const setData = () => {
108 |     obs.aa = 123
109 |     obs.bb = 321
110 |   }
111 |   const handler = jest.fn()
112 |   reaction(() => {
113 |     return [obs.aa, obs.bb]
114 |   }, handler)
115 |   setData()
116 |   expect(handler).toBeCalledTimes(2)
117 |   expect(handler).nthCalledWith(1, [123, undefined], [undefined, undefined])
118 |   expect(handler).nthCalledWith(2, [123, 321], [123, undefined])
119 | })
120 | 
121 | test('computed annotation', () => {
122 |   const obs = observable({
123 |     aa: 11,
124 |     bb: 22,
125 |   })
126 |   const handler = jest.fn(() => obs.aa + obs.bb)
127 |   const runner1 = jest.fn()
128 |   const runner2 = jest.fn()
129 |   const runner3 = jest.fn()
130 |   const compu = observable.computed(handler)
131 |   expect(compu.value).toEqual(33)
132 |   expect(handler).toBeCalledTimes(1)
133 |   obs.aa = 22
134 |   expect(handler).toBeCalledTimes(1)
135 |   const dispose = autorun(() => {
136 |     compu.value
137 |     runner1()
138 |   })
139 |   const dispose2 = autorun(() => {
140 |     compu.value
141 |     runner2()
142 |   })
143 |   expect(compu.value).toEqual(44)
144 |   expect(handler).toBeCalledTimes(2)
145 |   obs.bb = 33
146 |   expect(runner1).toBeCalledTimes(2)
147 |   expect(runner2).toBeCalledTimes(2)
148 |   expect(handler).toBeCalledTimes(3)
149 |   expect(compu.value).toEqual(55)
150 |   expect(handler).toBeCalledTimes(3)
151 |   obs.aa = 11
152 |   expect(runner1).toBeCalledTimes(3)
153 |   expect(runner2).toBeCalledTimes(3)
154 |   expect(handler).toBeCalledTimes(4)
155 |   expect(compu.value).toEqual(44)
156 |   expect(handler).toBeCalledTimes(4)
157 |   dispose()
158 |   obs.aa = 22
159 |   expect(runner1).toBeCalledTimes(3)
160 |   expect(runner2).toBeCalledTimes(4)
161 |   expect(handler).toBeCalledTimes(5)
162 |   expect(compu.value).toEqual(55)
163 |   expect(handler).toBeCalledTimes(5)
164 |   dispose2()
165 |   obs.aa = 33
166 |   expect(runner1).toBeCalledTimes(3)
167 |   expect(runner2).toBeCalledTimes(4)
168 |   expect(handler).toBeCalledTimes(5)
169 |   expect(compu.value).toEqual(66)
170 |   expect(handler).toBeCalledTimes(6)
171 |   expect(compu.value).toEqual(66)
172 |   expect(handler).toBeCalledTimes(6)
173 |   autorun(() => {
174 |     compu.value
175 |     runner3()
176 |   })
177 |   expect(compu.value).toEqual(66)
178 |   expect(handler).toBeCalledTimes(6)
179 |   expect(compu.value).toEqual(66)
180 |   expect(handler).toBeCalledTimes(6)
181 |   obs.aa = 11
182 |   expect(handler).toBeCalledTimes(7)
183 |   expect(compu.value).toEqual(44)
184 |   expect(handler).toBeCalledTimes(7)
185 | })
186 | 
187 | test('computed chain annotation', () => {
188 |   const obs = observable({
189 |     aa: 11,
190 |     bb: 22,
191 |   })
192 |   const handler = jest.fn(() => obs.aa + obs.bb)
193 |   const compu1 = observable.computed(handler)
194 |   const handler1 = jest.fn(() => compu1.value + 33)
195 |   const compu2 = observable.computed(handler1)
196 |   const dispose = autorun(() => {
197 |     compu2.value
198 |   })
199 |   expect(handler).toBeCalledTimes(1)
200 |   expect(handler1).toBeCalledTimes(1)
201 |   expect(compu2.value).toEqual(66)
202 |   expect(handler).toBeCalledTimes(1)
203 |   expect(handler1).toBeCalledTimes(1)
204 |   obs.aa = 22
205 |   expect(handler).toBeCalledTimes(2)
206 |   expect(handler1).toBeCalledTimes(2)
207 |   expect(compu2.value).toEqual(77)
208 |   expect(handler).toBeCalledTimes(2)
209 |   expect(handler1).toBeCalledTimes(2)
210 |   dispose()
211 |   obs.aa = 11
212 |   expect(handler).toBeCalledTimes(2)
213 |   expect(handler1).toBeCalledTimes(2)
214 |   expect(compu2.value).toEqual(66)
215 |   expect(handler).toBeCalledTimes(3)
216 |   expect(handler1).toBeCalledTimes(3)
217 | })
218 | 
219 | test('computed with array length', () => {
220 |   const obs = model({
221 |     arr: [],
222 |     get isEmpty() {
223 |       return this.arr.length === 0
224 |     },
225 |     get isNotEmpty() {
226 |       return !this.isEmpty
227 |     },
228 |   })
229 |   const handler = jest.fn()
230 |   autorun(() => {
231 |     handler(obs.isEmpty)
232 |     handler(obs.isNotEmpty)
233 |   })
234 |   expect(handler).toBeCalledTimes(2)
235 |   obs.arr = ['1']
236 |   obs.arr = []
237 |   expect(handler).toBeCalledTimes(6)
238 | })
239 | 
240 | test('computed with computed array length', () => {
241 |   const obs = model({
242 |     arr: [],
243 |     get arr2() {
244 |       return this.arr.map((item: number) => item + 1)
245 |     },
246 |     get isEmpty() {
247 |       return this.arr2.length === 0
248 |     },
249 |     get isNotEmpty() {
250 |       return !this.isEmpty
251 |     },
252 |   })
253 |   const handler = jest.fn()
254 |   const handler2 = jest.fn()
255 |   autorun(() => {
256 |     handler(obs.isNotEmpty)
257 |     handler2(obs.arr2)
258 |   })
259 |   expect(handler).toBeCalledTimes(1)
260 |   expect(handler).lastCalledWith(false)
261 |   expect(handler2).toBeCalledTimes(1)
262 |   expect(handler2.mock.calls[0][0]).toEqual([])
263 |   obs.arr.push(1)
264 |   expect(handler).lastCalledWith(true)
265 |   expect(handler2.mock.calls[1][0]).toEqual([2])
266 |   obs.arr = []
267 |   expect(handler).lastCalledWith(false)
268 |   expect(handler2.mock.calls[2][0]).toEqual([])
269 | })
270 | 
271 | test('computed recollect dependencies', () => {
272 |   const computed = jest.fn()
273 |   const obs = model({
274 |     aa: 'aaa',
275 |     bb: 'bbb',
276 |     cc: 'ccc',
277 |     get compute() {
278 |       computed()
279 |       if (this.aa === 'aaa') {
280 |         return this.bb
281 |       }
282 |       return this.cc
283 |     },
284 |   })
285 |   const handler = jest.fn()
286 |   autorun(() => {
287 |     handler(obs.compute)
288 |   })
289 |   obs.aa = '111'
290 |   obs.bb = '222'
291 |   expect(computed).toBeCalledTimes(2)
292 | })
293 | 
294 | test('computed no params', () => {
295 |   observable.computed(null)
296 | })
297 | 
298 | test('computed object params', () => {
299 |   observable.computed({ get: () => {} })
300 | })
301 | 
302 | test('computed no track get', () => {
303 |   const obs = observable({ aa: 123 })
304 |   const compu = observable.computed({ get: () => obs.aa })
305 |   untracked(() => {
306 |     expect(compu.value).toBe(123)
307 |   })
308 | })
309 | 
310 | test('computed cache descriptor', () => {
311 |   class A {
312 |     _value = 0
313 |     constructor() {
314 |       define(this, {
315 |         _value: observable.ref,
316 |         value: observable.computed,
317 |       })
318 |     }
319 | 
320 |     get value() {
321 |       return this._value
322 |     }
323 |   }
324 |   const obs1 = new A()
325 |   const obs2 = new A()
326 |   const handler1 = jest.fn()
327 |   const handler2 = jest.fn()
328 |   autorun(() => {
329 |     handler1(obs1.value)
330 |   })
331 |   autorun(() => {
332 |     handler2(obs2.value)
333 |   })
334 |   expect(handler1).toBeCalledTimes(1)
335 |   expect(handler2).toBeCalledTimes(1)
336 |   obs1._value = 123
337 |   obs2._value = 123
338 |   expect(handler1).toBeCalledTimes(2)
339 |   expect(handler2).toBeCalledTimes(2)
340 | })
341 | 
342 | test('computed normal object', () => {
343 |   const obs = define(
344 |     {
345 |       _value: 0,
346 |       get value() {
347 |         return this._value
348 |       },
349 |     },
350 |     {
351 |       _value: observable.ref,
352 |       value: observable.computed,
353 |     }
354 |   )
355 |   const handler = jest.fn()
356 |   autorun(() => {
357 |     handler(obs.value)
358 |   })
359 |   expect(handler).toBeCalledTimes(1)
360 |   obs._value = 123
361 |   expect(handler).toBeCalledTimes(2)
362 | })
363 | 
```

--------------------------------------------------------------------------------
/packages/react/src/__tests__/field.spec.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React from 'react'
  2 | import { act } from 'react-dom/test-utils'
  3 | import { render, fireEvent, waitFor } from '@testing-library/react'
  4 | import { createForm, onFieldUnmount, isArrayField } from '@formily/core'
  5 | import {
  6 |   isField,
  7 |   Field as FieldType,
  8 |   isVoidField,
  9 |   onFieldChange,
 10 | } from '@formily/core'
 11 | import {
 12 |   FormProvider,
 13 |   ArrayField,
 14 |   ObjectField,
 15 |   VoidField,
 16 |   Field,
 17 |   useField,
 18 |   useFormEffects,
 19 |   observer,
 20 |   connect,
 21 |   mapProps,
 22 |   mapReadPretty,
 23 | } from '..'
 24 | import { ReactiveField } from '../components/ReactiveField'
 25 | import { expectThrowError } from './shared'
 26 | 
 27 | type InputProps = {
 28 |   value?: string
 29 |   onChange?: (...args: any) => void
 30 | }
 31 | 
 32 | type CustomProps = {
 33 |   list?: string[]
 34 | }
 35 | 
 36 | const Decorator = (props) => <div>{props.children}</div>
 37 | const Input: React.FC<React.PropsWithChildren<InputProps>> = (props) => (
 38 |   <input
 39 |     {...props}
 40 |     value={props.value || ''}
 41 |     data-testid={useField().path.toString()}
 42 |   />
 43 | )
 44 | 
 45 | const Normal = () => <div></div>
 46 | 
 47 | test('render field', async () => {
 48 |   const form = createForm()
 49 |   const onChange = jest.fn()
 50 |   const { getByTestId, queryByTestId, unmount } = render(
 51 |     <FormProvider form={form}>
 52 |       <Field
 53 |         name="aa"
 54 |         decorator={[Decorator]}
 55 |         component={[Input, { onChange }]}
 56 |       />
 57 |       <ArrayField name="bb" decorator={[Decorator]}>
 58 |         <div data-testid="bb-children"></div>
 59 |       </ArrayField>
 60 |       <ObjectField name="cc" decorator={[Decorator]}>
 61 |         <Field name="mm" decorator={[Decorator]} component={[Input]} />
 62 |         <ObjectField name="pp" decorator={[Decorator]} />
 63 |         <ArrayField name="tt" decorator={[Decorator]} />
 64 |         <VoidField name="ww" />
 65 |       </ObjectField>
 66 |       <VoidField name="dd" decorator={[Decorator]}>
 67 |         {() => (
 68 |           <div data-testid="dd-children">
 69 |             <Field name="oo" decorator={[Decorator]} component={[Input]} />
 70 |           </div>
 71 |         )}
 72 |       </VoidField>
 73 |       <VoidField name="xx" decorator={[Decorator]} component={[Normal]} />
 74 |       <Field
 75 |         name="ee"
 76 |         visible={false}
 77 |         decorator={[Decorator]}
 78 |         component={[Input]}
 79 |       />
 80 |       <Field name="ff" decorator={[]} component={[]} />
 81 |       <Field name="gg" decorator={null} component={null} />
 82 |       <Field name="hh" decorator={[null]} component={[null, null]} />
 83 |       <Field
 84 |         name="kk"
 85 |         decorator={[Decorator]}
 86 |         component={[Input, { onChange: null }]}
 87 |       />
 88 |     </FormProvider>
 89 |   )
 90 |   expect(form.mounted).toBeTruthy()
 91 |   expect(form.query('aa').take().mounted).toBeTruthy()
 92 |   expect(form.query('bb').take().mounted).toBeTruthy()
 93 |   expect(form.query('cc').take().mounted).toBeTruthy()
 94 |   expect(form.query('dd').take().mounted).toBeTruthy()
 95 |   fireEvent.change(getByTestId('aa'), {
 96 |     target: {
 97 |       value: '123',
 98 |     },
 99 |   })
100 |   fireEvent.change(getByTestId('kk'), {
101 |     target: {
102 |       value: '123',
103 |     },
104 |   })
105 |   expect(onChange).toBeCalledTimes(1)
106 |   expect(getByTestId('bb-children')).not.toBeUndefined()
107 |   expect(getByTestId('dd-children')).not.toBeUndefined()
108 |   expect(queryByTestId('ee')).toBeNull()
109 |   expect(form.query('aa').get('value')).toEqual('123')
110 |   expect(form.query('kk').get('value')).toEqual('123')
111 |   unmount()
112 | })
113 | 
114 | test('render field no context', () => {
115 |   expectThrowError(() => {
116 |     return (
117 |       <>
118 |         <Field name="aa">{() => <div></div>}</Field>
119 |         <ArrayField name="bb">
120 |           <div></div>
121 |         </ArrayField>
122 |         <ObjectField name="cc" />
123 |         <VoidField name="dd" />
124 |       </>
125 |     )
126 |   })
127 | })
128 | 
129 | test('ReactiveField', () => {
130 |   render(<ReactiveField field={null} />)
131 |   render(<ReactiveField field={null}>{() => <div></div>}</ReactiveField>)
132 | })
133 | 
134 | test('useAttach basic', async () => {
135 |   const form = createForm()
136 |   const MyComponent = (props: any) => {
137 |     return (
138 |       <FormProvider form={form}>
139 |         <Field name={props.name} decorator={[Decorator]} component={[Input]} />
140 |       </FormProvider>
141 |     )
142 |   }
143 |   const { rerender } = render(<MyComponent name="aa" />)
144 |   expect(form.query('aa').take().mounted).toBeTruthy()
145 |   rerender(<MyComponent name="bb" />)
146 |   await waitFor(() => {
147 |     expect(form.query('aa').take().mounted).toBeFalsy()
148 |     expect(form.query('bb').take().mounted).toBeTruthy()
149 |   })
150 | })
151 | 
152 | test('useAttach with array field', async () => {
153 |   const form = createForm()
154 |   const MyComponent = () => {
155 |     return (
156 |       <FormProvider form={form}>
157 |         <ArrayField
158 |           name="array"
159 |           initialValue={[{ input: '11' }, { input: '22' }]}
160 |         >
161 |           {(field) => {
162 |             return field.value.map((val, index) => {
163 |               return (
164 |                 <Field
165 |                   key={index}
166 |                   name={index + '.input'}
167 |                   decorator={[Decorator]}
168 |                   component={[Input]}
169 |                 />
170 |               )
171 |             })
172 |           }}
173 |         </ArrayField>
174 |       </FormProvider>
175 |     )
176 |   }
177 |   render(<MyComponent />)
178 |   await waitFor(() => {
179 |     expect(form.query('array.0.input').take().mounted).toBeTruthy()
180 |     expect(form.query('array.1.input').take().mounted).toBeTruthy()
181 |   })
182 |   form.query('array').take((field) => {
183 |     if (isArrayField(field)) {
184 |       field.moveDown(0)
185 |     }
186 |   })
187 |   await waitFor(() => {
188 |     expect(form.query('array.0.input').take().mounted).toBeTruthy()
189 |     expect(form.query('array.1.input').take().mounted).toBeTruthy()
190 |   })
191 | })
192 | 
193 | test('useFormEffects', async () => {
194 |   const form = createForm()
195 |   const CustomField = observer(() => {
196 |     const field = useField<FieldType>()
197 |     useFormEffects(() => {
198 |       onFieldChange('aa', ['value'], (target) => {
199 |         if (isVoidField(target)) return
200 |         field.setValue(target.value)
201 |       })
202 |     })
203 |     return <div data-testid="custom-value">{field.value}</div>
204 |   })
205 |   act(async () => {
206 |     const { queryByTestId, rerender } = render(
207 |       <FormProvider form={form}>
208 |         <Field name="aa" decorator={[Decorator]} component={[Input]} />
209 |         <Field name="bb" component={[CustomField, { tag: 'xxx' }]} />
210 |       </FormProvider>
211 |     )
212 | 
213 |     expect(queryByTestId('custom-value')?.textContent).toEqual('')
214 |     form.query('aa').take((aa) => {
215 |       if (isField(aa)) {
216 |         aa.setValue('123')
217 |       }
218 |     })
219 |     await waitFor(() => {
220 |       expect(queryByTestId('custom-value')?.textContent).toEqual('123')
221 |     })
222 |     rerender(
223 |       <FormProvider form={form}>
224 |         <Field name="aa" decorator={[Decorator]} component={[Input]} />
225 |         <Field name="bb" component={[CustomField, { tag: 'yyy' }]} />
226 |       </FormProvider>
227 |     )
228 |   })
229 | })
230 | 
231 | test('connect', async () => {
232 |   const CustomField = connect(
233 |     (props: CustomProps) => {
234 |       return <div>{props.list}</div>
235 |     },
236 |     mapProps({ value: 'list', loading: true }, (props, field) => {
237 |       return {
238 |         ...props,
239 |         mounted: field.mounted ? 1 : 2,
240 |       }
241 |     }),
242 |     mapReadPretty(() => <div>read pretty</div>)
243 |   )
244 |   const BaseComponent = (props: any) => {
245 |     return <div>{props.value}</div>
246 |   }
247 |   BaseComponent.displayName = 'BaseComponent'
248 |   const CustomField2 = connect(
249 |     BaseComponent,
250 |     mapProps({ value: true, loading: true }),
251 |     mapReadPretty(() => <div>read pretty</div>)
252 |   )
253 |   const form = createForm()
254 |   const MyComponent = () => {
255 |     return (
256 |       <FormProvider form={form}>
257 |         <Field name="aa" decorator={[Decorator]} component={[CustomField]} />
258 |         <Field name="bb" decorator={[Decorator]} component={[CustomField2]} />
259 |       </FormProvider>
260 |     )
261 |   }
262 |   const { queryByText } = render(<MyComponent />)
263 |   form.query('aa').take((field) => {
264 |     field.setState((state) => {
265 |       state.value = '123'
266 |     })
267 |   })
268 |   await waitFor(() => {
269 |     expect(queryByText('123')).toBeVisible()
270 |   })
271 | 
272 |   form.query('aa').take((field) => {
273 |     if (!isField(field)) return
274 |     field.readPretty = true
275 |   })
276 |   await waitFor(() => {
277 |     expect(queryByText('123')).toBeNull()
278 |     expect(queryByText('read pretty')).toBeVisible()
279 |   })
280 | })
281 | 
282 | test('fields unmount and validate', async () => {
283 |   const fn = jest.fn()
284 |   const form = createForm({
285 |     initialValues: {
286 |       parent: {
287 |         type: 'mounted',
288 |       },
289 |     },
290 |     effects: () => {
291 |       onFieldUnmount('parent.child', () => {
292 |         fn()
293 |       })
294 |     },
295 |   })
296 |   const Parent = observer(() => {
297 |     const field = useField<FieldType>()
298 |     if (field.value.type === 'mounted') {
299 |       return (
300 |         <Field
301 |           name="child"
302 |           component={[Input]}
303 |           validator={{ required: true }}
304 |         />
305 |       )
306 |     }
307 |     return <div data-testid="unmounted"></div>
308 |   })
309 | 
310 |   const MyComponent = () => {
311 |     return (
312 |       <FormProvider form={form}>
313 |         <Field name="parent" component={[Parent]} />
314 |       </FormProvider>
315 |     )
316 |   }
317 |   render(<MyComponent />)
318 | 
319 |   try {
320 |     await form.validate()
321 |   } catch {}
322 | 
323 |   expect(form.invalid).toBeTruthy()
324 | 
325 |   form.query('parent').take((field) => {
326 |     field.setState((state) => {
327 |       state.value.type = 'unmounted'
328 |     })
329 |   })
330 | 
331 |   await waitFor(() => {
332 |     expect(fn.mock.calls.length).toBe(1)
333 |   })
334 | 
335 |   try {
336 |     await form.validate()
337 |   } catch {}
338 |   expect(form.invalid).toBeTruthy()
339 | })
340 | 
```

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

```markdown
  1 | # FormDialog
  2 | 
  3 | > Pop-up form, mainly used in simple event to open the form scene
  4 | 
  5 | ## Markup Schema example
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
 10 | import { createSchemaField } from '@formily/react'
 11 | import { Button } from '@alifd/next'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     FormItem,
 16 |     Input,
 17 |   },
 18 | })
 19 | 
 20 | export default () => {
 21 |   return (
 22 |     <Button
 23 |       onClick={() => {
 24 |         FormDialog('Pop-up form', () => {
 25 |           return (
 26 |             <FormLayout labelCol={6} wrapperCol={14}>
 27 |               <SchemaField>
 28 |                 <SchemaField.String
 29 |                   name="aaa"
 30 |                   required
 31 |                   title="input box 1"
 32 |                   x-decorator="FormItem"
 33 |                   x-component="Input"
 34 |                 />
 35 |                 <SchemaField.String
 36 |                   name="bbb"
 37 |                   required
 38 |                   title="input box 2"
 39 |                   x-decorator="FormItem"
 40 |                   x-component="Input"
 41 |                 />
 42 |                 <SchemaField.String
 43 |                   name="ccc"
 44 |                   required
 45 |                   title="input box 3"
 46 |                   x-decorator="FormItem"
 47 |                   x-component="Input"
 48 |                 />
 49 |                 <SchemaField.String
 50 |                   name="ddd"
 51 |                   required
 52 |                   title="input box 4"
 53 |                   x-decorator="FormItem"
 54 |                   x-component="Input"
 55 |                 />
 56 |               </SchemaField>
 57 |               <FormDialog.Footer>
 58 |                 <span style={{ marginLeft: 4 }}>Extended copywriting</span>
 59 |               </FormDialog.Footer>
 60 |             </FormLayout>
 61 |           )
 62 |         })
 63 |           .open({
 64 |             initialValues: {
 65 |               aaa: '123',
 66 |             },
 67 |           })
 68 |           .then(console.log)
 69 |       }}
 70 |     >
 71 |       Click me to open the form
 72 |     </Button>
 73 |   )
 74 | }
 75 | ```
 76 | 
 77 | ## JSON Schema case
 78 | 
 79 | ```tsx
 80 | import React from 'react'
 81 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
 82 | import { createSchemaField } from '@formily/react'
 83 | import { Button } from '@alifd/next'
 84 | 
 85 | const SchemaField = createSchemaField({
 86 |   components: {
 87 |     FormItem,
 88 |     Input,
 89 |   },
 90 | })
 91 | 
 92 | const schema = {
 93 |   type: 'object',
 94 |   properties: {
 95 |     aaa: {
 96 |       type: 'string',
 97 |       title: 'input box 1',
 98 |       required: true,
 99 |       'x-decorator': 'FormItem',
100 |       'x-component': 'Input',
101 |     },
102 |     bbb: {
103 |       type: 'string',
104 |       title: 'input box 2',
105 |       required: true,
106 |       'x-decorator': 'FormItem',
107 |       'x-component': 'Input',
108 |     },
109 |     ccc: {
110 |       type: 'string',
111 |       title: 'input box 3',
112 |       required: true,
113 |       'x-decorator': 'FormItem',
114 |       'x-component': 'Input',
115 |     },
116 |     ddd: {
117 |       type: 'string',
118 |       title: 'input box 4',
119 |       required: true,
120 |       'x-decorator': 'FormItem',
121 |       'x-component': 'Input',
122 |     },
123 |   },
124 | }
125 | 
126 | export default () => {
127 |   return (
128 |     <Button
129 |       onClick={() => {
130 |         FormDialog('Pop-up form', () => {
131 |           return (
132 |             <FormLayout labelCol={6} wrapperCol={14}>
133 |               <SchemaField schema={schema} />
134 |               <FormDialog.Footer>
135 |                 <span style={{ marginLeft: 4 }}>Extended copywriting</span>
136 |               </FormDialog.Footer>
137 |             </FormLayout>
138 |           )
139 |         })
140 |           .open({
141 |             initialValues: {
142 |               aaa: '123',
143 |             },
144 |           })
145 |           .then(console.log)
146 |       }}
147 |     >
148 |       Click me to open the form
149 |     </Button>
150 |   )
151 | }
152 | ```
153 | 
154 | ## Pure JSX case
155 | 
156 | ```tsx
157 | import React from 'react'
158 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
159 | import { Field } from '@formily/react'
160 | import { Button } from '@alifd/next'
161 | 
162 | export default () => {
163 |   return (
164 |     <Button
165 |       onClick={() => {
166 |         FormDialog('Pop-up form', () => {
167 |           return (
168 |             <FormLayout labelCol={6} wrapperCol={14}>
169 |               <Field
170 |                 name="aaa"
171 |                 required
172 |                 title="input box 1"
173 |                 decorator={[FormItem]}
174 |                 component={[Input]}
175 |               />
176 |               <Field
177 |                 name="bbb"
178 |                 required
179 |                 title="input box 2"
180 |                 decorator={[FormItem]}
181 |                 component={[Input]}
182 |               />
183 |               <Field
184 |                 name="ccc"
185 |                 required
186 |                 title="input box 3"
187 |                 decorator={[FormItem]}
188 |                 component={[Input]}
189 |               />
190 |               <Field
191 |                 name="ddd"
192 |                 required
193 |                 title="input box 4"
194 |                 decorator={[FormItem]}
195 |                 component={[Input]}
196 |               />
197 |               <FormDialog.Footer>
198 |                 <span style={{ marginLeft: 4 }}>Extended copywriting</span>
199 |               </FormDialog.Footer>
200 |             </FormLayout>
201 |           )
202 |         })
203 |           .open({
204 |             initialValues: {
205 |               aaa: '123',
206 |             },
207 |           })
208 |           .then(console.log)
209 |       }}
210 |     >
211 |       Click me to open the form
212 |     </Button>
213 |   )
214 | }
215 | ```
216 | 
217 | ## Use Fusion Context
218 | 
219 | ```tsx
220 | import React from 'react'
221 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
222 | import { Field } from '@formily/react'
223 | import { Button, ConfigProvider } from '@alifd/next'
224 | 
225 | export default () => {
226 |   return (
227 |     <ConfigProvider
228 |       locale={{
229 |         Dialog: {
230 |           ok: 'OK',
231 |           cancel: 'Cancel',
232 |         },
233 |       }}
234 |       defaultPropsConfig={{
235 |         Dialog: {
236 |           isFullScreen: true,
237 |           footerActions: ['cancel', 'ok'],
238 |         },
239 |       }}
240 |     >
241 |       <Button
242 |         onClick={() => {
243 |           FormDialog('Pop-up form', () => {
244 |             return (
245 |               <FormLayout labelCol={6} wrapperCol={14}>
246 |                 <Field
247 |                   name="aaa"
248 |                   required
249 |                   title="input box 1"
250 |                   decorator={[FormItem]}
251 |                   component={[Input]}
252 |                 />
253 |                 <Field
254 |                   name="bbb"
255 |                   required
256 |                   title="input box 2"
257 |                   decorator={[FormItem]}
258 |                   component={[Input]}
259 |                 />
260 |                 <Field
261 |                   name="ccc"
262 |                   required
263 |                   title="input box 3"
264 |                   decorator={[FormItem]}
265 |                   component={[Input]}
266 |                 />
267 |                 <Field
268 |                   name="ddd"
269 |                   required
270 |                   title="input box 4"
271 |                   decorator={[FormItem]}
272 |                   component={[Input]}
273 |                 />
274 |                 <FormDialog.Footer>
275 |                   <span style={{ marginLeft: 4 }}>Extended copywriting</span>
276 |                 </FormDialog.Footer>
277 |               </FormLayout>
278 |             )
279 |           })
280 |             .open({
281 |               initialValues: {
282 |                 aaa: '123',
283 |               },
284 |             })
285 |             .then(console.log)
286 |         }}
287 |       >
288 |         Click me to open the form
289 |       </Button>
290 |     </ConfigProvider>
291 |   )
292 | }
293 | ```
294 | 
295 | ## API
296 | 
297 | ### FormDialog
298 | 
299 | ```ts pure
300 | import { IFormProps, Form } from '@formily/core'
301 | 
302 | type FormDialogRenderer =
303 |   | React.ReactElement
304 |   | ((form: Form) => React.ReactElement)
305 | 
306 | interface IFormDialog {
307 |   forOpen(
308 |     middleware: (
309 |       props: IFormProps,
310 |       next: (props?: IFormProps) => Promise<any>
311 |     ) => any
312 |   ): any //Middleware interceptor, can intercept Dialog to open
313 |   forConfirm(
314 |     middleware: (props: Form, next: (props?: Form) => Promise<any>) => any
315 |   ): any //Middleware interceptor, which can intercept Dialog confirmation
316 |   forCancel(
317 |     middleware: (props: Form, next: (props?: Form) => Promise<any>) => any
318 |   ): any //Middleware interceptor, can intercept Dialog to cancel
319 |   //Open the pop-up window to receive form attributes, you can pass in initialValues/values/effects etc.
320 |   open(props: IFormProps): Promise<any> //return form data
321 |   //Close the pop-up window
322 |   close(): void
323 | }
324 | 
325 | interface IDialogProps extends DialogProps {
326 |   onOk?: (event: React.MouseEvent) => void | boolean // return false can prevent onOk
327 |   onCancel?: (event: React.MouseEvent) => void | boolean // return false can prevent onCancel
328 |   loadingText?: React.ReactText
329 | }
330 | 
331 | interface FormDialog {
332 |   (title: IDialogProps, id: string, renderer: FormDialogRenderer): IFormDialog
333 |   (title: IDialogProps, renderer: FormDialogRenderer): IFormDialog
334 |   (title: ModalTitle, id: string, renderer: FormDialogRenderer): IFormDialog
335 |   (title: ModalTitle, renderer: FormDialogRenderer): IFormDialog
336 | }
337 | ```
338 | 
339 | `DialogProps` type definition reference fusion [Dialog API](https://fusion.design/pc/component/dialog?themeid=2#API)
340 | 
341 | ### FormDialog.Footer
342 | 
343 | No attributes, only child nodes are received
344 | 
345 | ### FormDialog.Portal
346 | 
347 | Receive the optional id attribute, the default value is `form-dialog`, if there are multiple prefixCls in an application, and the prefixCls in the pop-up window of different regions are different, then it is recommended to specify the id as the region-level id
348 | 
```

--------------------------------------------------------------------------------
/packages/core/docs/api/models/VoidField.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | order: 4
  3 | ---
  4 | 
  5 | # VoidField
  6 | 
  7 | Call the VoidField model returned by [createVoidField](/api/models/form#createvoidfield).
  8 | 
  9 | All model attributes are listed below. If the attribute is writable, then we can directly refer to it to modify the attribute, and @formily/reactive will respond to trigger the UI update.
 10 | 
 11 | ## Attributes
 12 | 
 13 | | Property    | Description                               | Type                                    | Read-only or not | Default value |
 14 | | ----------- | ----------------------------------------- | --------------------------------------- | ---------------- | ------------- |
 15 | | initialized | Whether the field has been initialized    | Boolean                                 | No               | `false`       |
 16 | | mounted     | Is the field mounted                      | Boolean                                 | No               | `false`       |
 17 | | unmounted   | Is the field unmounted                    | Boolean                                 | No               | `false`       |
 18 | | address     | Field node path                           | [FormPath](/api/entry/form-path)        | Yes              |               |
 19 | | path        | Field data path                           | [FormPath](/api/entry/form-path)        | Yes              |               |
 20 | | title       | Field Title                               | [FieldMessage](#fieldmessage)           | No               | `""`          |
 21 | | description | Field description                         | [FieldMessage](#fieldmessage)           | No               | `""`          |
 22 | | decorator   | field decorator                           | Any[]                                   | No               | `null`        |
 23 | | component   | Field component                           | Any[]                                   | No               | `null`        |
 24 | | parent      | Parent field                              | [GeneralField](#generalfield)           | yes              | `null`        |
 25 | | display     | Field display status                      | [FieldDisplayTypes](#fielddisplaytypes) | No               | `"visible"`   |
 26 | | pattern     | Field interaction mode                    | [FieldPatternTypes](#fieldpatterntypes) | No               | `"editable"`  |
 27 | | hidden      | Whether the field is hidden               | Boolean                                 | No               | `false`       |
 28 | | visible     | Whether the field is displayed            | Boolean                                 | No               | `true`        |
 29 | | disabled    | Whether the field is disabled             | Boolean                                 | No               | `false`       |
 30 | | readOnly    | Is the field read-only                    | Boolean                                 | No               | `false`       |
 31 | | readPretty  | Whether the field is in the reading state | Boolean                                 | No               | `false`       |
 32 | | editable    | Field is editable                         | Boolean                                 | No               | `true`        |
 33 | 
 34 | #### explain in detail
 35 | 
 36 | **hidden**
 37 | 
 38 | When true, display is hidden, when false, display is visible
 39 | 
 40 | **visible**
 41 | 
 42 | When true, display is visible, when false, display is none
 43 | 
 44 | ## Method
 45 | 
 46 | ### setTitle
 47 | 
 48 | #### Description
 49 | 
 50 | Set field title
 51 | 
 52 | #### Signature
 53 | 
 54 | ```ts
 55 | interface setTitle {
 56 |   (title?: FieldMessage): void
 57 | }
 58 | ```
 59 | 
 60 | FieldMessage Reference [FieldMessage](#fieldmessage)
 61 | 
 62 | ### setDescription
 63 | 
 64 | #### Description
 65 | 
 66 | Set field description information
 67 | 
 68 | #### Signature
 69 | 
 70 | ```ts
 71 | interface setDescription {
 72 |   (title?: FieldMessage): void
 73 | }
 74 | ```
 75 | 
 76 | FieldMessage Reference [FieldMessage](#fieldmessage)
 77 | 
 78 | ### setDisplay
 79 | 
 80 | #### Description
 81 | 
 82 | Set field display status
 83 | 
 84 | #### Signature
 85 | 
 86 | ```ts
 87 | interface setDisplay {
 88 |   (display?: FieldDisplayTypes): void
 89 | }
 90 | ```
 91 | 
 92 | FieldDisplayTypes Reference [FieldDisplayTypes](#fielddisplaytypes)
 93 | 
 94 | ### setPattern
 95 | 
 96 | #### Description
 97 | 
 98 | Set field interaction mode
 99 | 
100 | #### Signature
101 | 
102 | ```ts
103 | interface setPattern {
104 |   (pattern?: FieldPatternTypes): void
105 | }
106 | ```
107 | 
108 | FieldPatternTypes Reference [FieldPatternTypes](#fieldpatterntypes)
109 | 
110 | ### setComponent
111 | 
112 | #### Description
113 | 
114 | Set field component
115 | 
116 | #### Signature
117 | 
118 | ```ts
119 | interface setComponent {
120 |   (component?: FieldComponent, props?: any): void
121 | }
122 | ```
123 | 
124 | FieldComponent Reference [FieldComponent](#fieldcomponent)
125 | 
126 | ### setComponentProps
127 | 
128 | #### Description
129 | 
130 | Set field component properties
131 | 
132 | #### Signature
133 | 
134 | ```ts
135 | interface setComponentProps {
136 |   (props?: any): void
137 | }
138 | ```
139 | 
140 | ### setDecorator
141 | 
142 | #### Description
143 | 
144 | Set field decorator
145 | 
146 | #### Signature
147 | 
148 | ```ts
149 | interface setDecorator {
150 |   (decorator?: FieldDecorator, props?: any): void
151 | }
152 | ```
153 | 
154 | FieldDecorator Reference [FieldDecorator](#fielddecorator)
155 | 
156 | ### setDecoratorProps
157 | 
158 | #### Description
159 | 
160 | Set field decorator properties
161 | 
162 | #### Signature
163 | 
164 | ```ts
165 | interface setDecoratorProps {
166 |   (props?: any): void
167 | }
168 | ```
169 | 
170 | ### setState
171 | 
172 | #### Description
173 | 
174 | Set field status
175 | 
176 | #### Signature
177 | 
178 | ```ts
179 | interface setState {
180 |   (state: IVoidFieldState): void
181 |   (callback: (state: IVoidFieldState) => void): void
182 | }
183 | ```
184 | 
185 | IVoidFieldState Reference [IVoidFieldState](#ifieldstate)
186 | 
187 | ### getState
188 | 
189 | #### Description
190 | 
191 | Get field status
192 | 
193 | #### Signature
194 | 
195 | ```ts
196 | interface getState<T> {
197 |   (): IVoidFieldState
198 |   (callback: (state: IVoidFieldState) => T): T
199 | }
200 | ```
201 | 
202 | IVoidFieldState Reference [IVoidFieldState](#ifieldstate)
203 | 
204 | ### setData
205 | 
206 | #### Description
207 | 
208 | set field data
209 | 
210 | #### Signature
211 | 
212 | ```ts
213 | interface setData {
214 |   (data: any): void
215 | }
216 | ```
217 | 
218 | ### setContent
219 | 
220 | #### Description
221 | 
222 | set field content
223 | 
224 | #### Signature
225 | 
226 | ```ts
227 | interface setContent {
228 |   (content: any): void
229 | }
230 | ```
231 | 
232 | ### onInit
233 | 
234 | #### Description
235 | 
236 | Trigger field initialization, no need to call manually
237 | 
238 | #### Signature
239 | 
240 | ```ts
241 | interface onInit {
242 |   (): void
243 | }
244 | ```
245 | 
246 | ### onMount
247 | 
248 | #### Description
249 | 
250 | Trigger field mount
251 | 
252 | #### Signature
253 | 
254 | ```ts
255 | interface onMount {
256 |   (): void
257 | }
258 | ```
259 | 
260 | ### onUnmount
261 | 
262 | #### Description
263 | 
264 | Trigger field unloading
265 | 
266 | #### Signature
267 | 
268 | ```ts
269 | interface onUnmount {
270 |   (): void
271 | }
272 | ```
273 | 
274 | ### query
275 | 
276 | #### Description
277 | 
278 | Query field, you can query adjacent fields based on the current field
279 | 
280 | #### Signature
281 | 
282 | ```ts
283 | interface query {
284 |   (pattern: FormPathPattern): Query
285 | }
286 | ```
287 | 
288 | FormPathPattern API Reference [FormPath](/api/entry/form-path#formpathpattern)
289 | 
290 | Query object API reference [Query](/api/models/query)
291 | 
292 | ### dispose
293 | 
294 | #### Description
295 | 
296 | Release observer, no need to release manually by default
297 | 
298 | #### Signature
299 | 
300 | ```ts
301 | interface dispose {
302 |   (): void
303 | }
304 | ```
305 | 
306 | ### destroy
307 | 
308 | #### Description
309 | 
310 | Release observer, and remove current field model
311 | 
312 | #### Signature
313 | 
314 | ```ts
315 | interface destroy {
316 |   (): void
317 | }
318 | ```
319 | 
320 | ### match
321 | 
322 | #### Description
323 | 
324 | Match fields based on path
325 | 
326 | #### Signature
327 | 
328 | ```ts
329 | interface match {
330 |   (pattern: FormPathPattern): boolean
331 | }
332 | ```
333 | 
334 | FormPathPattern API Reference [FormPath](/api/entry/form-path#formpathpattern)
335 | 
336 | ### inject
337 | 
338 | #### Description
339 | 
340 | Inject executable methods into field models
341 | 
342 | #### Signature
343 | 
344 | ```ts
345 | interface inject {
346 |   (actions: Record<string, (...args: any[]) => any>): void
347 | }
348 | ```
349 | 
350 | ### invoke
351 | 
352 | #### Description
353 | 
354 | Invoke an executable method injected by the field model via inject
355 | 
356 | #### Signature
357 | 
358 | ```ts
359 | interface invoke {
360 |   (name: string, ...args: any[]): any
361 | }
362 | ```
363 | 
364 | ## Types of
365 | 
366 | <Alert>
367 | Note: If you want to manually consume the type, just export it directly from the package module
368 | </Alert>
369 | 
370 | ### FieldMessage
371 | 
372 | ```ts
373 | type FieldMessage = string | JSXElement
374 | ```
375 | 
376 | If under the UI framework that supports JSX, we can directly pass the Node of JSX, otherwise, we can only pass the string
377 | 
378 | ### FieldComponent
379 | 
380 | ```ts
381 | type FieldComponent = string | JSXComponentConstructor
382 | ```
383 | 
384 | Field component, if we use it in a framework that supports JSX, FieldComponent recommends to store the JSX component reference directly, otherwise it can store a component identification string and distribute it during actual rendering.
385 | 
386 | ### FieldDecorator
387 | 
388 | ```ts
389 | type FieldDecorator = string | JSXComponentConstructor
390 | ```
391 | 
392 | Field decorator, if we use it in a framework that supports JSX, FieldDecorator recommends to store the JSX component reference directly, otherwise it can store a component identification string and distribute it during actual rendering.
393 | 
394 | ### FieldReaction
395 | 
396 | ```ts
397 | type FieldReaction = (field: GeneralField) => void
398 | ```
399 | 
400 | ### FieldDisplayTypes
401 | 
402 | ```ts
403 | type FieldDisplayTypes = 'none' | 'hidden' | 'visible'
404 | ```
405 | 
406 | ### FieldPatternTypes
407 | 
408 | ```ts
409 | type FieldPatternTypes = 'editable' | 'disabled' | 'readOnly' | 'readPretty'
410 | ```
411 | 
412 | ### GeneralField
413 | 
414 | ```ts
415 | type GeneralField = Field | VoidField | ArrayField | ObjectField
416 | ```
417 | 
418 | Field Reference [Field](/api/models/field)
419 | 
420 | ArrayField Reference [ArrayField](/api/models/array-field)
421 | 
422 | ObjectField Reference [ObjectField](/api/models/object-field)
423 | 
424 | ### IVoidFieldState
425 | 
426 | ```ts
427 | interface IVoidFieldState {
428 |   hidden?: boolean
429 |   visible?: boolean
430 |   editable?: boolean
431 |   readOnly?: boolean
432 |   disabled?: boolean
433 |   readPretty?: boolean
434 |   title?: any
435 |   description?: any
436 |   modified?: boolean
437 |   active?: boolean
438 |   visited?: boolean
439 |   initialized?: boolean
440 |   mounted?: boolean
441 |   unmounted?: boolean
442 |   decorator?: FieldDecorator
443 |   component?: FieldComponent
444 |   readonly parent?: GeneralField
445 |   display?: FieldDisplayTypes
446 |   pattern?: FieldPatternTypes
447 | }
448 | ```
449 | 
450 | ### IGeneralFieldState
451 | 
452 | ```ts
453 | type IGeneralFieldState = IVoidFieldState & IFieldState
454 | ```
455 | 
456 | IFieldState Reference [IFieldState](/api/models/field#ifieldstate)
457 | 
```

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

```typescript
  1 | import { Schema } from '../schema'
  2 | import { createForm } from '@formily/core'
  3 | import { isObservable } from '@formily/reactive'
  4 | import { ISchema, ISchemaTransformerOptions } from '../types'
  5 | 
  6 | const attach = <T extends { onMount: () => void }>(target: T): T => {
  7 |   target.onMount()
  8 |   return target
  9 | }
 10 | 
 11 | const getFormAndFields = (
 12 |   field1SchemaProps: Omit<ISchema, 'name'> = {},
 13 |   field2SchemaProps: Omit<ISchema, 'name'> = {},
 14 |   options: ISchemaTransformerOptions = {}
 15 | ) => {
 16 |   const filed1Schema = new Schema({
 17 |     name: 'field1',
 18 |     ...field1SchemaProps,
 19 |   }).toFieldProps(options)
 20 | 
 21 |   const filed2Schema = new Schema({
 22 |     name: 'field2',
 23 |     ...field2SchemaProps,
 24 |   }).toFieldProps(options)
 25 | 
 26 |   const form = createForm()
 27 |   const field1 = form.createField(filed1Schema)
 28 |   const field2 = form.createField(filed2Schema)
 29 | 
 30 |   return {
 31 |     form,
 32 |     field1,
 33 |     field2,
 34 |   }
 35 | }
 36 | 
 37 | test('baseReaction', () => {
 38 |   const { field1, field2 } = getFormAndFields(
 39 |     {
 40 |       title: 'field1Title',
 41 |     },
 42 |     {
 43 |       title: 'field2Title',
 44 |     }
 45 |   )
 46 | 
 47 |   expect(field1.title).toBe('field1Title')
 48 |   expect(field2.title).toBe('field2Title')
 49 | })
 50 | 
 51 | test('baseReaction with scopes', () => {
 52 |   const scopeTitle = 'fieldTitle'
 53 |   const scopeDescription = 'fieldDescription'
 54 | 
 55 |   const { field1, field2 } = getFormAndFields(
 56 |     {
 57 |       title: '{{scopeTitle}}',
 58 |     },
 59 |     {
 60 |       description: '{{scopeDescription}}',
 61 |     },
 62 |     {
 63 |       scope: {
 64 |         scopeTitle,
 65 |         scopeDescription,
 66 |       },
 67 |     }
 68 |   )
 69 | 
 70 |   expect(field1.title).toBe(scopeTitle)
 71 |   expect(field2.description).toBe(scopeDescription)
 72 | })
 73 | 
 74 | test('userReactions with target(state)', () => {
 75 |   const field2Title = 'field2Title'
 76 |   const { field2 } = getFormAndFields({
 77 |     'x-reactions': {
 78 |       target: 'field2',
 79 |       fulfill: {
 80 |         state: {
 81 |           title: field2Title,
 82 |         },
 83 |       },
 84 |     },
 85 |   })
 86 | 
 87 |   expect(field2.title).toBe(field2Title)
 88 | })
 89 | 
 90 | test('userReactions with target(schema)', () => {
 91 |   const field2Data = 'fieldData'
 92 |   const { field2 } = getFormAndFields({
 93 |     'x-reactions': {
 94 |       target: 'field2',
 95 |       fulfill: {
 96 |         schema: {
 97 |           'x-data': field2Data,
 98 |         },
 99 |       },
100 |     },
101 |   })
102 | 
103 |   expect(field2.data).toBe(field2Data)
104 | })
105 | 
106 | test('userReactions with target(runner)', () => {
107 |   const mockFn = jest.fn()
108 |   const field2Title = 'field2Title'
109 |   const { field2 } = getFormAndFields(
110 |     {
111 |       'x-reactions': {
112 |         target: 'field2',
113 |         fulfill: {
114 |           run: `$target.title='${field2Title}';fn()`,
115 |         },
116 |       },
117 |     },
118 |     {},
119 |     {
120 |       scope: {
121 |         fn: mockFn,
122 |       },
123 |     }
124 |   )
125 | 
126 |   expect(mockFn).toBeCalledTimes(1)
127 |   expect(field2.title).toBe(field2Title)
128 | })
129 | 
130 | test('userReactions without target(state)', () => {
131 |   const field1Title = 'field1Title'
132 |   const { field1 } = getFormAndFields({
133 |     'x-reactions': {
134 |       fulfill: {
135 |         state: {
136 |           title: field1Title,
137 |         },
138 |       },
139 |     },
140 |   })
141 | 
142 |   expect(field1.title).toBe(field1Title)
143 | })
144 | 
145 | test('userReactions without target(schema)', () => {
146 |   const field1Data = 'fieldData'
147 |   const { field1 } = getFormAndFields({
148 |     'x-reactions': {
149 |       fulfill: {
150 |         schema: {
151 |           'x-data': field1Data,
152 |         },
153 |       },
154 |     },
155 |   })
156 | 
157 |   expect(field1.data).toBe(field1Data)
158 | })
159 | 
160 | test('userReactions without target(runner)', () => {
161 |   const mockFn = jest.fn()
162 |   const { field1 } = getFormAndFields(
163 |     {
164 |       'x-reactions': {
165 |         fulfill: {
166 |           run: `$self.__target__=$target;fn()`,
167 |         },
168 |       },
169 |     },
170 |     {},
171 |     {
172 |       scope: {
173 |         fn: mockFn,
174 |       },
175 |     }
176 |   )
177 | 
178 |   expect(mockFn).toBeCalledTimes(1)
179 |   expect((field1 as any).__target__).toBe(null)
180 | })
181 | 
182 | test('userReactions with condition', () => {
183 |   const mockFn = jest.fn()
184 |   const { field1 } = getFormAndFields(
185 |     {
186 |       'x-value': true,
187 |       'x-reactions': {
188 |         when: '$self.value===true',
189 |         fulfill: {
190 |           run: 'mockFn($self.value)',
191 |         },
192 |         otherwise: {
193 |           run: 'mockFn($self.value)',
194 |         },
195 |       },
196 |     },
197 |     {},
198 |     {
199 |       scope: {
200 |         mockFn,
201 |       },
202 |     }
203 |   )
204 | 
205 |   expect(mockFn).nthCalledWith(1, true)
206 | 
207 |   field1.value = false
208 | 
209 |   expect(mockFn).nthCalledWith(2, false)
210 | })
211 | 
212 | test('userReactions with condition(wrong type)', () => {
213 |   const field1Value = 'field1Value'
214 |   const mockFn = jest.fn()
215 |   getFormAndFields(
216 |     {
217 |       'x-value': field1Value,
218 |       'x-reactions': {
219 |         dependencies: 'value',
220 |         fulfill: {
221 |           run: 'mockFn($deps, $dependencies)',
222 |         },
223 |       },
224 |     },
225 |     {},
226 |     {
227 |       scope: {
228 |         mockFn,
229 |       },
230 |     }
231 |   )
232 | 
233 |   expect(mockFn).nthCalledWith(1, [], [])
234 | })
235 | 
236 | test('userReactions with condition(array)', () => {
237 |   const field1Value = 'field1Value'
238 |   const field2Value = 'field2Value'
239 |   const field1Title = 'field1Title'
240 |   const field1Description = 'field1Description'
241 |   const mockFn = jest.fn()
242 | 
243 |   getFormAndFields(
244 |     {
245 |       title: field1Title,
246 |       description: field1Description,
247 |       'x-value': field1Value,
248 |     },
249 |     {
250 |       'x-value': field2Value,
251 |       'x-reactions': {
252 |         dependencies: [
253 |           'field2',
254 |           {
255 |             name: 1,
256 |             source: 'field1',
257 |           },
258 |           {
259 |             name: 2,
260 |             source: 'field1#title',
261 |           },
262 |           {
263 |             name: 3,
264 |             source: 'field1',
265 |             property: 'description',
266 |           },
267 |         ],
268 |         fulfill: {
269 |           run: `mockFn($deps)`,
270 |         },
271 |       },
272 |     },
273 |     {
274 |       scope: {
275 |         mockFn,
276 |       },
277 |     }
278 |   )
279 | 
280 |   expect(mockFn).nthCalledWith(1, [
281 |     field2Value,
282 |     field1Value,
283 |     field1Title,
284 |     field1Description,
285 |   ])
286 | })
287 | 
288 | test('userReactions with condition(object)', () => {
289 |   const field2Value = 'field2Value'
290 |   const field1Title = 'field1Title'
291 |   const mockFn = jest.fn()
292 | 
293 |   getFormAndFields(
294 |     {
295 |       title: field1Title,
296 |     },
297 |     {
298 |       'x-value': field2Value,
299 |       'x-reactions': {
300 |         dependencies: {
301 |           key1: 'field1#title',
302 |           key2: 'field2',
303 |         },
304 |         fulfill: {
305 |           run: `mockFn($deps)`,
306 |         },
307 |       },
308 |     },
309 |     {
310 |       scope: {
311 |         mockFn,
312 |       },
313 |     }
314 |   )
315 | 
316 |   expect(mockFn).nthCalledWith(1, {
317 |     key1: field1Title,
318 |     key2: field2Value,
319 |   })
320 | })
321 | 
322 | test('userReactions with user-defined effects', () => {
323 |   const field2Value = 'field2Value'
324 |   const field1Title = 'field1Title'
325 |   const mockFn = jest.fn()
326 | 
327 |   const { field2 } = getFormAndFields(
328 |     {
329 |       title: field1Title,
330 |       'x-reactions': {
331 |         target: 'field2',
332 |         fulfill: {
333 |           run: `mockFn($target.value)`,
334 |         },
335 |         effects: ['onFieldInit'],
336 |       },
337 |     },
338 |     {
339 |       'x-value': field2Value,
340 |     },
341 |     {
342 |       scope: {
343 |         mockFn,
344 |       },
345 |     }
346 |   )
347 | 
348 |   expect(mockFn).toBeCalledTimes(1)
349 |   expect(mockFn).nthCalledWith(1, field2Value)
350 | 
351 |   field2.value = field1Title
352 |   expect(mockFn).toBeCalledTimes(1)
353 | })
354 | 
355 | test('userReactions with function type', () => {
356 |   const componentProps = {
357 |     prop: 1,
358 |   }
359 |   let observable: any = {}
360 |   const { field1 } = getFormAndFields({
361 |     'x-reactions': (field, baseScope) => {
362 |       baseScope.$props(componentProps)
363 |       observable = baseScope.$observable({})
364 |     },
365 |   })
366 | 
367 |   expect(field1.componentProps).toMatchObject(componentProps)
368 |   expect(isObservable(observable)).toBe(true)
369 | })
370 | 
371 | test('userReactions with $lookup $record $records $index', () => {
372 |   const initialValues = {
373 |     array: [
374 |       { a: 1, b: 2 },
375 |       { a: 3, b: 4 },
376 |     ],
377 |   }
378 |   const form = attach(
379 |     createForm({
380 |       initialValues,
381 |     })
382 |   )
383 | 
384 |   form.createArrayField({
385 |     name: 'array',
386 |   })
387 |   form.createObjectField({
388 |     name: '0',
389 |     basePath: 'array',
390 |   })
391 |   form.createObjectField({
392 |     name: '1',
393 |     basePath: 'array',
394 |   })
395 | 
396 |   const field0aSchema = new Schema({
397 |     name: 'array.0.a',
398 |     'x-reactions': `{{$self.title = $record.b}}`,
399 |   }).toFieldProps({})
400 | 
401 |   const field0bSchema = new Schema({
402 |     name: 'array.0.b',
403 |     'x-reactions': '{{$self.title = $lookup.array[0].a}}',
404 |   }).toFieldProps({})
405 | 
406 |   const field1aSchema = new Schema({
407 |     name: 'array.1.a',
408 |     'x-reactions': '{{$self.title = $records[$index].b}}',
409 |   }).toFieldProps({})
410 | 
411 |   const field1bSchema = new Schema({
412 |     name: 'array.1.b',
413 |     'x-reactions': `{{$self.title = $record.$lookup.array[$record.$index].a}}`,
414 |   }).toFieldProps({})
415 | 
416 |   const field0a = attach(form.createField(field0aSchema))
417 |   const field0b = attach(form.createField(field0bSchema))
418 |   const field1a = attach(form.createField(field1aSchema))
419 |   const field1b = attach(form.createField(field1bSchema))
420 | 
421 |   expect(field0a.title).toEqual(2)
422 |   expect(field0b.title).toEqual(1)
423 |   expect(field1a.title).toEqual(4)
424 |   expect(field1b.title).toEqual(3)
425 | })
426 | 
427 | test('userReactions with primary type record', () => {
428 |   const initialValues = {
429 |     array: [1, 2, 3],
430 |   }
431 | 
432 |   const form = attach(
433 |     createForm({
434 |       initialValues,
435 |     })
436 |   )
437 | 
438 |   const field0Schema = new Schema({
439 |     name: 'array.0',
440 |     'x-reactions': `{{$self.title = $record}}`,
441 |   }).toFieldProps({})
442 | 
443 |   const field1Schema = new Schema({
444 |     name: 'array.1',
445 |     'x-reactions': '{{$self.title = $record}}',
446 |   }).toFieldProps({})
447 | 
448 |   form.createArrayField({
449 |     name: 'array',
450 |   })
451 |   const field0 = attach(form.createField(field0Schema))
452 |   const field1 = attach(form.createField(field1Schema))
453 |   expect(field0.title).toEqual(1)
454 |   expect(field1.title).toEqual(2)
455 | })
456 | 
```

--------------------------------------------------------------------------------
/packages/next/docs/components/Select.zh-CN.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Select
  2 | 
  3 | > 下拉框组件
  4 | 
  5 | ## Markup Schema 同步数据源案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
 10 | import { createForm } from '@formily/core'
 11 | import { FormProvider, createSchemaField } from '@formily/react'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     Select,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.Number
 26 |         name="select"
 27 |         title="选择框"
 28 |         x-decorator="FormItem"
 29 |         x-component="Select"
 30 |         enum={[
 31 |           { label: '选项1', value: 1 },
 32 |           { label: '选项2', value: 2 },
 33 |         ]}
 34 |         x-component-props={{
 35 |           style: {
 36 |             width: 120,
 37 |           },
 38 |         }}
 39 |       />
 40 |     </SchemaField>
 41 |     <FormButtonGroup>
 42 |       <Submit onSubmit={console.log}>提交</Submit>
 43 |     </FormButtonGroup>
 44 |   </FormProvider>
 45 | )
 46 | ```
 47 | 
 48 | ## Markup Schema 异步联动数据源案例
 49 | 
 50 | ```tsx
 51 | import React from 'react'
 52 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
 53 | import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'
 54 | import { FormProvider, createSchemaField } from '@formily/react'
 55 | import { action } from '@formily/reactive'
 56 | 
 57 | const SchemaField = createSchemaField({
 58 |   components: {
 59 |     Select,
 60 |     FormItem,
 61 |   },
 62 | })
 63 | 
 64 | const useAsyncDataSource = (
 65 |   pattern: FormPathPattern,
 66 |   service: (field: Field) => Promise<{ label: string; value: any }[]>
 67 | ) => {
 68 |   onFieldReact(pattern, (field) => {
 69 |     field.loading = true
 70 |     service(field).then(
 71 |       action.bound((data) => {
 72 |         field.dataSource = data
 73 |         field.loading = false
 74 |       })
 75 |     )
 76 |   })
 77 | }
 78 | 
 79 | const form = createForm({
 80 |   effects: () => {
 81 |     useAsyncDataSource('select', async (field) => {
 82 |       const linkage = field.query('linkage').get('value')
 83 |       if (!linkage) return []
 84 |       return new Promise((resolve) => {
 85 |         setTimeout(() => {
 86 |           if (linkage === 1) {
 87 |             resolve([
 88 |               {
 89 |                 label: 'AAA',
 90 |                 value: 'aaa',
 91 |               },
 92 |               {
 93 |                 label: 'BBB',
 94 |                 value: 'ccc',
 95 |               },
 96 |             ])
 97 |           } else if (linkage === 2) {
 98 |             resolve([
 99 |               {
100 |                 label: 'CCC',
101 |                 value: 'ccc',
102 |               },
103 |               {
104 |                 label: 'DDD',
105 |                 value: 'ddd',
106 |               },
107 |             ])
108 |           }
109 |         }, 1500)
110 |       })
111 |     })
112 |   },
113 | })
114 | 
115 | export default () => (
116 |   <FormProvider form={form}>
117 |     <SchemaField>
118 |       <SchemaField.Number
119 |         name="linkage"
120 |         title="联动选择框"
121 |         x-decorator="FormItem"
122 |         x-component="Select"
123 |         enum={[
124 |           { label: '发请求1', value: 1 },
125 |           { label: '发请求2', value: 2 },
126 |         ]}
127 |         x-component-props={{
128 |           style: {
129 |             width: 120,
130 |           },
131 |         }}
132 |       />
133 |       <SchemaField.String
134 |         name="select"
135 |         title="异步选择框"
136 |         x-decorator="FormItem"
137 |         x-component="Select"
138 |         x-component-props={{
139 |           style: {
140 |             width: 120,
141 |           },
142 |         }}
143 |       />
144 |     </SchemaField>
145 |     <FormButtonGroup>
146 |       <Submit onSubmit={console.log}>提交</Submit>
147 |     </FormButtonGroup>
148 |   </FormProvider>
149 | )
150 | ```
151 | 
152 | ## JSON Schema 同步数据源案例
153 | 
154 | ```tsx
155 | import React from 'react'
156 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
157 | import { createForm } from '@formily/core'
158 | import { FormProvider, createSchemaField } from '@formily/react'
159 | 
160 | const SchemaField = createSchemaField({
161 |   components: {
162 |     Select,
163 |     FormItem,
164 |   },
165 | })
166 | 
167 | const form = createForm()
168 | 
169 | const schema = {
170 |   type: 'object',
171 |   properties: {
172 |     select: {
173 |       type: 'string',
174 |       title: '选择框',
175 |       'x-decorator': 'FormItem',
176 |       'x-component': 'Select',
177 |       enum: [
178 |         { label: '选项1', value: 1 },
179 |         { label: '选项2', value: 2 },
180 |       ],
181 |       'x-component-props': {
182 |         style: {
183 |           width: 120,
184 |         },
185 |       },
186 |     },
187 |   },
188 | }
189 | 
190 | export default () => (
191 |   <FormProvider form={form}>
192 |     <SchemaField schema={schema} />
193 |     <FormButtonGroup>
194 |       <Submit onSubmit={console.log}>提交</Submit>
195 |     </FormButtonGroup>
196 |   </FormProvider>
197 | )
198 | ```
199 | 
200 | ## JSON Schema 异步联动数据源案例
201 | 
202 | ```tsx
203 | import React from 'react'
204 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
205 | import { createForm } from '@formily/core'
206 | import { FormProvider, createSchemaField } from '@formily/react'
207 | import { action } from '@formily/reactive'
208 | 
209 | const SchemaField = createSchemaField({
210 |   components: {
211 |     Select,
212 |     FormItem,
213 |   },
214 | })
215 | 
216 | const loadData = async (field) => {
217 |   const linkage = field.query('linkage').get('value')
218 |   if (!linkage) return []
219 |   return new Promise((resolve) => {
220 |     setTimeout(() => {
221 |       if (linkage === 1) {
222 |         resolve([
223 |           {
224 |             label: 'AAA',
225 |             value: 'aaa',
226 |           },
227 |           {
228 |             label: 'BBB',
229 |             value: 'ccc',
230 |           },
231 |         ])
232 |       } else if (linkage === 2) {
233 |         resolve([
234 |           {
235 |             label: 'CCC',
236 |             value: 'ccc',
237 |           },
238 |           {
239 |             label: 'DDD',
240 |             value: 'ddd',
241 |           },
242 |         ])
243 |       }
244 |     }, 1500)
245 |   })
246 | }
247 | 
248 | const useAsyncDataSource = (service) => (field) => {
249 |   field.loading = true
250 |   service(field).then(
251 |     action.bound((data) => {
252 |       field.dataSource = data
253 |       field.loading = false
254 |     })
255 |   )
256 | }
257 | 
258 | const form = createForm()
259 | 
260 | const schema = {
261 |   type: 'object',
262 |   properties: {
263 |     linkage: {
264 |       type: 'string',
265 |       title: '联动选择框',
266 |       enum: [
267 |         { label: '发请求1', value: 1 },
268 |         { label: '发请求2', value: 2 },
269 |       ],
270 |       'x-decorator': 'FormItem',
271 |       'x-component': 'Select',
272 |       'x-component-props': {
273 |         style: {
274 |           width: 120,
275 |         },
276 |       },
277 |     },
278 |     select: {
279 |       type: 'string',
280 |       title: '异步选择框',
281 |       'x-decorator': 'FormItem',
282 |       'x-component': 'Select',
283 |       'x-component-props': {
284 |         style: {
285 |           width: 120,
286 |         },
287 |       },
288 |       'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
289 |     },
290 |   },
291 | }
292 | 
293 | export default () => (
294 |   <FormProvider form={form}>
295 |     <SchemaField schema={schema} scope={{ useAsyncDataSource, loadData }} />
296 |     <FormButtonGroup>
297 |       <Submit onSubmit={console.log}>提交</Submit>
298 |     </FormButtonGroup>
299 |   </FormProvider>
300 | )
301 | ```
302 | 
303 | ## 纯 JSX 同步数据源案例
304 | 
305 | ```tsx
306 | import React from 'react'
307 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
308 | import { createForm } from '@formily/core'
309 | import { FormProvider, Field } from '@formily/react'
310 | 
311 | const form = createForm()
312 | 
313 | export default () => (
314 |   <FormProvider form={form}>
315 |     <Field
316 |       name="select"
317 |       title="选择框"
318 |       dataSource={[
319 |         { label: '选项1', value: 1 },
320 |         { label: '选项2', value: 2 },
321 |       ]}
322 |       decorator={[FormItem]}
323 |       component={[
324 |         Select,
325 |         {
326 |           style: {
327 |             width: 120,
328 |           },
329 |         },
330 |       ]}
331 |     />
332 |     <FormButtonGroup>
333 |       <Submit onSubmit={console.log}>提交</Submit>
334 |     </FormButtonGroup>
335 |   </FormProvider>
336 | )
337 | ```
338 | 
339 | ## 纯 JSX 异步联动数据源案例
340 | 
341 | ```tsx
342 | import React from 'react'
343 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
344 | import {
345 |   createForm,
346 |   onFieldReact,
347 |   FormPathPattern,
348 |   FieldType,
349 | } from '@formily/core'
350 | import { FormProvider, Field } from '@formily/react'
351 | import { action } from '@formily/reactive'
352 | 
353 | const useAsyncDataSource = (
354 |   pattern: FormPathPattern,
355 |   service: (field: FieldType) => Promise<{ label: string; value: any }[]>
356 | ) => {
357 |   onFieldReact(pattern, (field) => {
358 |     field.loading = true
359 |     service(field).then(
360 |       action.bound((data) => {
361 |         field.dataSource = data
362 |         field.loading = false
363 |       })
364 |     )
365 |   })
366 | }
367 | 
368 | const form = createForm({
369 |   effects: () => {
370 |     useAsyncDataSource('select', async (field) => {
371 |       const linkage = field.query('linkage').get('value')
372 |       if (!linkage) return []
373 |       return new Promise((resolve) => {
374 |         setTimeout(() => {
375 |           if (linkage === 1) {
376 |             resolve([
377 |               {
378 |                 label: 'AAA',
379 |                 value: 'aaa',
380 |               },
381 |               {
382 |                 label: 'BBB',
383 |                 value: 'ccc',
384 |               },
385 |             ])
386 |           } else if (linkage === 2) {
387 |             resolve([
388 |               {
389 |                 label: 'CCC',
390 |                 value: 'ccc',
391 |               },
392 |               {
393 |                 label: 'DDD',
394 |                 value: 'ddd',
395 |               },
396 |             ])
397 |           }
398 |         }, 1500)
399 |       })
400 |     })
401 |   },
402 | })
403 | 
404 | export default () => (
405 |   <FormProvider form={form}>
406 |     <Field
407 |       name="linkage"
408 |       title="联动选择框"
409 |       dataSource={[
410 |         { label: '发请求1', value: 1 },
411 |         { label: '发请求2', value: 2 },
412 |       ]}
413 |       decorator={[FormItem]}
414 |       component={[
415 |         Select,
416 |         {
417 |           style: {
418 |             width: 120,
419 |           },
420 |         },
421 |       ]}
422 |     />
423 |     <Field
424 |       name="select"
425 |       title="异步选择框"
426 |       decorator={[FormItem]}
427 |       component={[
428 |         Select,
429 |         {
430 |           style: {
431 |             width: 120,
432 |           },
433 |         },
434 |       ]}
435 |     />
436 |     <FormButtonGroup>
437 |       <Submit onSubmit={console.log}>提交</Submit>
438 |     </FormButtonGroup>
439 |   </FormProvider>
440 | )
441 | ```
442 | 
443 | ## API
444 | 
445 | 参考 https://fusion.design/pc/component/basic/select
446 | 
```
Page 24/52FirstPrevNextLast