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

# Directory Structure

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

# Files

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

```typescript
import React, { Fragment } from 'react'
import { define, observable, model, markRaw, action } from '@formily/reactive'
import cls from 'classnames'
import {
  StepProps as StepsProps,
  ItemProps as StepProps,
} from '@alifd/next/lib/step'
import { Form, VoidField } from '@formily/core'
import {
  connect,
  useField,
  observer,
  useFieldSchema,
  RecursionField,
} from '@formily/react'
import { Schema, SchemaKey } from '@formily/json-schema'
import { Step as Steps } from '@alifd/next'
import { usePrefixCls } from '../__builtins__'

export interface IFormStep {
  connect: (steps: SchemaStep[], field: VoidField) => void
  current: number
  allowNext: boolean
  allowBack: boolean
  setCurrent(key: number): void
  submit: Form['submit']
  next(): void
  back(): void
}

export interface IFormStepProps extends StepsProps {
  formStep?: IFormStep
}

type ComposedFormTab = React.FC<React.PropsWithChildren<IFormStepProps>> & {
  StepPane?: React.FC<React.PropsWithChildren<StepProps>>
  createFormStep?: (defaultCurrent?: number) => IFormStep
}

type SchemaStep = {
  name: SchemaKey
  props: any
  schema: Schema
}

type FormStepEnv = {
  form: Form
  field: VoidField
  steps: SchemaStep[]
}

const parseSteps = (schema: Schema) => {
  const steps: SchemaStep[] = []
  schema.mapProperties((schema, name) => {
    if (schema['x-component']?.indexOf('StepPane') > -1) {
      steps.push({
        name,
        props: schema['x-component-props'],
        schema,
      })
    }
  })
  return steps
}

const createFormStep = (defaultCurrent = 0): IFormStep => {
  const env: FormStepEnv = define(
    {
      form: null,
      field: null,
      steps: [],
    },
    {
      form: observable.ref,
      field: observable.ref,
      steps: observable.shallow,
    }
  )

  const setDisplay = action.bound((target: number) => {
    const currentStep = env.steps[target]
    env.steps.forEach(({ name }) => {
      env.form.query(`${env.field.address}.${name}`).take((field) => {
        if (name === currentStep.name) {
          field.setDisplay('visible')
        } else {
          field.setDisplay('hidden')
        }
      })
    })
  })

  const next = () => {
    if (formStep.allowNext) {
      formStep.setCurrent(formStep.current + 1)
    }
  }

  const back = () => {
    if (formStep.allowBack) {
      formStep.setCurrent(formStep.current - 1)
    }
  }

  const formStep: IFormStep = model({
    connect(steps, field) {
      env.steps = steps
      env.form = field?.form
      env.field = field
    },
    current: defaultCurrent,
    setCurrent(key: number) {
      setDisplay(key)
      formStep.current = key
    },
    get allowNext() {
      return formStep.current < env.steps.length - 1
    },
    get allowBack() {
      return formStep.current > 0
    },
    async next() {
      try {
        await env.form.validate()
        if (env.form.valid) {
          next()
        }
      } catch {}
    },
    async back() {
      back()
    },
    async submit(onSubmit) {
      return env.form?.submit?.(onSubmit)
    },
  })
  return markRaw(formStep)
}

export const FormStep: ComposedFormTab = connect(
  observer(({ formStep, className, ...props }: IFormStepProps) => {
    const field = useField<VoidField>()
    const prefixCls = usePrefixCls('formily-step', props)
    const schema = useFieldSchema()
    const steps = parseSteps(schema)
    const current = props.current || formStep?.current || 0
    formStep?.connect?.(steps, field)
    return (
      <div className={cls(prefixCls, className)}>
        <Steps
          {...props}
          style={{ marginBottom: 10, ...props.style }}
          current={current}
        >
          {steps.map(({ props }, key) => {
            return <Steps.Item {...props} key={key} />
          })}
        </Steps>
        {steps.map(({ name, schema }, key) => {
          if (key !== current) return
          return <RecursionField key={key} name={name} schema={schema} />
        })}
      </div>
    )
  })
)

const StepPane: React.FC<React.PropsWithChildren<StepProps>> = ({
  children,
}) => {
  return <Fragment>{children}</Fragment>
}

FormStep.StepPane = StepPane
FormStep.createFormStep = createFormStep

export default FormStep

```

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

```typescript
import { Schema, SchemaKey } from '@formily/json-schema'
import { model } from '@formily/reactive'
import { observer } from '@formily/reactive-vue'
import {
  Fragment,
  h,
  RecursionField,
  useField,
  useFieldSchema,
} from '@formily/vue'
import { Badge, TabPane, Tabs } from 'element-ui'
import { computed, defineComponent, reactive } from 'vue-demi'
import { stylePrefix } from '../__builtins__/configs'

import type { TabPane as TabPaneProps, Tabs as TabsProps } from 'element-ui'
import { composeExport } from '../__builtins__/shared'

export interface IFormTab {
  activeKey: string
  setActiveKey(key: string): void
}

export interface IFormTabProps extends TabsProps {
  formTab?: IFormTab
}

export interface IFormTabPaneProps extends TabPaneProps {
  key: string | number
}

const useTabs = () => {
  const tabsField = useField().value
  const schema = useFieldSchema().value
  const tabs: { name: SchemaKey; props: any; schema: Schema }[] = reactive([])
  schema.mapProperties((schema, name) => {
    const field = tabsField.query(tabsField.address.concat(name)).take()
    if (field?.display === 'none' || field?.display === 'hidden') return
    if (schema['x-component']?.indexOf('TabPane') > -1) {
      tabs.push({
        name,
        props: {
          name: schema?.['x-component-props']?.name || name,
          ...schema?.['x-component-props'],
        },
        schema,
      })
    }
  })
  return tabs
}

const createFormTab = (defaultActiveKey?: string) => {
  const formTab = model({
    activeKey: defaultActiveKey,
    setActiveKey(key: string) {
      formTab.activeKey = key
    },
  })
  return formTab
}

const FormTabInner = observer(
  defineComponent<IFormTabProps>({
    name: 'FFormTab',
    props: ['formTab'],
    setup(props, { attrs, listeners }) {
      const field = useField().value
      const formTabRef = computed(() => props.formTab ?? createFormTab())

      const prefixCls = `${stylePrefix}-form-tab`

      return () => {
        const formTab = formTabRef.value
        const tabs = useTabs()
        const activeKey = props.value || formTab?.activeKey || tabs?.[0]?.name
        const badgedTab = (key: SchemaKey, props: any) => {
          const errors = field.form.queryFeedbacks({
            type: 'error',
            address: `${field.address.concat(key)}.*`,
          })
          if (errors.length) {
            return () =>
              h(
                Badge,
                {
                  class: [`${prefixCls}-errors-badge`],
                  props: {
                    value: errors.length,
                  },
                },
                { default: () => props.label }
              )
          }
          return () => props.label
        }

        const getTabs = (tabs) => {
          return tabs.map(({ props, schema, name }, key) => {
            return h(
              TabPane,
              {
                key,
                props,
              },
              {
                default: () => [
                  h(
                    RecursionField,
                    {
                      props: {
                        schema,
                        name,
                      },
                    },
                    {}
                  ),
                ],
                label: () => [
                  h('div', {}, { default: badgedTab(name, props) }),
                ],
              }
            )
          })
        }

        return h(
          Tabs,
          {
            class: [prefixCls],
            style: attrs.style,
            props: {
              ...attrs,
              value: activeKey,
            },
            on: {
              ...listeners,
              input: (key) => {
                listeners.input?.(key)
                formTab.setActiveKey?.(key)
              },
            },
          },
          {
            default: () => getTabs(tabs),
          }
        )
      }
    },
  })
)

const FormTabPane = defineComponent<IFormTabPaneProps>({
  name: 'FFormTabPane',
  setup(_props, { slots }) {
    return () => h(Fragment, {}, slots)
  },
})

export const FormTab = composeExport(FormTabInner, {
  TabPane: FormTabPane,
  createFormTab,
})

export default FormTab

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaArrayField
        name="string_array"
        :maxItems="3"
        x-decorator="FormItem"
        x-component="ArrayCollapse"
        :x-component-props="{
          accordion: true,
          defaultOpenPanelCount: 3,
        }"
      >
        <SchemaVoidField
          x-component="ArrayCollapse.Item"
          :x-component-props="{
            title: '字符串数组',
          }"
        >
          <SchemaVoidField x-component="ArrayCollapse.Index" />
          <SchemaStringField
            name="input"
            x-decorator="FormItem"
            title="Input"
            required
            x-component="Input"
          />
          <SchemaVoidField x-component="ArrayCollapse.Remove" />
          <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
          <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
        </SchemaVoidField>
        <SchemaVoidField
          x-component="ArrayCollapse.Addition"
          title="添加条目"
        />
      </SchemaArrayField>
      <SchemaArrayField
        name="array"
        :maxItems="3"
        x-decorator="FormItem"
        x-component="ArrayCollapse"
      >
        <SchemaObjectField
          x-component="ArrayCollapse.Item"
          :x-component-props="{
            title: '对象数组',
          }"
        >
          <SchemaVoidField x-component="ArrayCollapse.Index" />
          <SchemaStringField
            name="input"
            x-decorator="FormItem"
            title="Input"
            required
            x-component="Input"
          />
          <SchemaVoidField x-component="ArrayCollapse.Remove" />
          <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
          <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
        </SchemaObjectField>
        <SchemaVoidField
          x-component="ArrayCollapse.Addition"
          title="添加条目"
        />
      </SchemaArrayField>
      <SchemaArrayField
        name="string_array_unshift"
        :maxItems="3"
        x-decorator="FormItem"
        x-component="ArrayCollapse"
        :x-component-props="{
          defaultOpenPanelCount: 8,
        }"
      >
        <SchemaVoidField
          x-component="ArrayCollapse.Item"
          :x-component-props="{
            title: '字符串数组',
          }"
        >
          <SchemaVoidField x-component="ArrayCollapse.Index" />
          <SchemaStringField
            name="input"
            x-decorator="FormItem"
            title="Input"
            required
            x-component="Input"
          />
          <SchemaVoidField x-component="ArrayCollapse.Remove" />
          <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
          <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
        </SchemaVoidField>
        <SchemaVoidField
          x-component="ArrayCollapse.Addition"
          title="添加条目(unshift)"
          :x-component-props="{
            method: 'unshift',
          }"
        />
      </SchemaArrayField>
    </SchemaField>
    <FormButtonGroup>
      <Button
        @click="
          () => {
            form.setInitialValues({
              array: Array.from({ length: 10 }).map(() => ({
                input: 'default value',
              })),
              string_array: Array.from({ length: 10 }).map(
                () => 'default value'
              ),
              string_array_unshift: Array.from({ length: 10 }).map(
                () => 'default value'
              ),
            })
          }
        "
      >
        加载默认数据
      </Button>
      <Submit @submit="log">提交</Submit>
    </FormButtonGroup>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormButtonGroup,
  Submit,
  Input,
  ArrayCollapse,
} from '@formily/element'
import { Button } from 'element-ui'

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

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    Button,
    Submit,
    ...SchemaField,
  },

  data() {
    const form = createForm()

    return {
      form,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```typescript
import { connect, h, mapProps, mapReadPretty } from '@formily/vue'
import type {
  Checkbox as _ElCheckboxProps,
  CheckboxGroup as ElCheckboxGroupProps,
} from 'element-ui'
import {
  Checkbox as ElCheckbox,
  CheckboxButton as ElCheckboxButton,
  CheckboxGroup as ElCheckboxGroup,
} from 'element-ui'
import { defineComponent, PropType } from 'vue-demi'
import { PreviewText } from '../preview-text'
import {
  composeExport,
  resolveComponent,
  SlotTypes,
  transformComponent,
} from '../__builtins__/shared'

type ElCheckboxProps = Omit<_ElCheckboxProps, 'value'> & {
  value: ElCheckboxProps['label']
}

export interface CheckboxProps extends ElCheckboxProps {
  option: Omit<_ElCheckboxProps, 'value'> & {
    value: ElCheckboxProps['label']
    label: SlotTypes
  }
}

