#
tokens: 45038/50000 5/1152 files (page 33/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 33 of 52. Use http://codebase.md/alibaba/formily?lines=true&page={x} to view the full context.

# Directory Structure

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

# Files

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

```typescript
  1 | import { isVoidField } from '@formily/core'
  2 | import { connect, h, mapProps } from '@formily/vue'
  3 | import { Tooltip } from 'element-ui'
  4 | import ResizeObserver from 'resize-observer-polyfill'
  5 | import { Component } from 'vue'
  6 | import {
  7 |   defineComponent,
  8 |   onBeforeUnmount,
  9 |   provide,
 10 |   ref,
 11 |   Ref,
 12 |   watch,
 13 | } from 'vue-demi'
 14 | import { FormLayoutShallowContext, useFormLayout } from '../form-layout'
 15 | import { stylePrefix } from '../__builtins__/configs'
 16 | import {
 17 |   composeExport,
 18 |   resolveComponent,
 19 |   useCompatRef,
 20 | } from '../__builtins__/shared'
 21 | 
 22 | export type FormItemProps = {
 23 |   className?: string
 24 |   required?: boolean
 25 |   label?: string | Component
 26 |   colon?: boolean
 27 |   tooltip?: string | Component
 28 |   layout?: 'vertical' | 'horizontal' | 'inline'
 29 |   labelStyle?: Record<string, any>
 30 |   labelAlign?: 'left' | 'right'
 31 |   labelWrap?: boolean
 32 |   labelWidth?: number
 33 |   wrapperWidth?: number
 34 |   labelCol?: number
 35 |   wrapperCol?: number
 36 |   wrapperAlign?: 'left' | 'right'
 37 |   wrapperWrap?: boolean
 38 |   wrapperStyle?: Record<string, any>
 39 |   fullness?: boolean
 40 |   addonBefore?: string | Component
 41 |   addonAfter?: string | Component
 42 |   size?: 'small' | 'default' | 'large'
 43 |   extra?: string
 44 |   feedbackText?: string | Component
 45 |   feedbackLayout?: 'loose' | 'terse' | 'popover' | 'none' | (string & {})
 46 |   feedbackStatus?: 'error' | 'warning' | 'success' | 'pending' | (string & {})
 47 |   tooltipLayout?: 'icon' | 'text'
 48 |   feedbackIcon?: string | Component
 49 |   asterisk?: boolean
 50 |   gridSpan?: number
 51 |   bordered?: boolean
 52 |   inset?: boolean
 53 | }
 54 | 
 55 | const useOverflow = (containerRef: Ref<HTMLElement>) => {
 56 |   const overflow = ref(false)
 57 |   let resizeObserver: ResizeObserver | undefined
 58 | 
 59 |   const cleanup = () => {
 60 |     if (resizeObserver) {
 61 |       resizeObserver.unobserve(containerRef.value)
 62 |       resizeObserver = null
 63 |     }
 64 |   }
 65 | 
 66 |   const observer = () => {
 67 |     const container = containerRef.value
 68 |     const content = container.querySelector('label')
 69 |     const containerWidth = container.getBoundingClientRect().width
 70 |     const contentWidth = content?.getBoundingClientRect().width
 71 | 
 72 |     if (containerWidth !== 0) {
 73 |       if (contentWidth > containerWidth) {
 74 |         overflow.value = true
 75 |       } else {
 76 |         overflow.value = false
 77 |       }
 78 |     }
 79 |   }
 80 | 
 81 |   const stopWatch = watch(
 82 |     () => containerRef.value,
 83 |     (el) => {
 84 |       cleanup()
 85 | 
 86 |       if (el) {
 87 |         resizeObserver = new ResizeObserver(observer)
 88 |         resizeObserver.observe(el)
 89 |       }
 90 |     },
 91 |     { immediate: true, flush: 'post' }
 92 |   )
 93 | 
 94 |   onBeforeUnmount(() => {
 95 |     cleanup()
 96 |     stopWatch()
 97 |   })
 98 | 
 99 |   return overflow
100 | }
101 | 
102 | const ICON_MAP = {
103 |   error: () => h('i', { class: 'el-icon-circle-close' }, {}),
104 |   success: () => h('i', { class: 'el-icon-circle-check' }, {}),
105 |   warning: () => h('i', { class: 'el-icon-warning-outline' }, {}),
106 | }
107 | 
108 | export const FormBaseItem = defineComponent<FormItemProps>({
109 |   name: 'FormItem',
110 |   props: {
111 |     className: {},
112 |     required: {},
113 |     label: {},
114 |     colon: {},
115 |     layout: {},
116 |     tooltip: {},
117 |     labelStyle: {},
118 |     labelAlign: {},
119 |     labelWrap: {},
120 |     labelWidth: {},
121 |     wrapperWidth: {},
122 |     labelCol: {},
123 |     wrapperCol: {},
124 |     wrapperAlign: {},
125 |     wrapperWrap: {},
126 |     wrapperStyle: {},
127 |     fullness: {},
128 |     addonBefore: {},
129 |     addonAfter: {},
130 |     size: {},
131 |     extra: {},
132 |     feedbackText: {},
133 |     feedbackLayout: {},
134 |     tooltipLayout: {},
135 |     feedbackStatus: {},
136 |     feedbackIcon: {},
137 |     asterisk: {},
138 |     gridSpan: {},
139 |     bordered: { default: true },
140 |     inset: { default: false },
141 |   },
142 |   setup(props, { slots, refs }) {
143 |     const active = ref(false)
144 |     const deepLayoutRef = useFormLayout()
145 | 
146 |     const prefixCls = `${stylePrefix}-form-item`
147 | 
148 |     const { elRef: containerRef, elRefBinder } = useCompatRef(refs)
149 |     const overflow = useOverflow(containerRef)
150 | 
151 |     provide(FormLayoutShallowContext, ref(null))
152 | 
153 |     return () => {
154 |       const gridStyles: Record<string, any> = {}
155 | 
156 |       const deepLayout = deepLayoutRef.value
157 |       const {
158 |         label,
159 |         colon = deepLayout.colon ?? true,
160 |         layout = deepLayout.layout ?? 'horizontal',
161 |         tooltip,
162 |         labelStyle = {},
163 |         labelWrap = deepLayout.labelWrap ?? false,
164 |         labelWidth = deepLayout.labelWidth,
165 |         wrapperWidth = deepLayout.wrapperWidth,
166 |         labelCol = deepLayout.labelCol,
167 |         wrapperCol = deepLayout.wrapperCol,
168 |         wrapperAlign = deepLayout.wrapperAlign ?? 'left',
169 |         wrapperWrap = deepLayout.wrapperWrap,
170 |         wrapperStyle = {},
171 |         fullness = deepLayout.fullness,
172 |         addonBefore,
173 |         addonAfter,
174 |         size = deepLayout.size,
175 |         extra,
176 |         feedbackText,
177 |         feedbackLayout = deepLayout.feedbackLayout ?? 'loose',
178 |         tooltipLayout = deepLayout.tooltipLayout ?? 'icon',
179 |         feedbackStatus,
180 |         feedbackIcon,
181 |         asterisk,
182 |         bordered = deepLayout.bordered,
183 |         inset = deepLayout.inset,
184 |       } = props
185 |       const labelAlign =
186 |         deepLayout.layout === 'vertical'
187 |           ? props.labelAlign ?? deepLayout.labelAlign ?? 'left'
188 |           : props.labelAlign ?? deepLayout.labelAlign ?? 'right'
189 | 
190 |       // 固定宽度
191 |       let enableCol = false
192 |       if (labelWidth || wrapperWidth) {
193 |         if (labelWidth) {
194 |           labelStyle.width = `${labelWidth}px`
195 |           labelStyle.maxWidth = `${labelWidth}px`
196 |         }
197 |         if (wrapperWidth) {
198 |           wrapperStyle.width = `${wrapperWidth}px`
199 |           wrapperStyle.maxWidth = `${wrapperWidth}px`
200 |         }
201 |         // 栅格模式
202 |       } else if (labelCol || wrapperCol) {
203 |         enableCol = true
204 |       }
205 | 
206 |       const formatChildren =
207 |         feedbackLayout === 'popover'
208 |           ? h(
209 |               'el-popover',
210 |               {
211 |                 props: {
212 |                   disabled: !feedbackText,
213 |                   placement: 'top',
214 |                 },
215 |               },
216 |               {
217 |                 reference: () =>
218 |                   h('div', {}, { default: () => slots.default?.() }),
219 |                 default: () => [
220 |                   h(
221 |                     'div',
222 |                     {
223 |                       class: {
224 |                         [`${prefixCls}-${feedbackStatus}-help`]:
225 |                           !!feedbackStatus,
226 |                         [`${prefixCls}-help`]: true,
227 |                       },
228 |                     },
229 |                     {
230 |                       default: () => [
231 |                         feedbackStatus &&
232 |                         ['error', 'success', 'warning'].includes(feedbackStatus)
233 |                           ? ICON_MAP[
234 |                               feedbackStatus as 'error' | 'success' | 'warning'
235 |                             ]()
236 |                           : '',
237 |                         resolveComponent(feedbackText),
238 |                       ],
239 |                     }
240 |                   ),
241 |                 ],
242 |               }
243 |             )
244 |           : slots.default?.()
245 | 
246 |       const renderLabelText = () => {
247 |         const labelChildren = h(
248 |           'div',
249 |           {
250 |             class: `${prefixCls}-label-content`,
251 |             ref: elRefBinder,
252 |           },
253 |           {
254 |             default: () => [
255 |               asterisk &&
256 |                 h(
257 |                   'span',
258 |                   { class: `${prefixCls}-asterisk` },
259 |                   { default: () => ['*'] }
260 |                 ),
261 |               h('label', {}, { default: () => [resolveComponent(label)] }),
262 |             ],
263 |           }
264 |         )
265 |         const isTextTooltip = tooltip && tooltipLayout === 'text'
266 |         if (isTextTooltip || overflow.value) {
267 |           return h(
268 |             Tooltip,
269 |             {
270 |               props: {
271 |                 placement: 'top',
272 |               },
273 |             },
274 |             {
275 |               default: () => [labelChildren],
276 |               content: () =>
277 |                 h(
278 |                   'div',
279 |                   {},
280 |                   {
281 |                     default: () => [
282 |                       overflow.value && resolveComponent(label),
283 |                       isTextTooltip && resolveComponent(tooltip),
284 |                     ],
285 |                   }
286 |                 ),
287 |             }
288 |           )
289 |         } else {
290 |           return labelChildren
291 |         }
292 |       }
293 |       const renderTooltipIcon = () => {
294 |         if (tooltip && tooltipLayout === 'icon') {
295 |           return h(
296 |             'span',
297 |             {
298 |               class: `${prefixCls}-label-tooltip`,
299 |             },
300 |             {
301 |               default: () => [
302 |                 h(
303 |                   Tooltip,
304 |                   {
305 |                     props: {
306 |                       placement: 'top',
307 |                     },
308 |                   },
309 |                   {
310 |                     default: () => [h('i', { class: 'el-icon-info' }, {})],
311 |                     content: () =>
312 |                       h(
313 |                         'div',
314 |                         {
315 |                           class: `${prefixCls}-label-tooltip-content`,
316 |                         },
317 |                         {
318 |                           default: () => [resolveComponent(tooltip)],
319 |                         }
320 |                       ),
321 |                   }
322 |                 ),
323 |               ],
324 |             }
325 |           )
326 |         }
327 |       }
328 |       const renderLabel =
329 |         label &&
330 |         h(
331 |           'div',
332 |           {
333 |             class: {
334 |               [`${prefixCls}-label`]: true,
335 |               [`${prefixCls}-label-tooltip`]:
336 |                 (tooltip && tooltipLayout === 'text') || overflow.value,
337 |               [`${prefixCls}-item-col-${labelCol}`]: enableCol && !!labelCol,
338 |             },
339 |             style: labelStyle,
340 |           },
341 |           {
342 |             default: () => [
343 |               // label content
344 |               renderLabelText(),
345 |               // label tooltip
346 |               renderTooltipIcon(),
347 |               // label colon
348 |               label &&
349 |                 h(
350 |                   'span',
351 |                   {
352 |                     class: `${prefixCls}-colon`,
353 |                   },
354 |                   { default: () => [colon ? ':' : ''] }
355 |                 ),
356 |             ],
357 |           }
358 |         )
359 | 
360 |       const renderFeedback =
361 |         !!feedbackText &&
362 |         feedbackLayout !== 'popover' &&
363 |         feedbackLayout !== 'none' &&
364 |         h(
365 |           'div',
366 |           {
367 |             class: {
368 |               [`${prefixCls}-${feedbackStatus}-help`]: !!feedbackStatus,
369 |               [`${prefixCls}-help`]: true,
370 |               [`${prefixCls}-help-enter`]: true,
371 |               [`${prefixCls}-help-enter-active`]: true,
372 |             },
373 |           },
374 |           { default: () => [resolveComponent(feedbackText)] }
375 |         )
376 | 
377 |       const renderExtra =
378 |         extra &&
379 |         h(
380 |           'div',
381 |           { class: `${prefixCls}-extra` },
382 |           { default: () => [resolveComponent(extra)] }
383 |         )
384 |       const renderContent = h(
385 |         'div',
386 |         {
387 |           class: {
388 |             [`${prefixCls}-control`]: true,
389 |             [`${prefixCls}-item-col-${wrapperCol}`]: enableCol && !!wrapperCol,
390 |           },
391 |         },
392 |         {
393 |           default: () => [
394 |             h(
395 |               'div',
396 |               { class: `${prefixCls}-control-content` },
397 |               {
398 |                 default: () => [
399 |                   addonBefore &&
400 |                     h(
401 |                       'div',
402 |                       { class: `${prefixCls}-addon-before` },
403 |                       {
404 |                         default: () => [resolveComponent(addonBefore)],
405 |                       }
406 |                     ),
407 |                   h(
408 |                     'div',
409 |                     {
410 |                       class: {
411 |                         [`${prefixCls}-control-content-component`]: true,
412 |                         [`${prefixCls}-control-content-component-has-feedback-icon`]:
413 |                           !!feedbackIcon,
414 |                       },
415 |                       style: wrapperStyle,
416 |                     },
417 |                     {
418 |                       default: () => [
419 |                         formatChildren,
420 |                         feedbackIcon &&
421 |                           h(
422 |                             'div',
423 |                             { class: `${prefixCls}-feedback-icon` },
424 |                             {
425 |                               default: () => [
426 |                                 typeof feedbackIcon === 'string'
427 |                                   ? h('i', { class: feedbackIcon }, {})
428 |                                   : resolveComponent(feedbackIcon),
429 |                               ],
430 |                             }
431 |                           ),
432 |                       ],
433 |                     }
434 |                   ),
435 |                   addonAfter &&
436 |                     h(
437 |                       'div',
438 |                       { class: `${prefixCls}-addon-after` },
439 |                       {
440 |                         default: () => [resolveComponent(addonAfter)],
441 |                       }
442 |                     ),
443 |                 ],
444 |               }
445 |             ),
446 |             renderFeedback,
447 |             renderExtra,
448 |           ],
449 |         }
450 |       )
451 |       return h(
452 |         'div',
453 |         {
454 |           style: {
455 |             ...gridStyles,
456 |           },
457 |           attrs: {
458 |             'data-grid-span': props.gridSpan,
459 |           },
460 |           class: {
461 |             [`${prefixCls}`]: true,
462 |             [`${prefixCls}-layout-${layout}`]: true,
463 |             [`${prefixCls}-${feedbackStatus}`]: !!feedbackStatus,
464 |             [`${prefixCls}-feedback-has-text`]: !!feedbackText,
465 |             [`${prefixCls}-size-${size}`]: !!size,
466 |             [`${prefixCls}-feedback-layout-${feedbackLayout}`]:
467 |               !!feedbackLayout,
468 |             [`${prefixCls}-fullness`]: !!fullness || !!inset || !!feedbackIcon,
469 |             [`${prefixCls}-inset`]: !!inset,
470 |             [`${prefixCls}-active`]: active.value,
471 |             [`${prefixCls}-inset-active`]: !!inset && active.value,
472 |             [`${prefixCls}-label-align-${labelAlign}`]: true,
473 |             [`${prefixCls}-control-align-${wrapperAlign}`]: true,
474 |             [`${prefixCls}-label-wrap`]: !!labelWrap,
475 |             [`${prefixCls}-control-wrap`]: !!wrapperWrap,
476 |             [`${prefixCls}-bordered-none`]:
477 |               bordered === false || !!inset || !!feedbackIcon,
478 |             [`${props.className}`]: !!props.className,
479 |           },
480 |           on: {
481 |             focus: () => {
482 |               if (feedbackIcon || inset) {
483 |                 active.value = true
484 |               }
485 |             },
486 |             blur: () => {
487 |               if (feedbackIcon || inset) {
488 |                 active.value = false
489 |               }
490 |             },
491 |           },
492 |         },
493 |         {
494 |           default: () => [renderLabel, renderContent],
495 |         }
496 |       )
497 |     }
498 |   },
499 | })
500 | 
501 | const Item = connect(
502 |   FormBaseItem,
503 |   mapProps(
504 |     { validateStatus: true, title: 'label', required: true },
505 |     (props, field) => {
506 |       if (isVoidField(field)) return props
507 |       if (!field) return props
508 |       const takeMessage = () => {
509 |         if (field.validating) return
510 |         if (props.feedbackText) return props.feedbackText
511 |         if (field.selfErrors.length) return field.selfErrors
512 |         if (field.selfWarnings.length) return field.selfWarnings
513 |         if (field.selfSuccesses.length) return field.selfSuccesses
514 |       }
515 |       const errorMessages = takeMessage()
516 |       return {
517 |         feedbackText: Array.isArray(errorMessages)
518 |           ? errorMessages.join(', ')
519 |           : errorMessages,
520 |         extra: props.extra || field.description,
521 |       }
522 |     },
523 |     (props, field) => {
524 |       if (isVoidField(field)) return props
525 |       if (!field) return props
526 |       return {
527 |         feedbackStatus:
528 |           field.validateStatus === 'validating'
529 |             ? 'pending'
530 |             : (Array.isArray(field.decorator) &&
531 |                 field.decorator[1]?.feedbackStatus) ||
532 |               field.validateStatus,
533 |       }
534 |     },
535 |     (props, field) => {
536 |       if (isVoidField(field)) return props
537 | 
538 |       if (!field) return props
539 |       let asterisk = false
540 |       if (field.required && field.pattern !== 'readPretty') {
541 |         asterisk = true
542 |       }
543 |       if ('asterisk' in props) {
544 |         asterisk = props.asterisk
545 |       }
546 |       return {
547 |         asterisk,
548 |       }
549 |     }
550 |   )
551 | )
552 | 
553 | export const FormItem = composeExport(Item, {
554 |   BaseItem: FormBaseItem,
555 | })
556 | 
557 | export default FormItem
558 | 
```

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

```markdown
  1 | # ArrayCollapse
  2 | 
  3 | > Folding panel, it is more suitable to use ArrayCollapse for scenes with more fields in each row and more linkage
  4 | >
  5 | > Note: This component is only applicable to Schema scenarios
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormItem,
 13 |   Input,
 14 |   ArrayCollapse,
 15 |   FormButtonGroup,
 16 |   Submit,
 17 | } from '@formily/next'
 18 | import { createForm } from '@formily/core'
 19 | import { FormProvider, createSchemaField } from '@formily/react'
 20 | import { Button } from '@alifd/next'
 21 | 
 22 | const SchemaField = createSchemaField({
 23 |   components: {
 24 |     FormItem,
 25 |     Input,
 26 |     ArrayCollapse,
 27 |   },
 28 | })
 29 | 
 30 | const form = createForm()
 31 | 
 32 | export default () => {
 33 |   return (
 34 |     <FormProvider form={form}>
 35 |       <SchemaField>
 36 |         <SchemaField.Array
 37 |           name="string_array"
 38 |           maxItems={3}
 39 |           x-decorator="FormItem"
 40 |           x-component="ArrayCollapse"
 41 |           x-component-props={{
 42 |             accordion: true,
 43 |             defaultOpenPanelCount: 3,
 44 |           }}
 45 |         >
 46 |           <SchemaField.Void
 47 |             x-component="ArrayCollapse.CollapsePanel"
 48 |             x-component-props={{
 49 |               title: 'String array',
 50 |             }}
 51 |           >
 52 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
 53 |             <SchemaField.String
 54 |               name="input"
 55 |               x-decorator="FormItem"
 56 |               title="Input"
 57 |               required
 58 |               x-component="Input"
 59 |             />
 60 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
 61 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
 62 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
 63 |           </SchemaField.Void>
 64 |           <SchemaField.Void
 65 |             x-component="ArrayCollapse.Addition"
 66 |             title="Add entry"
 67 |           />
 68 |         </SchemaField.Array>
 69 |         <SchemaField.Array
 70 |           name="array"
 71 |           maxItems={3}
 72 |           x-decorator="FormItem"
 73 |           x-component="ArrayCollapse"
 74 |         >
 75 |           <SchemaField.Object
 76 |             x-component="ArrayCollapse.CollapsePanel"
 77 |             x-component-props={{
 78 |               title: 'Object array',
 79 |             }}
 80 |           >
 81 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
 82 |             <SchemaField.String
 83 |               name="input"
 84 |               x-decorator="FormItem"
 85 |               title="Input"
 86 |               required
 87 |               x-component="Input"
 88 |             />
 89 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
 90 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
 91 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
 92 |           </SchemaField.Object>
 93 |           <SchemaField.Void
 94 |             x-component="ArrayCollapse.Addition"
 95 |             title="Add entry"
 96 |           />
 97 |         </SchemaField.Array>
 98 |         <SchemaField.Array
 99 |           name="string_array_unshift"
100 |           maxItems={3}
101 |           x-decorator="FormItem"
102 |           x-component="ArrayCollapse"
103 |           x-component-props={{
104 |             defaultOpenPanelCount: 8,
105 |           }}
106 |         >
107 |           <SchemaField.Void
108 |             x-component="ArrayCollapse.CollapsePanel"
109 |             x-component-props={{
110 |               title: 'String array',
111 |             }}
112 |           >
113 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
114 |             <SchemaField.String
115 |               name="input"
116 |               x-decorator="FormItem"
117 |               title="Input"
118 |               required
119 |               x-component="Input"
120 |             />
121 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
122 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
123 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
124 |           </SchemaField.Void>
125 |           <SchemaField.Void
126 |             x-component="ArrayCollapse.Addition"
127 |             title="Add entry (unshift)"
128 |             x-component-props={{
129 |               method: 'unshift',
130 |             }}
131 |           />
132 |         </SchemaField.Array>
133 |       </SchemaField>
134 |       <FormButtonGroup>
135 |         <Button
136 |           onClick={() => {
137 |             form.setInitialValues({
138 |               array: Array.from({ length: 10 }).map(() => ({
139 |                 input: 'default value',
140 |               })),
141 |               string_array: Array.from({ length: 10 }).map(
142 |                 () => 'default value'
143 |               ),
144 |               string_array_unshift: Array.from({ length: 10 }).map(
145 |                 () => 'default value'
146 |               ),
147 |             })
148 |           }}
149 |         >
150 |           Load default data
151 |         </Button>
152 |         <Submit onSubmit={console.log}>Submit</Submit>
153 |       </FormButtonGroup>
154 |     </FormProvider>
155 |   )
156 | }
157 | ```
158 | 
159 | ## JSON Schema case
160 | 
161 | ```tsx
162 | import React from 'react'
163 | import {
164 |   FormItem,
165 |   Input,
166 |   ArrayCollapse,
167 |   FormButtonGroup,
168 |   Submit,
169 | } from '@formily/next'
170 | import { createForm } from '@formily/core'
171 | import { FormProvider, createSchemaField } from '@formily/react'
172 | 
173 | const SchemaField = createSchemaField({
174 |   components: {
175 |     FormItem,
176 |     Input,
177 |     ArrayCollapse,
178 |   },
179 | })
180 | 
181 | const form = createForm()
182 | 
183 | const schema = {
184 |   type: 'object',
185 |   properties: {
186 |     string_array: {
187 |       type: 'array',
188 |       'x-component': 'ArrayCollapse',
189 |       maxItems: 3,
190 |       'x-decorator': 'FormItem',
191 |       items: {
192 |         type: 'void',
193 |         'x-component': 'ArrayCollapse.CollapsePanel',
194 |         'x-component-props': {
195 |           title: 'String array',
196 |         },
197 |         properties: {
198 |           index: {
199 |             type: 'void',
200 |             'x-component': 'ArrayCollapse.Index',
201 |           },
202 |           input: {
203 |             type: 'string',
204 |             'x-decorator': 'FormItem',
205 |             title: 'Input',
206 |             required: true,
207 |             'x-component': 'Input',
208 |           },
209 |           remove: {
210 |             type: 'void',
211 |             'x-component': 'ArrayCollapse.Remove',
212 |           },
213 |           moveUp: {
214 |             type: 'void',
215 |             'x-component': 'ArrayCollapse.MoveUp',
216 |           },
217 |           moveDown: {
218 |             type: 'void',
219 |             'x-component': 'ArrayCollapse.MoveDown',
220 |           },
221 |         },
222 |       },
223 |       properties: {
224 |         addition: {
225 |           type: 'void',
226 |           title: 'Add entry',
227 |           'x-component': 'ArrayCollapse.Addition',
228 |         },
229 |       },
230 |     },
231 |     array: {
232 |       type: 'array',
233 |       'x-component': 'ArrayCollapse',
234 |       maxItems: 3,
235 |       'x-decorator': 'FormItem',
236 |       items: {
237 |         type: 'object',
238 |         'x-component': 'ArrayCollapse.CollapsePanel',
239 |         'x-component-props': {
240 |           title: 'Object array',
241 |         },
242 |         properties: {
243 |           index: {
244 |             type: 'void',
245 |             'x-component': 'ArrayCollapse.Index',
246 |           },
247 |           input: {
248 |             type: 'string',
249 |             'x-decorator': 'FormItem',
250 |             title: 'Input',
251 |             required: true,
252 |             'x-component': 'Input',
253 |           },
254 |           remove: {
255 |             type: 'void',
256 |             'x-component': 'ArrayCollapse.Remove',
257 |           },
258 |           moveUp: {
259 |             type: 'void',
260 |             'x-component': 'ArrayCollapse.MoveUp',
261 |           },
262 |           moveDown: {
263 |             type: 'void',
264 |             'x-component': 'ArrayCollapse.MoveDown',
265 |           },
266 |         },
267 |       },
268 |       properties: {
269 |         addition: {
270 |           type: 'void',
271 |           title: 'Add entry',
272 |           'x-component': 'ArrayCollapse.Addition',
273 |         },
274 |       },
275 |     },
276 |     array_unshift: {
277 |       type: 'array',
278 |       'x-component': 'ArrayCollapse',
279 |       maxItems: 3,
280 |       'x-decorator': 'FormItem',
281 |       items: {
282 |         type: 'object',
283 |         'x-component': 'ArrayCollapse.CollapsePanel',
284 |         'x-component-props': {
285 |           title: 'Object array',
286 |         },
287 |         properties: {
288 |           index: {
289 |             type: 'void',
290 |             'x-component': 'ArrayCollapse.Index',
291 |           },
292 |           input: {
293 |             type: 'string',
294 |             'x-decorator': 'FormItem',
295 |             title: 'Input',
296 |             required: true,
297 |             'x-component': 'Input',
298 |           },
299 |           remove: {
300 |             type: 'void',
301 |             'x-component': 'ArrayCollapse.Remove',
302 |           },
303 |           moveUp: {
304 |             type: 'void',
305 |             'x-component': 'ArrayCollapse.MoveUp',
306 |           },
307 |           moveDown: {
308 |             type: 'void',
309 |             'x-component': 'ArrayCollapse.MoveDown',
310 |           },
311 |         },
312 |       },
313 |       properties: {
314 |         addition: {
315 |           type: 'void',
316 |           title: 'Add entry (unshift)',
317 |           'x-component': 'ArrayCollapse.Addition',
318 |           'x-component-props': {
319 |             method: 'unshift',
320 |           },
321 |         },
322 |       },
323 |     },
324 |   },
325 | }
326 | 
327 | export default () => {
328 |   return (
329 |     <FormProvider form={form}>
330 |       <SchemaField schema={schema} />
331 |       <FormButtonGroup>
332 |         <Submit onSubmit={console.log}>Submit</Submit>
333 |       </FormButtonGroup>
334 |     </FormProvider>
335 |   )
336 | }
337 | ```
338 | 
339 | ## Effects linkage case
340 | 
341 | ```tsx
342 | import React from 'react'
343 | import {
344 |   FormItem,
345 |   Input,
346 |   ArrayCollapse,
347 |   FormButtonGroup,
348 |   Submit,
349 | } from '@formily/next'
350 | import { createForm, onFieldChange, onFieldReact } from '@formily/core'
351 | import { FormProvider, createSchemaField } from '@formily/react'
352 | 
353 | const SchemaField = createSchemaField({
354 |   components: {
355 |     FormItem,
356 |     Input,
357 |     ArrayCollapse,
358 |   },
359 | })
360 | 
361 | const form = createForm({
362 |   effects: () => {
363 |     //Active linkage mode
364 |     onFieldChange('array.*.aa', ['value'], (field, form) => {
365 |       form.setFieldState(field.query('.bb'), (state) => {
366 |         state.visible = field.value != '123'
367 |       })
368 |     })
369 |     //Passive linkage mode
370 |     onFieldReact('array.*.dd', (field) => {
371 |       field.visible = field.query('.cc').get('value') != '123'
372 |     })
373 |   },
374 | })
375 | 
376 | export default () => {
377 |   return (
378 |     <FormProvider form={form}>
379 |       <SchemaField>
380 |         <SchemaField.Array
381 |           name="array"
382 |           maxItems={3}
383 |           x-component="ArrayCollapse"
384 |           x-decorator="FormItem"
385 |           x-component-props={{
386 |             title: 'Object array',
387 |           }}
388 |         >
389 |           <SchemaField.Object
390 |             x-component="ArrayCollapse.CollapsePanel"
391 |             x-component-props={{
392 |               title: 'Object array',
393 |             }}
394 |           >
395 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
396 |             <SchemaField.String
397 |               name="aa"
398 |               x-decorator="FormItem"
399 |               title="AA"
400 |               required
401 |               description="AA hide BB when entering 123"
402 |               x-component="Input"
403 |             />
404 |             <SchemaField.String
405 |               name="bb"
406 |               x-decorator="FormItem"
407 |               title="BB"
408 |               required
409 |               x-component="Input"
410 |             />
411 |             <SchemaField.String
412 |               name="cc"
413 |               x-decorator="FormItem"
414 |               title="CC"
415 |               required
416 |               description="Hide DD when CC enters 123"
417 |               x-component="Input"
418 |             />
419 |             <SchemaField.String
420 |               name="dd"
421 |               x-decorator="FormItem"
422 |               title="DD"
423 |               required
424 |               x-component="Input"
425 |             />
426 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
427 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
428 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
429 |           </SchemaField.Object>
430 |           <SchemaField.Void
431 |             x-component="ArrayCollapse.Addition"
432 |             title="Add entry"
433 |           />
434 |         </SchemaField.Array>
435 |       </SchemaField>
436 |       <FormButtonGroup>
437 |         <Submit onSubmit={console.log}>Submit</Submit>
438 |       </FormButtonGroup>
439 |     </FormProvider>
440 |   )
441 | }
442 | ```
443 | 
444 | ## JSON Schema linkage case
445 | 
446 | ```tsx
447 | import React from 'react'
448 | import {
449 |   FormItem,
450 |   Input,
451 |   ArrayCollapse,
452 |   FormButtonGroup,
453 |   Submit,
454 | } from '@formily/next'
455 | import { createForm } from '@formily/core'
456 | import { FormProvider, createSchemaField } from '@formily/react'
457 | 
458 | const SchemaField = createSchemaField({
459 |   components: {
460 |     FormItem,
461 |     Input,
462 |     ArrayCollapse,
463 |   },
464 | })
465 | 
466 | const form = createForm()
467 | 
468 | const schema = {
469 |   type: 'object',
470 |   properties: {
471 |     array: {
472 |       type: 'array',
473 |       'x-component': 'ArrayCollapse',
474 |       maxItems: 3,
475 |       title: 'Object array',
476 |       items: {
477 |         type: 'object',
478 |         'x-component': 'ArrayCollapse.CollapsePanel',
479 |         'x-component-props': {
480 |           title: 'Object array',
481 |         },
482 |         properties: {
483 |           index: {
484 |             type: 'void',
485 |             'x-component': 'ArrayCollapse.Index',
486 |           },
487 |           aa: {
488 |             type: 'string',
489 |             'x-decorator': 'FormItem',
490 |             title: 'AA',
491 |             required: true,
492 |             'x-component': 'Input',
493 |             description: 'Enter 123',
494 |           },
495 |           bb: {
496 |             type: 'string',
497 |             title: 'BB',
498 |             required: true,
499 |             'x-decorator': 'FormItem',
500 |             'x-component': 'Input',
501 |             'x-reactions': [
502 |               {
503 |                 dependencies: ['.aa'],
504 |                 when: "{{$deps[0] != '123'}}",
505 |                 fulfill: {
506 |                   schema: {
507 |                     title: 'BB',
508 |                     'x-disabled': true,
509 |                   },
510 |                 },
511 |                 otherwise: {
512 |                   schema: {
513 |                     title: 'Changed',
514 |                     'x-disabled': false,
515 |                   },
516 |                 },
517 |               },
518 |             ],
519 |           },
520 |           remove: {
521 |             type: 'void',
522 |             'x-component': 'ArrayCollapse.Remove',
523 |           },
524 |           moveUp: {
525 |             type: 'void',
526 |             'x-component': 'ArrayCollapse.MoveUp',
527 |           },
528 |           moveDown: {
529 |             type: 'void',
530 |             'x-component': 'ArrayCollapse.MoveDown',
531 |           },
532 |         },
533 |       },
534 |       properties: {
535 |         addition: {
536 |           type: 'void',
537 |           title: 'Add entry',
538 |           'x-component': 'ArrayCollapse.Addition',
539 |         },
540 |       },
541 |     },
542 |   },
543 | }
544 | 
545 | export default () => {
546 |   return (
547 |     <FormProvider form={form}>
548 |       <SchemaField schema={schema} />
549 |       <FormButtonGroup>
550 |         <Submit onSubmit={console.log}>Submit</Submit>
551 |       </FormButtonGroup>
552 |     </FormProvider>
553 |   )
554 | }
555 | ```
556 | 
557 | ## API
558 | 
559 | ### ArrayCollapse
560 | 
561 | Reference https://fusion.design/pc/component/collapse
562 | 
563 | Extended attributes
564 | 
565 | | Property name         | Type   | Description                  | Default value |
566 | | --------------------- | ------ | ---------------------------- | ------------- |
567 | | defaultOpenPanelCount | number | Default expanded Panel count | 5             |
568 | 
569 | ### ArrayCollapse.CollapsePanel
570 | 
571 | Reference https://fusion.design/pc/component/collapse
572 | 
573 | ### ArrayCollapse.Addition
574 | 
575 | > Add button
576 | 
577 | Extended attributes
578 | 
579 | | Property name | Type                 | Description   | Default value |
580 | | ------------- | -------------------- | ------------- | ------------- |
581 | | title         | ReactText            | Copywriting   |               |
582 | | method        | `'push' \|'unshift'` | add method    | `'push'`      |
583 | | defaultValue  | `any`                | Default value |               |
584 | 
585 | Other references https://fusion.design/pc/component/basic/button
586 | 
587 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
588 | 
589 | ### ArrayCollapse.Remove
590 | 
591 | > Delete button
592 | 
593 | | Property name | Type      | Description | Default value |
594 | | ------------- | --------- | ----------- | ------------- |
595 | | title         | ReactText | Copywriting |               |
596 | 
597 | Other references https://ant.design/components/icon-cn/
598 | 
599 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
600 | 
601 | ### ArrayCollapse.MoveDown
602 | 
603 | > Move down button
604 | 
605 | | Property name | Type      | Description | Default value |
606 | | ------------- | --------- | ----------- | ------------- |
607 | | title         | ReactText | Copywriting |               |
608 | 
609 | Other references https://ant.design/components/icon-cn/
610 | 
611 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
612 | 
613 | ### ArrayCollapse.MoveUp
614 | 
615 | > Move up button
616 | 
617 | | Property name | Type      | Description | Default value |
618 | | ------------- | --------- | ----------- | ------------- |
619 | | title         | ReactText | Copywriting |               |
620 | 
621 | Other references https://ant.design/components/icon-cn/
622 | 
623 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
624 | 
625 | ### ArrayCollapse.Index
626 | 
627 | > Index Renderer
628 | 
629 | No attributes
630 | 
631 | ### ArrayCollapse.useIndex
632 | 
633 | > Read the React Hook of the current rendering row index
634 | 
635 | ### ArrayCollapse.useRecord
636 | 
637 | > Read the React Hook of the current rendering row
638 | 
```

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

```markdown
  1 | # ArrayCollapse
  2 | 
  3 | > Folding panel, it is more suitable to use ArrayCollapse for scenes with more fields in each row and more linkage
  4 | >
  5 | > Note: This component is only applicable to Schema scenarios
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormItem,
 13 |   Input,
 14 |   ArrayCollapse,
 15 |   FormButtonGroup,
 16 |   Submit,
 17 | } from '@formily/antd'
 18 | import { createForm } from '@formily/core'
 19 | import { FormProvider, createSchemaField } from '@formily/react'
 20 | import { Button } from 'antd'
 21 | 
 22 | const SchemaField = createSchemaField({
 23 |   components: {
 24 |     FormItem,
 25 |     Input,
 26 |     ArrayCollapse,
 27 |   },
 28 | })
 29 | 
 30 | const form = createForm()
 31 | 
 32 | export default () => {
 33 |   return (
 34 |     <FormProvider form={form}>
 35 |       <SchemaField>
 36 |         <SchemaField.Array
 37 |           name="string_array"
 38 |           maxItems={3}
 39 |           x-decorator="FormItem"
 40 |           x-component="ArrayCollapse"
 41 |           x-component-props={{
 42 |             accordion: true,
 43 |             defaultOpenPanelCount: 3,
 44 |           }}
 45 |         >
 46 |           <SchemaField.Void
 47 |             x-component="ArrayCollapse.CollapsePanel"
 48 |             x-component-props={{
 49 |               header: 'String array',
 50 |             }}
 51 |           >
 52 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
 53 |             <SchemaField.String
 54 |               name="input"
 55 |               x-decorator="FormItem"
 56 |               title="Input"
 57 |               required
 58 |               x-component="Input"
 59 |             />
 60 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
 61 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
 62 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
 63 |           </SchemaField.Void>
 64 |           <SchemaField.Void
 65 |             x-component="ArrayCollapse.Addition"
 66 |             title="Add entry"
 67 |           />
 68 |         </SchemaField.Array>
 69 |         <SchemaField.Array
 70 |           name="array"
 71 |           maxItems={3}
 72 |           x-decorator="FormItem"
 73 |           x-component="ArrayCollapse"
 74 |         >
 75 |           <SchemaField.Object
 76 |             x-component="ArrayCollapse.CollapsePanel"
 77 |             x-component-props={{
 78 |               header: 'Object array',
 79 |             }}
 80 |           >
 81 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
 82 |             <SchemaField.String
 83 |               name="input"
 84 |               x-decorator="FormItem"
 85 |               title="Input"
 86 |               required
 87 |               x-component="Input"
 88 |             />
 89 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
 90 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
 91 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
 92 |           </SchemaField.Object>
 93 |           <SchemaField.Void
 94 |             x-component="ArrayCollapse.Addition"
 95 |             title="Add entry"
 96 |           />
 97 |         </SchemaField.Array>
 98 |         <SchemaField.Array
 99 |           name="string_array_unshift"
100 |           maxItems={3}
101 |           x-decorator="FormItem"
102 |           x-component="ArrayCollapse"
103 |           x-component-props={{
104 |             defaultOpenPanelCount: 8,
105 |           }}
106 |         >
107 |           <SchemaField.Void
108 |             x-component="ArrayCollapse.CollapsePanel"
109 |             x-component-props={{
110 |               header: 'String array',
111 |             }}
112 |           >
113 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
114 |             <SchemaField.String
115 |               name="input"
116 |               x-decorator="FormItem"
117 |               title="Input"
118 |               required
119 |               x-component="Input"
120 |             />
121 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
122 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
123 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
124 |           </SchemaField.Void>
125 |           <SchemaField.Void
126 |             x-component="ArrayCollapse.Addition"
127 |             title="Add entry (unshift)"
128 |             x-component-props={{
129 |               method: 'unshift',
130 |             }}
131 |           />
132 |         </SchemaField.Array>
133 |       </SchemaField>
134 |       <FormButtonGroup>
135 |         <Button
136 |           onClick={() => {
137 |             form.setInitialValues({
138 |               array: Array.from({ length: 10 }).map(() => ({
139 |                 input: 'default value',
140 |               })),
141 |               string_array: Array.from({ length: 10 }).map(
142 |                 () => 'default value'
143 |               ),
144 |               string_array_unshift: Array.from({ length: 10 }).map(
145 |                 () => 'default value'
146 |               ),
147 |             })
148 |           }}
149 |         >
150 |           Load default data
151 |         </Button>
152 |         <Submit onSubmit={console.log}>Submit</Submit>
153 |       </FormButtonGroup>
154 |     </FormProvider>
155 |   )
156 | }
157 | ```
158 | 
159 | ## JSON Schema case
160 | 
161 | ```tsx
162 | import React from 'react'
163 | import {
164 |   FormItem,
165 |   Input,
166 |   ArrayCollapse,
167 |   FormButtonGroup,
168 |   Submit,
169 | } from '@formily/antd'
170 | import { createForm } from '@formily/core'
171 | import { FormProvider, createSchemaField } from '@formily/react'
172 | 
173 | const SchemaField = createSchemaField({
174 |   components: {
175 |     FormItem,
176 |     Input,
177 |     ArrayCollapse,
178 |   },
179 | })
180 | 
181 | const form = createForm()
182 | 
183 | const schema = {
184 |   type: 'object',
185 |   properties: {
186 |     string_array: {
187 |       type: 'array',
188 |       'x-component': 'ArrayCollapse',
189 |       maxItems: 3,
190 |       'x-decorator': 'FormItem',
191 |       items: {
192 |         type: 'void',
193 |         'x-component': 'ArrayCollapse.CollapsePanel',
194 |         'x-component-props': {
195 |           header: 'String array',
196 |         },
197 |         properties: {
198 |           index: {
199 |             type: 'void',
200 |             'x-component': 'ArrayCollapse.Index',
201 |           },
202 |           input: {
203 |             type: 'string',
204 |             'x-decorator': 'FormItem',
205 |             title: 'Input',
206 |             required: true,
207 |             'x-component': 'Input',
208 |           },
209 |           remove: {
210 |             type: 'void',
211 |             'x-component': 'ArrayCollapse.Remove',
212 |           },
213 |           moveUp: {
214 |             type: 'void',
215 |             'x-component': 'ArrayCollapse.MoveUp',
216 |           },
217 |           moveDown: {
218 |             type: 'void',
219 |             'x-component': 'ArrayCollapse.MoveDown',
220 |           },
221 |         },
222 |       },
223 |       properties: {
224 |         addition: {
225 |           type: 'void',
226 |           title: 'Add entry',
227 |           'x-component': 'ArrayCollapse.Addition',
228 |         },
229 |       },
230 |     },
231 |     array: {
232 |       type: 'array',
233 |       'x-component': 'ArrayCollapse',
234 |       maxItems: 3,
235 |       'x-decorator': 'FormItem',
236 |       items: {
237 |         type: 'object',
238 |         'x-component': 'ArrayCollapse.CollapsePanel',
239 |         'x-component-props': {
240 |           header: 'Object array',
241 |         },
242 |         properties: {
243 |           index: {
244 |             type: 'void',
245 |             'x-component': 'ArrayCollapse.Index',
246 |           },
247 |           input: {
248 |             type: 'string',
249 |             'x-decorator': 'FormItem',
250 |             title: 'Input',
251 |             required: true,
252 |             'x-component': 'Input',
253 |           },
254 |           remove: {
255 |             type: 'void',
256 |             'x-component': 'ArrayCollapse.Remove',
257 |           },
258 |           moveUp: {
259 |             type: 'void',
260 |             'x-component': 'ArrayCollapse.MoveUp',
261 |           },
262 |           moveDown: {
263 |             type: 'void',
264 |             'x-component': 'ArrayCollapse.MoveDown',
265 |           },
266 |         },
267 |       },
268 |       properties: {
269 |         addition: {
270 |           type: 'void',
271 |           title: 'Add entry',
272 |           'x-component': 'ArrayCollapse.Addition',
273 |         },
274 |       },
275 |     },
276 |     array_unshift: {
277 |       type: 'array',
278 |       'x-component': 'ArrayCollapse',
279 |       maxItems: 3,
280 |       'x-decorator': 'FormItem',
281 |       items: {
282 |         type: 'object',
283 |         'x-component': 'ArrayCollapse.CollapsePanel',
284 |         'x-component-props': {
285 |           header: 'Object array',
286 |         },
287 |         properties: {
288 |           index: {
289 |             type: 'void',
290 |             'x-component': 'ArrayCollapse.Index',
291 |           },
292 |           input: {
293 |             type: 'string',
294 |             'x-decorator': 'FormItem',
295 |             title: 'Input',
296 |             required: true,
297 |             'x-component': 'Input',
298 |           },
299 |           remove: {
300 |             type: 'void',
301 |             'x-component': 'ArrayCollapse.Remove',
302 |           },
303 |           moveUp: {
304 |             type: 'void',
305 |             'x-component': 'ArrayCollapse.MoveUp',
306 |           },
307 |           moveDown: {
308 |             type: 'void',
309 |             'x-component': 'ArrayCollapse.MoveDown',
310 |           },
311 |         },
312 |       },
313 |       properties: {
314 |         addition: {
315 |           type: 'void',
316 |           title: 'Add entry (unshift)',
317 |           'x-component': 'ArrayCollapse.Addition',
318 |           'x-component-props': {
319 |             method: 'unshift',
320 |           },
321 |         },
322 |       },
323 |     },
324 |   },
325 | }
326 | 
327 | export default () => {
328 |   return (
329 |     <FormProvider form={form}>
330 |       <SchemaField schema={schema} />
331 |       <FormButtonGroup>
332 |         <Submit onSubmit={console.log}>Submit</Submit>
333 |       </FormButtonGroup>
334 |     </FormProvider>
335 |   )
336 | }
337 | ```
338 | 
339 | ## Effects linkage case
340 | 
341 | ```tsx
342 | import React from 'react'
343 | import {
344 |   FormItem,
345 |   Input,
346 |   ArrayCollapse,
347 |   FormButtonGroup,
348 |   Submit,
349 | } from '@formily/antd'
350 | import { createForm, onFieldChange, onFieldReact } from '@formily/core'
351 | import { FormProvider, createSchemaField } from '@formily/react'
352 | 
353 | const SchemaField = createSchemaField({
354 |   components: {
355 |     FormItem,
356 |     Input,
357 |     ArrayCollapse,
358 |   },
359 | })
360 | 
361 | const form = createForm({
362 |   effects: () => {
363 |     //Active linkage mode
364 |     onFieldChange('array.*.aa', ['value'], (field, form) => {
365 |       form.setFieldState(field.query('.bb'), (state) => {
366 |         state.visible = field.value != '123'
367 |       })
368 |     })
369 |     //Passive linkage mode
370 |     onFieldReact('array.*.dd', (field) => {
371 |       field.visible = field.query('.cc').get('value') != '123'
372 |     })
373 |   },
374 | })
375 | 
376 | export default () => {
377 |   return (
378 |     <FormProvider form={form}>
379 |       <SchemaField>
380 |         <SchemaField.Array
381 |           name="array"
382 |           maxItems={3}
383 |           x-component="ArrayCollapse"
384 |           x-decorator="FormItem"
385 |           x-component-props={{
386 |             title: 'Object array',
387 |           }}
388 |         >
389 |           <SchemaField.Object
390 |             x-component="ArrayCollapse.CollapsePanel"
391 |             x-component-props={{
392 |               header: 'Object array',
393 |             }}
394 |           >
395 |             <SchemaField.Void x-component="ArrayCollapse.Index" />
396 |             <SchemaField.String
397 |               name="aa"
398 |               x-decorator="FormItem"
399 |               title="AA"
400 |               required
401 |               description="AA hide BB when entering 123"
402 |               x-component="Input"
403 |             />
404 |             <SchemaField.String
405 |               name="bb"
406 |               x-decorator="FormItem"
407 |               title="BB"
408 |               required
409 |               x-component="Input"
410 |             />
411 |             <SchemaField.String
412 |               name="cc"
413 |               x-decorator="FormItem"
414 |               title="CC"
415 |               required
416 |               description="Hide DD when CC enters 123"
417 |               x-component="Input"
418 |             />
419 |             <SchemaField.String
420 |               name="dd"
421 |               x-decorator="FormItem"
422 |               title="DD"
423 |               required
424 |               x-component="Input"
425 |             />
426 |             <SchemaField.Void x-component="ArrayCollapse.Remove" />
427 |             <SchemaField.Void x-component="ArrayCollapse.MoveUp" />
428 |             <SchemaField.Void x-component="ArrayCollapse.MoveDown" />
429 |           </SchemaField.Object>
430 |           <SchemaField.Void
431 |             x-component="ArrayCollapse.Addition"
432 |             title="Add entry"
433 |           />
434 |         </SchemaField.Array>
435 |       </SchemaField>
436 |       <FormButtonGroup>
437 |         <Submit onSubmit={console.log}>Submit</Submit>
438 |       </FormButtonGroup>
439 |     </FormProvider>
440 |   )
441 | }
442 | ```
443 | 
444 | ## JSON Schema linkage case
445 | 
446 | ```tsx
447 | import React from 'react'
448 | import {
449 |   FormItem,
450 |   Input,
451 |   ArrayCollapse,
452 |   FormButtonGroup,
453 |   Submit,
454 | } from '@formily/antd'
455 | import { createForm } from '@formily/core'
456 | import { FormProvider, createSchemaField } from '@formily/react'
457 | 
458 | const SchemaField = createSchemaField({
459 |   components: {
460 |     FormItem,
461 |     Input,
462 |     ArrayCollapse,
463 |   },
464 | })
465 | 
466 | const form = createForm()
467 | 
468 | const schema = {
469 |   type: 'object',
470 |   properties: {
471 |     array: {
472 |       type: 'array',
473 |       'x-component': 'ArrayCollapse',
474 |       maxItems: 3,
475 |       title: 'Object array',
476 |       items: {
477 |         type: 'object',
478 |         'x-component': 'ArrayCollapse.CollapsePanel',
479 |         'x-component-props': {
480 |           header: 'Object array',
481 |         },
482 |         properties: {
483 |           index: {
484 |             type: 'void',
485 |             'x-component': 'ArrayCollapse.Index',
486 |           },
487 |           aa: {
488 |             type: 'string',
489 |             'x-decorator': 'FormItem',
490 |             title: 'AA',
491 |             required: true,
492 |             'x-component': 'Input',
493 |             description: 'Enter 123',
494 |           },
495 |           bb: {
496 |             type: 'string',
497 |             title: 'BB',
498 |             required: true,
499 |             'x-decorator': 'FormItem',
500 |             'x-component': 'Input',
501 |             'x-reactions': [
502 |               {
503 |                 dependencies: ['.aa'],
504 |                 when: "{{$deps[0] != '123'}}",
505 |                 fulfill: {
506 |                   schema: {
507 |                     title: 'BB',
508 |                     'x-disabled': true,
509 |                   },
510 |                 },
511 |                 otherwise: {
512 |                   schema: {
513 |                     title: 'Changed',
514 |                     'x-disabled': false,
515 |                   },
516 |                 },
517 |               },
518 |             ],
519 |           },
520 |           remove: {
521 |             type: 'void',
522 |             'x-component': 'ArrayCollapse.Remove',
523 |           },
524 |           moveUp: {
525 |             type: 'void',
526 |             'x-component': 'ArrayCollapse.MoveUp',
527 |           },
528 |           moveDown: {
529 |             type: 'void',
530 |             'x-component': 'ArrayCollapse.MoveDown',
531 |           },
532 |         },
533 |       },
534 |       properties: {
535 |         addition: {
536 |           type: 'void',
537 |           title: 'Add entry',
538 |           'x-component': 'ArrayCollapse.Addition',
539 |         },
540 |       },
541 |     },
542 |   },
543 | }
544 | 
545 | export default () => {
546 |   return (
547 |     <FormProvider form={form}>
548 |       <SchemaField schema={schema} />
549 |       <FormButtonGroup>
550 |         <Submit onSubmit={console.log}>Submit</Submit>
551 |       </FormButtonGroup>
552 |     </FormProvider>
553 |   )
554 | }
555 | ```
556 | 
557 | ## API
558 | 
559 | ### ArrayCollapse
560 | 
561 | Reference https://ant.design/components/collapse-cn/
562 | 
563 | ### ArrayCollapse.CollapsePanel
564 | 
565 | Reference https://ant.design/components/collapse-cn/
566 | 
567 | ### ArrayCollapse.Addition
568 | 
569 | > Add button
570 | 
571 | Extended attributes
572 | 
573 | | Property name | Type                 | Description   | Default value |
574 | | ------------- | -------------------- | ------------- | ------------- |
575 | | title         | ReactText            | Copywriting   |               |
576 | | method        | `'push' \|'unshift'` | add method    | `'push'`      |
577 | | defaultValue  | `any`                | Default value |               |
578 | 
579 | Other references https://ant.design/components/button-cn/
580 | 
581 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
582 | 
583 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
584 | 
585 | ### ArrayCollapse.Remove
586 | 
587 | > Delete button
588 | 
589 | | Property name | Type      | Description | Default value |
590 | | ------------- | --------- | ----------- | ------------- |
591 | | title         | ReactText | Copywriting |               |
592 | 
593 | Other references https://ant.design/components/icon-cn/
594 | 
595 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
596 | 
597 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
598 | 
599 | ### ArrayCollapse.MoveDown
600 | 
601 | > Move down button
602 | 
603 | | Property name | Type      | Description | Default value |
604 | | ------------- | --------- | ----------- | ------------- |
605 | | title         | ReactText | Copywriting |               |
606 | 
607 | Other references https://ant.design/components/icon-cn/
608 | 
609 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
610 | 
611 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
612 | 
613 | ### ArrayCollapse.MoveUp
614 | 
615 | > Move up button
616 | 
617 | | Property name | Type      | Description | Default value |
618 | | ------------- | --------- | ----------- | ------------- |
619 | | title         | ReactText | Copywriting |               |
620 | 
621 | Other references https://ant.design/components/icon-cn/
622 | 
623 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
624 | 
625 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
626 | 
627 | ### ArrayCollapse.Index
628 | 
629 | > Index Renderer
630 | 
631 | No attributes
632 | 
633 | ### ArrayCollapse.useIndex
634 | 
635 | > Read the React Hook of the current rendering row index
636 | 
637 | ### ArrayCollapse.useRecord
638 | 
639 | > Read the React Hook of the current rendering row
640 | 
```

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

