#
tokens: 48839/50000 19/1152 files (page 15/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 15 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

--------------------------------------------------------------------------------
/packages/antd/src/form-step/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { Fragment } from 'react'
  2 | import { define, observable, action, markRaw, model } from '@formily/reactive'
  3 | import { Steps } from 'antd'
  4 | import cls from 'classnames'
  5 | import { StepsProps, StepProps } from 'antd/lib/steps'
  6 | import { Form, VoidField } from '@formily/core'
  7 | import {
  8 |   connect,
  9 |   useField,
 10 |   observer,
 11 |   useFieldSchema,
 12 |   RecursionField,
 13 | } from '@formily/react'
 14 | import { Schema, SchemaKey } from '@formily/json-schema'
 15 | import { usePrefixCls } from '../__builtins__'
 16 | 
 17 | export interface IFormStep {
 18 |   connect: (steps: SchemaStep[], field: VoidField) => void
 19 |   current: number
 20 |   allowNext: boolean
 21 |   allowBack: boolean
 22 |   setCurrent(key: number): void
 23 |   submit: Form['submit']
 24 |   next(): void
 25 |   back(): void
 26 | }
 27 | 
 28 | export interface IFormStepProps extends StepsProps {
 29 |   formStep?: IFormStep
 30 | }
 31 | 
 32 | type ComposedFormStep = React.FC<React.PropsWithChildren<IFormStepProps>> & {
 33 |   StepPane: React.FC<React.PropsWithChildren<StepProps>>
 34 |   createFormStep: (defaultCurrent?: number) => IFormStep
 35 | }
 36 | 
 37 | type SchemaStep = {
 38 |   name: SchemaKey
 39 |   props: any
 40 |   schema: Schema
 41 | }
 42 | 
 43 | type FormStepEnv = {
 44 |   form: Form
 45 |   field: VoidField
 46 |   steps: SchemaStep[]
 47 | }
 48 | 
 49 | const parseSteps = (schema: Schema) => {
 50 |   const steps: SchemaStep[] = []
 51 |   schema.mapProperties((schema, name) => {
 52 |     if (schema['x-component']?.indexOf('StepPane') > -1) {
 53 |       steps.push({
 54 |         name,
 55 |         props: schema['x-component-props'],
 56 |         schema,
 57 |       })
 58 |     }
 59 |   })
 60 |   return steps
 61 | }
 62 | 
 63 | const createFormStep = (defaultCurrent = 0): IFormStep => {
 64 |   const env: FormStepEnv = define(
 65 |     {
 66 |       form: null,
 67 |       field: null,
 68 |       steps: [],
 69 |     },
 70 |     {
 71 |       form: observable.ref,
 72 |       field: observable.ref,
 73 |       steps: observable.shallow,
 74 |     }
 75 |   )
 76 | 
 77 |   const setDisplay = action.bound((target: number) => {
 78 |     const currentStep = env.steps[target]
 79 |     env.steps.forEach(({ name }) => {
 80 |       env.form.query(`${env.field.address}.${name}`).take((field) => {
 81 |         if (name === currentStep.name) {
 82 |           field.setDisplay('visible')
 83 |         } else {
 84 |           field.setDisplay('hidden')
 85 |         }
 86 |       })
 87 |     })
 88 |   })
 89 | 
 90 |   const next = action.bound(() => {
 91 |     if (formStep.allowNext) {
 92 |       formStep.setCurrent(formStep.current + 1)
 93 |     }
 94 |   })
 95 | 
 96 |   const back = action.bound(() => {
 97 |     if (formStep.allowBack) {
 98 |       formStep.setCurrent(formStep.current - 1)
 99 |     }
100 |   })
101 | 
102 |   const formStep: IFormStep = model({
103 |     connect(steps, field) {
104 |       env.steps = steps
105 |       env.form = field?.form
106 |       env.field = field
107 |     },
108 |     current: defaultCurrent,
109 |     setCurrent(key: number) {
110 |       setDisplay(key)
111 |       formStep.current = key
112 |     },
113 |     get allowNext() {
114 |       return formStep.current < env.steps.length - 1
115 |     },
116 |     get allowBack() {
117 |       return formStep.current > 0
118 |     },
119 |     async next() {
120 |       try {
121 |         await env.form.validate()
122 |         if (env.form.valid) {
123 |           next()
124 |         }
125 |       } catch {}
126 |     },
127 |     async back() {
128 |       back()
129 |     },
130 |     async submit(onSubmit) {
131 |       return env.form?.submit?.(onSubmit)
132 |     },
133 |   })
134 |   return markRaw(formStep)
135 | }
136 | 
137 | export const FormStep = connect(
138 |   observer(({ formStep, className, ...props }: IFormStepProps) => {
139 |     const field = useField<VoidField>()
140 |     const prefixCls = usePrefixCls('formily-step', props)
141 |     const schema = useFieldSchema()
142 |     const steps = parseSteps(schema)
143 |     const current = props.current || formStep?.current || 0
144 |     formStep?.connect?.(steps, field)
145 |     return (
146 |       <div className={cls(prefixCls, className)}>
147 |         <Steps
148 |           {...props}
149 |           style={{ marginBottom: 10, ...props.style }}
150 |           current={current}
151 |         >
152 |           {steps.map(({ props }, key) => {
153 |             return <Steps.Step {...props} key={key} />
154 |           })}
155 |         </Steps>
156 |         {steps.map(({ name, schema }, key) => {
157 |           if (key !== current) return
158 |           return <RecursionField key={key} name={name} schema={schema} />
159 |         })}
160 |       </div>
161 |     )
162 |   })
163 | ) as unknown as ComposedFormStep
164 | 
165 | const StepPane: React.FC<React.PropsWithChildren<StepProps>> = ({
166 |   children,
167 | }) => {
168 |   return <Fragment>{children}</Fragment>
169 | }
170 | 
171 | FormStep.StepPane = StepPane
172 | FormStep.createFormStep = createFormStep
173 | 
174 | export default FormStep
175 | 
```

--------------------------------------------------------------------------------
/packages/next/src/form-step/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { Fragment } from 'react'
  2 | import { define, observable, model, markRaw, action } from '@formily/reactive'
  3 | import cls from 'classnames'
  4 | import {
  5 |   StepProps as StepsProps,
  6 |   ItemProps as StepProps,
  7 | } from '@alifd/next/lib/step'
  8 | import { Form, VoidField } from '@formily/core'
  9 | import {
 10 |   connect,
 11 |   useField,
 12 |   observer,
 13 |   useFieldSchema,
 14 |   RecursionField,
 15 | } from '@formily/react'
 16 | import { Schema, SchemaKey } from '@formily/json-schema'
 17 | import { Step as Steps } from '@alifd/next'
 18 | import { usePrefixCls } from '../__builtins__'
 19 | 
 20 | export interface IFormStep {
 21 |   connect: (steps: SchemaStep[], field: VoidField) => void
 22 |   current: number
 23 |   allowNext: boolean
 24 |   allowBack: boolean
 25 |   setCurrent(key: number): void
 26 |   submit: Form['submit']
 27 |   next(): void
 28 |   back(): void
 29 | }
 30 | 
 31 | export interface IFormStepProps extends StepsProps {
 32 |   formStep?: IFormStep
 33 | }
 34 | 
 35 | type ComposedFormTab = React.FC<React.PropsWithChildren<IFormStepProps>> & {
 36 |   StepPane?: React.FC<React.PropsWithChildren<StepProps>>
 37 |   createFormStep?: (defaultCurrent?: number) => IFormStep
 38 | }
 39 | 
 40 | type SchemaStep = {
 41 |   name: SchemaKey
 42 |   props: any
 43 |   schema: Schema
 44 | }
 45 | 
 46 | type FormStepEnv = {
 47 |   form: Form
 48 |   field: VoidField
 49 |   steps: SchemaStep[]
 50 | }
 51 | 
 52 | const parseSteps = (schema: Schema) => {
 53 |   const steps: SchemaStep[] = []
 54 |   schema.mapProperties((schema, name) => {
 55 |     if (schema['x-component']?.indexOf('StepPane') > -1) {
 56 |       steps.push({
 57 |         name,
 58 |         props: schema['x-component-props'],
 59 |         schema,
 60 |       })
 61 |     }
 62 |   })
 63 |   return steps
 64 | }
 65 | 
 66 | const createFormStep = (defaultCurrent = 0): IFormStep => {
 67 |   const env: FormStepEnv = define(
 68 |     {
 69 |       form: null,
 70 |       field: null,
 71 |       steps: [],
 72 |     },
 73 |     {
 74 |       form: observable.ref,
 75 |       field: observable.ref,
 76 |       steps: observable.shallow,
 77 |     }
 78 |   )
 79 | 
 80 |   const setDisplay = action.bound((target: number) => {
 81 |     const currentStep = env.steps[target]
 82 |     env.steps.forEach(({ name }) => {
 83 |       env.form.query(`${env.field.address}.${name}`).take((field) => {
 84 |         if (name === currentStep.name) {
 85 |           field.setDisplay('visible')
 86 |         } else {
 87 |           field.setDisplay('hidden')
 88 |         }
 89 |       })
 90 |     })
 91 |   })
 92 | 
 93 |   const next = () => {
 94 |     if (formStep.allowNext) {
 95 |       formStep.setCurrent(formStep.current + 1)
 96 |     }
 97 |   }
 98 | 
 99 |   const back = () => {
100 |     if (formStep.allowBack) {
101 |       formStep.setCurrent(formStep.current - 1)
102 |     }
103 |   }
104 | 
105 |   const formStep: IFormStep = model({
106 |     connect(steps, field) {
107 |       env.steps = steps
108 |       env.form = field?.form
109 |       env.field = field
110 |     },
111 |     current: defaultCurrent,
112 |     setCurrent(key: number) {
113 |       setDisplay(key)
114 |       formStep.current = key
115 |     },
116 |     get allowNext() {
117 |       return formStep.current < env.steps.length - 1
118 |     },
119 |     get allowBack() {
120 |       return formStep.current > 0
121 |     },
122 |     async next() {
123 |       try {
124 |         await env.form.validate()
125 |         if (env.form.valid) {
126 |           next()
127 |         }
128 |       } catch {}
129 |     },
130 |     async back() {
131 |       back()
132 |     },
133 |     async submit(onSubmit) {
134 |       return env.form?.submit?.(onSubmit)
135 |     },
136 |   })
137 |   return markRaw(formStep)
138 | }
139 | 
140 | export const FormStep: ComposedFormTab = connect(
141 |   observer(({ formStep, className, ...props }: IFormStepProps) => {
142 |     const field = useField<VoidField>()
143 |     const prefixCls = usePrefixCls('formily-step', props)
144 |     const schema = useFieldSchema()
145 |     const steps = parseSteps(schema)
146 |     const current = props.current || formStep?.current || 0
147 |     formStep?.connect?.(steps, field)
148 |     return (
149 |       <div className={cls(prefixCls, className)}>
150 |         <Steps
151 |           {...props}
152 |           style={{ marginBottom: 10, ...props.style }}
153 |           current={current}
154 |         >
155 |           {steps.map(({ props }, key) => {
156 |             return <Steps.Item {...props} key={key} />
157 |           })}
158 |         </Steps>
159 |         {steps.map(({ name, schema }, key) => {
160 |           if (key !== current) return
161 |           return <RecursionField key={key} name={name} schema={schema} />
162 |         })}
163 |       </div>
164 |     )
165 |   })
166 | )
167 | 
168 | const StepPane: React.FC<React.PropsWithChildren<StepProps>> = ({
169 |   children,
170 | }) => {
171 |   return <Fragment>{children}</Fragment>
172 | }
173 | 
174 | FormStep.StepPane = StepPane
175 | FormStep.createFormStep = createFormStep
176 | 
177 | export default FormStep
178 | 
```

--------------------------------------------------------------------------------
/packages/element/src/form-tab/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Schema, SchemaKey } from '@formily/json-schema'
  2 | import { model } from '@formily/reactive'
  3 | import { observer } from '@formily/reactive-vue'
  4 | import {
  5 |   Fragment,
  6 |   h,
  7 |   RecursionField,
  8 |   useField,
  9 |   useFieldSchema,
 10 | } from '@formily/vue'
 11 | import { Badge, TabPane, Tabs } from 'element-ui'
 12 | import { computed, defineComponent, reactive } from 'vue-demi'
 13 | import { stylePrefix } from '../__builtins__/configs'
 14 | 
 15 | import type { TabPane as TabPaneProps, Tabs as TabsProps } from 'element-ui'
 16 | import { composeExport } from '../__builtins__/shared'
 17 | 
 18 | export interface IFormTab {
 19 |   activeKey: string
 20 |   setActiveKey(key: string): void
 21 | }
 22 | 
 23 | export interface IFormTabProps extends TabsProps {
 24 |   formTab?: IFormTab
 25 | }
 26 | 
 27 | export interface IFormTabPaneProps extends TabPaneProps {
 28 |   key: string | number
 29 | }
 30 | 
 31 | const useTabs = () => {
 32 |   const tabsField = useField().value
 33 |   const schema = useFieldSchema().value
 34 |   const tabs: { name: SchemaKey; props: any; schema: Schema }[] = reactive([])
 35 |   schema.mapProperties((schema, name) => {
 36 |     const field = tabsField.query(tabsField.address.concat(name)).take()
 37 |     if (field?.display === 'none' || field?.display === 'hidden') return
 38 |     if (schema['x-component']?.indexOf('TabPane') > -1) {
 39 |       tabs.push({
 40 |         name,
 41 |         props: {
 42 |           name: schema?.['x-component-props']?.name || name,
 43 |           ...schema?.['x-component-props'],
 44 |         },
 45 |         schema,
 46 |       })
 47 |     }
 48 |   })
 49 |   return tabs
 50 | }
 51 | 
 52 | const createFormTab = (defaultActiveKey?: string) => {
 53 |   const formTab = model({
 54 |     activeKey: defaultActiveKey,
 55 |     setActiveKey(key: string) {
 56 |       formTab.activeKey = key
 57 |     },
 58 |   })
 59 |   return formTab
 60 | }
 61 | 
 62 | const FormTabInner = observer(
 63 |   defineComponent<IFormTabProps>({
 64 |     name: 'FFormTab',
 65 |     props: ['formTab'],
 66 |     setup(props, { attrs, listeners }) {
 67 |       const field = useField().value
 68 |       const formTabRef = computed(() => props.formTab ?? createFormTab())
 69 | 
 70 |       const prefixCls = `${stylePrefix}-form-tab`
 71 | 
 72 |       return () => {
 73 |         const formTab = formTabRef.value
 74 |         const tabs = useTabs()
 75 |         const activeKey = props.value || formTab?.activeKey || tabs?.[0]?.name
 76 |         const badgedTab = (key: SchemaKey, props: any) => {
 77 |           const errors = field.form.queryFeedbacks({
 78 |             type: 'error',
 79 |             address: `${field.address.concat(key)}.*`,
 80 |           })
 81 |           if (errors.length) {
 82 |             return () =>
 83 |               h(
 84 |                 Badge,
 85 |                 {
 86 |                   class: [`${prefixCls}-errors-badge`],
 87 |                   props: {
 88 |                     value: errors.length,
 89 |                   },
 90 |                 },
 91 |                 { default: () => props.label }
 92 |               )
 93 |           }
 94 |           return () => props.label
 95 |         }
 96 | 
 97 |         const getTabs = (tabs) => {
 98 |           return tabs.map(({ props, schema, name }, key) => {
 99 |             return h(
100 |               TabPane,
101 |               {
102 |                 key,
103 |                 props,
104 |               },
105 |               {
106 |                 default: () => [
107 |                   h(
108 |                     RecursionField,
109 |                     {
110 |                       props: {
111 |                         schema,
112 |                         name,
113 |                       },
114 |                     },
115 |                     {}
116 |                   ),
117 |                 ],
118 |                 label: () => [
119 |                   h('div', {}, { default: badgedTab(name, props) }),
120 |                 ],
121 |               }
122 |             )
123 |           })
124 |         }
125 | 
126 |         return h(
127 |           Tabs,
128 |           {
129 |             class: [prefixCls],
130 |             style: attrs.style,
131 |             props: {
132 |               ...attrs,
133 |               value: activeKey,
134 |             },
135 |             on: {
136 |               ...listeners,
137 |               input: (key) => {
138 |                 listeners.input?.(key)
139 |                 formTab.setActiveKey?.(key)
140 |               },
141 |             },
142 |           },
143 |           {
144 |             default: () => getTabs(tabs),
145 |           }
146 |         )
147 |       }
148 |     },
149 |   })
150 | )
151 | 
152 | const FormTabPane = defineComponent<IFormTabPaneProps>({
153 |   name: 'FFormTabPane',
154 |   setup(_props, { slots }) {
155 |     return () => h(Fragment, {}, slots)
156 |   },
157 | })
158 | 
159 | export const FormTab = composeExport(FormTabInner, {
160 |   TabPane: FormTabPane,
161 |   createFormTab,
162 | })
163 | 
164 | export default FormTab
165 | 
```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/array-collapse/markup-schema.vue:
--------------------------------------------------------------------------------

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField>
  4 |       <SchemaArrayField
  5 |         name="string_array"
  6 |         :maxItems="3"
  7 |         x-decorator="FormItem"
  8 |         x-component="ArrayCollapse"
  9 |         :x-component-props="{
 10 |           accordion: true,
 11 |           defaultOpenPanelCount: 3,
 12 |         }"
 13 |       >
 14 |         <SchemaVoidField
 15 |           x-component="ArrayCollapse.Item"
 16 |           :x-component-props="{
 17 |             title: '字符串数组',
 18 |           }"
 19 |         >
 20 |           <SchemaVoidField x-component="ArrayCollapse.Index" />
 21 |           <SchemaStringField
 22 |             name="input"
 23 |             x-decorator="FormItem"
 24 |             title="Input"
 25 |             required
 26 |             x-component="Input"
 27 |           />
 28 |           <SchemaVoidField x-component="ArrayCollapse.Remove" />
 29 |           <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
 30 |           <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
 31 |         </SchemaVoidField>
 32 |         <SchemaVoidField
 33 |           x-component="ArrayCollapse.Addition"
 34 |           title="添加条目"
 35 |         />
 36 |       </SchemaArrayField>
 37 |       <SchemaArrayField
 38 |         name="array"
 39 |         :maxItems="3"
 40 |         x-decorator="FormItem"
 41 |         x-component="ArrayCollapse"
 42 |       >
 43 |         <SchemaObjectField
 44 |           x-component="ArrayCollapse.Item"
 45 |           :x-component-props="{
 46 |             title: '对象数组',
 47 |           }"
 48 |         >
 49 |           <SchemaVoidField x-component="ArrayCollapse.Index" />
 50 |           <SchemaStringField
 51 |             name="input"
 52 |             x-decorator="FormItem"
 53 |             title="Input"
 54 |             required
 55 |             x-component="Input"
 56 |           />
 57 |           <SchemaVoidField x-component="ArrayCollapse.Remove" />
 58 |           <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
 59 |           <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
 60 |         </SchemaObjectField>
 61 |         <SchemaVoidField
 62 |           x-component="ArrayCollapse.Addition"
 63 |           title="添加条目"
 64 |         />
 65 |       </SchemaArrayField>
 66 |       <SchemaArrayField
 67 |         name="string_array_unshift"
 68 |         :maxItems="3"
 69 |         x-decorator="FormItem"
 70 |         x-component="ArrayCollapse"
 71 |         :x-component-props="{
 72 |           defaultOpenPanelCount: 8,
 73 |         }"
 74 |       >
 75 |         <SchemaVoidField
 76 |           x-component="ArrayCollapse.Item"
 77 |           :x-component-props="{
 78 |             title: '字符串数组',
 79 |           }"
 80 |         >
 81 |           <SchemaVoidField x-component="ArrayCollapse.Index" />
 82 |           <SchemaStringField
 83 |             name="input"
 84 |             x-decorator="FormItem"
 85 |             title="Input"
 86 |             required
 87 |             x-component="Input"
 88 |           />
 89 |           <SchemaVoidField x-component="ArrayCollapse.Remove" />
 90 |           <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
 91 |           <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
 92 |         </SchemaVoidField>
 93 |         <SchemaVoidField
 94 |           x-component="ArrayCollapse.Addition"
 95 |           title="添加条目(unshift)"
 96 |           :x-component-props="{
 97 |             method: 'unshift',
 98 |           }"
 99 |         />
100 |       </SchemaArrayField>
101 |     </SchemaField>
102 |     <FormButtonGroup>
103 |       <Button
104 |         @click="
105 |           () => {
106 |             form.setInitialValues({
107 |               array: Array.from({ length: 10 }).map(() => ({
108 |                 input: 'default value',
109 |               })),
110 |               string_array: Array.from({ length: 10 }).map(
111 |                 () => 'default value'
112 |               ),
113 |               string_array_unshift: Array.from({ length: 10 }).map(
114 |                 () => 'default value'
115 |               ),
116 |             })
117 |           }
118 |         "
119 |       >
120 |         加载默认数据
121 |       </Button>
122 |       <Submit @submit="log">提交</Submit>
123 |     </FormButtonGroup>
124 |   </FormProvider>
125 | </template>
126 | 
127 | <script>
128 | import { createForm } from '@formily/core'
129 | import { FormProvider, createSchemaField } from '@formily/vue'
130 | import {
131 |   FormItem,
132 |   FormButtonGroup,
133 |   Submit,
134 |   Input,
135 |   ArrayCollapse,
136 | } from '@formily/element'
137 | import { Button } from 'element-ui'
138 | 
139 | const SchemaField = createSchemaField({
140 |   components: {
141 |     FormItem,
142 |     Input,
143 |     ArrayCollapse,
144 |   },
145 | })
146 | 
147 | export default {
148 |   components: {
149 |     FormProvider,
150 |     FormButtonGroup,
151 |     Button,
152 |     Submit,
153 |     ...SchemaField,
154 |   },
155 | 
156 |   data() {
157 |     const form = createForm()
158 | 
159 |     return {
160 |       form,
161 |     }
162 |   },
163 |   methods: {
164 |     log(values) {
165 |       console.log(values)
166 |     },
167 |   },
168 | }
169 | </script>
170 | 
171 | <style lang="scss" scoped></style>
172 | 
```