const CheckboxOption = defineComponent<CheckboxProps>({
  name: 'Checkbox',
  inheritAttrs: false,
  props: {
    option: {
      type: Object,
      default: null,
    },
  },
  setup(curtomProps, { attrs, slots, listeners }) {
    return () => {
      const props = attrs as unknown as CheckboxProps
      const option = curtomProps?.option
      if (option) {
        const children = {
          default: () => [
            resolveComponent(slots.default ?? option.label, { option }),
          ],
        }
        const newProps = {} as Partial<ElCheckboxProps>
        Object.assign(newProps, option)
        newProps.label = option.value
        delete newProps.value

        return h(
          attrs.optionType === 'button' ? ElCheckboxButton : ElCheckbox,
          {
            attrs: {
              ...newProps,
            },
          },
          children
        )
      }

      return h(
        ElCheckbox,
        {
          attrs: {
            ...props,
          },
          on: listeners,
        },
        slots
      )
    }
  },
})

export type CheckboxGroupProps = ElCheckboxGroupProps & {
  value: any[]
  options?: Array<CheckboxProps | string>
  optionType: 'default' | 'button'
}

const TransformElCheckboxGroup = transformComponent(ElCheckboxGroup, {
  change: 'input',
  uselessChange: 'change'
})

const CheckboxGroupOption = defineComponent<CheckboxGroupProps>({
  name: 'CheckboxGroup',
  props: {
    options: {
      type: Array,
      default: () => [],
    },
    optionType: {
      type: String as PropType<CheckboxGroupProps['optionType']>,
      default: 'default',
    },
  },
  setup(customProps, { attrs, slots, listeners }) {
    return () => {
      const options = customProps.options || []
      const children =
        options.length !== 0
          ? {
              default: () =>
                options.map((option) => {
                  if (typeof option === 'string') {
                    return h(
                      Checkbox,
                      {
                        props: {
                          option: {
                            label: option,
                            value: option,
                          },
                        },
                        attrs: {
                          optionType: customProps.optionType,
                        },
                      },
                      slots?.option
                        ? { default: () => slots.option({ option }) }
                        : {}
                    )
                  } else {
                    return h(
                      Checkbox,
                      {
                        props: {
                          option,
                        },
                        attrs: {
                          optionType: customProps.optionType,
                        },
                      },
                      slots?.option
                        ? { default: () => slots.option({ option }) }
                        : {}
                    )
                  }
                }),
            }
          : slots
      return h(
        TransformElCheckboxGroup,
        {
          attrs: {
            ...attrs,
          },
          on: listeners,
        },
        children
      )
    }
  },
})

const CheckboxGroup = connect(
  CheckboxGroupOption,
  mapProps({ dataSource: 'options' }),
  mapReadPretty(PreviewText.Select, {
    multiple: true,
  })
)

export const Checkbox = composeExport(connect(CheckboxOption), {
  Group: CheckboxGroup,
})

export default Checkbox

```

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

```typescript
import React, { Fragment, useMemo } from 'react'
import { FormPath, isBool, isFn, isValid } from '@formily/shared'
import { GeneralField } from '@formily/core'
import { Schema } from '@formily/json-schema'
import { SchemaContext } from '../shared'
import { IRecursionFieldProps, ReactFC } from '../types'
import { useField, useExpressionScope } from '../hooks'
import { ObjectField } from './ObjectField'
import { ArrayField } from './ArrayField'
import { Field } from './Field'
import { VoidField } from './VoidField'
import { ExpressionScope } from './ExpressionScope'
import { observable } from '@formily/reactive'

const useFieldProps = (schema: Schema) => {
  const scope = useExpressionScope()
  return schema.toFieldProps({
    scope,
  }) as any
}

const useBasePath = (props: IRecursionFieldProps) => {
  const parent = useField()
  if (props.onlyRenderProperties) {
    return props.basePath || parent?.address.concat(props.name)
  }
  return props.basePath || parent?.address
}

export const RecursionField: ReactFC<IRecursionFieldProps> = (props) => {
  const basePath = useBasePath(props)
  const fieldSchema = useMemo(() => new Schema(props.schema), [props.schema])
  const fieldProps = useFieldProps(fieldSchema)

  const renderSlots = (innerSchema, key) => {
    const slot = innerSchema['x-slot-node']
    const { target, isRenderProp } = slot
    if (isRenderProp) {
      const args = observable({ $slotArgs: [] })
      FormPath.setIn(fieldSchema.properties, target, (..._args: any) => {
        args.$slotArgs = _args
        return (
          <ExpressionScope value={args}>
            <RecursionField schema={innerSchema} name={key} />
          </ExpressionScope>
        )
      })
    } else {
      FormPath.setIn(
        fieldSchema.properties,
        target,
        <RecursionField schema={innerSchema} name={key} />
      )
    }
  }

  const renderProperties = (field?: GeneralField) => {
    if (props.onlyRenderSelf) return
    const properties = Schema.getOrderProperties(fieldSchema)
    if (!properties.length) return
    return (
      <Fragment>
        {properties.map(({ schema: item, key: name }, index) => {
          const base = field?.address || basePath
          let schema: Schema = item
          if (schema['x-slot-node']) {
            renderSlots(schema, name)
            return null
          }

          if (isFn(props.mapProperties)) {
            const mapped = props.mapProperties(item, name)
            if (mapped) {
              schema = mapped
            }
          }
          if (isFn(props.filterProperties)) {
            if (props.filterProperties(schema, name) === false) {
              return null
            }
          }
          if (isBool(props.propsRecursion) && props.propsRecursion) {
            return (
              <RecursionField
                propsRecursion={true}
                filterProperties={props.filterProperties}
                mapProperties={props.mapProperties}
                schema={schema}
                key={`${index}-${name}`}
                name={name}
                basePath={base}
              />
            )
          }
          return (
            <RecursionField
              schema={schema}
              key={`${index}-${name}`}
              name={name}
              basePath={base}
            />
          )
        })}
      </Fragment>
    )
  }

  const render = () => {
    if (!isValid(props.name)) return renderProperties()
    if (fieldSchema.type === 'object') {
      if (props.onlyRenderProperties) return renderProperties()
      return (
        <ObjectField {...fieldProps} name={props.name} basePath={basePath}>
          {renderProperties}
        </ObjectField>
      )
    } else if (fieldSchema.type === 'array') {
      return (
        <ArrayField {...fieldProps} name={props.name} basePath={basePath} />
      )
    } else if (fieldSchema.type === 'void') {
      if (props.onlyRenderProperties) return renderProperties()
      return (
        <VoidField {...fieldProps} name={props.name} basePath={basePath}>
          {renderProperties}
        </VoidField>
      )
    }
    return <Field {...fieldProps} name={props.name} basePath={basePath} />
  }

  if (!fieldSchema) return <Fragment />

  return (
    <SchemaContext.Provider value={fieldSchema}>
      {render()}
    </SchemaContext.Provider>
  )
}

```

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

```typescript
import React from 'react'
import { Card, Empty } from 'antd'
import { CardProps } from 'antd/lib/card'
import { ArrayField } from '@formily/core'
import {
  useField,
  observer,
  useFieldSchema,
  RecursionField,
} from '@formily/react'
import cls from 'classnames'
import { ISchema } from '@formily/json-schema'
import { usePrefixCls } from '../__builtins__'
import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from '../array-base'

type ComposedArrayCards = React.FC<
  React.PropsWithChildren<CardProps & IArrayBaseProps>
> &
  ArrayBaseMixins

const isAdditionComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Addition') > -1
}

const isIndexComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf?.('Index') > -1
}

const isRemoveComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf?.('Remove') > -1
}

const isCopyComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf?.('Copy') > -1
}

const isMoveUpComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf?.('MoveUp') > -1
}

const isMoveDownComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf?.('MoveDown') > -1
}

const isOperationComponent = (schema: ISchema) => {
  return (
    isAdditionComponent(schema) ||
    isRemoveComponent(schema) ||
    isCopyComponent(schema) ||
    isMoveDownComponent(schema) ||
    isMoveUpComponent(schema)
  )
}

export const ArrayCards: ComposedArrayCards = observer((props) => {
  const field = useField<ArrayField>()
  const schema = useFieldSchema()
  const dataSource = Array.isArray(field.value) ? field.value : []
  const prefixCls = usePrefixCls('formily-array-cards', props)
  const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp } = props

  if (!schema) throw new Error('can not found schema object')

  const renderItems = () => {
    return dataSource?.map((item, index) => {
      const items = Array.isArray(schema.items)
        ? schema.items[index] || schema.items[0]
        : schema.items
      const title = (
        <span>
          <RecursionField
            schema={items}
            name={index}
            filterProperties={(schema) => {
              if (!isIndexComponent(schema)) return false
              return true
            }}
            onlyRenderProperties
          />
          {props.title || field.title}
        </span>
      )
      const extra = (
        <span>
          <RecursionField
            schema={items}
            name={index}
            filterProperties={(schema) => {
              if (!isOperationComponent(schema)) return false
              return true
            }}
            onlyRenderProperties
          />
          {props.extra}
        </span>
      )
      const content = (
        <RecursionField
          schema={items}
          name={index}
          filterProperties={(schema) => {
            if (isIndexComponent(schema)) return false
            if (isOperationComponent(schema)) return false
            return true
          }}
        />
      )
      return (
        <ArrayBase.Item
          key={index}
          index={index}
          record={() => field.value?.[index]}
        >
          <Card
            {...props}
            onChange={() => {}}
            className={cls(`${prefixCls}-item`, props.className)}
            title={title}
            extra={extra}
          >
            {content}
          </Card>
        </ArrayBase.Item>
      )
    })
  }

  const renderAddition = () => {
    return schema.reduceProperties((addition, schema, key) => {
      if (isAdditionComponent(schema)) {
        return <RecursionField schema={schema} name={key} />
      }
      return addition
    }, null)
  }

  const renderEmpty = () => {
    if (dataSource?.length) return
    return (
      <Card
        {...props}
        onChange={() => {}}
        className={cls(`${prefixCls}-item`, props.className)}
        title={props.title || field.title}
      >
        <Empty />
      </Card>
    )
  }

  return (
    <ArrayBase
      onAdd={onAdd}
      onCopy={onCopy}
      onRemove={onRemove}
      onMoveUp={onMoveUp}
      onMoveDown={onMoveDown}
    >
      {renderEmpty()}
      {renderItems()}
      {renderAddition()}
    </ArrayBase>
  )
})

ArrayCards.displayName = 'ArrayCards'

ArrayBase.mixin(ArrayCards)

export default ArrayCards

```

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

```typescript
import { define, model, observable, autorun } from '..'
import { observe } from '../observe'
import { FormPath } from '@formily/shared'
import { batch } from '../batch'