```typescript
  1 | import {
  2 |   ArrayField,
  3 |   FieldDisplayTypes,
  4 |   GeneralField,
  5 |   IVoidFieldFactoryProps,
  6 | } from '@formily/core'
  7 | import type { Schema } from '@formily/json-schema'
  8 | import { observer } from '@formily/reactive-vue'
  9 | import { isArr, isBool, isFn } from '@formily/shared'
 10 | import {
 11 |   Fragment,
 12 |   h,
 13 |   RecursionField as _RecursionField,
 14 |   useField,
 15 |   useFieldSchema,
 16 | } from '@formily/vue'
 17 | import type {
 18 |   Pagination as PaginationProps,
 19 |   Table as TableProps,
 20 |   TableColumn as ElColumnProps,
 21 | } from 'element-ui'
 22 | import {
 23 |   Badge,
 24 |   Option,
 25 |   Pagination,
 26 |   Select,
 27 |   Table as ElTable,
 28 |   TableColumn as ElTableColumn,
 29 | } from 'element-ui'
 30 | import type { Component, VNode } from 'vue'
 31 | import { computed, defineComponent, inject, provide, ref, Ref } from 'vue-demi'
 32 | import { ArrayBase } from '../array-base'
 33 | import { Space } from '../space'
 34 | import { stylePrefix } from '../__builtins__/configs'
 35 | import { composeExport } from '../__builtins__/shared'
 36 | 
 37 | const RecursionField = _RecursionField as unknown as Component
 38 | 
 39 | interface IArrayTableProps extends TableProps {
 40 |   pagination?: PaginationProps | boolean
 41 | }
 42 | interface IArrayTablePaginationProps extends PaginationProps {
 43 |   dataSource?: any[]
 44 | }
 45 | 
 46 | interface ObservableColumnSource {
 47 |   field: GeneralField
 48 |   fieldProps: IVoidFieldFactoryProps<any, any>
 49 |   columnProps: ElColumnProps & { title: string; asterisk: boolean }
 50 |   schema: Schema
 51 |   display: FieldDisplayTypes
 52 |   required: boolean
 53 |   name: string
 54 | }
 55 | 
 56 | type ColumnProps = ElColumnProps & {
 57 |   key: string | number
 58 |   asterisk: boolean
 59 |   render?: (
 60 |     startIndex?: Ref<number>
 61 |   ) => (props: {
 62 |     row: Record<string, any>
 63 |     column: ElColumnProps
 64 |     $index: number
 65 |   }) => VNode
 66 | }
 67 | 
 68 | interface PaginationAction {
 69 |   totalPage?: number
 70 |   pageSize?: number
 71 |   changePage?: (page: number) => void
 72 | }
 73 | 
 74 | const PaginationSymbol = Symbol('pagination')
 75 | 
 76 | const isColumnComponent = (schema: Schema) => {
 77 |   return schema['x-component']?.indexOf('Column') > -1
 78 | }
 79 | 
 80 | const isOperationsComponent = (schema: Schema) => {
 81 |   return schema['x-component']?.indexOf('Operations') > -1
 82 | }
 83 | 
 84 | const isAdditionComponent = (schema: Schema) => {
 85 |   return schema['x-component']?.indexOf('Addition') > -1
 86 | }
 87 | 
 88 | const getArrayTableSources = (
 89 |   arrayFieldRef: Ref<ArrayField>,
 90 |   schemaRef: Ref<Schema>
 91 | ) => {
 92 |   const arrayField = arrayFieldRef.value
 93 |   const parseSources = (schema: Schema): ObservableColumnSource[] => {
 94 |     if (
 95 |       isColumnComponent(schema) ||
 96 |       isOperationsComponent(schema) ||
 97 |       isAdditionComponent(schema)
 98 |     ) {
 99 |       if (!schema['x-component-props']?.['prop'] && !schema['name']) return []
100 |       const name = schema['x-component-props']?.['prop'] || schema['name']
101 |       const field = arrayField.query(arrayField.address.concat(name)).take()
102 |       const fieldProps = field?.props || schema.toFieldProps()
103 |       const columnProps =
104 |         (field?.component as any[])?.[1] || schema['x-component-props'] || {}
105 |       const display = field?.display || schema['x-display']
106 |       const required = schema.reduceProperties((required, property) => {
107 |         if (required) {
108 |           return required
109 |         }
110 |         return !!property.required
111 |       }, false)
112 | 
113 |       return [
114 |         {
115 |           name,
116 |           display,
117 |           required,
118 |           field,
119 |           fieldProps,
120 |           schema,
121 |           columnProps,
122 |         },
123 |       ]
124 |     } else if (schema.properties) {
125 |       return schema.reduceProperties((buf: any[], schema) => {
126 |         return buf.concat(parseSources(schema))
127 |       }, [])
128 |     } else {
129 |       return []
130 |     }
131 |   }
132 | 
133 |   const parseArrayTable = (schema: Schema['items']) => {
134 |     if (!schema) return []
135 |     const sources: ObservableColumnSource[] = []
136 |     const items = isArr(schema) ? schema : ([schema] as Schema[])
137 |     return items.reduce((columns, schema) => {
138 |       const item = parseSources(schema)
139 |       if (item) {
140 |         return columns.concat(item)
141 |       }
142 |       return columns
143 |     }, sources)
144 |   }
145 | 
146 |   if (!schemaRef.value) throw new Error('can not found schema object')
147 | 
148 |   return parseArrayTable(schemaRef.value.items)
149 | }
150 | 
151 | const getArrayTableColumns = (
152 |   sources: ObservableColumnSource[]
153 | ): ColumnProps[] => {
154 |   return sources.reduce(
155 |     (
156 |       buf: ColumnProps[],
157 |       { name, columnProps, schema, display, required },
158 |       key
159 |     ) => {
160 |       const { title, asterisk, ...props } = columnProps
161 |       if (display !== 'visible') return buf
162 |       if (!isColumnComponent(schema)) return buf
163 | 
164 |       const render = (startIndex?: Ref<number>) => {
165 |         return columnProps?.type && columnProps?.type !== 'default'
166 |           ? undefined
167 |           : (props: {
168 |               row: Record<string, any>
169 |               column: ElColumnProps
170 |               $index: number
171 |             }): VNode => {
172 |               let index = (startIndex?.value ?? 0) + props.$index
173 |               // const index = reactiveDataSource.value.indexOf(props.row)
174 | 
175 |               const children = h(
176 |                 ArrayBase.Item,
177 |                 { props: { index, record: props.row }, key: `${key}${index}` },
178 |                 {
179 |                   default: () =>
180 |                     h(
181 |                       RecursionField,
182 |                       {
183 |                         props: {
184 |                           schema,
185 |                           name: index,
186 |                           onlyRenderProperties: true,
187 |                         },
188 |                       },
189 |                       {}
190 |                     ),
191 |                 }
192 |               )
193 |               return children
194 |             }
195 |       }
196 | 
197 |       return buf.concat({
198 |         label: title,
199 |         ...props,
200 |         key,
201 |         prop: name,
202 |         asterisk: asterisk ?? required,
203 |         render,
204 |       })
205 |     },
206 |     []
207 |   )
208 | }
209 | 
210 | const renderAddition = () => {
211 |   const schema = useFieldSchema()
212 |   return schema.value.reduceProperties((addition, schema) => {
213 |     if (isAdditionComponent(schema)) {
214 |       return h(
215 |         RecursionField,
216 |         {
217 |           props: {
218 |             schema,
219 |             name: 'addition',
220 |           },
221 |         },
222 |         {}
223 |       )
224 |     }
225 |     return addition
226 |   }, null)
227 | }
228 | 
229 | const schedulerRequest = {
230 |   request: null,
231 | }
232 | 
233 | const StatusSelect = observer(
234 |   defineComponent({
235 |     props: {
236 |       value: Number,
237 |       onChange: Function,
238 |       options: Array,
239 |       pageSize: Number,
240 |     },
241 |     setup(props) {
242 |       const fieldRef = useField<ArrayField>()
243 |       const prefixCls = `${stylePrefix}-array-table`
244 | 
245 |       return () => {
246 |         const field = fieldRef.value
247 |         const width = String(props.options?.length).length * 15
248 |         const errors = field.errors
249 |         const parseIndex = (address: string) => {
250 |           return Number(
251 |             address
252 |               .slice(address.indexOf(field.address.toString()) + 1)
253 |               .match(/(\d+)/)?.[1]
254 |           )
255 |         }
256 | 
257 |         return h(
258 |           Select,
259 |           {
260 |             style: {
261 |               width: `${width < 60 ? 60 : width}px`,
262 |             },
263 |             class: [
264 |               `${prefixCls}-status-select`,
265 |               {
266 |                 'has-error': errors?.length,
267 |               },
268 |             ],
269 |             props: {
270 |               value: props.value,
271 |               popperClass: `${prefixCls}-status-select-dropdown`,
272 |             },
273 |             on: {
274 |               input: props.onChange,
275 |             },
276 |           },
277 |           {
278 |             default: () => {
279 |               return props.options?.map(({ label, value }) => {
280 |                 const hasError = errors.some(({ address }) => {
281 |                   const currentIndex = parseIndex(address)
282 |                   const startIndex = (value - 1) * props.pageSize
283 |                   const endIndex = value * props.pageSize
284 |                   return currentIndex >= startIndex && currentIndex <= endIndex
285 |                 })
286 | 
287 |                 return h(
288 |                   Option,
289 |                   {
290 |                     key: value,
291 |                     props: {
292 |                       label,
293 |                       value,
294 |                     },
295 |                   },
296 |                   {
297 |                     default: () => {
298 |                       if (hasError) {
299 |                         return h(
300 |                           Badge,
301 |                           {
302 |                             props: {
303 |                               isDot: true,
304 |                             },
305 |                           },
306 |                           { default: () => label }
307 |                         )
308 |                       }
309 | 
310 |                       return label
311 |                     },
312 |                   }
313 |                 )
314 |               })
315 |             },
316 |           }
317 |         )
318 |       }
319 |     },
320 |   }),
321 |   {
322 |     scheduler: (update) => {
323 |       clearTimeout(schedulerRequest.request)
324 |       schedulerRequest.request = setTimeout(() => {
325 |         update()
326 |       }, 100)
327 |     },
328 |   }
329 | )
330 | 
331 | const usePagination = () => {
332 |   return inject<Ref<PaginationAction>>(PaginationSymbol, ref({}))
333 | }
334 | 
335 | const ArrayTablePagination = defineComponent<IArrayTablePaginationProps>({
336 |   inheritAttrs: false,
337 |   props: ['pageSize', 'dataSource'],
338 |   setup(props, { attrs, slots }) {
339 |     const prefixCls = `${stylePrefix}-array-table`
340 |     const current = ref(1)
341 |     const pageSize = computed(() => props.pageSize || 10)
342 |     const dataSource = computed(() => props.dataSource || [])
343 |     const startIndex = computed(() => (current.value - 1) * pageSize.value)
344 |     const endIndex = computed(() => startIndex.value + pageSize.value - 1)
345 |     const total = computed(() => dataSource.value?.length || 0)
346 |     const totalPage = computed(() => Math.ceil(total.value / pageSize.value))
347 |     const pages = computed(() => {
348 |       return Array.from(new Array(totalPage.value)).map((_, index) => {
349 |         const page = index + 1
350 |         return {
351 |           label: page,
352 |           value: page,
353 |         }
354 |       })
355 |     })
356 | 
357 |     const renderPagination = function () {
358 |       if (totalPage.value <= 1) return
359 |       return h(
360 |         'div',
361 |         {
362 |           class: [`${prefixCls}-pagination`],
363 |         },
364 |         {
365 |           default: () =>
366 |             h(
367 |               Space,
368 |               {},
369 |               {
370 |                 default: () => [
371 |                   h(
372 |                     StatusSelect,
373 |                     {
374 |                       props: {
375 |                         value: current.value,
376 |                         onChange: (val: number) => {
377 |                           current.value = val
378 |                         },
379 |                         pageSize: pageSize.value,
380 |                         options: pages.value,
381 |                       },
382 |                     },
383 |                     {}
384 |                   ),
385 |                   h(
386 |                     Pagination,
387 |                     {
388 |                       props: {
389 |                         background: true,
390 |                         layout: 'prev, pager, next',
391 |                         ...attrs,
392 |                         pageSize: pageSize.value,
393 |                         pageCount: totalPage.value,
394 |                         currentPage: current.value,
395 |                       },
396 |                       on: {
397 |                         'current-change': (val: number) => {
398 |                           current.value = val
399 |                         },
400 |                       },
401 |                     },
402 |                     {}
403 |                   ),
404 |                 ],
405 |               }
406 |             ),
407 |         }
408 |       )
409 |     }
410 | 
411 |     const paginationContext = computed<PaginationAction>(() => {
412 |       return {
413 |         totalPage: totalPage.value,
414 |         pageSize: pageSize.value,
415 |         changePage: (page: number) => (current.value = page),
416 |       }
417 |     })
418 |     provide(PaginationSymbol, paginationContext)
419 | 
420 |     return () => {
421 |       return h(
422 |         Fragment,
423 |         {},
424 |         {
425 |           default: () =>
426 |             slots?.default?.(
427 |               dataSource.value?.slice(startIndex.value, endIndex.value + 1),
428 |               renderPagination,
429 |               startIndex
430 |             ),
431 |         }
432 |       )
433 |     }
434 |   },
435 | })
436 | 
437 | const ArrayTableInner = observer(
438 |   defineComponent<IArrayTableProps>({
439 |     name: 'FArrayTable',
440 |     inheritAttrs: false,
441 |     setup(props, { attrs, listeners, slots }) {
442 |       const fieldRef = useField<ArrayField>()
443 |       const schemaRef = useFieldSchema()
444 |       const prefixCls = `${stylePrefix}-array-table`
445 |       const { getKey, keyMap } = ArrayBase.useKey(schemaRef.value)
446 | 
447 |       const defaultRowKey = (record: any) => {
448 |         return getKey(record)
449 |       }
450 | 
451 |       return () => {
452 |         const props = attrs as unknown as IArrayTableProps
453 |         const field = fieldRef.value
454 |         const dataSource = Array.isArray(field.value) ? field.value.slice() : []
455 |         const pagination = props.pagination
456 |         const sources = getArrayTableSources(fieldRef, schemaRef)
457 |         const columns = getArrayTableColumns(sources)
458 | 
459 |         const renderColumns = (startIndex?: Ref<number>) => {
460 |           return columns.map(({ key, render, asterisk, ...props }) => {
461 |             const children = {} as Record<string, any>
462 |             if (render) {
463 |               children.default = render(startIndex)
464 |             }
465 |             if (asterisk) {
466 |               children.header = ({ column }: { column: ElColumnProps }) =>
467 |                 h(
468 |                   'span',
469 |                   {},
470 |                   {
471 |                     default: () => [
472 |                       h(
473 |                         'span',
474 |                         { class: `${prefixCls}-asterisk` },
475 |                         { default: () => ['*'] }
476 |                       ),
477 |                       column.label,
478 |                     ],
479 |                   }
480 |                 )
481 |             }
482 |             return h(
483 |               ElTableColumn,
484 |               {
485 |                 key,
486 |                 props,
487 |               },
488 |               children
489 |             )
490 |           })
491 |         }
492 | 
493 |         const renderStateManager = () =>
494 |           sources.map((column, key) => {
495 |             //专门用来承接对Column的状态管理
496 |             if (!isColumnComponent(column.schema)) return
497 |             return h(
498 |               RecursionField,
499 |               {
500 |                 props: {
501 |                   name: column.name,
502 |                   schema: column.schema,
503 |                   onlyRenderSelf: true,
504 |                 },
505 |                 key,
506 |               },
507 |               {}
508 |             )
509 |           })
510 | 
511 |         const renderTable = (
512 |           dataSource?: any[],
513 |           pager?: () => VNode,
514 |           startIndex?: Ref<number>
515 |         ) => {
516 |           return h(
517 |             'div',
518 |             { class: prefixCls },
519 |             {
520 |               default: () =>
521 |                 h(
522 |                   ArrayBase,
523 |                   {
524 |                     props: {
525 |                       keyMap,
526 |                     },
527 |                   },
528 |                   {
529 |                     default: () => [
530 |                       h(
531 |                         ElTable,
532 |                         {
533 |                           props: {
534 |                             rowKey: defaultRowKey,
535 |                             ...attrs,
536 |                             data: dataSource,
537 |                           },
538 |                           on: listeners,
539 |                         },
540 |                         {
541 |                           ...slots,
542 |                           default: () => renderColumns(startIndex),
543 |                         }
544 |                       ),
545 |                       pager?.(),
546 |                       renderStateManager(),
547 |                       renderAddition(),
548 |                     ],
549 |                   }
550 |                 ),
551 |             }
552 |           )
553 |         }
554 | 
555 |         if (!pagination) {
556 |           return renderTable(dataSource, null)
557 |         }
558 |         return h(
559 |           ArrayTablePagination,
560 |           {
561 |             attrs: {
562 |               ...(isBool(pagination) ? {} : pagination),
563 |               dataSource,
564 |             },
565 |           },
566 |           { default: renderTable }
567 |         )
568 |       }
569 |     },
570 |   })
571 | )
572 | 
573 | const ArrayTableColumn: Component = {
574 |   name: 'FArrayTableColumn',
575 |   render(h) {
576 |     return h()
577 |   },
578 | }
579 | 
580 | const ArrayAddition = defineComponent({
581 |   name: 'ArrayAddition',
582 |   setup(props, { attrs, listeners, slots }) {
583 |     const array = ArrayBase.useArray()
584 |     const paginationRef = usePagination()
585 | 
586 |     const onClick = listeners['click']
587 |     listeners['click'] = (e) => {
588 |       const { totalPage = 0, pageSize = 10, changePage } = paginationRef.value
589 |       // 如果添加数据后超过当前页,则自动切换到下一页
590 |       const total = array?.field?.value?.value.length || 0
591 |       if (total === (totalPage - 1) * pageSize + 1 && isFn(changePage)) {
592 |         changePage(totalPage)
593 |       }
594 |       if (onClick) onClick(e)
595 |     }
596 |     return () => {
597 |       return h(
598 |         ArrayBase.Addition,
599 |         {
600 |           props,
601 |           attrs,
602 |           on: listeners,
603 |         },
604 |         slots
605 |       )
606 |     }
607 |   },
608 | })
609 | 
610 | export const ArrayTable = composeExport(ArrayTableInner, {
611 |   Column: ArrayTableColumn,
612 |   Index: ArrayBase.Index,
613 |   SortHandle: ArrayBase.SortHandle,
614 |   Addition: ArrayAddition,
615 |   Remove: ArrayBase.Remove,
616 |   MoveDown: ArrayBase.MoveDown,
617 |   MoveUp: ArrayBase.MoveUp,
618 |   useArray: ArrayBase.useArray,
619 |   useIndex: ArrayBase.useIndex,
620 |   useRecord: ArrayBase.useRecord,
621 | })
622 | 
623 | export default ArrayTable
624 | 
```

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