--------------------------------------------------------------------------------
/packages/element/src/checkbox/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { connect, h, mapProps, mapReadPretty } from '@formily/vue'
  2 | import type {
  3 |   Checkbox as _ElCheckboxProps,
  4 |   CheckboxGroup as ElCheckboxGroupProps,
  5 | } from 'element-ui'
  6 | import {
  7 |   Checkbox as ElCheckbox,
  8 |   CheckboxButton as ElCheckboxButton,
  9 |   CheckboxGroup as ElCheckboxGroup,
 10 | } from 'element-ui'
 11 | import { defineComponent, PropType } from 'vue-demi'
 12 | import { PreviewText } from '../preview-text'
 13 | import {
 14 |   composeExport,
 15 |   resolveComponent,
 16 |   SlotTypes,
 17 |   transformComponent,
 18 | } from '../__builtins__/shared'
 19 | 
 20 | type ElCheckboxProps = Omit<_ElCheckboxProps, 'value'> & {
 21 |   value: ElCheckboxProps['label']
 22 | }
 23 | 
 24 | export interface CheckboxProps extends ElCheckboxProps {
 25 |   option: Omit<_ElCheckboxProps, 'value'> & {
 26 |     value: ElCheckboxProps['label']
 27 |     label: SlotTypes
 28 |   }
 29 | }
 30 | 
 31 | const CheckboxOption = defineComponent<CheckboxProps>({
 32 |   name: 'Checkbox',
 33 |   inheritAttrs: false,
 34 |   props: {
 35 |     option: {
 36 |       type: Object,
 37 |       default: null,
 38 |     },
 39 |   },
 40 |   setup(curtomProps, { attrs, slots, listeners }) {
 41 |     return () => {
 42 |       const props = attrs as unknown as CheckboxProps
 43 |       const option = curtomProps?.option
 44 |       if (option) {
 45 |         const children = {
 46 |           default: () => [
 47 |             resolveComponent(slots.default ?? option.label, { option }),
 48 |           ],
 49 |         }
 50 |         const newProps = {} as Partial<ElCheckboxProps>
 51 |         Object.assign(newProps, option)
 52 |         newProps.label = option.value
 53 |         delete newProps.value
 54 | 
 55 |         return h(
 56 |           attrs.optionType === 'button' ? ElCheckboxButton : ElCheckbox,
 57 |           {
 58 |             attrs: {
 59 |               ...newProps,
 60 |             },
 61 |           },
 62 |           children
 63 |         )
 64 |       }
 65 | 
 66 |       return h(
 67 |         ElCheckbox,
 68 |         {
 69 |           attrs: {
 70 |             ...props,
 71 |           },
 72 |           on: listeners,
 73 |         },
 74 |         slots
 75 |       )
 76 |     }
 77 |   },
 78 | })
 79 | 
 80 | export type CheckboxGroupProps = ElCheckboxGroupProps & {
 81 |   value: any[]
 82 |   options?: Array<CheckboxProps | string>
 83 |   optionType: 'default' | 'button'
 84 | }
 85 | 
 86 | const TransformElCheckboxGroup = transformComponent(ElCheckboxGroup, {
 87 |   change: 'input',
 88 |   uselessChange: 'change'
 89 | })
 90 | 
 91 | const CheckboxGroupOption = defineComponent<CheckboxGroupProps>({
 92 |   name: 'CheckboxGroup',
 93 |   props: {
 94 |     options: {
 95 |       type: Array,
 96 |       default: () => [],
 97 |     },
 98 |     optionType: {
 99 |       type: String as PropType<CheckboxGroupProps['optionType']>,
100 |       default: 'default',
101 |     },
102 |   },
103 |   setup(customProps, { attrs, slots, listeners }) {
104 |     return () => {
105 |       const options = customProps.options || []
106 |       const children =
107 |         options.length !== 0
108 |           ? {
109 |               default: () =>
110 |                 options.map((option) => {
111 |                   if (typeof option === 'string') {
112 |                     return h(
113 |                       Checkbox,
114 |                       {
115 |                         props: {
116 |                           option: {
117 |                             label: option,
118 |                             value: option,
119 |                           },
120 |                         },
121 |                         attrs: {
122 |                           optionType: customProps.optionType,
123 |                         },
124 |                       },
125 |                       slots?.option
126 |                         ? { default: () => slots.option({ option }) }
127 |                         : {}
128 |                     )
129 |                   } else {
130 |                     return h(
131 |                       Checkbox,
132 |                       {
133 |                         props: {
134 |                           option,
135 |                         },
136 |                         attrs: {
137 |                           optionType: customProps.optionType,
138 |                         },
139 |                       },
140 |                       slots?.option
141 |                         ? { default: () => slots.option({ option }) }
142 |                         : {}
143 |                     )
144 |                   }
145 |                 }),
146 |             }
147 |           : slots
148 |       return h(
149 |         TransformElCheckboxGroup,
150 |         {
151 |           attrs: {
152 |             ...attrs,
153 |           },
154 |           on: listeners,
155 |         },
156 |         children
157 |       )
158 |     }
159 |   },
160 | })
161 | 
162 | const CheckboxGroup = connect(
163 |   CheckboxGroupOption,
164 |   mapProps({ dataSource: 'options' }),
165 |   mapReadPretty(PreviewText.Select, {
166 |     multiple: true,
167 |   })
168 | )
169 | 
170 | export const Checkbox = composeExport(connect(CheckboxOption), {
171 |   Group: CheckboxGroup,
172 | })
173 | 
174 | export default Checkbox
175 | 
```

--------------------------------------------------------------------------------
/packages/react/src/components/RecursionField.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { Fragment, useMemo } from 'react'
  2 | import { FormPath, isBool, isFn, isValid } from '@formily/shared'
  3 | import { GeneralField } from '@formily/core'
  4 | import { Schema } from '@formily/json-schema'
  5 | import { SchemaContext } from '../shared'
  6 | import { IRecursionFieldProps, ReactFC } from '../types'
  7 | import { useField, useExpressionScope } from '../hooks'
  8 | import { ObjectField } from './ObjectField'
  9 | import { ArrayField } from './ArrayField'
 10 | import { Field } from './Field'
 11 | import { VoidField } from './VoidField'
 12 | import { ExpressionScope } from './ExpressionScope'
 13 | import { observable } from '@formily/reactive'
 14 | 
 15 | const useFieldProps = (schema: Schema) => {
 16 |   const scope = useExpressionScope()
 17 |   return schema.toFieldProps({
 18 |     scope,
 19 |   }) as any
 20 | }
 21 | 
 22 | const useBasePath = (props: IRecursionFieldProps) => {
 23 |   const parent = useField()
 24 |   if (props.onlyRenderProperties) {
 25 |     return props.basePath || parent?.address.concat(props.name)
 26 |   }
 27 |   return props.basePath || parent?.address
 28 | }
 29 | 
 30 | export const RecursionField: ReactFC<IRecursionFieldProps> = (props) => {
 31 |   const basePath = useBasePath(props)
 32 |   const fieldSchema = useMemo(() => new Schema(props.schema), [props.schema])
 33 |   const fieldProps = useFieldProps(fieldSchema)
 34 | 
 35 |   const renderSlots = (innerSchema, key) => {
 36 |     const slot = innerSchema['x-slot-node']
 37 |     const { target, isRenderProp } = slot
 38 |     if (isRenderProp) {
 39 |       const args = observable({ $slotArgs: [] })
 40 |       FormPath.setIn(fieldSchema.properties, target, (..._args: any) => {
 41 |         args.$slotArgs = _args
 42 |         return (
 43 |           <ExpressionScope value={args}>
 44 |             <RecursionField schema={innerSchema} name={key} />
 45 |           </ExpressionScope>
 46 |         )
 47 |       })
 48 |     } else {
 49 |       FormPath.setIn(
 50 |         fieldSchema.properties,
 51 |         target,
 52 |         <RecursionField schema={innerSchema} name={key} />
 53 |       )
 54 |     }
 55 |   }
 56 | 
 57 |   const renderProperties = (field?: GeneralField) => {
 58 |     if (props.onlyRenderSelf) return
 59 |     const properties = Schema.getOrderProperties(fieldSchema)
 60 |     if (!properties.length) return
 61 |     return (
 62 |       <Fragment>
 63 |         {properties.map(({ schema: item, key: name }, index) => {
 64 |           const base = field?.address || basePath
 65 |           let schema: Schema = item
 66 |           if (schema['x-slot-node']) {
 67 |             renderSlots(schema, name)
 68 |             return null
 69 |           }
 70 | 
 71 |           if (isFn(props.mapProperties)) {
 72 |             const mapped = props.mapProperties(item, name)
 73 |             if (mapped) {
 74 |               schema = mapped
 75 |             }
 76 |           }
 77 |           if (isFn(props.filterProperties)) {
 78 |             if (props.filterProperties(schema, name) === false) {
 79 |               return null
 80 |             }
 81 |           }
 82 |           if (isBool(props.propsRecursion) && props.propsRecursion) {
 83 |             return (
 84 |               <RecursionField
 85 |                 propsRecursion={true}
 86 |                 filterProperties={props.filterProperties}
 87 |                 mapProperties={props.mapProperties}
 88 |                 schema={schema}
 89 |                 key={`${index}-${name}`}
 90 |                 name={name}
 91 |                 basePath={base}
 92 |               />
 93 |             )
 94 |           }
 95 |           return (
 96 |             <RecursionField
 97 |               schema={schema}
 98 |               key={`${index}-${name}`}
 99 |               name={name}
100 |               basePath={base}
101 |             />
102 |           )
103 |         })}
104 |       </Fragment>
105 |     )
106 |   }
107 | 
108 |   const render = () => {
109 |     if (!isValid(props.name)) return renderProperties()
110 |     if (fieldSchema.type === 'object') {
111 |       if (props.onlyRenderProperties) return renderProperties()
112 |       return (
113 |         <ObjectField {...fieldProps} name={props.name} basePath={basePath}>
114 |           {renderProperties}
115 |         </ObjectField>
116 |       )
117 |     } else if (fieldSchema.type === 'array') {
118 |       return (
119 |         <ArrayField {...fieldProps} name={props.name} basePath={basePath} />
120 |       )
121 |     } else if (fieldSchema.type === 'void') {
122 |       if (props.onlyRenderProperties) return renderProperties()
123 |       return (
124 |         <VoidField {...fieldProps} name={props.name} basePath={basePath}>
125 |           {renderProperties}
126 |         </VoidField>
127 |       )
128 |     }
129 |     return <Field {...fieldProps} name={props.name} basePath={basePath} />
130 |   }
131 | 
132 |   if (!fieldSchema) return <Fragment />
133 | 
134 |   return (
135 |     <SchemaContext.Provider value={fieldSchema}>
136 |       {render()}
137 |     </SchemaContext.Provider>
138 |   )
139 | }
140 | 
```