describe('makeObservable', () => {
  test('observable annotation', () => {
    const target: any = {
      aa: {},
    }
    define(target, {
      aa: observable,
    })
    const handler = jest.fn()
    const handler1 = jest.fn()
    const handler2 = jest.fn()
    autorun(() => {
      handler(FormPath.getIn(target, 'aa.bb.cc'))
    })
    observe(target, handler1)
    observe(target.aa, handler2)
    target.aa.bb = { cc: { dd: { ee: 123 } } }
    target.aa = { hh: 123 }
    expect(handler).toBeCalledTimes(3)
    expect(handler).nthCalledWith(1, undefined)
    expect(handler).nthCalledWith(2, { dd: { ee: 123 } })
    expect(handler).nthCalledWith(3, undefined)
    expect(handler1).toBeCalledTimes(2)
    expect(handler2).toBeCalledTimes(2)
  })
  test('shallow annotation', () => {
    const target: any = {
      aa: {},
    }
    define(target, {
      aa: observable.shallow,
    })
    const handler = jest.fn()
    const handler1 = jest.fn()
    const handler2 = jest.fn()
    autorun(() => {
      handler(FormPath.getIn(target, 'aa.bb.cc'))
    })
    observe(target, handler1)
    observe(target.aa, handler2)
    target.aa.bb = { cc: { dd: { ee: 123 } } }
    target.aa.bb.cc.kk = 333
    target.aa = { hh: 123 }
    expect(handler).toBeCalledTimes(3)
    expect(handler).nthCalledWith(1, undefined)
    expect(handler).nthCalledWith(2, { dd: { ee: 123 }, kk: 333 })
    expect(handler).nthCalledWith(3, undefined)
    expect(handler1).toBeCalledTimes(2)
    expect(handler2).toBeCalledTimes(2)
  })
  test('box annotation', () => {
    const target: any = {}
    define(target, {
      aa: observable.box,
    })
    const handler = jest.fn()
    const handler1 = jest.fn()
    const handler2 = jest.fn()
    autorun(() => {
      handler(target.aa.get())
    })
    observe(target, handler1)
    observe(target.aa, handler2)

    expect(handler).lastCalledWith(undefined)
    target.aa.set(123)
    expect(handler).toBeCalledTimes(2)
    expect(handler).lastCalledWith(123)
    expect(handler1).toBeCalledTimes(1)
    expect(handler2).toBeCalledTimes(1)
  })
  test('ref annotation', () => {
    const target: any = {}
    define(target, {
      aa: observable.ref,
    })
    const handler = jest.fn()
    const handler1 = jest.fn()
    autorun(() => {
      handler(target.aa)
    })
    observe(target, handler1)
    expect(handler).lastCalledWith(undefined)
    target.aa = 123
    expect(handler).toBeCalledTimes(2)
    expect(handler).lastCalledWith(123)
    expect(handler1).toBeCalledTimes(1)
  })
  test('action annotation', () => {
    const target = {
      aa: {
        bb: null,
        cc: null,
      },
      setData() {
        target.aa.bb = 123
        target.aa.cc = 312
      },
    }
    define(target, {
      aa: observable,
      setData: batch,
    })
    const handler = jest.fn()
    autorun(() => {
      handler([target.aa.bb, target.aa.cc])
    })
    expect(handler).toBeCalledTimes(1)
    target.setData()
    expect(handler).toBeCalledTimes(2)
  })
  test('computed annotation', () => {
    const handler = jest.fn()
    const target = {
      aa: 11,
      bb: 22,
      get cc() {
        handler()
        return this.aa + this.bb
      },
    }
    define(target, {
      aa: observable,
      bb: observable,
      cc: observable.computed,
    })
    autorun(() => {
      target.cc
    })
    expect(handler).toBeCalledTimes(1)
    expect(target.cc).toEqual(33)
    target.aa = 22
    expect(handler).toBeCalledTimes(2)
    expect(target.cc).toEqual(44)
  })
  test('unexpect target', () => {
    const testFn = jest.fn()
    const testArr = []
    const obs1 = define(4 as any, {
      value: observable.computed,
    })
    const obs2 = define('123' as any, {
      value: observable.computed,
    })
    const obs3 = define(testFn as any, {
      value: observable.computed,
    })
    const obs4 = define(testArr as any, {
      value: observable.computed,
    })
    expect(obs1).toBe(4)
    expect(obs2).toBe('123')
    expect(obs3).toBe(testFn)
    expect(obs4).toBe(testArr)
  })
})

test('define model', () => {
  const obs = model({
    aa: 1,
    action() {
      this.aa++
    },
  })
  const { action } = obs
  action()
  expect(obs.aa).toEqual(2)
})

```

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

```markdown
# Reset

> 重置按钮

## 普通重置

> 有默认值的控件无法被清空

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset>重置</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## 强制清空重置

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear>重置</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## 重置并校验

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset validate>重置</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## 强制清空重置并校验

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear validate>
        重置
      </Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

### Reset

其余 API 参考 https://ant.design/components/button-cn/

| 属性名                 | 类型                                                                                                   | 描述                                  | 默认值 |
| ---------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ |
| onClick                | `(event: MouseEvent) => void \| boolean`                                                               | 点击事件,如果返回 false 可以阻塞重置 | -      |
| onResetValidateSuccess | (payload: any) => void                                                                                 | 重置校验成功事件                      | -      |
| onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/zh-CN/api/models/form#iformfeedback)[]) => void | 重置校验失败事件                      | -      |

```

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

```markdown
# Reset

> 重置按钮

## 普通重置

> 有默认值的控件无法被清空

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset>重置</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## 强制清空重置

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear>重置</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## 重置并校验

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset validate>重置</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## 强制清空重置并校验

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear validate>
        重置
      </Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

### Reset

其余 API 参考 https://fusion.design/pc/component/basic/button

| 属性名                 | 类型                                                                                                   | 描述                                  | 默认值 |
| ---------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ |
| onClick                | `(event: MouseEvent) => void \| boolean`                                                               | 点击事件,如果返回 false 可以阻塞重置 | -      |
| onResetValidateSuccess | (payload: any) => void                                                                                 | 重置校验成功事件                      | -      |
| onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/zh-CN/api/models/form#iformfeedback)[]) => void | 重置校验失败事件                      | -      |

```

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

```markdown
# Form

> 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

## Use Cases

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

const form = createForm()