```markdown
  1 | # TreeSelect
  2 | 
  3 | > 树选择器
  4 | 
  5 | ## Markup Schema 同步数据源案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { TreeSelect, FormItem, FormButtonGroup, Submit } from '@formily/antd'
 10 | import { createForm } from '@formily/core'
 11 | import { FormProvider, createSchemaField } from '@formily/react'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     TreeSelect,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.Number
 26 |         name="select"
 27 |         title="选择框"
 28 |         x-decorator="FormItem"
 29 |         x-component="TreeSelect"
 30 |         enum={[
 31 |           {
 32 |             label: '选项1',
 33 |             value: 1,
 34 |             children: [
 35 |               {
 36 |                 title: 'Child Node1',
 37 |                 value: '0-0-0',
 38 |                 key: '0-0-0',
 39 |               },
 40 |               {
 41 |                 title: 'Child Node2',
 42 |                 value: '0-0-1',
 43 |                 key: '0-0-1',
 44 |               },
 45 |               {
 46 |                 title: 'Child Node3',
 47 |                 value: '0-0-2',
 48 |                 key: '0-0-2',
 49 |               },
 50 |             ],
 51 |           },
 52 |           {
 53 |             label: '选项2',
 54 |             value: 2,
 55 |             children: [
 56 |               {
 57 |                 title: 'Child Node3',
 58 |                 value: '0-1-0',
 59 |                 key: '0-1-0',
 60 |               },
 61 |               {
 62 |                 title: 'Child Node4',
 63 |                 value: '0-1-1',
 64 |                 key: '0-1-1',
 65 |               },
 66 |               {
 67 |                 title: 'Child Node5',
 68 |                 value: '0-1-2',
 69 |                 key: '0-1-2',
 70 |               },
 71 |             ],
 72 |           },
 73 |         ]}
 74 |         x-component-props={{
 75 |           style: {
 76 |             width: 200,
 77 |           },
 78 |         }}
 79 |       />
 80 |     </SchemaField>
 81 |     <FormButtonGroup>
 82 |       <Submit onSubmit={console.log}>提交</Submit>
 83 |     </FormButtonGroup>
 84 |   </FormProvider>
 85 | )
 86 | ```
 87 | 
 88 | ## Markup Schema 异步联动数据源案例
 89 | 
 90 | ```tsx
 91 | import React from 'react'
 92 | import {
 93 |   TreeSelect,
 94 |   Select,
 95 |   FormItem,
 96 |   FormButtonGroup,
 97 |   Submit,
 98 | } from '@formily/antd'
 99 | import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'
100 | import { FormProvider, createSchemaField } from '@formily/react'
101 | import { action } from '@formily/reactive'
102 | 
103 | const SchemaField = createSchemaField({
104 |   components: {
105 |     Select,
106 |     TreeSelect,
107 |     FormItem,
108 |   },
109 | })
110 | 
111 | const useAsyncDataSource = (
112 |   pattern: FormPathPattern,
113 |   service: (field: Field) => Promise<{ label: string; value: any }[]>
114 | ) => {
115 |   onFieldReact(pattern, (field) => {
116 |     field.loading = true
117 |     service(field).then(
118 |       action.bound((data) => {
119 |         field.dataSource = data
120 |         field.loading = false
121 |       })
122 |     )
123 |   })
124 | }
125 | 
126 | const form = createForm({
127 |   effects: () => {
128 |     useAsyncDataSource('select', async (field) => {
129 |       const linkage = field.query('linkage').get('value')
130 |       if (!linkage) return []
131 |       return new Promise((resolve) => {
132 |         setTimeout(() => {
133 |           if (linkage === 1) {
134 |             resolve([
135 |               {
136 |                 label: 'AAA',
137 |                 value: 'aaa',
138 |                 children: [
139 |                   {
140 |                     title: 'Child Node1',
141 |                     value: '0-0-0',
142 |                     key: '0-0-0',
143 |                   },
144 |                   {
145 |                     title: 'Child Node2',
146 |                     value: '0-0-1',
147 |                     key: '0-0-1',
148 |                   },
149 |                   {
150 |                     title: 'Child Node3',
151 |                     value: '0-0-2',
152 |                     key: '0-0-2',
153 |                   },
154 |                 ],
155 |               },
156 |               {
157 |                 label: 'BBB',
158 |                 value: 'ccc',
159 |                 children: [
160 |                   {
161 |                     title: 'Child Node1',
162 |                     value: '0-1-0',
163 |                     key: '0-1-0',
164 |                   },
165 |                   {
166 |                     title: 'Child Node2',
167 |                     value: '0-1-1',
168 |                     key: '0-1-1',
169 |                   },
170 |                   {
171 |                     title: 'Child Node3',
172 |                     value: '0-1-2',
173 |                     key: '0-1-2',
174 |                   },
175 |                 ],
176 |               },
177 |             ])
178 |           } else if (linkage === 2) {
179 |             resolve([
180 |               {
181 |                 label: 'CCC',
182 |                 value: 'ccc',
183 |                 children: [
184 |                   {
185 |                     title: 'Child Node1',
186 |                     value: '0-0-0',
187 |                     key: '0-0-0',
188 |                   },
189 |                   {
190 |                     title: 'Child Node2',
191 |                     value: '0-0-1',
192 |                     key: '0-0-1',
193 |                   },
194 |                   {
195 |                     title: 'Child Node3',
196 |                     value: '0-0-2',
197 |                     key: '0-0-2',
198 |                   },
199 |                 ],
200 |               },
201 |               {
202 |                 label: 'DDD',
203 |                 value: 'ddd',
204 |                 children: [
205 |                   {
206 |                     title: 'Child Node1',
207 |                     value: '0-1-0',
208 |                     key: '0-1-0',
209 |                   },
210 |                   {
211 |                     title: 'Child Node2',
212 |                     value: '0-1-1',
213 |                     key: '0-1-1',
214 |                   },
215 |                   {
216 |                     title: 'Child Node3',
217 |                     value: '0-1-2',
218 |                     key: '0-1-2',
219 |                   },
220 |                 ],
221 |               },
222 |             ])
223 |           }
224 |         }, 1500)
225 |       })
226 |     })
227 |   },
228 | })
229 | 
230 | export default () => (
231 |   <FormProvider form={form}>
232 |     <SchemaField>
233 |       <SchemaField.Number
234 |         name="linkage"
235 |         title="联动选择框"
236 |         x-decorator="FormItem"
237 |         x-component="Select"
238 |         enum={[
239 |           { label: '发请求1', value: 1 },
240 |           { label: '发请求2', value: 2 },
241 |         ]}
242 |         x-component-props={{
243 |           style: {
244 |             width: 200,
245 |           },
246 |         }}
247 |       />
248 |       <SchemaField.String
249 |         name="select"
250 |         title="异步选择框"
251 |         x-decorator="FormItem"
252 |         x-component="TreeSelect"
253 |         x-component-props={{
254 |           style: {
255 |             width: 200,
256 |           },
257 |         }}
258 |       />
259 |     </SchemaField>
260 |     <FormButtonGroup>
261 |       <Submit onSubmit={console.log}>提交</Submit>
262 |     </FormButtonGroup>
263 |   </FormProvider>
264 | )
265 | ```
266 | 
267 | ## JSON Schema 同步数据源案例
268 | 
269 | ```tsx
270 | import React from 'react'
271 | import { TreeSelect, FormItem, FormButtonGroup, Submit } from '@formily/antd'
272 | import { createForm } from '@formily/core'
273 | import { FormProvider, createSchemaField } from '@formily/react'
274 | 
275 | const SchemaField = createSchemaField({
276 |   components: {
277 |     TreeSelect,
278 |     FormItem,
279 |   },
280 | })
281 | 
282 | const form = createForm()
283 | 
284 | const schema = {
285 |   type: 'object',
286 |   properties: {
287 |     select: {
288 |       type: 'string',
289 |       title: '选择框',
290 |       'x-decorator': 'FormItem',
291 |       'x-component': 'TreeSelect',
292 |       enum: [
293 |         {
294 |           label: '选项1',
295 |           value: 1,
296 |           children: [
297 |             {
298 |               title: 'Child Node1',
299 |               value: '0-0-0',
300 |               key: '0-0-0',
301 |             },
302 |             {
303 |               title: 'Child Node2',
304 |               value: '0-0-1',
305 |               key: '0-0-1',
306 |             },
307 |             {
308 |               title: 'Child Node3',
309 |               value: '0-0-2',
310 |               key: '0-0-2',
311 |             },
312 |           ],
313 |         },
314 |         {
315 |           label: '选项2',
316 |           value: 2,
317 |           children: [
318 |             {
319 |               title: 'Child Node1',
320 |               value: '0-1-0',
321 |               key: '0-1-0',
322 |             },
323 |             {
324 |               title: 'Child Node2',
325 |               value: '0-1-1',
326 |               key: '0-1-1',
327 |             },
328 |             {
329 |               title: 'Child Node3',
330 |               value: '0-1-2',
331 |               key: '0-1-2',
332 |             },
333 |           ],
334 |         },
335 |       ],
336 |       'x-component-props': {
337 |         style: {
338 |           width: 200,
339 |         },
340 |       },
341 |     },
342 |   },
343 | }
344 | 
345 | export default () => (
346 |   <FormProvider form={form}>
347 |     <SchemaField schema={schema} />
348 |     <FormButtonGroup>
349 |       <Submit onSubmit={console.log}>提交</Submit>
350 |     </FormButtonGroup>
351 |   </FormProvider>
352 | )
353 | ```
354 | 
355 | ## JSON Schema 异步联动数据源案例
356 | 
357 | ```tsx
358 | import React from 'react'
359 | import {
360 |   TreeSelect,
361 |   Select,
362 |   FormItem,
363 |   FormButtonGroup,
364 |   Submit,
365 | } from '@formily/antd'
366 | import { createForm } from '@formily/core'
367 | import { FormProvider, createSchemaField } from '@formily/react'
368 | import { action } from '@formily/reactive'
369 | 
370 | const SchemaField = createSchemaField({
371 |   components: {
372 |     Select,
373 |     TreeSelect,
374 |     FormItem,
375 |   },
376 | })
377 | 
378 | const loadData = async (field) => {
379 |   const linkage = field.query('linkage').get('value')
380 |   if (!linkage) return []
381 |   return new Promise((resolve) => {
382 |     setTimeout(() => {
383 |       if (linkage === 1) {
384 |         resolve([
385 |           {
386 |             label: 'AAA',
387 |             value: 'aaa',
388 |             children: [
389 |               {
390 |                 title: 'Child Node1',
391 |                 value: '0-0-0',
392 |                 key: '0-0-0',
393 |               },
394 |               {
395 |                 title: 'Child Node2',
396 |                 value: '0-0-1',
397 |                 key: '0-0-1',
398 |               },
399 |               {
400 |                 title: 'Child Node3',
401 |                 value: '0-0-2',
402 |                 key: '0-0-2',
403 |               },
404 |             ],
405 |           },
406 |           {
407 |             label: 'BBB',
408 |             value: 'ccc',
409 |             children: [
410 |               {
411 |                 title: 'Child Node1',
412 |                 value: '0-1-0',
413 |                 key: '0-1-0',
414 |               },
415 |               {
416 |                 title: 'Child Node2',
417 |                 value: '0-1-1',
418 |                 key: '0-1-1',
419 |               },
420 |               {
421 |                 title: 'Child Node3',
422 |                 value: '0-1-2',
423 |                 key: '0-1-2',
424 |               },
425 |             ],
426 |           },
427 |         ])
428 |       } else if (linkage === 2) {
429 |         resolve([
430 |           {
431 |             label: 'CCC',
432 |             value: 'ccc',
433 |             children: [
434 |               {
435 |                 title: 'Child Node1',
436 |                 value: '0-0-0',
437 |                 key: '0-0-0',
438 |               },
439 |               {
440 |                 title: 'Child Node2',
441 |                 value: '0-0-1',
442 |                 key: '0-0-1',
443 |               },
444 |               {
445 |                 title: 'Child Node3',
446 |                 value: '0-0-2',
447 |                 key: '0-0-2',
448 |               },
449 |             ],
450 |           },
451 |           {
452 |             label: 'DDD',
453 |             value: 'ddd',
454 |             children: [
455 |               {
456 |                 title: 'Child Node1',
457 |                 value: '0-1-0',
458 |                 key: '0-1-0',
459 |               },
460 |               {
461 |                 title: 'Child Node2',
462 |                 value: '0-1-1',
463 |                 key: '0-1-1',
464 |               },
465 |               {
466 |                 title: 'Child Node3',
467 |                 value: '0-1-2',
468 |                 key: '0-1-2',
469 |               },
470 |             ],
471 |           },
472 |         ])
473 |       }
474 |     }, 1500)
475 |   })
476 | }
477 | 
478 | const useAsyncDataSource = (service) => (field) => {
479 |   field.loading = true
480 |   service(field).then(
481 |     action.bound((data) => {
482 |       field.dataSource = data
483 |       field.loading = false
484 |     })
485 |   )
486 | }
487 | 
488 | const form = createForm()
489 | 
490 | const schema = {
491 |   type: 'object',
492 |   properties: {
493 |     linkage: {
494 |       type: 'string',
495 |       title: '联动选择框',
496 |       enum: [
497 |         { label: '发请求1', value: 1 },
498 |         { label: '发请求2', value: 2 },
499 |       ],
500 |       'x-decorator': 'FormItem',
501 |       'x-component': 'Select',
502 |       'x-component-props': {
503 |         style: {
504 |           width: 200,
505 |         },
506 |       },
507 |     },
508 |     select: {
509 |       type: 'string',
510 |       title: '异步选择框',
511 |       'x-decorator': 'FormItem',
512 |       'x-component': 'TreeSelect',
513 |       'x-component-props': {
514 |         style: {
515 |           width: 200,
516 |         },
517 |       },
518 |       'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
519 |     },
520 |   },
521 | }
522 | 
523 | export default () => (
524 |   <FormProvider form={form}>
525 |     <SchemaField schema={schema} scope={{ useAsyncDataSource, loadData }} />
526 |     <FormButtonGroup>
527 |       <Submit onSubmit={console.log}>提交</Submit>
528 |     </FormButtonGroup>
529 |   </FormProvider>
530 | )
531 | ```
532 | 
533 | ## 纯 JSX 同步数据源案例
534 | 
535 | ```tsx
536 | import React from 'react'
537 | import { TreeSelect, FormItem, FormButtonGroup, Submit } from '@formily/antd'
538 | import { createForm } from '@formily/core'
539 | import { FormProvider, Field } from '@formily/react'
540 | 
541 | const form = createForm()
542 | 
543 | export default () => (
544 |   <FormProvider form={form}>
545 |     <Field
546 |       name="select"
547 |       title="选择框"
548 |       dataSource={[
549 |         {
550 |           label: '选项1',
551 |           value: 1,
552 |           children: [
553 |             {
554 |               title: 'Child Node1',
555 |               value: '0-0-0',
556 |               key: '0-0-0',
557 |             },
558 |             {
559 |               title: 'Child Node2',
560 |               value: '0-0-1',
561 |               key: '0-0-1',
562 |             },
563 |             {
564 |               title: 'Child Node3',
565 |               value: '0-0-2',
566 |               key: '0-0-2',
567 |             },
568 |           ],
569 |         },
570 |         {
571 |           label: '选项2',
572 |           value: 2,
573 |           children: [
574 |             {
575 |               title: 'Child Node3',
576 |               value: '0-1-0',
577 |               key: '0-1-0',
578 |             },
579 |             {
580 |               title: 'Child Node4',
581 |               value: '0-1-1',
582 |               key: '0-1-1',
583 |             },
584 |             {
585 |               title: 'Child Node5',
586 |               value: '0-1-2',
587 |               key: '0-1-2',
588 |             },
589 |           ],
590 |         },
591 |       ]}
592 |       decorator={[FormItem]}
593 |       component={[TreeSelect]}
594 |     />
595 |     <FormButtonGroup>
596 |       <Submit onSubmit={console.log}>提交</Submit>
597 |     </FormButtonGroup>
598 |   </FormProvider>
599 | )
600 | ```
601 | 
602 | ## 纯 JSX 异步联动数据源案例
603 | 
604 | ```tsx
605 | import React from 'react'
606 | import {
607 |   TreeSelect,
608 |   Select,
609 |   FormItem,
610 |   FormButtonGroup,
611 |   Submit,
612 | } from '@formily/antd'
613 | import {
614 |   createForm,
615 |   onFieldReact,
616 |   FormPathPattern,
617 |   Field as FieldType,
618 | } from '@formily/core'
619 | import { FormProvider, Field } from '@formily/react'
620 | import { action } from '@formily/reactive'
621 | 
622 | const useAsyncDataSource = (
623 |   pattern: FormPathPattern,
624 |   service: (field: FieldType) => Promise<{ label: string; value: any }[]>
625 | ) => {
626 |   onFieldReact(pattern, (field) => {
627 |     field.loading = true
628 |     service(field).then(
629 |       action.bound((data) => {
630 |         field.dataSource = data
631 |         field.loading = false
632 |       })
633 |     )
634 |   })
635 | }
636 | 
637 | const form = createForm({
638 |   effects: () => {
639 |     useAsyncDataSource('select', async (field) => {
640 |       const linkage = field.query('linkage').get('value')
641 |       if (!linkage) return []
642 |       return new Promise((resolve) => {
643 |         setTimeout(() => {
644 |           if (linkage === 1) {
645 |             resolve([
646 |               {
647 |                 label: 'AAA',
648 |                 value: 'aaa',
649 |                 children: [
650 |                   {
651 |                     title: 'Child Node1',
652 |                     value: '0-0-0',
653 |                     key: '0-0-0',
654 |                   },
655 |                   {
656 |                     title: 'Child Node2',
657 |                     value: '0-0-1',
658 |                     key: '0-0-1',
659 |                   },
660 |                   {
661 |                     title: 'Child Node3',
662 |                     value: '0-0-2',
663 |                     key: '0-0-2',
664 |                   },
665 |                 ],
666 |               },
667 |               {
668 |                 label: 'BBB',
669 |                 value: 'ccc',
670 |                 children: [
671 |                   {
672 |                     title: 'Child Node1',
673 |                     value: '0-1-0',
674 |                     key: '0-1-0',
675 |                   },
676 |                   {
677 |                     title: 'Child Node2',
678 |                     value: '0-1-1',
679 |                     key: '0-1-1',
680 |                   },
681 |                   {
682 |                     title: 'Child Node3',
683 |                     value: '0-1-2',
684 |                     key: '0-1-2',
685 |                   },
686 |                 ],
687 |               },
688 |             ])
689 |           } else if (linkage === 2) {
690 |             resolve([
691 |               {
692 |                 label: 'CCC',
693 |                 value: 'ccc',
694 |                 children: [
695 |                   {
696 |                     title: 'Child Node1',
697 |                     value: '0-0-0',
698 |                     key: '0-0-0',
699 |                   },
700 |                   {
701 |                     title: 'Child Node2',
702 |                     value: '0-0-1',
703 |                     key: '0-0-1',
704 |                   },
705 |                   {
706 |                     title: 'Child Node3',
707 |                     value: '0-0-2',
708 |                     key: '0-0-2',
709 |                   },
710 |                 ],
711 |               },
712 |               {
713 |                 label: 'DDD',
714 |                 value: 'ddd',
715 |                 children: [
716 |                   {
717 |                     title: 'Child Node1',
718 |                     value: '0-1-0',
719 |                     key: '0-1-0',
720 |                   },
721 |                   {
722 |                     title: 'Child Node2',
723 |                     value: '0-1-1',
724 |                     key: '0-1-1',
725 |                   },
726 |                   {
727 |                     title: 'Child Node3',
728 |                     value: '0-1-2',
729 |                     key: '0-1-2',
730 |                   },
731 |                 ],
732 |               },
733 |             ])
734 |           }
735 |         }, 1500)
736 |       })
737 |     })
738 |   },
739 | })
740 | 
741 | export default () => (
742 |   <FormProvider form={form}>
743 |     <Field
744 |       name="linkage"
745 |       title="联动选择框"
746 |       dataSource={[
747 |         { label: '发请求1', value: 1 },
748 |         { label: '发请求2', value: 2 },
749 |       ]}
750 |       decorator={[FormItem]}
751 |       component={[
752 |         Select,
753 |         {
754 |           style: {
755 |             width: 200,
756 |           },
757 |         },
758 |       ]}
759 |     />
760 |     <Field
761 |       name="select"
762 |       title="异步选择框"
763 |       decorator={[FormItem]}
764 |       component={[
765 |         TreeSelect,
766 |         {
767 |           style: {
768 |             width: 200,
769 |           },
770 |         },
771 |       ]}
772 |     />
773 |     <FormButtonGroup>
774 |       <Submit onSubmit={console.log}>提交</Submit>
775 |     </FormButtonGroup>
776 |   </FormProvider>
777 | )
778 | ```
779 | 
780 | ## API
781 | 
782 | 参考 https://ant.design/components/tree-select-cn/
783 | 
```
Page 33/52FirstPrevNextLast