--------------------------------------------------------------------------------
/packages/antd/src/array-cards/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React from 'react'
  2 | import { Card, Empty } from 'antd'
  3 | import { CardProps } from 'antd/lib/card'
  4 | import { ArrayField } from '@formily/core'
  5 | import {
  6 |   useField,
  7 |   observer,
  8 |   useFieldSchema,
  9 |   RecursionField,
 10 | } from '@formily/react'
 11 | import cls from 'classnames'
 12 | import { ISchema } from '@formily/json-schema'
 13 | import { usePrefixCls } from '../__builtins__'
 14 | import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from '../array-base'
 15 | 
 16 | type ComposedArrayCards = React.FC<
 17 |   React.PropsWithChildren<CardProps & IArrayBaseProps>
 18 | > &
 19 |   ArrayBaseMixins
 20 | 
 21 | const isAdditionComponent = (schema: ISchema) => {
 22 |   return schema['x-component']?.indexOf('Addition') > -1
 23 | }
 24 | 
 25 | const isIndexComponent = (schema: ISchema) => {
 26 |   return schema['x-component']?.indexOf?.('Index') > -1
 27 | }
 28 | 
 29 | const isRemoveComponent = (schema: ISchema) => {
 30 |   return schema['x-component']?.indexOf?.('Remove') > -1
 31 | }
 32 | 
 33 | const isCopyComponent = (schema: ISchema) => {
 34 |   return schema['x-component']?.indexOf?.('Copy') > -1
 35 | }
 36 | 
 37 | const isMoveUpComponent = (schema: ISchema) => {
 38 |   return schema['x-component']?.indexOf?.('MoveUp') > -1
 39 | }
 40 | 
 41 | const isMoveDownComponent = (schema: ISchema) => {
 42 |   return schema['x-component']?.indexOf?.('MoveDown') > -1
 43 | }
 44 | 
 45 | const isOperationComponent = (schema: ISchema) => {
 46 |   return (
 47 |     isAdditionComponent(schema) ||
 48 |     isRemoveComponent(schema) ||
 49 |     isCopyComponent(schema) ||
 50 |     isMoveDownComponent(schema) ||
 51 |     isMoveUpComponent(schema)
 52 |   )
 53 | }
 54 | 
 55 | export const ArrayCards: ComposedArrayCards = observer((props) => {
 56 |   const field = useField<ArrayField>()
 57 |   const schema = useFieldSchema()
 58 |   const dataSource = Array.isArray(field.value) ? field.value : []
 59 |   const prefixCls = usePrefixCls('formily-array-cards', props)
 60 |   const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp } = props
 61 | 
 62 |   if (!schema) throw new Error('can not found schema object')
 63 | 
 64 |   const renderItems = () => {
 65 |     return dataSource?.map((item, index) => {
 66 |       const items = Array.isArray(schema.items)
 67 |         ? schema.items[index] || schema.items[0]
 68 |         : schema.items
 69 |       const title = (
 70 |         <span>
 71 |           <RecursionField
 72 |             schema={items}
 73 |             name={index}
 74 |             filterProperties={(schema) => {
 75 |               if (!isIndexComponent(schema)) return false
 76 |               return true
 77 |             }}
 78 |             onlyRenderProperties
 79 |           />
 80 |           {props.title || field.title}
 81 |         </span>
 82 |       )
 83 |       const extra = (
 84 |         <span>
 85 |           <RecursionField
 86 |             schema={items}
 87 |             name={index}
 88 |             filterProperties={(schema) => {
 89 |               if (!isOperationComponent(schema)) return false
 90 |               return true
 91 |             }}
 92 |             onlyRenderProperties
 93 |           />
 94 |           {props.extra}
 95 |         </span>
 96 |       )
 97 |       const content = (
 98 |         <RecursionField
 99 |           schema={items}
100 |           name={index}
101 |           filterProperties={(schema) => {
102 |             if (isIndexComponent(schema)) return false
103 |             if (isOperationComponent(schema)) return false
104 |             return true
105 |           }}
106 |         />
107 |       )
108 |       return (
109 |         <ArrayBase.Item
110 |           key={index}
111 |           index={index}
112 |           record={() => field.value?.[index]}
113 |         >
114 |           <Card
115 |             {...props}
116 |             onChange={() => {}}
117 |             className={cls(`${prefixCls}-item`, props.className)}
118 |             title={title}
119 |             extra={extra}
120 |           >
121 |             {content}
122 |           </Card>
123 |         </ArrayBase.Item>
124 |       )
125 |     })
126 |   }
127 | 
128 |   const renderAddition = () => {
129 |     return schema.reduceProperties((addition, schema, key) => {
130 |       if (isAdditionComponent(schema)) {
131 |         return <RecursionField schema={schema} name={key} />
132 |       }
133 |       return addition
134 |     }, null)
135 |   }
136 | 
137 |   const renderEmpty = () => {
138 |     if (dataSource?.length) return
139 |     return (
140 |       <Card
141 |         {...props}
142 |         onChange={() => {}}
143 |         className={cls(`${prefixCls}-item`, props.className)}
144 |         title={props.title || field.title}
145 |       >
146 |         <Empty />
147 |       </Card>
148 |     )
149 |   }
150 | 
151 |   return (
152 |     <ArrayBase
153 |       onAdd={onAdd}
154 |       onCopy={onCopy}
155 |       onRemove={onRemove}
156 |       onMoveUp={onMoveUp}
157 |       onMoveDown={onMoveDown}
158 |     >
159 |       {renderEmpty()}
160 |       {renderItems()}
161 |       {renderAddition()}
162 |     </ArrayBase>
163 |   )
164 | })
165 | 
166 | ArrayCards.displayName = 'ArrayCards'
167 | 
168 | ArrayBase.mixin(ArrayCards)
169 | 
170 | export default ArrayCards
171 | 
```

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

```typescript
  1 | import { define, model, observable, autorun } from '..'
  2 | import { observe } from '../observe'
  3 | import { FormPath } from '@formily/shared'
  4 | import { batch } from '../batch'
  5 | 
  6 | describe('makeObservable', () => {
  7 |   test('observable annotation', () => {
  8 |     const target: any = {
  9 |       aa: {},
 10 |     }
 11 |     define(target, {
 12 |       aa: observable,
 13 |     })
 14 |     const handler = jest.fn()
 15 |     const handler1 = jest.fn()
 16 |     const handler2 = jest.fn()
 17 |     autorun(() => {
 18 |       handler(FormPath.getIn(target, 'aa.bb.cc'))
 19 |     })
 20 |     observe(target, handler1)
 21 |     observe(target.aa, handler2)
 22 |     target.aa.bb = { cc: { dd: { ee: 123 } } }
 23 |     target.aa = { hh: 123 }
 24 |     expect(handler).toBeCalledTimes(3)
 25 |     expect(handler).nthCalledWith(1, undefined)
 26 |     expect(handler).nthCalledWith(2, { dd: { ee: 123 } })
 27 |     expect(handler).nthCalledWith(3, undefined)
 28 |     expect(handler1).toBeCalledTimes(2)
 29 |     expect(handler2).toBeCalledTimes(2)
 30 |   })
 31 |   test('shallow annotation', () => {
 32 |     const target: any = {
 33 |       aa: {},
 34 |     }
 35 |     define(target, {
 36 |       aa: observable.shallow,
 37 |     })
 38 |     const handler = jest.fn()
 39 |     const handler1 = jest.fn()
 40 |     const handler2 = jest.fn()
 41 |     autorun(() => {
 42 |       handler(FormPath.getIn(target, 'aa.bb.cc'))
 43 |     })
 44 |     observe(target, handler1)
 45 |     observe(target.aa, handler2)
 46 |     target.aa.bb = { cc: { dd: { ee: 123 } } }
 47 |     target.aa.bb.cc.kk = 333
 48 |     target.aa = { hh: 123 }
 49 |     expect(handler).toBeCalledTimes(3)
 50 |     expect(handler).nthCalledWith(1, undefined)
 51 |     expect(handler).nthCalledWith(2, { dd: { ee: 123 }, kk: 333 })
 52 |     expect(handler).nthCalledWith(3, undefined)
 53 |     expect(handler1).toBeCalledTimes(2)
 54 |     expect(handler2).toBeCalledTimes(2)
 55 |   })
 56 |   test('box annotation', () => {
 57 |     const target: any = {}
 58 |     define(target, {
 59 |       aa: observable.box,
 60 |     })
 61 |     const handler = jest.fn()
 62 |     const handler1 = jest.fn()
 63 |     const handler2 = jest.fn()
 64 |     autorun(() => {
 65 |       handler(target.aa.get())
 66 |     })
 67 |     observe(target, handler1)
 68 |     observe(target.aa, handler2)
 69 | 
 70 |     expect(handler).lastCalledWith(undefined)
 71 |     target.aa.set(123)
 72 |     expect(handler).toBeCalledTimes(2)
 73 |     expect(handler).lastCalledWith(123)
 74 |     expect(handler1).toBeCalledTimes(1)
 75 |     expect(handler2).toBeCalledTimes(1)
 76 |   })
 77 |   test('ref annotation', () => {
 78 |     const target: any = {}
 79 |     define(target, {
 80 |       aa: observable.ref,
 81 |     })
 82 |     const handler = jest.fn()
 83 |     const handler1 = jest.fn()
 84 |     autorun(() => {
 85 |       handler(target.aa)
 86 |     })
 87 |     observe(target, handler1)
 88 |     expect(handler).lastCalledWith(undefined)
 89 |     target.aa = 123
 90 |     expect(handler).toBeCalledTimes(2)
 91 |     expect(handler).lastCalledWith(123)
 92 |     expect(handler1).toBeCalledTimes(1)
 93 |   })
 94 |   test('action annotation', () => {
 95 |     const target = {
 96 |       aa: {
 97 |         bb: null,
 98 |         cc: null,
 99 |       },
100 |       setData() {
101 |         target.aa.bb = 123
102 |         target.aa.cc = 312
103 |       },
104 |     }
105 |     define(target, {
106 |       aa: observable,
107 |       setData: batch,
108 |     })
109 |     const handler = jest.fn()
110 |     autorun(() => {
111 |       handler([target.aa.bb, target.aa.cc])
112 |     })
113 |     expect(handler).toBeCalledTimes(1)
114 |     target.setData()
115 |     expect(handler).toBeCalledTimes(2)
116 |   })
117 |   test('computed annotation', () => {
118 |     const handler = jest.fn()
119 |     const target = {
120 |       aa: 11,
121 |       bb: 22,
122 |       get cc() {
123 |         handler()
124 |         return this.aa + this.bb
125 |       },
126 |     }
127 |     define(target, {
128 |       aa: observable,
129 |       bb: observable,
130 |       cc: observable.computed,
131 |     })
132 |     autorun(() => {
133 |       target.cc
134 |     })
135 |     expect(handler).toBeCalledTimes(1)
136 |     expect(target.cc).toEqual(33)
137 |     target.aa = 22
138 |     expect(handler).toBeCalledTimes(2)
139 |     expect(target.cc).toEqual(44)
140 |   })
141 |   test('unexpect target', () => {
142 |     const testFn = jest.fn()
143 |     const testArr = []
144 |     const obs1 = define(4 as any, {
145 |       value: observable.computed,
146 |     })
147 |     const obs2 = define('123' as any, {
148 |       value: observable.computed,
149 |     })
150 |     const obs3 = define(testFn as any, {
151 |       value: observable.computed,
152 |     })
153 |     const obs4 = define(testArr as any, {
154 |       value: observable.computed,
155 |     })
156 |     expect(obs1).toBe(4)
157 |     expect(obs2).toBe('123')
158 |     expect(obs3).toBe(testFn)
159 |     expect(obs4).toBe(testArr)
160 |   })
161 | })
162 | 
163 | test('define model', () => {
164 |   const obs = model({
165 |     aa: 1,
166 |     action() {
167 |       this.aa++
168 |     },
169 |   })
170 |   const { action } = obs
171 |   action()
172 |   expect(obs.aa).toEqual(2)
173 | })
174 | 
```

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

```markdown
  1 | # Reset
  2 | 
  3 | > 重置按钮
  4 | 
  5 | ## 普通重置
  6 | 
  7 | > 有默认值的控件无法被清空
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
 12 | import { createForm } from '@formily/core'
 13 | import { FormProvider, createSchemaField } from '@formily/react'
 14 | 
 15 | const SchemaField = createSchemaField({
 16 |   components: {
 17 |     Input,
 18 |     FormItem,
 19 |   },
 20 | })
 21 | 
 22 | const form = createForm()
 23 | 
 24 | export default () => (
 25 |   <FormProvider form={form}>
 26 |     <SchemaField>
 27 |       <SchemaField.String
 28 |         name="input"
 29 |         title="输入框"
 30 |         required
 31 |         x-decorator="FormItem"
 32 |         x-component="Input"
 33 |       />
 34 |       <SchemaField.String
 35 |         name="input2"
 36 |         title="输入框"
 37 |         default="123"
 38 |         required
 39 |         x-decorator="FormItem"
 40 |         x-component="Input"
 41 |       />
 42 |     </SchemaField>
 43 |     <FormButtonGroup>
 44 |       <Reset>重置</Reset>
 45 |     </FormButtonGroup>
 46 |   </FormProvider>
 47 | )
 48 | ```
 49 | 
 50 | ## 强制清空重置
 51 | 
 52 | ```tsx
 53 | import React from 'react'
 54 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
 55 | import { createForm } from '@formily/core'
 56 | import { FormProvider, createSchemaField } from '@formily/react'
 57 | 
 58 | const SchemaField = createSchemaField({
 59 |   components: {
 60 |     Input,
 61 |     FormItem,
 62 |   },
 63 | })
 64 | 
 65 | const form = createForm()
 66 | 
 67 | export default () => (
 68 |   <FormProvider form={form}>
 69 |     <SchemaField>
 70 |       <SchemaField.String
 71 |         name="input"
 72 |         title="输入框"
 73 |         required
 74 |         x-decorator="FormItem"
 75 |         x-component="Input"
 76 |       />
 77 |       <SchemaField.String
 78 |         name="input2"
 79 |         title="输入框"
 80 |         default="123"
 81 |         required
 82 |         x-decorator="FormItem"
 83 |         x-component="Input"
 84 |       />
 85 |     </SchemaField>
 86 |     <FormButtonGroup>
 87 |       <Reset forceClear>重置</Reset>
 88 |     </FormButtonGroup>
 89 |   </FormProvider>
 90 | )
 91 | ```
 92 | 
 93 | ## 重置并校验
 94 | 
 95 | ```tsx
 96 | import React from 'react'
 97 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
 98 | import { createForm } from '@formily/core'
 99 | import { FormProvider, createSchemaField } from '@formily/react'