export default () => (
  <Form
    form={form}
    layout="vertical"
    feedbackLayout="terse"
    onAutoSubmit={console.log}
    onAutoSubmitFailed={console.log}
  >
    <FormGrid maxColumns={4}>
      <Field
        name="aa"
        title="select box"
        decorator={[FormItem]}
        component={[Select]}
        dataSource={[
          {
            label: 'Option 1',
            value: 1,
          },
          {
            label: 'Option 2',
            value: 2,
          },
        ]}
      />
      <Field
        name="bb"
        title="input box"
        required
        decorator={[FormItem]}
        component={[Input]}
      />
      <Field
        name="cc"
        title="input box"
        decorator={[FormItem]}
        component={[Input]}
      />
      <Field
        name="dd"
        title="input box"
        decorator={[FormItem]}
        component={[Input]}
      />
      <Field
        name="ee"
        title="input box"
        decorator={[FormItem]}
        component={[Input]}
      />
      <FormButtonGroup.FormItem>
        <Submit>Query</Submit>
      </FormButtonGroup.FormItem>
    </FormGrid>
  </Form>
)
```

## Fusion Multilingual

```tsx
import React from 'react'
import { Input, Form, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { Field } from '@formily/react'
import { ConfigProvider } from '@alifd/next'
import enUS from '@alifd/next/lib/locale/en-us'

const form = createForm()

export default () => (
  <ConfigProvider locale={enUS}>
    <Form
      form={form}
      layout="vertical"
      feedbackLayout="terse"
      onAutoSubmit={console.log}
    >
      <Field
        name="bb"
        title="User Name"
        required
        decorator={[FormItem]}
        component={[Input]}
      />

      <FormButtonGroup.FormItem>
        <Submit>Submit</Submit>
      </FormButtonGroup.FormItem>
    </Form>
  </ConfigProvider>
)
```

<Alert style="margin-top:20px">
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.
</Alert>

## API

For layout-related API properties, we can refer to [FormLayout](./form-layout), and the rest are the unique API properties of the Form component

| Property name          | Type                                                                                             | Description                                                         | Default value |
| ---------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | ------------- |
| form                   | [Form](https://core.formilyjs.org/api/models/form)                                               | Form example                                                        | -             |
| component              | string                                                                                           | Rendering component, can be specified as custom component rendering | `form`        |
| previewTextPlaceholder | ReactNode                                                                                        | Preview State Placeholder                                           | `N/A`         |
| onAutoSubmit           | `(values:any)=>any`                                                                              | Carriage return submit event callback                               | -             |
| onAutoSubmitFailed     | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Carriage return submission verification failure event callback      | -             |

```

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

```typescript
import {
  isEmpty,
  isValid,
  stringLength,
  isStr,
  isArr,
  isFn,
  toArr,
  isBool,
  isNum,
  isEqual,
  each,
} from '@formily/shared'
import { getValidateFormats } from './registry'
import { IRegistryRules } from './types'

const isValidateEmpty = (value: any) => {
  if (isArr(value)) {
    for (let i = 0; i < value.length; i++) {
      if (isValid(value[i])) return false
    }
    return true
  } else {
    //compat to draft-js
    if (value?.getCurrentContent) {
      /* istanbul ignore next */
      return !value.getCurrentContent()?.hasText()
    }
    return isEmpty(value)
  }
}

const getLength = (value: any) =>
  isStr(value) ? stringLength(value) : value ? value.length : 0

const extendSameRules = (
  rules: IRegistryRules,
  names: Record<string, string>
) => {
  each(names, (realName, name) => {
    rules[name] = (value, rule, ...args) =>
      rules[realName](value, { ...rule, [realName]: rule[name] }, ...args)
  })
}

const RULES: IRegistryRules = {
  format(value, rule) {
    if (isValidateEmpty(value)) return ''
    if (rule.format) {
      const format = getValidateFormats(rule.format)
      if (format) {
        return !new RegExp(format).test(value) ? rule.message : ''
      }
    }
    return ''
  },
  required(value, rule) {
    if (rule.required !== true) return ''
    return isValidateEmpty(value) ? rule.message : ''
  },
  max(value, rule) {
    if (isValidateEmpty(value)) return ''
    const length = isNum(value) ? value : getLength(value)
    const max = Number(rule.max)
    return length > max ? rule.message : ''
  },
  min(value, rule) {
    if (isValidateEmpty(value)) return ''
    const length = isNum(value) ? value : getLength(value)
    const min = Number(rule.min)
    return length < min ? rule.message : ''
  },
  exclusiveMaximum(value, rule) {
    if (isValidateEmpty(value)) return ''
    const length = isNum(value) ? value : getLength(value)
    const max = Number(rule.exclusiveMaximum)
    return length >= max ? rule.message : ''
  },
  exclusiveMinimum(value, rule) {
    if (isValidateEmpty(value)) return ''
    const length = isNum(value) ? value : getLength(value)
    const min = Number(rule.exclusiveMinimum)
    return length <= min ? rule.message : ''
  },
  len(value, rule) {
    if (isValidateEmpty(value)) return ''
    const length = getLength(value)
    const len = Number(rule.len)
    return length !== len ? rule.message : ''
  },

  pattern(value, rule) {
    if (isValidateEmpty(value)) return ''
    return !new RegExp(rule.pattern).test(value) ? rule.message : ''
  },
  async validator(value, rule, context, format) {
    if (isFn(rule.validator)) {
      const response = await Promise.resolve(
        rule.validator(value, rule, context, format)
      )
      if (isBool(response)) {
        return !response ? rule.message : ''
      } else {
        return response
      }
    }
    /* istanbul ignore next */
    throw new Error("The rule's validator property must be a function.")
  },
  whitespace(value, rule) {
    if (isValidateEmpty(value)) return ''
    if (rule.whitespace) {
      return /^\s+$/.test(value) ? rule.message : ''
    }
  },
  enum(value, rule) {
    if (isValidateEmpty(value)) return ''
    const enums = toArr(rule.enum)
    return enums.indexOf(value) === -1 ? rule.message : ''
  },
  const(value, rule) {
    if (isValidateEmpty(value)) return ''
    return rule.const !== value ? rule.message : ''
  },
  multipleOf(value, rule) {
    if (isValidateEmpty(value)) return ''
    return Number(value) % Number(rule.multipleOf) !== 0 ? rule.message : ''
  },
  uniqueItems(value, rule) {
    if (isValidateEmpty(value)) return ''
    value = toArr(value)
    return value.some((item: any, index: number) => {
      for (let i = 0; i < value.length; i++) {
        if (i !== index && !isEqual(value[i], item)) {
          return false
        }
      }
      return true
    })
      ? ''
      : rule.message
  },
  maxProperties(value, rule) {
    if (isValidateEmpty(value)) return ''
    return Object.keys(value || {}).length <= Number(rule.maxProperties)
      ? ''
      : rule.message
  },
  minProperties(value, rule) {
    if (isValidateEmpty(value)) return ''
    return Object.keys(value || {}).length >= Number(rule.minProperties)
      ? ''
      : rule.message
  },
}

extendSameRules(RULES, {
  maximum: 'max',
  minimum: 'min',
  maxItems: 'max',
  minItems: 'min',
  maxLength: 'max',
  minLength: 'min',
})

export default RULES

```

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

```typescript
import { FormPath, isFn, toArr } from '@formily/shared'
import { autorun, reaction, batch } from '@formily/reactive'
import { Form } from '../models'
import {
  LifeCycleTypes,
  FormPathPattern,
  GeneralField,
  DataField,
  IFieldState,
} from '../types'
import { createEffectHook, useEffectForm } from '../shared/effective'

function createFieldEffect<Result extends GeneralField = GeneralField>(
  type: LifeCycleTypes
) {
  return createEffectHook(
    type,
    (field: Result, form: Form) =>
      (
        pattern: FormPathPattern,
        callback: (field: Result, form: Form) => void
      ) => {
        if (
          FormPath.parse(pattern).matchAliasGroup(field.address, field.path)
        ) {
          batch(() => {
            callback(field, form)
          })
        }
      }
  )
}
const _onFieldInit = createFieldEffect(LifeCycleTypes.ON_FIELD_INIT)
export const onFieldMount = createFieldEffect(LifeCycleTypes.ON_FIELD_MOUNT)
export const onFieldUnmount = createFieldEffect(LifeCycleTypes.ON_FIELD_UNMOUNT)
export const onFieldValueChange = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_VALUE_CHANGE
)
export const onFieldInitialValueChange = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_INITIAL_VALUE_CHANGE
)
export const onFieldInputValueChange = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_INPUT_VALUE_CHANGE
)
export const onFieldValidateStart = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_VALIDATE_START
)
export const onFieldValidateEnd = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_VALIDATE_END
)
export const onFieldValidating = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_VALIDATING
)
export const onFieldValidateFailed = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_VALIDATE_FAILED
)
export const onFieldValidateSuccess = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_VALIDATE_SUCCESS
)
export const onFieldSubmit = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT
)
export const onFieldSubmitStart = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_START
)
export const onFieldSubmitEnd = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_END
)
export const onFieldSubmitValidateStart = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_START
)
export const onFieldSubmitValidateEnd = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_END
)
export const onFieldSubmitSuccess = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_SUCCESS
)
export const onFieldSubmitFailed = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_FAILED
)
export const onFieldSubmitValidateSuccess = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_SUCCESS
)
export const onFieldSubmitValidateFailed = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_SUBMIT_VALIDATE_FAILED
)
export const onFieldReset = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_RESET
)
export const onFieldLoading = createFieldEffect<DataField>(
  LifeCycleTypes.ON_FIELD_LOADING
)

export function onFieldInit(
  pattern: FormPathPattern,
  callback?: (field: GeneralField, form: Form) => void
) {
  const form = useEffectForm()
  const count = form.query(pattern).reduce((count, field) => {
    callback(field, form)
    return count + 1
  }, 0)
  if (count === 0) {
    _onFieldInit(pattern, callback)
  }
}

export function onFieldReact(
  pattern: FormPathPattern,
  callback?: (field: GeneralField, form: Form) => void
) {
  onFieldInit(pattern, (field, form) => {
    field.disposers.push(
      autorun(() => {
        if (isFn(callback)) callback(field, form)
      })
    )
  })
}
export function onFieldChange(
  pattern: FormPathPattern,
  callback?: (field: GeneralField, form: Form) => void
): void
export function onFieldChange(
  pattern: FormPathPattern,
  watches: (keyof IFieldState)[],
  callback?: (field: GeneralField, form: Form) => void
): void
export function onFieldChange(
  pattern: FormPathPattern,
  watches: any,
  callback?: (field: GeneralField, form: Form) => void
): void {
  if (isFn(watches)) {
    callback = watches
    watches = ['value']
  } else {
    watches = watches || ['value']
  }
  onFieldInit(pattern, (field, form) => {
    if (isFn(callback)) callback(field, form)
    const dispose = reaction(
      () => {
        return toArr(watches).map((key) => {
          return field[key]
        })
      },
      () => {
        if (isFn(callback)) callback(field, form)
      }
    )
    field.disposers.push(dispose)
  })
}

```

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

```typescript
import { shallowMount, createLocalVue } from '@vue/test-utils'
import { observable, autorun } from '@formily/reactive'
import { CreateElement } from 'vue'
import CompositionAPI, { defineComponent, h } from '@vue/composition-api'
import { observer } from '../'
import collectData from '../observer/collectData'
import { observer as observerInVue2 } from '../observer/observerInVue2'
import expect from 'expect'

test('observer: component', async () => {
  const model = observable<any>({
    age: 10,
    setAge() {
      model.age++
    },
  })
  const Component = observer({
    data() {
      return {
        model,
      }
    },
    render(this: any, h: CreateElement) {
      return h('button', {
        on: { click: this.model.setAge },
        domProps: { textContent: this.model.age },
      })
    },
  })
  const wrapper = shallowMount(Component)
  expect(wrapper.find('button').text()).toBe('10')
  wrapper.find('button').trigger('click')
  expect(wrapper.find('button').text()).toBe('11')
  wrapper.destroy()
})

test('observer: component with setup', async () => {
  const Vue = createLocalVue()
  Vue.use(CompositionAPI)
  const model = observable<any>({
    age: 30,
    get sub10() {
      return model.age - 10
    },
    get sub20() {
      return model.sub10 - 10
    },
    setAge() {
      model.age++
    },
  })
  const Component = observer(
    defineComponent({
      setup() {
        return () => {
          return h('button', {
            on: { click: model.setAge },
            domProps: { textContent: model.sub20 },
          })
        }
      },
      // to fix 'Maximum call stack size exceeded' error of @vue/test-utils
      render() {
        return null
      },
    })
  )
  const wrapper = shallowMount(Component)
  expect(wrapper.find('button').text()).toBe('10')
  wrapper.find('button').trigger('click')
  expect(wrapper.find('button').text()).toBe('11')
  model.age++
  expect(wrapper.find('button').text()).toBe('12')
  wrapper.destroy()
})

test('observer: component scheduler', async () => {
  let schedulerRequest = null

  const model = observable<any>({
    age: 10,
    setAge() {
      model.age++
    },
  })
  const Component = observer(
    {
      data() {
        return {
          model,
        }
      },
      render(this: any, h: CreateElement) {
        return h('button', {
          on: { click: this.model.setAge },
          domProps: { textContent: this.model.age },
        })
      },
    },
    {
      scheduler: (update) => {
        clearTimeout(schedulerRequest)
        schedulerRequest = setTimeout(() => {
          update()
        }, 100)
      },
    }
  )
  const wrapper = shallowMount(Component)

  expect(wrapper.find('button').text()).toBe('10')

  wrapper.find('button').trigger('click')
  await new Promise((r) => setTimeout(r, 150))
  expect(wrapper.find('button').text()).toBe('11')

  // test second render
  wrapper.find('button').trigger('click')
  await new Promise((r) => setTimeout(r, 150))
  expect(wrapper.find('button').text()).toBe('12')

  wrapper.destroy()
})

test('observer: stop tracking if watcher is destroyed', async () => {
  let count = 0
  const model = observable<any>({
    age: 10,
    name: 'test',
  })

  const Component = observer({
    name: 'test',
    data() {
      return {
        model: model,
      }
    },
    render() {
      count++
      return h('div', [this.model.name, this.model.age])
    },
  })

  const wrapper = shallowMount(Component)

  const childInst = wrapper.find({ name: 'test' })

  expect(childInst.exists()).toBe(true)
  ;(childInst.vm as any)._isDestroyed = true
  model.age++
  wrapper.destroy()
  expect(count).toEqual(1) // 不触发 reactiveRender
})

test('collectData', async () => {
  const model = observable<any>({
    age: 10,
    name: 'test',
  })

  const target = {
    value: 1,
  }

  const data = collectData(
    {},
    {
      model,
      target,
    }
  )

  const fn1 = jest.fn()
  const fn2 = jest.fn()

  autorun(() => fn1(model.age))
  autorun(() => fn2(data.target.value))

  model.age++
  expect(fn1).toBeCalledTimes(2)

  target.value++
  expect(fn2).toBeCalledTimes(1)
})

test('observerInVue2', () => {
  const componentObj = Object.create(null)

  componentObj.data = () => {
    return {}
  }

  const ExtendedComponent1 = observerInVue2(componentObj)
  expect(ExtendedComponent1.name).toEqual('<component>')

  function Component() {}
  Component.options = {
    data: () => {
      return {}
    },
  }

  const ExtendedComponent2 = observerInVue2(Component, { name: 'abc' })
  expect(ExtendedComponent2.name).toEqual('abc')
})

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField :schema="schema" />
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>

<script>
import { createForm, onFieldChange, onFieldReact } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  Submit,
  FormItem,
  ArrayTable,
  Input,
  Editable,
  Switch,
} from '@formily/element'

const fields = createSchemaField({
  components: {
    FormItem,
    ArrayTable,
    Input,
    Editable,
    Switch,
  },
})

export default {
  components: { FormProvider, Submit, ...fields },
  data() {
    const form = createForm({
      effects: () => {
        //主动联动模式
        onFieldChange('hideFirstColumn', ['value'], (field) => {
          field.query('array.column3').take((target) => {
            target.visible = !field.value
          })
          field.query('array.*.a2').take((target) => {
            target.visible = !field.value
          })
        })
        //被动联动模式
        onFieldReact('array.*.a2', (field) => {
          field.visible = !field.query('.a1').get('value')
        })
      },
    })
    const schema = {
      type: 'object',
      properties: {
        hideFirstColumn: {
          type: 'boolean',
          title: '隐藏A2',
          'x-decorator': 'FormItem',
          'x-component': 'Switch',
        },
        array: {
          type: 'array',
          'x-decorator': 'FormItem',
          'x-component': 'ArrayTable',
          items: {
            type: 'object',
            properties: {
              column1: {
                type: 'void',
                'x-component': 'ArrayTable.Column',
                'x-component-props': {
                  width: 80,
                  title: 'Index',
                  align: 'center',
                },
                properties: {
                  index: {
                    type: 'void',
                    'x-component': 'ArrayTable.Index',
                  },
                },
              },
              column2: {
                type: 'void',
                'x-component': 'ArrayTable.Column',
                'x-component-props': { width: 100, title: '显隐->A2' },
                properties: {
                  a1: {
                    type: 'boolean',
                    'x-decorator': 'FormItem',
                    'x-component': 'Switch',
                  },
                },
              },
              column3: {
                type: 'void',
                'x-component': 'ArrayTable.Column',
                'x-component-props': { width: 200, title: 'A2' },
                properties: {
                  a2: {
                    type: 'string',
                    'x-decorator': 'FormItem',
                    'x-component': 'Input',
                  },
                },
              },
              column4: {
                type: 'void',
                'x-component': 'ArrayTable.Column',
                'x-component-props': { title: 'A3' },
                properties: {
                  a3: {
                    type: 'string',
                    'x-decorator': 'FormItem',
                    'x-component': 'Input',
                  },
                },
              },
              column5: {
                type: 'void',
                'x-component': 'ArrayTable.Column',
                'x-component-props': {
                  title: 'Operations',
                  prop: 'operations',
                  width: 200,
                  fixed: 'right',
                },
                properties: {
                  item: {
                    type: 'void',
                    'x-component': 'FormItem',
                    properties: {
                      remove: {
                        type: 'void',
                        'x-component': 'ArrayTable.Remove',
                      },
                      moveDown: {
                        type: 'void',
                        'x-component': 'ArrayTable.MoveDown',
                      },
                      moveUp: {
                        type: 'void',
                        'x-component': 'ArrayTable.MoveUp',
                      },
                    },
                  },
                },
              },
            },
          },
          properties: {
            add: {
              type: 'void',
              'x-component': 'ArrayTable.Addition',
              title: '添加条目',
            },
          },
        },
      },
    }
    return {
      form,
      schema,
    }
  },
  methods: {
    log(...v) {
      console.log(...v)
    },
  },
}
</script>

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaArrayField
        name="string_array"
        title="字符串数组"
        x-decorator="FormItem"
        x-component="ArrayItems"
      >
        <SchemaVoidField x-component="Space">
          <SchemaVoidField
            x-decorator="FormItem"
            x-component="ArrayItems.SortHandle"
          />
          <SchemaStringField
            x-decorator="FormItem"
            required
            name="input"
            x-component="Input"
            :x-component-props="{
              style: {
                width: '160px',
              },
            }"
          />
          <SchemaVoidField
            x-decorator="FormItem"
            x-component="ArrayItems.Remove"
          />
        </SchemaVoidField>
        <SchemaVoidField x-component="ArrayItems.Addition" title="添加条目" />
      </SchemaArrayField>
      <SchemaArrayField
        name="array"
        title="对象数组"
        x-decorator="FormItem"
        x-component="ArrayItems"
      >
        <SchemaObjectField>
          <SchemaVoidField x-component="Space">
            <SchemaVoidField
              x-decorator="FormItem"
              x-component="ArrayItems.SortHandle"
            />
            <SchemaStringField
              x-decorator="FormItem"
              required
              title="日期"
              name="date"
              x-component="DatePicker"
              :x-component-props="{
                type: 'daterange',
                style: {
                  width: '160px',
                },
              }"
            />
            <SchemaStringField
              x-decorator="FormItem"
              required
              title="输入框"
              name="input"
              x-component="Input"
            />
            <SchemaStringField
              x-decorator="FormItem"
              required
              title="选择框"
              name="select"
              :enum="[
                { label: '选项1', value: 1 },
                { label: '选项2', value: 2 },
              ]"
              x-component="Select"
              :x-component-props="{
                style: {
                  width: 160,
                },
              }"
            />
            <SchemaVoidField
              x-decorator="FormItem"
              x-component="ArrayItems.Remove"
            />
          </SchemaVoidField>
        </SchemaObjectField>
        <SchemaVoidField x-component="ArrayItems.Addition" title="添加条目" />
      </SchemaArrayField>
      <SchemaArrayField
        name="array2"
        title="对象数组"
        x-decorator="FormItem"
        x-component="ArrayItems"
        :x-component-props="{ style: { width: '600px' } }"
      >
        <SchemaObjectField x-decorator="ArrayItems.Item">
          <SchemaVoidField x-component="Space">
            <SchemaVoidField
              x-decorator="FormItem"
              x-component="ArrayItems.SortHandle"
            />
            <SchemaStringField
              x-decorator="FormItem"
              required
              title="日期"
              name="date"
              x-component="DatePicker"
              :x-component-props="{
                type: 'daterange',
                style: {
                  width: '250px',
                },
              }"
            />
            <SchemaStringField
              x-decorator="FormItem"
              required
              title="输入框"
              name="input"
              x-component="Input"
            />
            <SchemaVoidField
              x-decorator="FormItem"
              x-component="ArrayItems.Remove"
            />
          </SchemaVoidField>
        </SchemaObjectField>
        <SchemaVoidField x-component="ArrayItems.Addition" title="添加条目" />
      </SchemaArrayField>
    </SchemaField>
    <FormButtonGroup>
      <Submit @submit="log">提交</Submit>
    </FormButtonGroup>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormButtonGroup,
  Submit,
  Input,
  Select,
  Space,
  DatePicker,
  ArrayItems,
} from '@formily/element'
import { Button } from 'element-ui'

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

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    Button,
    Submit,
    ...SchemaField,
  },

  data() {
    const form = createForm()

    return {
      form,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```markdown
# Reset

> Reset button

## Normal reset

> Controls with default values cannot be cleared

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

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

const form = createForm()

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

## Force empty reset

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="input box"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear>Reset</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## Reset and verify

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="input box"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset validate>Reset</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## Force empty reset and verify

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="input box"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear validate>
        Reset
      </Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

### Reset

Other API reference https://ant.design/components/button-cn/

| Property name          | Type                                                                                             | Description                                              | Default value |
| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------- | ------------- |
| onClick                | `(event: MouseEvent) => void \| boolean`                                                         | Click event, if it returns false, it can block resetting | -             |
| onResetValidateSuccess | (payload: any) => void                                                                           | Reset validation success event                           | -             |
| onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Reset validation failure event                           | -             |

```

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

```markdown
# Reset

> Reset button

## Normal reset

> Controls with default values cannot be cleared

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

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

const form = createForm()

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

## Force empty reset

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="input box"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear>Reset</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## Reset and verify

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="input box"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset validate>Reset</Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## Force empty reset and verify

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="input box"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Reset forceClear validate>
        Reset
      </Reset>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

### Reset

Other API reference https://fusion.design/pc/component/basic/button

| Property name          | Type                                                                                             | Description                                              | Default value |
| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------- | ------------- |
| onClick                | `(event: MouseEvent) => void \| boolean`                                                         | Click event, if it returns false, it can block resetting | -             |
| onResetValidateSuccess | (payload: any) => void                                                                           | Reset validation success event                           | -             |
| onResetValidateFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Reset validation failure event                           | -             |

```

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

```typescript
import { Form, VoidField } from '@formily/core'
import { Schema, SchemaKey } from '@formily/json-schema'
import { action, model, observable } from '@formily/reactive'
import { observer } from '@formily/reactive-vue'
import {
  Fragment,
  h,
  RecursionField,
  useField,
  useFieldSchema,
} from '@formily/vue'
import { Step, Steps } from 'element-ui'
import { defineComponent, PropType } from 'vue-demi'
import { stylePrefix } from '../__builtins__/configs'

import type { Step as StepProps, Steps as StepsProps } from 'element-ui'
import { composeExport } from '../__builtins__/shared'

export interface IFormStep {
  connect: (steps: SchemaStep[], field: VoidField) => void
  current: number
  allowNext: boolean
  allowBack: boolean
  setCurrent(key: number): void
  submit: Form['submit']
  next(): void
  back(): void
}

export interface IFormStepProps extends StepsProps {
  formStep?: IFormStep
}

type SchemaStep = {
  name: SchemaKey
  props: any
  schema: Schema
}

type FormStepEnv = {
  form: Form
  field: VoidField
  steps: SchemaStep[]
}

const parseSteps = (schema: Schema) => {
  const steps: SchemaStep[] = []
  schema.mapProperties((schema, name) => {
    if (schema['x-component']?.indexOf('StepPane') > -1) {
      steps.push({
        name,
        props: schema['x-component-props'],
        schema,
      })
    }
  })
  return steps
}

const createFormStep = (defaultCurrent = 0): IFormStep => {
  const env: FormStepEnv = observable({
    form: null,
    field: null,
    steps: [],
  })

  const setDisplay = action.bound((target: number) => {
    const currentStep = env.steps[target]
    env.steps.forEach(({ name }) => {
      env.form.query(`${env.field.address}.${name}`).take((field) => {
        if (name === currentStep.name) {
          field.setDisplay('visible')
        } else {
          field.setDisplay('hidden')
        }
      })
    })
  })

  const next = action.bound(() => {
    if (formStep.allowNext) {
      setDisplay(formStep.current + 1)
      formStep.setCurrent(formStep.current + 1)
    }
  })

  const back = action.bound(() => {
    if (formStep.allowBack) {
      setDisplay(formStep.current - 1)
      formStep.setCurrent(formStep.current - 1)
    }
  })

  const formStep: IFormStep = model({
    connect(steps, field) {
      env.steps = steps
      env.form = field?.form
      env.field = field
    },
    current: defaultCurrent,
    setCurrent(key: number) {
      formStep.current = key
    },
    get allowNext() {
      return formStep.current < env.steps.length - 1
    },
    get allowBack() {
      return formStep.current > 0
    },
    async next() {
      try {
        await env.form.validate()
        next()
      } catch {}
    },
    async back() {
      back()
    },
    async submit(onSubmit) {
      return env.form?.submit?.(onSubmit)
    },
  })
  return formStep
}

const FormStepInner = observer(
  defineComponent<IFormStepProps>({
    name: 'FFormStep',
    props: {
      formStep: {
        type: Object as PropType<IFormStep>,
        default() {
          return {
            current: 0,
          }
        },
      },
    },
    setup(props, { attrs }) {
      const field = useField<VoidField>().value
      const prefixCls = `${stylePrefix}-form-step`
      const fieldSchemaRef = useFieldSchema()

      const steps = parseSteps(fieldSchemaRef.value)

      props.formStep.connect?.(steps, field)

      return () => {
        const current = props.active || props.formStep?.current || 0

        const renderSteps = (steps: SchemaStep[], callback) => {
          return steps.map(callback)
        }

        return h(
          'div',
          {
            class: [prefixCls],
          },
          {
            default: () => [
              h(
                Steps,
                {
                  props: {
                    active: current,
                  },
                  style: [{ marginBottom: '10px' }, attrs.style],
                  attrs,
                },
                {
                  default: () =>
                    renderSteps(steps, ({ props }, key) => {
                      return h(Step, { props, key }, {})
                    }),
                }
              ),

              renderSteps(steps, ({ name, schema }, key) => {
                if (key !== current) return
                return h(RecursionField, { props: { name, schema }, key }, {})
              }),
            ],
          }
        )
      }
    },
  })
)

const StepPane = defineComponent<StepProps>({
  name: 'FFormStepPane',
  setup(_props, { slots }) {
    return () => h(Fragment, {}, slots)
  },
})

export const FormStep = composeExport(FormStepInner, {
  StepPane,
  createFormStep,
})

export default FormStep

```

--------------------------------------------------------------------------------
/packages/reactive/docs/guide/concept.md:
--------------------------------------------------------------------------------

```markdown
# Core idea

## Observable

Observable is the most important part of the reactive programming model. Its core concepts are:

An observable object, literally means a subscribable object, **we create a subscribable object, each time we manipulate the attribute data of the object, we will automatically notify the subscriber**, @formily/reactive creates an observable object mainly It is created by ES Proxy, which can perfectly hijack data operations

We mainly use the following APIs to create observable objects in @formily/reactive:

- The observable function creates a deep observable object
  - The observable.deep function creates a deep hijacking observable object
  - The observable.shallow function creates shallow hijacked observable objects
  - The observable.computed function creates a cache calculator
  - The observable.box function creates observable objects with get/set methods
  - The observable.ref function creates a reference-level observable object
- The define function defines the observable domain model, which can be combined with the observable function and its static attribute (such as observable.computed) function to complete the definition of the domain model
- The model function defines an automatic observable domain model. It will wrap the getter setter attribute as a computed attribute, wrap the function as an action, and wrap other data attributes with observable (note that this is a deep hijacking)

## Reaction

In the reactive programming model, reaction is equivalent to the subscriber of the subscribeable object. It receives a tracker function. When this function is executed, if there is a **read operation* on an attribute in the observable object inside the function. * (Dependency collection), then the current reaction will be bound to the attribute (dependency tracking), until the attribute has a **write operation\*\* in other places, it will trigger the tracker function to repeat execution, using a picture Means:

![](https://img.alicdn.com/imgextra/i4/O1CN01DQMGUL22mFICDsKfY_!!6000000007162-2-tps-1234-614.png)

You can see that from subscribing to dispatching subscriptions, it is actually a closed loop state machine. Each time the tracker function is executed, the dependencies are re-collected, and the tracker execution is re-triggered when the dependencies change. So, if we don't want to subscribe to the reaction anymore, we must manually dispose, otherwise there will be memory leaks.

In @formily/reactive, we mainly use the following APIs to create reactions:

- autorun creates an automatically executed responder
- reaction creates a responder that can implement dirty checks
- Tracker creates a dependency tracker that requires users to manually perform tracking

## Computed

Computed is also a relatively important concept in the reactive programming model. In one sentence, **computed is a Reaction that can cache calculation results**

Its caching strategy is: as long as the observable data that the computed function relies on changes, the function will re-execute the calculation, otherwise the cached result will always be read

The requirement here is that the computed function must be a pure function. The internally dependent data is either observable data or external constant data. If it is external variable data (non-observable), then if the external variable data changes, the computed will not be re-executed computational.

## Batch

As mentioned earlier, @formily/reactive is a reactive programming model based on Proxy hijacking. Therefore, any atomic operation will trigger the execution of Reaction, which is obviously a waste of computing resources. For example, we have a function for multiple observables. Property to operate:

```ts
import { observable, autorun } from '@formily/reactive'
const obs = observable({})
const handler = () => {
  obs.aa = 123
  obs.bb = 321
}

autorun(() => {
  console.log(obs.aa, obs.bb)
})

handler()
```

This will execute 3 prints, autorun is executed once by default, plus the assignment of obs.aa is executed once, and the assignment of obs.bb is executed once. If there are more atomic operations, the number of executions will be more. Therefore, we recommend using batch mode To merge the updates:

```ts
import { observable, autorun, batch } from '@formily/reactive'
const obs = observable({})
const handler = () => {
  obs.aa = 123
  obs.bb = 321
}

autorun(() => {
  console.log(obs.aa, obs.bb)
})

batch(() => {
  handler()
})
```

Of course, we can also use action for high-level packaging:

```ts
import { observable, autorun, action } from '@formily/reactive'
const obs = observable({})
const handler = action.bound(() => {
  obs.aa = 123
  obs.bb = 321
})

autorun(() => {
  console.log(obs.aa, obs.bb)
})

handler()
```

The final number of executions is 2 times, even if there are more operations inside the handler, it is still 2 times

```

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

```typescript
import React, { Fragment, useMemo } from 'react'
import { Collapse, Badge } from 'antd'
import { model, markRaw } from '@formily/reactive'
import { CollapseProps, CollapsePanelProps } from 'antd/lib/collapse'
import {
  useField,
  observer,
  useFieldSchema,
  RecursionField,
} from '@formily/react'
import { Schema, SchemaKey } from '@formily/json-schema'
import cls from 'classnames'
import { usePrefixCls } from '../__builtins__'
import { toArr } from '@formily/shared'

type ActiveKeys = string | number | Array<string | number>

type ActiveKey = string | number
export interface IFormCollapse {
  activeKeys: ActiveKeys
  hasActiveKey(key: ActiveKey): boolean
  setActiveKeys(key: ActiveKeys): void
  addActiveKey(key: ActiveKey): void
  removeActiveKey(key: ActiveKey): void
  toggleActiveKey(key: ActiveKey): void
}

export interface IFormCollapseProps extends CollapseProps {
  formCollapse?: IFormCollapse
}

type ComposedFormCollapse = React.FC<
  React.PropsWithChildren<IFormCollapseProps>
> & {
  CollapsePanel?: React.FC<React.PropsWithChildren<CollapsePanelProps>>
  createFormCollapse?: (defaultActiveKeys?: ActiveKeys) => IFormCollapse
}

const usePanels = () => {
  const collapseField = useField()
  const schema = useFieldSchema()
  const panels: { name: SchemaKey; props: any; schema: Schema }[] = []
  schema.mapProperties((schema, name) => {
    const field = collapseField.query(collapseField.address.concat(name)).take()
    if (field?.display === 'none' || field?.display === 'hidden') return
    if (schema['x-component']?.indexOf('CollapsePanel') > -1) {
      const componentProps = field?.componentProps
      panels.push({
        name,
        props: {
          ...componentProps,
          key: componentProps?.key || name,
        },
        schema,
      })
    }
  })
  return panels
}

const createFormCollapse = (defaultActiveKeys?: ActiveKeys) => {
  const formCollapse = model({
    activeKeys: defaultActiveKeys,
    setActiveKeys(keys: ActiveKeys) {
      formCollapse.activeKeys = keys
    },
    hasActiveKey(key: ActiveKey) {
      if (Array.isArray(formCollapse.activeKeys)) {
        if (formCollapse.activeKeys.includes(key)) {
          return true
        }
      } else if (formCollapse.activeKeys == key) {
        return true
      }
      return false
    },
    addActiveKey(key: ActiveKey) {
      if (formCollapse.hasActiveKey(key)) return
      formCollapse.activeKeys = toArr(formCollapse.activeKeys).concat(key)
    },
    removeActiveKey(key: ActiveKey) {
      if (Array.isArray(formCollapse.activeKeys)) {
        formCollapse.activeKeys = formCollapse.activeKeys.filter(
          (item) => item != key
        )
      } else {
        formCollapse.activeKeys = ''
      }
    },
    toggleActiveKey(key: ActiveKey) {
      if (formCollapse.hasActiveKey(key)) {
        formCollapse.removeActiveKey(key)
      } else {
        formCollapse.addActiveKey(key)
      }
    },
  })
  return markRaw(formCollapse)
}

export const FormCollapse: ComposedFormCollapse = observer(
  ({ formCollapse, ...props }) => {
    const field = useField()
    const panels = usePanels()
    const prefixCls = usePrefixCls('formily-collapse', props)
    const _formCollapse = useMemo(() => {
      return formCollapse
        ? formCollapse
        : createFormCollapse(props.defaultActiveKey)
    }, [])

    const takeActiveKeys = () => {
      if (props.activeKey) return props.activeKey
      if (_formCollapse?.activeKeys) return _formCollapse?.activeKeys
      if (props.accordion) return panels[0]?.name
      return panels.map((item) => item.name)
    }

    const badgedHeader = (key: SchemaKey, props: any) => {
      const errors = field.form.queryFeedbacks({
        type: 'error',
        address: `${field.address.concat(key)}.*`,
      })
      if (errors.length) {
        return (
          <Badge size="small" className="errors-badge" count={errors.length}>
            {props.header}
          </Badge>
        )
      }
      return props.header
    }
    return (
      <Collapse
        {...props}
        className={cls(prefixCls, props.className)}
        activeKey={takeActiveKeys()}
        onChange={(key) => {
          props?.onChange?.(key)
          _formCollapse?.setActiveKeys?.(key)
        }}
      >
        {panels.map(({ props, schema, name }, index) => (
          <Collapse.Panel
            key={index}
            {...props}
            header={badgedHeader(name, props)}
            forceRender
          >
            <RecursionField schema={schema} name={name} />
          </Collapse.Panel>
        ))}
      </Collapse>
    )
  }
)

const CollapsePanel: React.FC<React.PropsWithChildren<CollapsePanelProps>> = ({
  children,
}) => {
  return <Fragment>{children}</Fragment>
}

FormCollapse.CollapsePanel = CollapsePanel
FormCollapse.createFormCollapse = createFormCollapse

export default FormCollapse

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField :schema="schema" />
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormButtonGroup,
  Submit,
  Input,
  ArrayCollapse,
} from '@formily/element'
import { Button } from 'element-ui'

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

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    Button,
    Submit,
    ...SchemaField,
  },

  data() {
    const form = createForm()
    const schema = {
      type: 'object',
      properties: {
        string_array: {
          type: 'array',
          'x-component': 'ArrayCollapse',
          maxItems: 3,
          'x-decorator': 'FormItem',
          items: {
            type: 'object',
            'x-component': 'ArrayCollapse.Item',
            'x-component-props': {
              title: '字符串数组',
            },
            properties: {
              index: {
                type: 'void',
                'x-component': 'ArrayCollapse.Index',
              },
              input: {
                type: 'string',
                'x-decorator': 'FormItem',
                title: 'Input',
                required: true,
                'x-component': 'Input',
              },
              remove: {
                type: 'void',
                'x-component': 'ArrayCollapse.Remove',
              },
              moveUp: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveUp',
              },
              moveDown: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveDown',
              },
            },
          },
          properties: {
            addition: {
              type: 'void',
              title: '添加条目',
              'x-component': 'ArrayCollapse.Addition',
            },
          },
        },
        array: {
          type: 'array',
          'x-component': 'ArrayCollapse',
          maxItems: 3,
          'x-decorator': 'FormItem',
          items: {
            type: 'object',
            'x-component': 'ArrayCollapse.Item',
            'x-component-props': {
              title: '对象数组',
            },
            properties: {
              index: {
                type: 'void',
                'x-component': 'ArrayCollapse.Index',
              },
              input: {
                type: 'string',
                'x-decorator': 'FormItem',
                title: 'Input',
                required: true,
                'x-component': 'Input',
              },
              remove: {
                type: 'void',
                'x-component': 'ArrayCollapse.Remove',
              },
              moveUp: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveUp',
              },
              moveDown: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveDown',
              },
            },
          },
          properties: {
            addition: {
              type: 'void',
              title: '添加条目',
              'x-component': 'ArrayCollapse.Addition',
            },
          },
        },
        array_unshift: {
          type: 'array',
          'x-component': 'ArrayCollapse',
          maxItems: 3,
          'x-decorator': 'FormItem',
          items: {
            type: 'object',
            'x-component': 'ArrayCollapse.Item',
            'x-component-props': {
              title: '对象数组',
            },
            properties: {
              index: {
                type: 'void',
                'x-component': 'ArrayCollapse.Index',
              },
              input: {
                type: 'string',
                'x-decorator': 'FormItem',
                title: 'Input',
                required: true,
                'x-component': 'Input',
              },
              remove: {
                type: 'void',
                'x-component': 'ArrayCollapse.Remove',
              },
              moveUp: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveUp',
              },
              moveDown: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveDown',
              },
            },
          },
          properties: {
            addition: {
              type: 'void',
              title: '添加条目(unshift)',
              'x-component': 'ArrayCollapse.Addition',
              'x-component-props': {
                method: 'unshift',
              },
            },
          },
        },
      },
    }

    return {
      form,
      schema,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

--------------------------------------------------------------------------------
/packages/element/src/array-items/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ArrayField } from '@formily/core'
import { ISchema } from '@formily/json-schema'
import { observer } from '@formily/reactive-vue'
import { h, RecursionField, useField, useFieldSchema } from '@formily/vue'
import { defineComponent } from 'vue-demi'
import { SlickItem, SlickList } from 'vue-slicksort'
import { ArrayBase } from '../array-base'
import { stylePrefix } from '../__builtins__/configs'
import { composeExport } from '../__builtins__/shared'

const isAdditionComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Addition') > -1
}

export interface IArrayItemsItemProps {
  type?: 'card' | 'divide'
}

const ArrayItemsInner = observer(
  defineComponent({
    name: 'FArrayItems',
    setup() {
      const fieldRef = useField<ArrayField>()
      const schemaRef = useFieldSchema()

      const prefixCls = `${stylePrefix}-array-items`
      const { getKey, keyMap } = ArrayBase.useKey(schemaRef.value)

      return () => {
        const field = fieldRef.value
        const schema = schemaRef.value
        const dataSource = Array.isArray(field.value) ? field.value.slice() : []

        const renderItems = () => {
          const items = dataSource?.map((item, index) => {
            const items = Array.isArray(schema.items)
              ? schema.items[index] || schema.items[0]
              : schema.items
            const key = getKey(item, index)
            return h(
              ArrayBase.Item,
              {
                key,
                props: {
                  index,
                  record: item,
                },
              },
              {
                default: () =>
                  h(
                    SlickItem,
                    {
                      class: [`${prefixCls}-item-inner`],
                      props: {
                        index,
                      },
                      key,
                    },
                    {
                      default: () =>
                        h(
                          RecursionField,
                          {
                            props: {
                              schema: items,
                              name: index,
                            },
                          },
                          {}
                        ),
                    }
                  ),
              }
            )
          })

          return h(
            SlickList,
            {
              class: [`${prefixCls}-list`],
              props: {
                useDragHandle: true,
                lockAxis: 'y',
                helperClass: `${prefixCls}-sort-helper`,
                value: [],
              },
              on: {
                'sort-end': ({ oldIndex, newIndex }) => {
                  if (Array.isArray(keyMap)) {
                    keyMap.splice(newIndex, 0, keyMap.splice(oldIndex, 1)[0])
                  }
                  field.move(oldIndex, newIndex)
                },
              },
            },
            { default: () => items }
          )
        }
        const renderAddition = () => {
          return schema.reduceProperties((addition, schema) => {
            if (isAdditionComponent(schema)) {
              return h(
                RecursionField,
                {
                  props: {
                    schema,
                    name: 'addition',
                  },
                },
                {}
              )
            }
            return addition
          }, null)
        }

        return h(
          ArrayBase,
          {
            props: {
              keyMap,
            },
          },
          {
            default: () =>
              h(
                'div',
                {
                  class: [prefixCls],
                  on: {
                    change: () => {},
                  },
                },
                {
                  default: () => [renderItems(), renderAddition()],
                }
              ),
          }
        )
      }
    },
  })
)