100 | 
101 | const SchemaField = createSchemaField({
102 |   components: {
103 |     Input,
104 |     FormItem,
105 |   },
106 | })
107 | 
108 | const form = createForm()
109 | 
110 | export default () => (
111 |   <FormProvider form={form}>
112 |     <SchemaField>
113 |       <SchemaField.String
114 |         name="input"
115 |         title="输入框"
116 |         required
117 |         x-decorator="FormItem"
118 |         x-component="Input"
119 |       />
120 |       <SchemaField.String
121 |         name="input2"
122 |         title="输入框"
123 |         default="123"
124 |         required
125 |         x-decorator="FormItem"
126 |         x-component="Input"
127 |       />
128 |     </SchemaField>
129 |     <FormButtonGroup>
130 |       <Reset validate>重置</Reset>
131 |     </FormButtonGroup>
132 |   </FormProvider>
133 | )
134 | ```
135 | 
136 | ## 强制清空重置并校验
137 | 
138 | ```tsx
139 | import React from 'react'
140 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
141 | import { createForm } from '@formily/core'
142 | import { FormProvider, createSchemaField } from '@formily/react'
143 | 
144 | const SchemaField = createSchemaField({
145 |   components: {
146 |     Input,
147 |     FormItem,
148 |   },
149 | })
150 | 
151 | const form = createForm()
152 | 
153 | export default () => (
154 |   <FormProvider form={form}>
155 |     <SchemaField>
156 |       <SchemaField.String
157 |         name="input"
158 |         title="输入框"
159 |         required
160 |         x-decorator="FormItem"
161 |         x-component="Input"
162 |       />
163 |       <SchemaField.String
164 |         name="input2"
165 |         title="输入框"
166 |         default="123"
167 |         required
168 |         x-decorator="FormItem"
169 |         x-component="Input"
170 |       />
171 |     </SchemaField>
172 |     <FormButtonGroup>
173 |       <Reset forceClear validate>
174 |         重置
175 |       </Reset>
176 |     </FormButtonGroup>
177 |   </FormProvider>
178 | )
179 | ```
180 | 
181 | ## API
182 | 
183 | ### Reset
184 | 
185 | 其余 API 参考 https://ant.design/components/button-cn/
186 | 
187 | | 属性名                 | 类型                                                                                                   | 描述                                  | 默认值 |
188 | | ---------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ |
189 | | onClick                | `(event: MouseEvent) => void \| boolean`                                                               | 点击事件,如果返回 false 可以阻塞重置 | -      |
190 | | onResetValidateSuccess | (payload: any) => void                                                                                 | 重置校验成功事件                      | -      |
191 | | onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/zh-CN/api/models/form#iformfeedback)[]) => void | 重置校验失败事件                      | -      |
192 | 
```

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