const ArrayItemsItem = defineComponent<IArrayItemsItemProps>({
  name: 'FArrayItemsItem',
  props: ['type'],
  setup(props, { attrs, slots }) {
    const prefixCls = `${stylePrefix}-array-items`

    return () =>
      h(
        'div',
        {
          class: [`${prefixCls}-${props.type || 'card'}`],
          attrs: {
            ...attrs,
          },
          on: {
            change: () => {},
          },
        },
        slots
      )
  },
})

export const ArrayItems = composeExport(ArrayItemsInner, {
  Item: ArrayItemsItem,
  Index: ArrayBase.Index,
  SortHandle: ArrayBase.SortHandle,
  Addition: ArrayBase.Addition,
  Remove: ArrayBase.Remove,
  MoveDown: ArrayBase.MoveDown,
  MoveUp: ArrayBase.MoveUp,
  useArray: ArrayBase.useArray,
  useIndex: ArrayBase.useIndex,
  useRecord: ArrayBase.useRecord,
})

export default ArrayItems

```

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

```typescript
import React, { Fragment, useMemo } from 'react'
import { Collapse, Badge } from '@alifd/next'
import { model, markRaw } from '@formily/reactive'
import {
  CollapseProps,
  PanelProps as CollapsePanelProps,
} from '@alifd/next/lib/collapse'
import {
  useField,
  observer,
  useFieldSchema,
  RecursionField,
} from '@formily/react'
import { Schema, SchemaKey } from '@formily/json-schema'
import { toArr } from '@formily/shared'
import cls from 'classnames'
import { usePrefixCls } from '../__builtins__'

type ActiveKeys = string | number | Array<string | number>

type ActiveKey = string | number

export interface IFormCollapse {
  activeKeys: ActiveKeys
  hasActiveKey(key: ActiveKey): boolean
  setActiveKeys(key: ActiveKeys): void
  addActiveKey(key: ActiveKey): void
  removeActiveKey(key: ActiveKey): void
  toggleActiveKey(key: ActiveKey): void
}

export interface IFormCollapseProps extends CollapseProps {
  formCollapse?: IFormCollapse
}

type ComposedFormCollapse = React.FC<
  React.PropsWithChildren<IFormCollapseProps>
> & {
  CollapsePanel?: React.FC<React.PropsWithChildren<CollapsePanelProps>>
  createFormCollapse?: (
    defaultActiveKeys?: CollapseProps['expandedKeys']
  ) => IFormCollapse
}

const usePanels = () => {
  const collapseField = useField()
  const schema = useFieldSchema()
  const panels: { name: SchemaKey; props: any; schema: Schema }[] = []
  schema.mapProperties((schema, name) => {
    const field = collapseField.query(collapseField.address.concat(name)).take()
    if (field?.display === 'none' || field?.display === 'hidden') return
    if (schema['x-component']?.indexOf('CollapsePanel') > -1) {
      panels.push({
        name,
        props: {
          ...schema?.['x-component-props'],
          title: schema?.['x-component-props']?.title || schema?.title,
          key: schema?.['x-component-props']?.key || name,
        },
        schema,
      })
    }
  })
  return panels
}

const createFormCollapse = (defaultActiveKeys?: ActiveKeys) => {
  const formCollapse = model({
    activeKeys: defaultActiveKeys,
    setActiveKeys(keys: ActiveKeys) {
      formCollapse.activeKeys = keys
    },
    hasActiveKey(key: ActiveKey) {
      if (Array.isArray(formCollapse.activeKeys)) {
        if (formCollapse.activeKeys.includes(key)) {
          return true
        }
      } else if (formCollapse.activeKeys == key) {
        return true
      }
      return false
    },
    addActiveKey(key: ActiveKey) {
      if (formCollapse.hasActiveKey(key)) return
      formCollapse.activeKeys = toArr(formCollapse.activeKeys).concat(key)
    },
    removeActiveKey(key: ActiveKey) {
      if (Array.isArray(formCollapse.activeKeys)) {
        formCollapse.activeKeys = formCollapse.activeKeys.filter(
          (item) => item != key
        )
      } else {
        formCollapse.activeKeys = []
      }
    },
    toggleActiveKey(key: ActiveKey) {
      if (formCollapse.hasActiveKey(key)) {
        formCollapse.removeActiveKey(key)
      } else {
        formCollapse.addActiveKey(key)
      }
    },
  })
  return markRaw(formCollapse)
}

export const FormCollapse: ComposedFormCollapse = observer(
  ({ formCollapse, ...props }) => {
    const field = useField()
    const panels = usePanels()
    const prefixCls = usePrefixCls('formily-collapse', props)
    const _formCollapse = useMemo(() => {
      return formCollapse
        ? formCollapse
        : createFormCollapse(props.defaultExpandedKeys)
    }, [])

    const takeExpandedKeys = () => {
      if (props.expandedKeys) return props.expandedKeys
      if (_formCollapse?.activeKeys) return _formCollapse?.activeKeys
      if (props.accordion) return panels[0]?.name
      return panels.map((item) => item.name)
    }

    const badgedHeader = (key: SchemaKey, props: any) => {
      const errors = field.form.queryFeedbacks({
        type: 'error',
        address: `${field.address.concat(key)}.*`,
      })
      if (errors.length) {
        return (
          <Badge className="errors-badge" count={errors.length}>
            {props.title}
          </Badge>
        )
      }
      return props.title
    }
    return (
      <Collapse
        {...props}
        className={cls(prefixCls, props.className)}
        expandedKeys={takeExpandedKeys() as any}
        onExpand={(keys) => {
          props?.onExpand?.(keys)
          _formCollapse?.setActiveKeys?.(keys)
        }}
      >
        {panels.map(({ props, schema, name }, index) => (
          <Collapse.Panel
            key={index}
            {...props}
            title={badgedHeader(name, props)}
          >
            <RecursionField schema={schema} name={name} />
          </Collapse.Panel>
        ))}
      </Collapse>
    )
  }
)

const CollapsePanel: React.FC<React.PropsWithChildren<CollapsePanelProps>> = ({
  children,
}) => {
  return <Fragment>{children}</Fragment>
}

FormCollapse.CollapsePanel = CollapsePanel
FormCollapse.createFormCollapse = createFormCollapse

export default FormCollapse

```

--------------------------------------------------------------------------------
/packages/react/src/types.ts:
--------------------------------------------------------------------------------

```typescript
import React from 'react'
import {
  Form,
  Field as FieldType,
  VoidField,
  ObjectField,
  GeneralField,
  IFieldFactoryProps,
  IVoidFieldFactoryProps,
  FormPatternTypes,
  FieldDisplayTypes,
  FieldValidator,
} from '@formily/core'
import { ReactFC } from '@formily/reactive-react'
import { ISchema, Schema, SchemaKey } from '@formily/json-schema'
import { FormPathPattern } from '@formily/shared'

export type JSXComponent =
  | keyof JSX.IntrinsicElements
  | React.JSXElementConstructor<any>

export type IProviderProps = {
  form: Form
}

export interface IFormSpyProps {
  children?: (form: Form) => ReactChild
}

export type RenderPropsChildren<Payload> =
  | ((field: Payload, form: Form) => React.ReactNode)
  | React.ReactNode

export interface IFieldProps<
  D extends JSXComponent,
  C extends JSXComponent,
  Field = FieldType
> extends IFieldFactoryProps<D, C> {
  children?: RenderPropsChildren<Field>
  decorator?: [] | [D] | [D, React.ComponentProps<D>] | any[]
  component?: [] | [C] | [C, React.ComponentProps<C>] | any[]
}

export interface IVoidFieldProps<
  D extends JSXComponent,
  C extends JSXComponent,
  Field = VoidField
> extends IVoidFieldFactoryProps<D, C> {
  children?: RenderPropsChildren<Field>
  decorator?: [] | [D] | [D, React.ComponentProps<D>] | any[]
  component?: [] | [C] | [C, React.ComponentProps<C>] | any[]
}

export interface IComponentMapper<T extends JSXComponent> {
  (target: T): JSXComponent
}

export type IStateMapper<Props> =
  | {
      [key in keyof FieldType]?: keyof Props | boolean
    }
  | ((props: Props, field: GeneralField) => Props)

export type SchemaReactComponents = Record<string, JSXComponent>

export interface ISchemaFieldReactFactoryOptions<
  Components extends SchemaReactComponents = any
> {
  components?: Components
  scope?: any
}

export interface ISchemaFieldOptionContext {
  components: SchemaReactComponents
}

export interface ISchemaFieldProps<
  Decorator extends JSXComponent = any,
  Component extends JSXComponent = any,
  InnerField = ObjectField<Decorator, Component>
> extends Omit<IFieldFactoryProps<Decorator, Component, InnerField>, 'name'> {
  schema?: ISchema
  components?: {
    [key: string]: JSXComponent
  }
  scope?: any
  name?: SchemaKey
  children?: React.ReactNode
}

export interface ISchemaMapper {
  (schema: Schema, name: SchemaKey): Schema
}

export interface ISchemaFilter {
  (schema: Schema, name: SchemaKey): boolean
}
export interface IRecursionFieldProps {
  schema: ISchema
  name?: SchemaKey
  basePath?: FormPathPattern
  propsRecursion?: boolean
  onlyRenderProperties?: boolean
  onlyRenderSelf?: boolean
  mapProperties?: ISchemaMapper
  filterProperties?: ISchemaFilter
}

export type ObjectKey = string | number | boolean | symbol

export type Path<T, Key extends keyof T = keyof T> = Key extends string
  ? T[Key] extends Record<string, any>
    ?
        | `${Key}.${Path<T[Key], Exclude<keyof T[Key], keyof Array<any>>> &
            string}`
        | `${Key}.${Exclude<keyof T[Key], keyof Array<any>> & string}`
        | Key
    : Key
  : never

export type PathValue<
  T,
  P extends Path<T>
> = P extends `${infer Key}.${infer Rest}`
  ? Key extends keyof T
    ? Rest extends Path<T[Key]>
      ? PathValue<T[Key], Rest>
      : never
    : never
  : P extends keyof T
  ? T[P]
  : never

export type KeyOfReactComponent<T> = Exclude<
  keyof T,
  'contextTypes' | 'displayName' | 'propTypes' | 'defaultProps'
>

export type ReactComponentPath<
  T,
  Key extends KeyOfReactComponent<T> = KeyOfReactComponent<T>
> = Key extends string
  ? T[Key] extends Record<string, any>
    ?
        | `${Key}.${Exclude<KeyOfReactComponent<T[Key]>, keyof Array<any>> &
            string}`
        | Key
    : Key
  : never

export type ReactComponentPropsByPathValue<
  T extends Record<string, any>,
  P extends ReactComponentPath<T>
> = P extends `${infer Key}.${infer Rest}`
  ? Key extends keyof T
    ? Rest extends ReactComponentPath<T[Key]>
      ? ReactComponentPropsByPathValue<T[Key], Rest>
      : never
    : React.ComponentProps<T[P]>
  : P extends keyof T
  ? React.ComponentProps<T[P]>
  : never
export interface ISchemaMarkupFieldProps<
  Components extends SchemaReactComponents,
  Decorator extends ReactComponentPath<Components>,
  Component extends ReactComponentPath<Components>
> extends ISchema<
    Decorator,
    Component,
    ReactComponentPropsByPathValue<Components, Decorator>,
    ReactComponentPropsByPathValue<Components, Component>,
    FormPatternTypes,
    FieldDisplayTypes,
    FieldValidator,
    React.ReactNode,
    GeneralField
  > {
  children?: React.ReactNode
}

export type ISchemaTypeFieldProps<
  Components extends SchemaReactComponents,
  Decorator extends ReactComponentPath<Components>,
  Component extends ReactComponentPath<Components>
> = ISchemaMarkupFieldProps<Components, Decorator, Component>

export interface IExpressionScopeProps {
  value?: any
}

export interface IRecordScopeProps {
  getIndex?(): number
  getRecord(): any
}

export interface IRecordsScopeProps {
  getRecords(): any[]
}

export type ReactChild = React.ReactElement | string | number

export { ReactFC }

```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/form-grid/form.vue:
--------------------------------------------------------------------------------

```vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaObjectField x-component="QueryForm">
        <SchemaStringField
          name="input1"
          title="Input 1"
          x-component="Input"
          x-decorator="FormItem"
        />
        <SchemaStringField
          name="input2"
          title="Input 2"
          x-component="Input"
          x-decorator="FormItem"
        />

        <SchemaStringField
          name="select1"
          title="Select 1"
          x-component="Select"
          x-decorator="FormItem"
        />
        <SchemaStringField
          name="select2"
          title="Select 2"
          x-component="Select"
          x-decorator="FormItem"
        />
        <SchemaStringField
          name="date"
          title="DatePicker"
          x-component="DatePicker"
          x-decorator="FormItem"
        />
        <SchemaStringField
          name="dateRange"
          title="DatePicker"
          x-component="DatePicker"
          x-decorator="FormItem"
          :x-decorator-props="{
            gridSpan: 2,
          }"
          :x-component-props="{
            type: 'daterange',
          }"
        />
        <SchemaStringField
          name="select3"
          title="Select 3"
          x-component="Select"
          x-decorator="FormItem"
        />
      </SchemaObjectField>
    </SchemaField>
  </FormProvider>
</template>

<script>
import { defineComponent, ref, onUnmounted } from 'vue-demi'
import { createForm } from '@formily/core'
import {
  createSchemaField,
  FormProvider,
  FragmentComponent,
} from '@formily/vue'
import { autorun } from '@formily/reactive'
import { observer } from '@formily/reactive-vue'
import {
  Form,
  Input,
  Select,
  DatePicker,
  FormItem,
  FormGrid,
  Submit,
  Reset,
  FormButtonGroup,
} from '@formily/element'