```markdown
  1 | # Reset
  2 | 
  3 | > 重置按钮
  4 | 
  5 | ## 普通重置
  6 | 
  7 | > 有默认值的控件无法被清空
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
 12 | import { createForm } from '@formily/core'
 13 | import { FormProvider, createSchemaField } from '@formily/react'
 14 | 
 15 | const SchemaField = createSchemaField({
 16 |   components: {
 17 |     Input,
 18 |     FormItem,
 19 |   },
 20 | })
 21 | 
 22 | const form = createForm()
 23 | 
 24 | export default () => (
 25 |   <FormProvider form={form}>
 26 |     <SchemaField>
 27 |       <SchemaField.String
 28 |         name="input"
 29 |         title="输入框"
 30 |         required
 31 |         x-decorator="FormItem"
 32 |         x-component="Input"
 33 |       />
 34 |       <SchemaField.String
 35 |         name="input2"
 36 |         title="输入框"
 37 |         default="123"
 38 |         required
 39 |         x-decorator="FormItem"
 40 |         x-component="Input"
 41 |       />
 42 |     </SchemaField>
 43 |     <FormButtonGroup>
 44 |       <Reset>重置</Reset>
 45 |     </FormButtonGroup>
 46 |   </FormProvider>
 47 | )
 48 | ```
 49 | 
 50 | ## 强制清空重置
 51 | 
 52 | ```tsx
 53 | import React from 'react'
 54 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
 55 | import { createForm } from '@formily/core'
 56 | import { FormProvider, createSchemaField } from '@formily/react'
 57 | 
 58 | const SchemaField = createSchemaField({
 59 |   components: {
 60 |     Input,
 61 |     FormItem,
 62 |   },
 63 | })
 64 | 
 65 | const form = createForm()
 66 | 
 67 | export default () => (
 68 |   <FormProvider form={form}>
 69 |     <SchemaField>
 70 |       <SchemaField.String
 71 |         name="input"
 72 |         title="输入框"
 73 |         required
 74 |         x-decorator="FormItem"
 75 |         x-component="Input"
 76 |       />
 77 |       <SchemaField.String
 78 |         name="input2"
 79 |         title="输入框"
 80 |         default="123"
 81 |         required
 82 |         x-decorator="FormItem"
 83 |         x-component="Input"
 84 |       />
 85 |     </SchemaField>
 86 |     <FormButtonGroup>
 87 |       <Reset forceClear>重置</Reset>
 88 |     </FormButtonGroup>
 89 |   </FormProvider>
 90 | )
 91 | ```
 92 | 
 93 | ## 重置并校验
 94 | 
 95 | ```tsx
 96 | import React from 'react'
 97 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
 98 | import { createForm } from '@formily/core'
 99 | import { FormProvider, createSchemaField } from '@formily/react'
100 | 
101 | const SchemaField = createSchemaField({
102 |   components: {
103 |     Input,
104 |     FormItem,
105 |   },
106 | })
107 | 
108 | const form = createForm()
109 | 
110 | export default () => (
111 |   <FormProvider form={form}>
112 |     <SchemaField>
113 |       <SchemaField.String
114 |         name="input"
115 |         title="输入框"
116 |         required
117 |         x-decorator="FormItem"
118 |         x-component="Input"
119 |       />
120 |       <SchemaField.String
121 |         name="input2"
122 |         title="输入框"
123 |         default="123"
124 |         required
125 |         x-decorator="FormItem"
126 |         x-component="Input"
127 |       />
128 |     </SchemaField>
129 |     <FormButtonGroup>
130 |       <Reset validate>重置</Reset>
131 |     </FormButtonGroup>
132 |   </FormProvider>
133 | )
134 | ```
135 | 
136 | ## 强制清空重置并校验
137 | 
138 | ```tsx
139 | import React from 'react'
140 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
141 | import { createForm } from '@formily/core'
142 | import { FormProvider, createSchemaField } from '@formily/react'
143 | 
144 | const SchemaField = createSchemaField({
145 |   components: {
146 |     Input,
147 |     FormItem,
148 |   },
149 | })
150 | 
151 | const form = createForm()
152 | 
153 | export default () => (
154 |   <FormProvider form={form}>
155 |     <SchemaField>
156 |       <SchemaField.String
157 |         name="input"
158 |         title="输入框"
159 |         required
160 |         x-decorator="FormItem"
161 |         x-component="Input"
162 |       />
163 |       <SchemaField.String
164 |         name="input2"
165 |         title="输入框"
166 |         default="123"
167 |         required
168 |         x-decorator="FormItem"
169 |         x-component="Input"
170 |       />
171 |     </SchemaField>
172 |     <FormButtonGroup>
173 |       <Reset forceClear validate>
174 |         重置
175 |       </Reset>
176 |     </FormButtonGroup>
177 |   </FormProvider>
178 | )
179 | ```
180 | 
181 | ## API
182 | 
183 | ### Reset
184 | 
185 | 其余 API 参考 https://fusion.design/pc/component/basic/button
186 | 
187 | | 属性名                 | 类型                                                                                                   | 描述                                  | 默认值 |
188 | | ---------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ |
189 | | onClick                | `(event: MouseEvent) => void \| boolean`                                                               | 点击事件,如果返回 false 可以阻塞重置 | -      |
190 | | onResetValidateSuccess | (payload: any) => void                                                                                 | 重置校验成功事件                      | -      |
191 | | onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/zh-CN/api/models/form#iformfeedback)[]) => void | 重置校验失败事件                      | -      |
192 | 
```

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

```markdown
  1 | # Form
  2 | 
  3 | > The combination of FormProvider + FormLayout + form tags can help us quickly implement forms that are submitted with carriage return and can be laid out in batches
  4 | 
  5 | ## Use Cases
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   Input,
 11 |   Select,
 12 |   Form,
 13 |   FormItem,
 14 |   FormGrid,
 15 |   FormButtonGroup,
 16 |   Submit,
 17 | } from '@formily/next'
 18 | import { createForm } from '@formily/core'
 19 | import { Field } from '@formily/react'
 20 | 
 21 | const form = createForm()
 22 | 
 23 | export default () => (
 24 |   <Form
 25 |     form={form}
 26 |     layout="vertical"
 27 |     feedbackLayout="terse"
 28 |     onAutoSubmit={console.log}
 29 |     onAutoSubmitFailed={console.log}
 30 |   >
 31 |     <FormGrid maxColumns={4}>
 32 |       <Field
 33 |         name="aa"
 34 |         title="select box"
 35 |         decorator={[FormItem]}
 36 |         component={[Select]}
 37 |         dataSource={[
 38 |           {
 39 |             label: 'Option 1',
 40 |             value: 1,
 41 |           },
 42 |           {
 43 |             label: 'Option 2',
 44 |             value: 2,
 45 |           },
 46 |         ]}
 47 |       />
 48 |       <Field
 49 |         name="bb"
 50 |         title="input box"
 51 |         required
 52 |         decorator={[FormItem]}
 53 |         component={[Input]}
 54 |       />
 55 |       <Field
 56 |         name="cc"
 57 |         title="input box"
 58 |         decorator={[FormItem]}
 59 |         component={[Input]}
 60 |       />
 61 |       <Field
 62 |         name="dd"
 63 |         title="input box"
 64 |         decorator={[FormItem]}
 65 |         component={[Input]}
 66 |       />
 67 |       <Field
 68 |         name="ee"
 69 |         title="input box"
 70 |         decorator={[FormItem]}
 71 |         component={[Input]}
 72 |       />
 73 |       <FormButtonGroup.FormItem>
 74 |         <Submit>Query</Submit>
 75 |       </FormButtonGroup.FormItem>
 76 |     </FormGrid>
 77 |   </Form>
 78 | )
 79 | ```
 80 | 
 81 | ## Fusion Multilingual
 82 | 
 83 | ```tsx
 84 | import React from 'react'
 85 | import { Input, Form, FormItem, FormButtonGroup, Submit } from '@formily/next'
 86 | import { createForm } from '@formily/core'
 87 | import { Field } from '@formily/react'
 88 | import { ConfigProvider } from '@alifd/next'
 89 | import enUS from '@alifd/next/lib/locale/en-us'
 90 | 
 91 | const form = createForm()
 92 | 
 93 | export default () => (
 94 |   <ConfigProvider locale={enUS}>
 95 |     <Form
 96 |       form={form}
 97 |       layout="vertical"
 98 |       feedbackLayout="terse"
 99 |       onAutoSubmit={console.log}
100 |     >
101 |       <Field
102 |         name="bb"
103 |         title="User Name"
104 |         required
105 |         decorator={[FormItem]}
106 |         component={[Input]}
107 |       />
108 | 
109 |       <FormButtonGroup.FormItem>
110 |         <Submit>Submit</Submit>
111 |       </FormButtonGroup.FormItem>
112 |     </Form>
113 |   </ConfigProvider>
114 | )
115 | ```
116 | 
117 | <Alert style="margin-top:20px">
118 | Note: To realize the carriage return submission, we cannot pass the onSubmit event to it when using the Submit component, otherwise the carriage return submission will become invalid. The purpose of this is to prevent users from writing onSubmit event listeners in multiple places at the same time, and processing logic If they are inconsistent, it is difficult to locate the problem when submitting.
119 | </Alert>
120 | 
121 | ## API
122 | 
123 | For layout-related API properties, we can refer to [FormLayout](./form-layout), and the rest are the unique API properties of the Form component
124 | 
125 | | Property name          | Type                                                                                             | Description                                                         | Default value |
126 | | ---------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | ------------- |
127 | | form                   | [Form](https://core.formilyjs.org/api/models/form)                                               | Form example                                                        | -             |
128 | | component              | string                                                                                           | Rendering component, can be specified as custom component rendering | `form`        |
129 | | previewTextPlaceholder | ReactNode                                                                                        | Preview State Placeholder                                           | `N/A`         |
130 | | onAutoSubmit           | `(values:any)=>any`                                                                              | Carriage return submit event callback                               | -             |
131 | | onAutoSubmitFailed     | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Carriage return submission verification failure event callback      | -             |
132 | 
```

--------------------------------------------------------------------------------
/packages/validator/src/rules.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import {
  2 |   isEmpty,
  3 |   isValid,
  4 |   stringLength,
  5 |   isStr,
  6 |   isArr,
  7 |   isFn,
  8 |   toArr,
  9 |   isBool,
 10 |   isNum,
 11 |   isEqual,
 12 |   each,
 13 | } from '@formily/shared'
 14 | import { getValidateFormats } from './registry'
 15 | import { IRegistryRules } from './types'
 16 | 
 17 | const isValidateEmpty = (value: any) => {
 18 |   if (isArr(value)) {
 19 |     for (let i = 0; i < value.length; i++) {
 20 |       if (isValid(value[i])) return false
 21 |     }
 22 |     return true
 23 |   } else {
 24 |     //compat to draft-js
 25 |     if (value?.getCurrentContent) {
 26 |       /* istanbul ignore next */
 27 |       return !value.getCurrentContent()?.hasText()
 28 |     }
 29 |     return isEmpty(value)
 30 |   }
 31 | }
 32 | 
 33 | const getLength = (value: any) =>
 34 |   isStr(value) ? stringLength(value) : value ? value.length : 0
 35 | 
 36 | const extendSameRules = (
 37 |   rules: IRegistryRules,
 38 |   names: Record<string, string>
 39 | ) => {
 40 |   each(names, (realName, name) => {
 41 |     rules[name] = (value, rule, ...args) =>
 42 |       rules[realName](value, { ...rule, [realName]: rule[name] }, ...args)
 43 |   })
 44 | }
 45 | 
 46 | const RULES: IRegistryRules = {
 47 |   format(value, rule) {
 48 |     if (isValidateEmpty(value)) return ''
 49 |     if (rule.format) {
 50 |       const format = getValidateFormats(rule.format)
 51 |       if (format) {
 52 |         return !new RegExp(format).test(value) ? rule.message : ''
 53 |       }
 54 |     }
 55 |     return ''
 56 |   },
 57 |   required(value, rule) {
 58 |     if (rule.required !== true) return ''
 59 |     return isValidateEmpty(value) ? rule.message : ''
 60 |   },
 61 |   max(value, rule) {
 62 |     if (isValidateEmpty(value)) return ''
 63 |     const length = isNum(value) ? value : getLength(value)
 64 |     const max = Number(rule.max)
 65 |     return length > max ? rule.message : ''
 66 |   },
 67 |   min(value, rule) {
 68 |     if (isValidateEmpty(value)) return ''
 69 |     const length = isNum(value) ? value : getLength(value)
 70 |     const min = Number(rule.min)
 71 |     return length < min ? rule.message : ''
 72 |   },
 73 |   exclusiveMaximum(value, rule) {
 74 |     if (isValidateEmpty(value)) return ''
 75 |     const length = isNum(value) ? value : getLength(value)
 76 |     const max = Number(rule.exclusiveMaximum)
 77 |     return length >= max ? rule.message : ''
 78 |   },
 79 |   exclusiveMinimum(value, rule) {
 80 |     if (isValidateEmpty(value)) return ''
 81 |     const length = isNum(value) ? value : getLength(value)
 82 |     const min = Number(rule.exclusiveMinimum)
 83 |     return length <= min ? rule.message : ''
 84 |   },
 85 |   len(value, rule) {
 86 |     if (isValidateEmpty(value)) return ''
 87 |     const length = getLength(value)
 88 |     const len = Number(rule.len)
 89 |     return length !== len ? rule.message : ''
 90 |   },
 91 | 
 92 |   pattern(value, rule) {
 93 |     if (isValidateEmpty(value)) return ''
 94 |     return !new RegExp(rule.pattern).test(value) ? rule.message : ''
 95 |   },
 96 |   async validator(value, rule, context, format) {
 97 |     if (isFn(rule.validator)) {
 98 |       const response = await Promise.resolve(
 99 |         rule.validator(value, rule, context, format)
100 |       )
101 |       if (isBool(response)) {
102 |         return !response ? rule.message : ''
103 |       } else {
104 |         return response
105 |       }
106 |     }
107 |     /* istanbul ignore next */
108 |     throw new Error("The rule's validator property must be a function.")
109 |   },
110 |   whitespace(value, rule) {
111 |     if (isValidateEmpty(value)) return ''
112 |     if (rule.whitespace) {
113 |       return /^\s+$/.test(value) ? rule.message : ''
114 |     }
115 |   },
116 |   enum(value, rule) {
117 |     if (isValidateEmpty(value)) return ''
118 |     const enums = toArr(rule.enum)
119 |     return enums.indexOf(value) === -1 ? rule.message : ''
120 |   },
121 |   const(value, rule) {
122 |     if (isValidateEmpty(value)) return ''
123 |     return rule.const !== value ? rule.message : ''
124 |   },
125 |   multipleOf(value, rule) {
126 |     if (isValidateEmpty(value)) return ''
127 |     return Number(value) % Number(rule.multipleOf) !== 0 ? rule.message : ''
128 |   },
129 |   uniqueItems(value, rule) {
130 |     if (isValidateEmpty(value)) return ''
131 |     value = toArr(value)
132 |     return value.some((item: any, index: number) => {
133 |       for (let i = 0; i < value.length; i++) {
134 |         if (i !== index && !isEqual(value[i], item)) {
135 |           return false
136 |         }
137 |       }
138 |       return true
139 |     })
140 |       ? ''
141 |       : rule.message
142 |   },
143 |   maxProperties(value, rule) {
144 |     if (isValidateEmpty(value)) return ''
145 |     return Object.keys(value || {}).length <= Number(rule.maxProperties)
146 |       ? ''
147 |       : rule.message
148 |   },
149 |   minProperties(value, rule) {
150 |     if (isValidateEmpty(value)) return ''
151 |     return Object.keys(value || {}).length >= Number(rule.minProperties)
152 |       ? ''
153 |       : rule.message
154 |   },
155 | }
156 | 
157 | extendSameRules(RULES, {
158 |   maximum: 'max',
159 |   minimum: 'min',
160 |   maxItems: 'max',
161 |   minItems: 'min',
162 |   maxLength: 'max',
163 |   minLength: 'min',
164 | })
165 | 
166 | export default RULES
167 | 
```

--------------------------------------------------------------------------------
/packages/core/src/effects/onFieldEffects.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { FormPath, isFn, toArr } from '@formily/shared'
  2 | import { autorun, reaction, batch } from '@formily/reactive'
  3 | import { Form } from '../models'
  4 | import {
  5 |   LifeCycleTypes,
  6 |   FormPathPattern,
  7 |   GeneralField,
  8 |   DataField,
  9 |   IFieldState,
 10 | } from '../types'
 11 | import { createEffectHook, useEffectForm } from '../shared/effective'
 12 | 
 13 | function createFieldEffect<Result extends GeneralField = GeneralField>(
 14 |   type: LifeCycleTypes
 15 | ) {
 16 |   return createEffectHook(
 17 |     type,
 18 |     (field: Result, form: Form) =>
 19 |       (
 20 |         pattern: FormPathPattern,
 21 |         callback: (field: Result, form: Form) => void
 22 |       ) => {
 23 |         if (
 24 |           FormPath.parse(pattern).matchAliasGroup(field.address, field.path)
 25 |         ) {
 26 |           batch(() => {
 27 |             callback(field, form)
 28 |           })
 29 |         }
 30 |       }
 31 |   )
 32 | }
 33 | const _onFieldInit = createFieldEffect(LifeCycleTypes.ON_FIELD_INIT)
 34 | export const onFieldMount = createFieldEffect(LifeCycleTypes.ON_FIELD_MOUNT)
 35 | export const onFieldUnmount = createFieldEffect(LifeCycleTypes.ON_FIELD_UNMOUNT)
 36 | export const onFieldValueChange = createFieldEffect<DataField>(
 37 |   LifeCycleTypes.ON_FIELD_VALUE_CHANGE
 38 | )
 39 | export const onFieldInitialValueChange = createFieldEffect<DataField>(
 40 |   LifeCycleTypes.ON_FIELD_INITIAL_VALUE_CHANGE
 41 | )
 42 | export const onFieldInputValueChange = createFieldEffect<DataField>(
 43 |   LifeCycleTypes.ON_FIELD_INPUT_VALUE_CHANGE
 44 | )
 45 | export const onFieldValidateStart = createFieldEffect<DataField>(
 46 |   LifeCycleTypes.ON_FIELD_VALIDATE_START
 47 | )
 48 | export const onFieldValidateEnd = createFieldEffect<DataField>(
 49 |   LifeCycleTypes.ON_FIELD_VALIDATE_END
 50 | )
 51 | export const onFieldValidating = createFieldEffect<DataField>(
 52 |   LifeCycleTypes.ON_FIELD_VALIDATING
 53 | )
 54 | export const onFieldValidateFailed = createFieldEffect<DataField>(
 55 |   LifeCycleTypes.ON_FIELD_VALIDATE_FAILED
 56 | )
 57 | export const onFieldValidateSuccess = createFieldEffect<DataField>(
 58 |   LifeCycleTypes.ON_FIELD_VALIDATE_SUCCESS
 59 | )
 60 | export const onFieldSubmit = createFieldEffect<DataField>(
 61 |   LifeCycleTypes.ON_FIELD_SUBMIT
 62 | )
 63 | export const onFieldSubmitStart = createFieldEffect<DataField>(
 64 |   LifeCycleTypes.ON_FIELD_SUBMIT_START
 65 | )
 66 | export const onFieldSubmitEnd = createFieldEffect<DataField>(
 67 |   LifeCycleTypes.ON_FIELD_SUBMIT_END
 68 | )
 69 | export const onFieldSubmitValidateStart = createFieldEffect<DataField>(
 70 |   LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_START
 71 | )
 72 | export const onFieldSubmitValidateEnd = createFieldEffect<DataField>(
 73 |   LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_END
 74 | )
 75 | export const onFieldSubmitSuccess = createFieldEffect<DataField>(
 76 |   LifeCycleTypes.ON_FIELD_SUBMIT_SUCCESS
 77 | )
 78 | export const onFieldSubmitFailed = createFieldEffect<DataField>(
 79 |   LifeCycleTypes.ON_FIELD_SUBMIT_FAILED
 80 | )
 81 | export const onFieldSubmitValidateSuccess = createFieldEffect<DataField>(
 82 |   LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_SUCCESS
 83 | )
 84 | export const onFieldSubmitValidateFailed = createFieldEffect<DataField>(
 85 |   LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_FAILED
 86 | )
 87 | export const onFieldReset = createFieldEffect<DataField>(
 88 |   LifeCycleTypes.ON_FIELD_RESET
 89 | )
 90 | export const onFieldLoading = createFieldEffect<DataField>(
 91 |   LifeCycleTypes.ON_FIELD_LOADING
 92 | )
 93 | 
 94 | export function onFieldInit(
 95 |   pattern: FormPathPattern,
 96 |   callback?: (field: GeneralField, form: Form) => void
 97 | ) {
 98 |   const form = useEffectForm()
 99 |   const count = form.query(pattern).reduce((count, field) => {
100 |     callback(field, form)
101 |     return count + 1
102 |   }, 0)
103 |   if (count === 0) {
104 |     _onFieldInit(pattern, callback)
105 |   }
106 | }
107 | 
108 | export function onFieldReact(
109 |   pattern: FormPathPattern,
110 |   callback?: (field: GeneralField, form: Form) => void
111 | ) {
112 |   onFieldInit(pattern, (field, form) => {
113 |     field.disposers.push(
114 |       autorun(() => {
115 |         if (isFn(callback)) callback(field, form)
116 |       })
117 |     )
118 |   })
119 | }
120 | export function onFieldChange(
121 |   pattern: FormPathPattern,
122 |   callback?: (field: GeneralField, form: Form) => void
123 | ): void
124 | export function onFieldChange(
125 |   pattern: FormPathPattern,
126 |   watches: (keyof IFieldState)[],
127 |   callback?: (field: GeneralField, form: Form) => void
128 | ): void
129 | export function onFieldChange(
130 |   pattern: FormPathPattern,
131 |   watches: any,
132 |   callback?: (field: GeneralField, form: Form) => void
133 | ): void {
134 |   if (isFn(watches)) {
135 |     callback = watches
136 |     watches = ['value']
137 |   } else {
138 |     watches = watches || ['value']
139 |   }
140 |   onFieldInit(pattern, (field, form) => {
141 |     if (isFn(callback)) callback(field, form)
142 |     const dispose = reaction(
143 |       () => {
144 |         return toArr(watches).map((key) => {
145 |           return field[key]
146 |         })
147 |       },
148 |       () => {
149 |         if (isFn(callback)) callback(field, form)
150 |       }
151 |     )
152 |     field.disposers.push(dispose)
153 |   })
154 | }
155 | 
```