const useCollapseGrid = (maxRows) => {
  const grid = FormGrid.createFormGrid({
    maxColumns: 4,
    maxWidth: 240,
    maxRows: maxRows,
    shouldVisible: (node, grid) => {
      if (node.index === grid.childSize - 1) return true
      if (grid.maxRows === Infinity) return true
      return node.shadowRow < maxRows + 1
    },
  })

  const expanded = ref(false)
  const type = ref('')

  const takeType = (realRows, computeRows) => {
    if (realRows < maxRows + 1) return 'incomplete-wrap'
    if (computeRows > maxRows) return 'collapsible'
    return 'complete-wrap'
  }

  const dispose = autorun(() => {
    expanded.value = grid.maxRows === Infinity

    const realRows = grid.shadowRows
    const computeRows = grid.fullnessLastColumn
      ? grid.shadowRows - 1
      : grid.shadowRows

    type.value = takeType(realRows, computeRows)
  })

  onUnmounted(dispose)

  const toggle = () => {
    if (grid.maxRows === Infinity) {
      grid.maxRows = maxRows
    } else {
      grid.maxRows = Infinity
    }
  }
  return {
    grid,
    expanded,
    toggle,
    type,
  }
}

const QueryForm = observer(
  defineComponent({
    setup(props, { slots }) {
      const { grid, expanded, toggle, type } = useCollapseGrid(1)

      const renderActions = () => {
        return (
          <FragmentComponent>
            <Submit onSubmit={console.log}>查询</Submit>
            <Reset>重置</Reset>
          </FragmentComponent>
        )
      }

      const renderButtonGroup = () => {
        if (type.value === 'incomplete-wrap') {
          return (
            <FormButtonGroup.FormItem>
              <FormButtonGroup>{renderActions()}</FormButtonGroup>
            </FormButtonGroup.FormItem>
          )
        }
        if (type.value === 'collapsible') {
          return (
            <FragmentComponent>
              <FormButtonGroup>
                <a
                  href=""
                  onClick={(e) => {
                    e.preventDefault()
                    toggle()
                  }}
                >
                  {expanded.value ? '收起' : '展开'}
                </a>
              </FormButtonGroup>
              <FormButtonGroup align="right">{renderActions()}</FormButtonGroup>
            </FragmentComponent>
          )
        }
        return (
          <FormButtonGroup
            align="right"
            style={{ display: 'flex', width: '100%' }}
          >
            {renderActions()}
          </FormButtonGroup>
        )
      }

      return () => {
        return (
          <Form {...props} layout="vertical" feedbackLayout="terse">
            <FormGrid grid={grid}>
              {slots.default()}
              <FormGrid.GridColumn
                gridSpan={-1}
                style={{ display: 'flex', justifyContent: 'space-between' }}
              >
                {renderButtonGroup()}
              </FormGrid.GridColumn>
            </FormGrid>
          </Form>
        )
      }
    },
  })
)

const form = createForm()
const fields = createSchemaField({
  components: {
    QueryForm,
    Input,
    Select,
    DatePicker,
    FormItem,
  },
})

export default {
  components: { FormProvider, ...fields, Submit },
  data() {
    return {
      form,
    }
  },
  methods: {
    onSubmit(value) {
      console.log(value)
    },
  },
}
</script>

```

--------------------------------------------------------------------------------
/packages/json-schema/src/shared.ts:
--------------------------------------------------------------------------------

```typescript
import { isFn, each, isPlainObj, isArr, toArr, FormPath } from '@formily/shared'
import { isObservable, untracked } from '@formily/reactive'
import { Schema } from './schema'
import { ISchema } from './types'

const REVA_ACTIONS_KEY = Symbol.for('__REVA_ACTIONS')

export const SchemaNestedMap = {
  parent: true,
  root: true,
  properties: true,
  patternProperties: true,
  additionalProperties: true,
  items: true,
  additionalItems: true,
  'x-linkages': true,
  'x-reactions': true,
}

export const SchemaStateMap = {
  title: 'title',
  description: 'description',
  default: 'initialValue',
  enum: 'dataSource',
  readOnly: 'readOnly',
  writeOnly: 'editable',
  'x-content': 'content',
  'x-data': 'data',
  'x-value': 'value',
  'x-editable': 'editable',
  'x-disabled': 'disabled',
  'x-read-pretty': 'readPretty',
  'x-read-only': 'readOnly',
  'x-visible': 'visible',
  'x-hidden': 'hidden',
  'x-display': 'display',
  'x-pattern': 'pattern',
  'x-validator': 'validator',
  'x-decorator': 'decoratorType',
  'x-component': 'componentType',
  'x-decorator-props': 'decoratorProps',
  'x-component-props': 'componentProps',
}

export const SchemaValidatorMap = {
  required: true,
  format: true,
  maxItems: true,
  minItems: true,
  maxLength: true,
  minLength: true,
  maximum: true,
  minimum: true,
  exclusiveMaximum: true,
  exclusiveMinimum: true,
  pattern: true,
  const: true,
  multipleOf: true,
  maxProperties: true,
  minProperties: true,
  uniqueItems: true,
}

export const SchemaNormalKeys = Object.keys(SchemaStateMap)

export const SchemaValidatorKeys = Object.keys(SchemaValidatorMap)

export const hasOwnProperty = Object.prototype.hasOwnProperty

export const traverse = (
  target: any,
  visitor: (value: any, path: Array<string | number>) => void
) => {
  const seenObjects = []
  const root = target
  const traverse = (target: any, path = []) => {
    if (isPlainObj(target)) {
      const seenIndex = seenObjects.indexOf(target)
      if (seenIndex > -1) {
        return
      }
      const addIndex = seenObjects.length
      seenObjects.push(target)
      if (isNoNeedCompileObject(target) && root !== target) {
        visitor(target, path)
        return
      }
      each(target, (value, key) => {
        traverse(value, path.concat(key))
      })
      seenObjects.splice(addIndex, 1)
    } else {
      visitor(target, path)
    }
  }
  traverse(target)
}

export const traverseSchema = (
  schema: ISchema,
  visitor: (value: any, path: any[], omitCompile?: boolean) => void
) => {
  if (schema['x-validator'] !== undefined) {
    visitor(
      schema['x-validator'],
      ['x-validator'],
      schema['x-compile-omitted']?.includes('x-validator')
    )
  }
  const seenObjects = []
  const root = schema
  const traverse = (target: any, path = []) => {
    if (
      path[0] === 'x-compile-omitted' ||
      path[0] === 'x-validator' ||
      path[0] === 'version' ||
      path[0] === '_isJSONSchemaObject'
    )
      return
    if (String(path[0]).indexOf('x-') == -1 && isFn(target)) return
    if (SchemaNestedMap[path[0]]) return
    if (schema['x-compile-omitted']?.indexOf(path[0]) > -1) {
      visitor(target, path, true)
      return
    }
    if (isPlainObj(target)) {
      if (path[0] === 'default' || path[0] === 'x-value') {
        visitor(target, path)
        return
      }
      const seenIndex = seenObjects.indexOf(target)
      if (seenIndex > -1) {
        return
      }
      const addIndex = seenObjects.length
      seenObjects.push(target)
      if (isNoNeedCompileObject(target) && root !== target) {
        visitor(target, path)
        return
      }
      each(target, (value, key) => {
        traverse(value, path.concat(key))
      })
      seenObjects.splice(addIndex, 1)
    } else {
      visitor(target, path)
    }
  }
  traverse(schema)
}

export const isNoNeedCompileObject = (source: any) => {
  if ('$$typeof' in source && '_owner' in source) {
    return true
  }
  if (source['_isAMomentObject']) {
    return true
  }
  if (Schema.isSchemaInstance(source)) {
    return true
  }
  if (source[REVA_ACTIONS_KEY]) {
    return true
  }
  if (isFn(source['toJS'])) {
    return true
  }
  if (isFn(source['toJSON'])) {
    return true
  }
  if (isObservable(source)) {
    return true
  }
  return false
}

export const createDataSource = (source: any[]) => {
  return toArr(source).map((item) => {
    if (typeof item === 'object') {
      return item
    } else {
      return {
        label: item,
        value: item,
      }
    }
  })
}

export const patchStateFormSchema = (
  targetState: any,
  pattern: any[],
  compiled: any
) => {
  untracked(() => {
    const path = FormPath.parse(pattern)
    const segments = path.segments
    const key = segments[0]
    const isEnum = key === 'enum' && isArr(compiled)
    const schemaMapKey = SchemaStateMap[key]
    if (schemaMapKey) {
      FormPath.setIn(
        targetState,
        [schemaMapKey].concat(segments.slice(1)),
        isEnum ? createDataSource(compiled) : compiled
      )
    } else {
      const isValidatorKey = SchemaValidatorMap[key]
      if (isValidatorKey) {
        targetState['setValidatorRule']?.(key, compiled)
      }
    }
  })
}

```

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

```markdown
# DatePicker

> 日期选择器

## Markup Schema 案例

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="date"
        title="普通日期"
        x-decorator="FormItem"
        x-component="DatePicker"
      />
      <SchemaField.String
        name="week"
        title="周选择"
        x-decorator="FormItem"
        x-component="DatePicker.WeekPicker"
      />
      <SchemaField.String
        name="month"
        title="月选择"
        x-decorator="FormItem"
        x-component="DatePicker.MonthPicker"
      />
      <SchemaField.String
        name="year"
        title="年选择"
        x-decorator="FormItem"
        x-component="DatePicker.YearPicker"
      />
      <SchemaField.String
        name="[startDate,endDate]"
        title="日期范围"
        x-decorator="FormItem"
        x-component="DatePicker.RangePicker"
        x-component-props={{
          showTime: true,
        }}
      />
      <SchemaField.String
        name="range_month"
        title="月范围选择"
        x-decorator="FormItem"
        x-component="DatePicker.RangePicker"
        x-component-props={{
          type: 'month',
        }}
      />
      <SchemaField.String
        name="range_year"
        title="年范围选择"
        x-decorator="FormItem"
        x-component="DatePicker.RangePicker"
        x-component-props={{
          type: 'year',
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    date: {
      title: '普通日期',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker',
      type: 'string',
    },
    week: {
      title: '周选择',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker.WeekPicker',
      type: 'string',
    },
    month: {
      title: '月选择',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker.MonthPicker',
      type: 'string',
    },
    year: {
      title: '年选择',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker.YearPicker',
      type: 'string',
    },
    '[startDate,endDate]': {
      title: '日期范围',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker.RangePicker',
      'x-component-props': {
        showTime: true,
      },
      type: 'string',
    },
    range_month: {
      title: '月范围选择',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker.RangePicker',
      'x-component-props': {
        type: 'month',
      },
      type: 'string',
    },
    range_year: {
      name: 'range_year',
      title: '年范围选择',
      'x-decorator': 'FormItem',
      'x-component': 'DatePicker.RangePicker',
      'x-component-props': {
        type: 'year',
      },
      type: 'string',
    },
  },
}

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

## 纯 JSX 案例

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="date"
      title="日期选择"
      decorator={[FormItem]}
      component={[DatePicker]}
    />
    <Field
      name="week"
      title="周选择"
      decorator={[FormItem]}
      component={[DatePicker.WeekPicker]}
    />
    <Field
      name="quarter"
      title="财年选择"
      decorator={[FormItem]}
      component={[DatePicker.MonthPicker]}
    />
    <Field
      name="year"
      title="年选择"
      decorator={[FormItem]}
      component={[DatePicker.YearPicker]}
    />
    <Field
      name="[startDate,endDate]"
      title="日期范围选择"
      decorator={[FormItem]}
      component={[DatePicker.RangePicker]}
    />
    <Field
      name="range_month"
      title="月范围选择"
      decorator={[FormItem]}
      component={[
        DatePicker.RangePicker,
        {
          type: 'month',
        },
      ]}
    />
    <Field
      name="range_year"
      title="年范围选择"
      decorator={[FormItem]}
      component={[
        DatePicker.RangePicker,
        {
          type: 'year',
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://fusion.design/pc/component/basic/date-picker

```
Page 11/35FirstPrevNextLast