--------------------------------------------------------------------------------
/packages/reactive-vue/src/__tests__/observer.spec.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { shallowMount, createLocalVue } from '@vue/test-utils'
  2 | import { observable, autorun } from '@formily/reactive'
  3 | import { CreateElement } from 'vue'
  4 | import CompositionAPI, { defineComponent, h } from '@vue/composition-api'
  5 | import { observer } from '../'
  6 | import collectData from '../observer/collectData'
  7 | import { observer as observerInVue2 } from '../observer/observerInVue2'
  8 | import expect from 'expect'
  9 | 
 10 | test('observer: component', async () => {
 11 |   const model = observable<any>({
 12 |     age: 10,
 13 |     setAge() {
 14 |       model.age++
 15 |     },
 16 |   })
 17 |   const Component = observer({
 18 |     data() {
 19 |       return {
 20 |         model,
 21 |       }
 22 |     },
 23 |     render(this: any, h: CreateElement) {
 24 |       return h('button', {
 25 |         on: { click: this.model.setAge },
 26 |         domProps: { textContent: this.model.age },
 27 |       })
 28 |     },
 29 |   })
 30 |   const wrapper = shallowMount(Component)
 31 |   expect(wrapper.find('button').text()).toBe('10')
 32 |   wrapper.find('button').trigger('click')
 33 |   expect(wrapper.find('button').text()).toBe('11')
 34 |   wrapper.destroy()
 35 | })
 36 | 
 37 | test('observer: component with setup', async () => {
 38 |   const Vue = createLocalVue()
 39 |   Vue.use(CompositionAPI)
 40 |   const model = observable<any>({
 41 |     age: 30,
 42 |     get sub10() {
 43 |       return model.age - 10
 44 |     },
 45 |     get sub20() {
 46 |       return model.sub10 - 10
 47 |     },
 48 |     setAge() {
 49 |       model.age++
 50 |     },
 51 |   })
 52 |   const Component = observer(
 53 |     defineComponent({
 54 |       setup() {
 55 |         return () => {
 56 |           return h('button', {
 57 |             on: { click: model.setAge },
 58 |             domProps: { textContent: model.sub20 },
 59 |           })
 60 |         }
 61 |       },
 62 |       // to fix 'Maximum call stack size exceeded' error of @vue/test-utils
 63 |       render() {
 64 |         return null
 65 |       },
 66 |     })
 67 |   )
 68 |   const wrapper = shallowMount(Component)
 69 |   expect(wrapper.find('button').text()).toBe('10')
 70 |   wrapper.find('button').trigger('click')
 71 |   expect(wrapper.find('button').text()).toBe('11')
 72 |   model.age++
 73 |   expect(wrapper.find('button').text()).toBe('12')
 74 |   wrapper.destroy()
 75 | })
 76 | 
 77 | test('observer: component scheduler', async () => {
 78 |   let schedulerRequest = null
 79 | 
 80 |   const model = observable<any>({
 81 |     age: 10,
 82 |     setAge() {
 83 |       model.age++
 84 |     },
 85 |   })
 86 |   const Component = observer(
 87 |     {
 88 |       data() {
 89 |         return {
 90 |           model,
 91 |         }
 92 |       },
 93 |       render(this: any, h: CreateElement) {
 94 |         return h('button', {
 95 |           on: { click: this.model.setAge },
 96 |           domProps: { textContent: this.model.age },
 97 |         })
 98 |       },
 99 |     },
100 |     {
101 |       scheduler: (update) => {
102 |         clearTimeout(schedulerRequest)
103 |         schedulerRequest = setTimeout(() => {
104 |           update()
105 |         }, 100)
106 |       },
107 |     }
108 |   )
109 |   const wrapper = shallowMount(Component)
110 | 
111 |   expect(wrapper.find('button').text()).toBe('10')
112 | 
113 |   wrapper.find('button').trigger('click')
114 |   await new Promise((r) => setTimeout(r, 150))
115 |   expect(wrapper.find('button').text()).toBe('11')
116 | 
117 |   // test second render
118 |   wrapper.find('button').trigger('click')
119 |   await new Promise((r) => setTimeout(r, 150))
120 |   expect(wrapper.find('button').text()).toBe('12')
121 | 
122 |   wrapper.destroy()
123 | })
124 | 
125 | test('observer: stop tracking if watcher is destroyed', async () => {
126 |   let count = 0
127 |   const model = observable<any>({
128 |     age: 10,
129 |     name: 'test',
130 |   })
131 | 
132 |   const Component = observer({
133 |     name: 'test',
134 |     data() {
135 |       return {
136 |         model: model,
137 |       }
138 |     },
139 |     render() {
140 |       count++
141 |       return h('div', [this.model.name, this.model.age])
142 |     },
143 |   })
144 | 
145 |   const wrapper = shallowMount(Component)
146 | 
147 |   const childInst = wrapper.find({ name: 'test' })
148 | 
149 |   expect(childInst.exists()).toBe(true)
150 |   ;(childInst.vm as any)._isDestroyed = true
151 |   model.age++
152 |   wrapper.destroy()
153 |   expect(count).toEqual(1) // 不触发 reactiveRender
154 | })
155 | 
156 | test('collectData', async () => {
157 |   const model = observable<any>({
158 |     age: 10,
159 |     name: 'test',
160 |   })
161 | 
162 |   const target = {
163 |     value: 1,
164 |   }
165 | 
166 |   const data = collectData(
167 |     {},
168 |     {
169 |       model,
170 |       target,
171 |     }
172 |   )
173 | 
174 |   const fn1 = jest.fn()
175 |   const fn2 = jest.fn()
176 | 
177 |   autorun(() => fn1(model.age))
178 |   autorun(() => fn2(data.target.value))
179 | 
180 |   model.age++
181 |   expect(fn1).toBeCalledTimes(2)
182 | 
183 |   target.value++
184 |   expect(fn2).toBeCalledTimes(1)
185 | })
186 | 
187 | test('observerInVue2', () => {
188 |   const componentObj = Object.create(null)
189 | 
190 |   componentObj.data = () => {
191 |     return {}
192 |   }
193 | 
194 |   const ExtendedComponent1 = observerInVue2(componentObj)
195 |   expect(ExtendedComponent1.name).toEqual('<component>')
196 | 
197 |   function Component() {}
198 |   Component.options = {
199 |     data: () => {
200 |       return {}
201 |     },
202 |   }
203 | 
204 |   const ExtendedComponent2 = observerInVue2(Component, { name: 'abc' })
205 |   expect(ExtendedComponent2.name).toEqual('abc')
206 | })
207 | 
```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/array-table/effects-json-schema.vue:
--------------------------------------------------------------------------------

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField :schema="schema" />
  4 |     <Submit @submit="log">提交</Submit>
  5 |   </FormProvider>
  6 | </template>
  7 | 
  8 | <script>
  9 | import { createForm, onFieldChange, onFieldReact } from '@formily/core'
 10 | import { FormProvider, createSchemaField } from '@formily/vue'
 11 | import {
 12 |   Submit,
 13 |   FormItem,
 14 |   ArrayTable,
 15 |   Input,
 16 |   Editable,
 17 |   Switch,
 18 | } from '@formily/element'
 19 | 
 20 | const fields = createSchemaField({
 21 |   components: {
 22 |     FormItem,
 23 |     ArrayTable,
 24 |     Input,
 25 |     Editable,
 26 |     Switch,
 27 |   },
 28 | })
 29 | 
 30 | export default {
 31 |   components: { FormProvider, Submit, ...fields },
 32 |   data() {
 33 |     const form = createForm({
 34 |       effects: () => {
 35 |         //主动联动模式
 36 |         onFieldChange('hideFirstColumn', ['value'], (field) => {
 37 |           field.query('array.column3').take((target) => {
 38 |             target.visible = !field.value
 39 |           })
 40 |           field.query('array.*.a2').take((target) => {
 41 |             target.visible = !field.value
 42 |           })
 43 |         })
 44 |         //被动联动模式
 45 |         onFieldReact('array.*.a2', (field) => {
 46 |           field.visible = !field.query('.a1').get('value')
 47 |         })
 48 |       },
 49 |     })
 50 |     const schema = {
 51 |       type: 'object',
 52 |       properties: {
 53 |         hideFirstColumn: {
 54 |           type: 'boolean',
 55 |           title: '隐藏A2',
 56 |           'x-decorator': 'FormItem',
 57 |           'x-component': 'Switch',
 58 |         },
 59 |         array: {
 60 |           type: 'array',
 61 |           'x-decorator': 'FormItem',
 62 |           'x-component': 'ArrayTable',
 63 |           items: {
 64 |             type: 'object',
 65 |             properties: {
 66 |               column1: {
 67 |                 type: 'void',
 68 |                 'x-component': 'ArrayTable.Column',
 69 |                 'x-component-props': {
 70 |                   width: 80,
 71 |                   title: 'Index',
 72 |                   align: 'center',
 73 |                 },
 74 |                 properties: {
 75 |                   index: {
 76 |                     type: 'void',
 77 |                     'x-component': 'ArrayTable.Index',
 78 |                   },
 79 |                 },
 80 |               },
 81 |               column2: {
 82 |                 type: 'void',
 83 |                 'x-component': 'ArrayTable.Column',
 84 |                 'x-component-props': { width: 100, title: '显隐->A2' },
 85 |                 properties: {
 86 |                   a1: {
 87 |                     type: 'boolean',
 88 |                     'x-decorator': 'FormItem',
 89 |                     'x-component': 'Switch',
 90 |                   },
 91 |                 },
 92 |               },
 93 |               column3: {
 94 |                 type: 'void',
 95 |                 'x-component': 'ArrayTable.Column',
 96 |                 'x-component-props': { width: 200, title: 'A2' },
 97 |                 properties: {
 98 |                   a2: {
 99 |                     type: 'string',
100 |                     'x-decorator': 'FormItem',
101 |                     'x-component': 'Input',
102 |                   },
103 |                 },
104 |               },
105 |               column4: {
106 |                 type: 'void',
107 |                 'x-component': 'ArrayTable.Column',
108 |                 'x-component-props': { title: 'A3' },
109 |                 properties: {
110 |                   a3: {
111 |                     type: 'string',
112 |                     'x-decorator': 'FormItem',
113 |                     'x-component': 'Input',
114 |                   },
115 |                 },
116 |               },
117 |               column5: {
118 |                 type: 'void',
119 |                 'x-component': 'ArrayTable.Column',
120 |                 'x-component-props': {
121 |                   title: 'Operations',
122 |                   prop: 'operations',
123 |                   width: 200,
124 |                   fixed: 'right',
125 |                 },
126 |                 properties: {
127 |                   item: {
128 |                     type: 'void',
129 |                     'x-component': 'FormItem',
130 |                     properties: {
131 |                       remove: {
132 |                         type: 'void',
133 |                         'x-component': 'ArrayTable.Remove',
134 |                       },
135 |                       moveDown: {
136 |                         type: 'void',
137 |                         'x-component': 'ArrayTable.MoveDown',
138 |                       },
139 |                       moveUp: {
140 |                         type: 'void',
141 |                         'x-component': 'ArrayTable.MoveUp',
142 |                       },
143 |                     },
144 |                   },
145 |                 },
146 |               },
147 |             },
148 |           },
149 |           properties: {
150 |             add: {
151 |               type: 'void',
152 |               'x-component': 'ArrayTable.Addition',
153 |               title: '添加条目',
154 |             },
155 |           },
156 |         },
157 |       },
158 |     }
159 |     return {
160 |       form,
161 |       schema,
162 |     }
163 |   },
164 |   methods: {
165 |     log(...v) {
166 |       console.log(...v)
167 |     },
168 |   },
169 | }
170 | </script>
171 | 
```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/array-items/markup-schema.vue:
--------------------------------------------------------------------------------

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField>
  4 |       <SchemaArrayField
  5 |         name="string_array"
  6 |         title="字符串数组"
  7 |         x-decorator="FormItem"
  8 |         x-component="ArrayItems"
  9 |       >
 10 |         <SchemaVoidField x-component="Space">
 11 |           <SchemaVoidField
 12 |             x-decorator="FormItem"
 13 |             x-component="ArrayItems.SortHandle"
 14 |           />
 15 |           <SchemaStringField
 16 |             x-decorator="FormItem"
 17 |             required
 18 |             name="input"
 19 |             x-component="Input"
 20 |             :x-component-props="{
 21 |               style: {
 22 |                 width: '160px',
 23 |               },
 24 |             }"
 25 |           />
 26 |           <SchemaVoidField
 27 |             x-decorator="FormItem"
 28 |             x-component="ArrayItems.Remove"
 29 |           />
 30 |         </SchemaVoidField>
 31 |         <SchemaVoidField x-component="ArrayItems.Addition" title="添加条目" />
 32 |       </SchemaArrayField>
 33 |       <SchemaArrayField
 34 |         name="array"
 35 |         title="对象数组"
 36 |         x-decorator="FormItem"
 37 |         x-component="ArrayItems"
 38 |       >
 39 |         <SchemaObjectField>
 40 |           <SchemaVoidField x-component="Space">
 41 |             <SchemaVoidField
 42 |               x-decorator="FormItem"
 43 |               x-component="ArrayItems.SortHandle"
 44 |             />
 45 |             <SchemaStringField
 46 |               x-decorator="FormItem"
 47 |               required
 48 |               title="日期"
 49 |               name="date"
 50 |               x-component="DatePicker"
 51 |               :x-component-props="{
 52 |                 type: 'daterange',
 53 |                 style: {
 54 |                   width: '160px',
 55 |                 },
 56 |               }"
 57 |             />
 58 |             <SchemaStringField
 59 |               x-decorator="FormItem"
 60 |               required
 61 |               title="输入框"
 62 |               name="input"
 63 |               x-component="Input"
 64 |             />
 65 |             <SchemaStringField
 66 |               x-decorator="FormItem"
 67 |               required
 68 |               title="选择框"
 69 |               name="select"
 70 |               :enum="[
 71 |                 { label: '选项1', value: 1 },
 72 |                 { label: '选项2', value: 2 },
 73 |               ]"
 74 |               x-component="Select"
 75 |               :x-component-props="{
 76 |                 style: {
 77 |                   width: 160,
 78 |                 },
 79 |               }"
 80 |             />
 81 |             <SchemaVoidField
 82 |               x-decorator="FormItem"
 83 |               x-component="ArrayItems.Remove"
 84 |             />
 85 |           </SchemaVoidField>
 86 |         </SchemaObjectField>
 87 |         <SchemaVoidField x-component="ArrayItems.Addition" title="添加条目" />
 88 |       </SchemaArrayField>
 89 |       <SchemaArrayField
 90 |         name="array2"
 91 |         title="对象数组"
 92 |         x-decorator="FormItem"
 93 |         x-component="ArrayItems"
 94 |         :x-component-props="{ style: { width: '600px' } }"
 95 |       >
 96 |         <SchemaObjectField x-decorator="ArrayItems.Item">
 97 |           <SchemaVoidField x-component="Space">
 98 |             <SchemaVoidField
 99 |               x-decorator="FormItem"
100 |               x-component="ArrayItems.SortHandle"
101 |             />
102 |             <SchemaStringField
103 |               x-decorator="FormItem"
104 |               required
105 |               title="日期"
106 |               name="date"
107 |               x-component="DatePicker"
108 |               :x-component-props="{
109 |                 type: 'daterange',
110 |                 style: {
111 |                   width: '250px',
112 |                 },
113 |               }"
114 |             />
115 |             <SchemaStringField
116 |               x-decorator="FormItem"
117 |               required
118 |               title="输入框"
119 |               name="input"
120 |               x-component="Input"
121 |             />
122 |             <SchemaVoidField
123 |               x-decorator="FormItem"
124 |               x-component="ArrayItems.Remove"
125 |             />
126 |           </SchemaVoidField>
127 |         </SchemaObjectField>
128 |         <SchemaVoidField x-component="ArrayItems.Addition" title="添加条目" />
129 |       </SchemaArrayField>
130 |     </SchemaField>
131 |     <FormButtonGroup>
132 |       <Submit @submit="log">提交</Submit>
133 |     </FormButtonGroup>
134 |   </FormProvider>
135 | </template>
136 | 
137 | <script>
138 | import { createForm } from '@formily/core'
139 | import { FormProvider, createSchemaField } from '@formily/vue'
140 | import {
141 |   FormItem,
142 |   FormButtonGroup,
143 |   Submit,
144 |   Input,
145 |   Select,
146 |   Space,
147 |   DatePicker,
148 |   ArrayItems,
149 | } from '@formily/element'
150 | import { Button } from 'element-ui'
151 | 
152 | const SchemaField = createSchemaField({
153 |   components: {
154 |     FormItem,
155 |     Space,
156 |     Input,
157 |     Select,
158 |     DatePicker,
159 |     ArrayItems,
160 |   },
161 | })
162 | 
163 | export default {
164 |   components: {
165 |     FormProvider,
166 |     FormButtonGroup,
167 |     Button,
168 |     Submit,
169 |     ...SchemaField,
170 |   },
171 | 
172 |   data() {
173 |     const form = createForm()
174 | 
175 |     return {
176 |       form,
177 |     }
178 |   },
179 |   methods: {
180 |     log(values) {
181 |       console.log(values)
182 |     },
183 |   },
184 | }
185 | </script>
186 | 
187 | <style lang="scss" scoped></style>
188 | 
```

--------------------------------------------------------------------------------
/packages/antd/docs/components/Reset.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Reset
  2 | 
  3 | > Reset button
  4 | 
  5 | ## Normal reset
  6 | 
  7 | > Controls with default values cannot be cleared
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
 12 | import { createForm } from '@formily/core'
 13 | import { FormProvider, createSchemaField } from '@formily/react'
 14 | 
 15 | const SchemaField = createSchemaField({
 16 |   components: {
 17 |     Input,
 18 |     FormItem,
 19 |   },
 20 | })
 21 | 
 22 | const form = createForm()
 23 | 
 24 | export default () => (
 25 |   <FormProvider form={form}>
 26 |     <SchemaField>
 27 |       <SchemaField.String
 28 |         name="input"
 29 |         title="input box"
 30 |         required
 31 |         x-decorator="FormItem"
 32 |         x-component="Input"
 33 |       />
 34 |       <SchemaField.String
 35 |         name="input2"
 36 |         title="input box"
 37 |         default="123"
 38 |         required
 39 |         x-decorator="FormItem"
 40 |         x-component="Input"
 41 |       />
 42 |     </SchemaField>
 43 |     <FormButtonGroup>
 44 |       <Reset>Reset</Reset>
 45 |     </FormButtonGroup>
 46 |   </FormProvider>
 47 | )
 48 | ```
 49 | 
 50 | ## Force empty reset
 51 | 
 52 | ```tsx
 53 | import React from 'react'
 54 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
 55 | import { createForm } from '@formily/core'
 56 | import { FormProvider, createSchemaField } from '@formily/react'
 57 | 
 58 | const SchemaField = createSchemaField({
 59 |   components: {
 60 |     Input,
 61 |     FormItem,
 62 |   },
 63 | })
 64 | 
 65 | const form = createForm()
 66 | 
 67 | export default () => (
 68 |   <FormProvider form={form}>
 69 |     <SchemaField>
 70 |       <SchemaField.String
 71 |         name="input"
 72 |         title="input box"
 73 |         required
 74 |         x-decorator="FormItem"
 75 |         x-component="Input"
 76 |       />
 77 |       <SchemaField.String
 78 |         name="input2"
 79 |         title="input box"
 80 |         default="123"
 81 |         required
 82 |         x-decorator="FormItem"
 83 |         x-component="Input"
 84 |       />
 85 |     </SchemaField>
 86 |     <FormButtonGroup>
 87 |       <Reset forceClear>Reset</Reset>
 88 |     </FormButtonGroup>
 89 |   </FormProvider>
 90 | )
 91 | ```
 92 | 
 93 | ## Reset and verify
 94 | 
 95 | ```tsx
 96 | import React from 'react'
 97 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
 98 | import { createForm } from '@formily/core'
 99 | import { FormProvider, createSchemaField } from '@formily/react'
100 | 
101 | const SchemaField = createSchemaField({
102 |   components: {
103 |     Input,
104 |     FormItem,
105 |   },
106 | })
107 | 
108 | const form = createForm()
109 | 
110 | export default () => (
111 |   <FormProvider form={form}>
112 |     <SchemaField>
113 |       <SchemaField.String
114 |         name="input"
115 |         title="input box"
116 |         required
117 |         x-decorator="FormItem"
118 |         x-component="Input"
119 |       />
120 |       <SchemaField.String
121 |         name="input2"
122 |         title="input box"
123 |         default="123"
124 |         required
125 |         x-decorator="FormItem"
126 |         x-component="Input"
127 |       />
128 |     </SchemaField>
129 |     <FormButtonGroup>
130 |       <Reset validate>Reset</Reset>
131 |     </FormButtonGroup>
132 |   </FormProvider>
133 | )
134 | ```
135 | 
136 | ## Force empty reset and verify
137 | 
138 | ```tsx
139 | import React from 'react'
140 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/antd'
141 | import { createForm } from '@formily/core'
142 | import { FormProvider, createSchemaField } from '@formily/react'
143 | 
144 | const SchemaField = createSchemaField({
145 |   components: {
146 |     Input,
147 |     FormItem,
148 |   },
149 | })
150 | 
151 | const form = createForm()
152 | 
153 | export default () => (
154 |   <FormProvider form={form}>
155 |     <SchemaField>
156 |       <SchemaField.String
157 |         name="input"
158 |         title="input box"
159 |         required
160 |         x-decorator="FormItem"
161 |         x-component="Input"
162 |       />
163 |       <SchemaField.String
164 |         name="input2"
165 |         title="input box"
166 |         default="123"
167 |         required
168 |         x-decorator="FormItem"
169 |         x-component="Input"
170 |       />
171 |     </SchemaField>
172 |     <FormButtonGroup>
173 |       <Reset forceClear validate>
174 |         Reset
175 |       </Reset>
176 |     </FormButtonGroup>
177 |   </FormProvider>
178 | )
179 | ```
180 | 
181 | ## API
182 | 
183 | ### Reset
184 | 
185 | Other API reference https://ant.design/components/button-cn/
186 | 
187 | | Property name          | Type                                                                                             | Description                                              | Default value |
188 | | ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------- | ------------- |
189 | | onClick                | `(event: MouseEvent) => void \| boolean`                                                         | Click event, if it returns false, it can block resetting | -             |
190 | | onResetValidateSuccess | (payload: any) => void                                                                           | Reset validation success event                           | -             |
191 | | onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Reset validation failure event                           | -             |
192 | 
```

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

```markdown
  1 | # Reset
  2 | 
  3 | > Reset button
  4 | 
  5 | ## Normal reset
  6 | 
  7 | > Controls with default values cannot be cleared
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
 12 | import { createForm } from '@formily/core'
 13 | import { FormProvider, createSchemaField } from '@formily/react'
 14 | 
 15 | const SchemaField = createSchemaField({
 16 |   components: {
 17 |     Input,
 18 |     FormItem,
 19 |   },
 20 | })
 21 | 
 22 | const form = createForm()
 23 | 
 24 | export default () => (
 25 |   <FormProvider form={form}>
 26 |     <SchemaField>
 27 |       <SchemaField.String
 28 |         name="input"
 29 |         title="input box"
 30 |         required
 31 |         x-decorator="FormItem"
 32 |         x-component="Input"
 33 |       />
 34 |       <SchemaField.String
 35 |         name="input2"
 36 |         title="input box"
 37 |         default="123"
 38 |         required
 39 |         x-decorator="FormItem"
 40 |         x-component="Input"
 41 |       />
 42 |     </SchemaField>
 43 |     <FormButtonGroup>
 44 |       <Reset>Reset</Reset>
 45 |     </FormButtonGroup>
 46 |   </FormProvider>
 47 | )
 48 | ```
 49 | 
 50 | ## Force empty reset
 51 | 
 52 | ```tsx
 53 | import React from 'react'
 54 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
 55 | import { createForm } from '@formily/core'
 56 | import { FormProvider, createSchemaField } from '@formily/react'
 57 | 
 58 | const SchemaField = createSchemaField({
 59 |   components: {
 60 |     Input,
 61 |     FormItem,
 62 |   },
 63 | })
 64 | 
 65 | const form = createForm()
 66 | 
 67 | export default () => (
 68 |   <FormProvider form={form}>
 69 |     <SchemaField>
 70 |       <SchemaField.String
 71 |         name="input"
 72 |         title="input box"
 73 |         required
 74 |         x-decorator="FormItem"
 75 |         x-component="Input"
 76 |       />
 77 |       <SchemaField.String
 78 |         name="input2"
 79 |         title="input box"
 80 |         default="123"
 81 |         required
 82 |         x-decorator="FormItem"
 83 |         x-component="Input"
 84 |       />
 85 |     </SchemaField>
 86 |     <FormButtonGroup>
 87 |       <Reset forceClear>Reset</Reset>
 88 |     </FormButtonGroup>
 89 |   </FormProvider>
 90 | )
 91 | ```
 92 | 
 93 | ## Reset and verify
 94 | 
 95 | ```tsx
 96 | import React from 'react'
 97 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
 98 | import { createForm } from '@formily/core'
 99 | import { FormProvider, createSchemaField } from '@formily/react'
100 | 
101 | const SchemaField = createSchemaField({
102 |   components: {
103 |     Input,
104 |     FormItem,
105 |   },
106 | })
107 | 
108 | const form = createForm()
109 | 
110 | export default () => (
111 |   <FormProvider form={form}>
112 |     <SchemaField>
113 |       <SchemaField.String
114 |         name="input"
115 |         title="input box"
116 |         required
117 |         x-decorator="FormItem"
118 |         x-component="Input"
119 |       />
120 |       <SchemaField.String
121 |         name="input2"
122 |         title="input box"
123 |         default="123"
124 |         required
125 |         x-decorator="FormItem"
126 |         x-component="Input"
127 |       />
128 |     </SchemaField>
129 |     <FormButtonGroup>
130 |       <Reset validate>Reset</Reset>
131 |     </FormButtonGroup>
132 |   </FormProvider>
133 | )
134 | ```
135 | 
136 | ## Force empty reset and verify
137 | 
138 | ```tsx
139 | import React from 'react'
140 | import { Input, FormItem, FormButtonGroup, Reset } from '@formily/next'
141 | import { createForm } from '@formily/core'
142 | import { FormProvider, createSchemaField } from '@formily/react'
143 | 
144 | const SchemaField = createSchemaField({
145 |   components: {
146 |     Input,
147 |     FormItem,
148 |   },
149 | })
150 | 
151 | const form = createForm()
152 | 
153 | export default () => (
154 |   <FormProvider form={form}>
155 |     <SchemaField>
156 |       <SchemaField.String
157 |         name="input"
158 |         title="input box"
159 |         required
160 |         x-decorator="FormItem"
161 |         x-component="Input"
162 |       />
163 |       <SchemaField.String
164 |         name="input2"
165 |         title="input box"
166 |         default="123"
167 |         required
168 |         x-decorator="FormItem"
169 |         x-component="Input"
170 |       />
171 |     </SchemaField>
172 |     <FormButtonGroup>
173 |       <Reset forceClear validate>
174 |         Reset
175 |       </Reset>
176 |     </FormButtonGroup>
177 |   </FormProvider>
178 | )
179 | ```
180 | 
181 | ## API
182 | 
183 | ### Reset
184 | 
185 | Other API reference https://fusion.design/pc/component/basic/button
186 | 
187 | | Property name          | Type                                                                                             | Description                                              | Default value |
188 | | ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------- | ------------- |
189 | | onClick                | `(event: MouseEvent) => void \| boolean`                                                         | Click event, if it returns false, it can block resetting | -             |
190 | | onResetValidateSuccess | (payload: any) => void                                                                           | Reset validation success event                           | -             |
191 | | onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Reset validation failure event                           | -             |
192 | 
```

--------------------------------------------------------------------------------
/packages/element/src/form-step/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Form, VoidField } from '@formily/core'
  2 | import { Schema, SchemaKey } from '@formily/json-schema'
  3 | import { action, model, observable } from '@formily/reactive'
  4 | import { observer } from '@formily/reactive-vue'
  5 | import {
  6 |   Fragment,
  7 |   h,
  8 |   RecursionField,
  9 |   useField,
 10 |   useFieldSchema,
 11 | } from '@formily/vue'
 12 | import { Step, Steps } from 'element-ui'
 13 | import { defineComponent, PropType } from 'vue-demi'
 14 | import { stylePrefix } from '../__builtins__/configs'
 15 | 
 16 | import type { Step as StepProps, Steps as StepsProps } from 'element-ui'
 17 | import { composeExport } from '../__builtins__/shared'
 18 | 
 19 | export interface IFormStep {
 20 |   connect: (steps: SchemaStep[], field: VoidField) => void
 21 |   current: number
 22 |   allowNext: boolean
 23 |   allowBack: boolean
 24 |   setCurrent(key: number): void
 25 |   submit: Form['submit']
 26 |   next(): void
 27 |   back(): void
 28 | }
 29 | 
 30 | export interface IFormStepProps extends StepsProps {
 31 |   formStep?: IFormStep
 32 | }
 33 | 
 34 | type SchemaStep = {
 35 |   name: SchemaKey
 36 |   props: any
 37 |   schema: Schema
 38 | }
 39 | 
 40 | type FormStepEnv = {
 41 |   form: Form
 42 |   field: VoidField
 43 |   steps: SchemaStep[]
 44 | }
 45 | 
 46 | const parseSteps = (schema: Schema) => {
 47 |   const steps: SchemaStep[] = []
 48 |   schema.mapProperties((schema, name) => {
 49 |     if (schema['x-component']?.indexOf('StepPane') > -1) {
 50 |       steps.push({
 51 |         name,
 52 |         props: schema['x-component-props'],
 53 |         schema,
 54 |       })
 55 |     }
 56 |   })
 57 |   return steps
 58 | }
 59 | 
 60 | const createFormStep = (defaultCurrent = 0): IFormStep => {
 61 |   const env: FormStepEnv = observable({
 62 |     form: null,
 63 |     field: null,
 64 |     steps: [],
 65 |   })
 66 | 
 67 |   const setDisplay = action.bound((target: number) => {
 68 |     const currentStep = env.steps[target]
 69 |     env.steps.forEach(({ name }) => {
 70 |       env.form.query(`${env.field.address}.${name}`).take((field) => {
 71 |         if (name === currentStep.name) {
 72 |           field.setDisplay('visible')
 73 |         } else {
 74 |           field.setDisplay('hidden')
 75 |         }
 76 |       })
 77 |     })
 78 |   })
 79 | 
 80 |   const next = action.bound(() => {
 81 |     if (formStep.allowNext) {
 82 |       setDisplay(formStep.current + 1)
 83 |       formStep.setCurrent(formStep.current + 1)
 84 |     }
 85 |   })
 86 | 
 87 |   const back = action.bound(() => {
 88 |     if (formStep.allowBack) {
 89 |       setDisplay(formStep.current - 1)
 90 |       formStep.setCurrent(formStep.current - 1)
 91 |     }
 92 |   })
 93 | 
 94 |   const formStep: IFormStep = model({
 95 |     connect(steps, field) {
 96 |       env.steps = steps
 97 |       env.form = field?.form
 98 |       env.field = field
 99 |     },
100 |     current: defaultCurrent,
101 |     setCurrent(key: number) {
102 |       formStep.current = key
103 |     },
104 |     get allowNext() {
105 |       return formStep.current < env.steps.length - 1
106 |     },
107 |     get allowBack() {
108 |       return formStep.current > 0
109 |     },
110 |     async next() {
111 |       try {
112 |         await env.form.validate()
113 |         next()
114 |       } catch {}
115 |     },
116 |     async back() {
117 |       back()
118 |     },
119 |     async submit(onSubmit) {
120 |       return env.form?.submit?.(onSubmit)
121 |     },
122 |   })
123 |   return formStep
124 | }
125 | 
126 | const FormStepInner = observer(
127 |   defineComponent<IFormStepProps>({
128 |     name: 'FFormStep',
129 |     props: {
130 |       formStep: {
131 |         type: Object as PropType<IFormStep>,
132 |         default() {
133 |           return {
134 |             current: 0,
135 |           }
136 |         },
137 |       },
138 |     },
139 |     setup(props, { attrs }) {
140 |       const field = useField<VoidField>().value
141 |       const prefixCls = `${stylePrefix}-form-step`
142 |       const fieldSchemaRef = useFieldSchema()
143 | 
144 |       const steps = parseSteps(fieldSchemaRef.value)
145 | 
146 |       props.formStep.connect?.(steps, field)
147 | 
148 |       return () => {
149 |         const current = props.active || props.formStep?.current || 0
150 | 
151 |         const renderSteps = (steps: SchemaStep[], callback) => {
152 |           return steps.map(callback)
153 |         }
154 | 
155 |         return h(
156 |           'div',
157 |           {
158 |             class: [prefixCls],
159 |           },
160 |           {
161 |             default: () => [
162 |               h(
163 |                 Steps,
164 |                 {
165 |                   props: {
166 |                     active: current,
167 |                   },
168 |                   style: [{ marginBottom: '10px' }, attrs.style],
169 |                   attrs,
170 |                 },
171 |                 {
172 |                   default: () =>
173 |                     renderSteps(steps, ({ props }, key) => {
174 |                       return h(Step, { props, key }, {})
175 |                     }),
176 |                 }
177 |               ),
178 | 
179 |               renderSteps(steps, ({ name, schema }, key) => {
180 |                 if (key !== current) return
181 |                 return h(RecursionField, { props: { name, schema }, key }, {})
182 |               }),
183 |             ],
184 |           }
185 |         )
186 |       }
187 |     },
188 |   })
189 | )
190 | 
191 | const StepPane = defineComponent<StepProps>({
192 |   name: 'FFormStepPane',
193 |   setup(_props, { slots }) {
194 |     return () => h(Fragment, {}, slots)
195 |   },
196 | })
197 | 
198 | export const FormStep = composeExport(FormStepInner, {
199 |   StepPane,
200 |   createFormStep,
201 | })
202 | 
203 | export default FormStep
204 | 
```
Page 15/52FirstPrevNextLast