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

# Directory Structure

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

# Files

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

```markdown
# TreeSelect

> 树选择器

## Markup Schema 同步数据源案例

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Number
        name="select"
        title="选择框"
        x-decorator="FormItem"
        x-component="TreeSelect"
        enum={[
          {
            label: '选项1',
            value: 1,
            children: [
              {
                title: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                title: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                title: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: '选项2',
            value: 2,
            children: [
              {
                title: 'Child Node3',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                title: 'Child Node4',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                title: 'Child Node5',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ]}
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Markup Schema 异步联动数据源案例

```tsx
import React from 'react'
import {
  TreeSelect,
  Select,
  FormItem,
  FormButtonGroup,
  Submit,
} from '@formily/antd'
import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { action } from '@formily/reactive'

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

const useAsyncDataSource = (
  pattern: FormPathPattern,
  service: (field: Field) => Promise<{ label: string; value: any }[]>
) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}

const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'BBB',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'DDD',
                value: 'ddd',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          }
        }, 1500)
      })
    })
  },
})

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Number
        name="linkage"
        title="联动选择框"
        x-decorator="FormItem"
        x-component="Select"
        enum={[
          { label: '发请求1', value: 1 },
          { label: '发请求2', value: 2 },
        ]}
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
      <SchemaField.String
        name="select"
        title="异步选择框"
        x-decorator="FormItem"
        x-component="TreeSelect"
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 同步数据源案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    select: {
      type: 'string',
      title: '选择框',
      'x-decorator': 'FormItem',
      'x-component': 'TreeSelect',
      enum: [
        {
          label: '选项1',
          value: 1,
          children: [
            {
              title: 'Child Node1',
              value: '0-0-0',
              key: '0-0-0',
            },
            {
              title: 'Child Node2',
              value: '0-0-1',
              key: '0-0-1',
            },
            {
              title: 'Child Node3',
              value: '0-0-2',
              key: '0-0-2',
            },
          ],
        },
        {
          label: '选项2',
          value: 2,
          children: [
            {
              title: 'Child Node1',
              value: '0-1-0',
              key: '0-1-0',
            },
            {
              title: 'Child Node2',
              value: '0-1-1',
              key: '0-1-1',
            },
            {
              title: 'Child Node3',
              value: '0-1-2',
              key: '0-1-2',
            },
          ],
        },
      ],
      'x-component-props': {
        style: {
          width: 200,
        },
      },
    },
  },
}

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

## JSON Schema 异步联动数据源案例

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

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

const loadData = async (field) => {
  const linkage = field.query('linkage').get('value')
  if (!linkage) return []
  return new Promise((resolve) => {
    setTimeout(() => {
      if (linkage === 1) {
        resolve([
          {
            label: 'AAA',
            value: 'aaa',
            children: [
              {
                title: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                title: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                title: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'BBB',
            value: 'ccc',
            children: [
              {
                title: 'Child Node1',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                title: 'Child Node2',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                title: 'Child Node3',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ])
      } else if (linkage === 2) {
        resolve([
          {
            label: 'CCC',
            value: 'ccc',
            children: [
              {
                title: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                title: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                title: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'DDD',
            value: 'ddd',
            children: [
              {
                title: 'Child Node1',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                title: 'Child Node2',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                title: 'Child Node3',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ])
      }
    }, 1500)
  })
}

const useAsyncDataSource = (service) => (field) => {
  field.loading = true
  service(field).then(
    action.bound((data) => {
      field.dataSource = data
      field.loading = false
    })
  )
}

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    linkage: {
      type: 'string',
      title: '联动选择框',
      enum: [
        { label: '发请求1', value: 1 },
        { label: '发请求2', value: 2 },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Select',
      'x-component-props': {
        style: {
          width: 200,
        },
      },
    },
    select: {
      type: 'string',
      title: '异步选择框',
      'x-decorator': 'FormItem',
      'x-component': 'TreeSelect',
      'x-component-props': {
        style: {
          width: 200,
        },
      },
      'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
    },
  },
}

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

## 纯 JSX 同步数据源案例

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="select"
      title="选择框"
      dataSource={[
        {
          label: '选项1',
          value: 1,
          children: [
            {
              title: 'Child Node1',
              value: '0-0-0',
              key: '0-0-0',
            },
            {
              title: 'Child Node2',
              value: '0-0-1',
              key: '0-0-1',
            },
            {
              title: 'Child Node3',
              value: '0-0-2',
              key: '0-0-2',
            },
          ],
        },
        {
          label: '选项2',
          value: 2,
          children: [
            {
              title: 'Child Node3',
              value: '0-1-0',
              key: '0-1-0',
            },
            {
              title: 'Child Node4',
              value: '0-1-1',
              key: '0-1-1',
            },
            {
              title: 'Child Node5',
              value: '0-1-2',
              key: '0-1-2',
            },
          ],
        },
      ]}
      decorator={[FormItem]}
      component={[TreeSelect]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 异步联动数据源案例

```tsx
import React from 'react'
import {
  TreeSelect,
  Select,
  FormItem,
  FormButtonGroup,
  Submit,
} from '@formily/antd'
import {
  createForm,
  onFieldReact,
  FormPathPattern,
  Field as FieldType,
} from '@formily/core'
import { FormProvider, Field } from '@formily/react'
import { action } from '@formily/reactive'

const useAsyncDataSource = (
  pattern: FormPathPattern,
  service: (field: FieldType) => Promise<{ label: string; value: any }[]>
) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}

const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'BBB',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'DDD',
                value: 'ddd',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          }
        }, 1500)
      })
    })
  },
})

export default () => (
  <FormProvider form={form}>
    <Field
      name="linkage"
      title="联动选择框"
      dataSource={[
        { label: '发请求1', value: 1 },
        { label: '发请求2', value: 2 },
      ]}
      decorator={[FormItem]}
      component={[
        Select,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <Field
      name="select"
      title="异步选择框"
      decorator={[FormItem]}
      component={[
        TreeSelect,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://ant.design/components/tree-select-cn/

```

--------------------------------------------------------------------------------
/packages/path/src/__tests__/parser.spec.ts:
--------------------------------------------------------------------------------

```typescript
import expect from 'expect'
import { Parser } from '../parser'
import { Path } from '../'
const parse = (string: string, json: any, index: number) => {
  test('test ' + string + ` : ${index}`, () => {
    const parser = new Parser(string)
    expect(parser.parse()).toEqual(json)
  })
}

const batchTest = (obj) => {
  let i = 0
  for (let key in obj) {
    i++
    parse(key, obj[key], i)
  }
}

test('relative', () => {
  const parser = new Parser('..[ + 1 ].dd.bb', new Path(['aa', '1', 'cc']))
  const parser2 = new Parser('.ee', new Path(['aa', '1', 'cc']))
  const parser3 = new Parser('.', new Path(['aa', '1', 'cc']))
  const parser4 = new Parser('..', new Path(['aa', '1', 'cc']))
  const parser5 = new Parser('.[].dd', new Path(['aa', '1']))
  const parser6 = new Parser('.[].[]', new Path(['aa', '1']))
  const parser7 = new Parser('.[].[aa]', new Path(['aa', '1']))
  parser2.parse()
  parser3.parse()
  parser4.parse()
  parser5.parse()
  parser6.parse()
  parser7.parse()
  expect(parser.parse()).toEqual({
    type: 'Identifier',
    value: 'aa',
    after: {
      type: 'DotOperator',
      after: {
        type: 'DestructorExpression',
        value: {
          type: 'ArrayPattern',
          elements: [
            {
              type: 'Identifier',
              value: '+',
              after: {
                type: 'Identifier',
                value: '1',
              },
            },
          ],
        },
        source: '2',
        after: {
          type: 'DotOperator',
          after: {
            type: 'Identifier',
            value: 'dd',
            after: {
              type: 'DotOperator',
              after: {
                type: 'Identifier',
                value: 'bb',
              },
            },
          },
        },
      },
    },
  })
  expect(parser.data.segments).toEqual(['aa', '2', 'dd', 'bb'])
  expect(parser2.data.segments).toEqual(['aa', '1', 'ee'])
  expect(parser3.data.segments).toEqual(['aa', '1'])
  expect(parser4.data.segments).toEqual(['aa'])
  expect(parser5.data.segments).toEqual(['aa', '1', 'dd'])
  expect(parser6.data.segments).toEqual(['aa', '1', '[]'])
  expect(parser7.data.segments).toEqual(['aa', '1', '[aa]'])
})

test('calculate', () => {
  const parser0 = new Parser('..[+].dd.bb', new Path(['aa', '1', 'cc']))
  parser0.parse()
  expect(parser0.data.segments).toEqual(['aa', '2', 'dd', 'bb'])

  const parser = new Parser('..[ -1 ].dd.bb', new Path(['aa', '1', 'cc']))
  parser.parse()
  expect(parser.data.segments).toEqual(['aa', '0', 'dd', 'bb'])

  // TODO support
  // const parser2 = new Parser('..[ *2 ].dd.bb', new Path(['aa', '2', 'cc']))
  // parser2.parse()
  // expect(parser2.data.segments).toEqual(['aa', '4', 'dd', 'bb'])

  const parser3 = new Parser('..[ /2 ].dd.bb', new Path(['aa', '2', 'cc']))
  parser3.parse()
  expect(parser3.data.segments).toEqual(['aa', '1', 'dd', 'bb'])

  const parser4 = new Parser('..[ +1 ].dd.bb', new Path(['aa', 'a', 'cc']))
  parser4.parse()
  expect(parser4.data.segments).toEqual(['aa', 'a1', 'dd', 'bb'])

  const parser5 = new Parser('..[ -1 ].dd.bb', new Path(['aa', 'a', 'cc']))
  parser5.parse()
  expect(parser5.data.segments).toEqual(['aa', 'NaN', 'dd', 'bb'])

  // TODO support
  // const parser6 = new Parser('..[ *1 ].dd.bb', new Path(['aa', 'a', 'cc']))
  // parser6.parse()
  // expect(parser6.data.segments).toEqual(['aa', 'NaN', 'dd', 'bb'])

  const parser7 = new Parser('..[ /1 ].dd.bb', new Path(['aa', 'a', 'cc']))
  parser7.parse()
  expect(parser7.data.segments).toEqual(['aa', 'NaN', 'dd', 'bb'])

  const parser8 = new Parser('..[1].dd.bb', new Path(['aa', '1', 'cc']))
  parser8.parse()
  expect(parser8.data.segments).toEqual(['aa', '2', 'dd', 'bb'])
  const parser9 = new Parser('')
  parser9.next()
  expect(parser9.parseObjectProperties()).toEqual([])
})

test('parser unexpected', () => {
  const parser = new Parser('array[]')
  expect(() => parser.parse()).toThrowError()

  const parser2 = new Parser('array[0.')
  expect(() => parser2.parse()).toThrowError()

  const parser3 = new Parser('.[+]', new Path('*.1.cc'))
  expect(() => parser3.parse()).toThrowError()

  const parser4 = new Parser('[:,4]')
  expect(() => parser4.parse()).toThrowError()
})

test('tokenizer', () => {
  const originFromCharCode = String.fromCharCode
  String.fromCharCode = null

  const parser = new Parser('aa.bb')
  parser.parse()
  expect(parser.data.segments).toEqual(['aa', 'bb'])

  const parser2 = new Parser('array.0.[aa,bb]')
  parser2.parse()
  expect(parser2.data.segments).toEqual(['array', '0', '[aa,bb]'])

  String.fromCharCode = originFromCharCode

  const char13 = String.fromCharCode(13)
  const parser3 = new Parser(`${char13} aa.bb`)
  parser3.parse()

  const char11 = String.fromCharCode(11)
  const parser4 = new Parser(`${char11} aa.bb`)
  parser4.parse()

  const parser5 = new Parser('')
  parser5.next()
  parser5.parse()
  expect(parser5.data.segments).toEqual([])

  const char10 = String.fromCharCode(10)
  const parser6 = new Parser(`{
                c${char13}${char10}: kk,
                d : mm
          }`)
  parser6.parse()
  expect(parser6.data.segments).toEqual(['{c:kk,d:mm}'])

  const parser7 = new Parser(`{
                c${char13}${char11}: kk,
                d : mm
          }`)
  parser7.parse()
  expect(parser7.data.segments).toEqual(['{c:kk,d:mm}'])

  const parser8 = new Parser(`\\name`)
  parser8.state.pos++
  parser8.parse()
  expect(parser8.data.segments).toEqual(['name'])

  const parser9 = new Parser(`[a,{b}]`)
  parser9.parse()
  expect(parser9.data.segments).toEqual(['[a,{b}]'])

  const parser10 = new Parser(`*(a.b.c.*(aa,bb))`)
  parser10.parse()
  expect(parser10.data.segments).toEqual([])

  const parser11 = new Parser(`{a,[b,{c}]. }`)
  expect(() => parser11.parse()).toThrowError()

  const parser12 = new Parser(`*(a.*[1:3])`)
  parser12.parse()
  expect(parser12.data.segments).toEqual([])

  const parser13 = new Parser(`*(a.*[1:3]])`)
  expect(() => parser13.parse()).toThrowError()
})

batchTest({
  '*': {
    type: 'WildcardOperator',
  },
  'a.b.c': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'Identifier',
            value: 'c',
          },
        },
      },
    },
  },
  'a.b.*': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
          },
        },
      },
    },
  },
  'a.b.*(111,222,aaa)': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'GroupExpression',
              value: [
                {
                  type: 'Identifier',
                  value: '111',
                },
                {
                  type: 'Identifier',
                  value: '222',
                },
                {
                  type: 'Identifier',
                  value: 'aaa',
                },
              ],
            },
          },
        },
      },
    },
  },
  'a.b.*(!111,222,aaa)': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'GroupExpression',
              isExclude: true,
              value: [
                {
                  type: 'Identifier',
                  value: '111',
                },
                {
                  type: 'Identifier',
                  value: '222',
                },
                {
                  type: 'Identifier',
                  value: 'aaa',
                },
              ],
            },
          },
        },
      },
    },
  },
  'a.b. * [  11 :  22  ]': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'RangeExpression',
              start: {
                type: 'Identifier',
                value: '11',
              },
              end: {
                type: 'Identifier',
                value: '22',
              },
            },
          },
        },
      },
    },
  },
  'a.b.*([[123123!,()]],[[aaa]])': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'GroupExpression',
              value: [
                {
                  type: 'IgnoreExpression',
                  value: '123123!,()',
                },
                {
                  type: 'IgnoreExpression',
                  value: 'aaa',
                },
              ],
            },
          },
        },
      },
    },
  },
  'a.b.*([[123123!,()]],aaa)': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'GroupExpression',
              value: [
                {
                  type: 'IgnoreExpression',
                  value: '123123!,()',
                },
                {
                  type: 'Identifier',
                  value: 'aaa',
                },
              ],
            },
          },
        },
      },
    },
  },
  'a.b.*(![[123123!,()]],aaa)': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'GroupExpression',
              value: [
                {
                  type: 'IgnoreExpression',
                  value: '123123!,()',
                },
                {
                  type: 'Identifier',
                  value: 'aaa',
                },
              ],
              isExclude: true,
            },
          },
        },
      },
    },
  },
  'a.b  . *   (![[123123!,()]],aaa,bbb)': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'WildcardOperator',
            filter: {
              type: 'GroupExpression',
              value: [
                {
                  type: 'IgnoreExpression',
                  value: '123123!,()',
                },
                {
                  type: 'Identifier',
                  value: 'aaa',
                },
                {
                  type: 'Identifier',
                  value: 'bbb',
                },
              ],
              isExclude: true,
            },
          },
        },
      },
    },
  },
  'a.b.[[123123!,()]]   ': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'IgnoreExpression',
            value: '123123!,()',
          },
        },
      },
    },
  },
  [`a .  
     b .  
       [[123123!,()]]
    
    .aaaa`]: {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'b',
        after: {
          type: 'DotOperator',
          after: {
            type: 'IgnoreExpression',
            value: '123123!,()',
            after: {
              type: 'DotOperator',
              after: {
                type: 'Identifier',
                value: 'aaaa',
              },
            },
          },
        },
      },
    },
  },
  'a.*(aaa.d.*(!sss),ddd,bbb).c.b': {
    type: 'Identifier',
    value: 'a',
    after: {
      type: 'DotOperator',
      after: {
        type: 'WildcardOperator',
        filter: {
          type: 'GroupExpression',
          value: [
            {
              type: 'Identifier',
              value: 'aaa',
              after: {
                type: 'DotOperator',
                after: {
                  type: 'Identifier',
                  value: 'd',
                  after: {
                    type: 'DotOperator',
                    after: {
                      type: 'WildcardOperator',
                      filter: {
                        type: 'GroupExpression',
                        isExclude: true,
                        value: [
                          {
                            type: 'Identifier',
                            value: 'sss',
                          },
                        ],
                      },
                    },
                  },
                },
              },
            },
            {
              type: 'Identifier',
              value: 'ddd',
            },
            {
              type: 'Identifier',
              value: 'bbb',
            },
          ],
        },
        after: {
          type: 'DotOperator',
          after: {
            type: 'Identifier',
            value: 'c',
            after: {
              type: 'DotOperator',
              after: {
                type: 'Identifier',
                value: 'b',
              },
            },
          },
        },
      },
    },
  },
  'aa.bb.cc.{aa,bb,cc:kk}': {
    type: 'Identifier',
    value: 'aa',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'bb',
        after: {
          type: 'DotOperator',
          after: {
            type: 'Identifier',
            value: 'cc',
            after: {
              type: 'DotOperator',
              after: {
                type: 'DestructorExpression',
                value: {
                  type: 'ObjectPattern',
                  properties: [
                    {
                      type: 'ObjectPatternProperty',
                      key: { type: 'Identifier', value: 'aa' },
                    },
                    {
                      type: 'ObjectPatternProperty',
                      key: { type: 'Identifier', value: 'bb' },
                    },
                    {
                      type: 'ObjectPatternProperty',
                      key: { type: 'Identifier', value: 'cc' },
                      value: { type: 'Identifier', value: 'kk' },
                    },
                  ],
                },
                source: '{aa,bb,cc:kk}',
              },
            },
          },
        },
      },
    },
  },
  'aa.bb.cc.[ [aa,bb,cc,[ [{aa:bb}] ]] ]': {
    type: 'Identifier',
    value: 'aa',
    after: {
      type: 'DotOperator',
      after: {
        type: 'Identifier',
        value: 'bb',
        after: {
          type: 'DotOperator',
          after: {
            type: 'Identifier',
            value: 'cc',
            after: {
              type: 'DotOperator',
              after: {
                type: 'DestructorExpression',
                value: {
                  type: 'ArrayPattern',
                  elements: [
                    {
                      type: 'ArrayPattern',
                      elements: [
                        {
                          type: 'Identifier',
                          value: 'aa',
                        },
                        {
                          type: 'Identifier',
                          value: 'bb',
                        },
                        {
                          type: 'Identifier',
                          value: 'cc',
                        },
                        {
                          type: 'ArrayPattern',
                          elements: [
                            {
                              type: 'ArrayPattern',
                              elements: [
                                {
                                  type: 'ObjectPattern',
                                  properties: [
                                    {
                                      type: 'ObjectPatternProperty',
                                      key: {
                                        type: 'Identifier',
                                        value: 'aa',
                                      },
                                      value: {
                                        type: 'Identifier',
                                        value: 'bb',
                                      },
                                    },
                                  ],
                                },
                              ],
                            },
                          ],
                        },
                      ],
                    },
                  ],
                },
                source: '[[aa,bb,cc,[[{aa:bb}]]]]',
              },
            },
          },
        },
      },
    },
  },
})

```

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

```markdown
# TreeSelect

> 树选择器

## Markup Schema 同步数据源案例

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Number
        name="select"
        label="选择框"
        x-decorator="FormItem"
        x-component="TreeSelect"
        enum={[
          {
            label: '选项1',
            value: 1,
            children: [
              {
                label: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                label: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                label: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: '选项2',
            value: 2,
            children: [
              {
                label: 'Child Node3',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                label: 'Child Node4',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                label: 'Child Node5',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ]}
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Markup Schema 异步联动数据源案例

```tsx
import React from 'react'
import {
  TreeSelect,
  Select,
  FormItem,
  FormButtonGroup,
  Submit,
} from '@formily/next'
import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { action } from '@formily/reactive'

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

const useAsyncDataSource = (
  pattern: FormPathPattern,
  service: (field: Field) => Promise<{ label: string; value: any }[]>
) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}

const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'BBB',
                value: 'ccc',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'DDD',
                value: 'ddd',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          }
        }, 1500)
      })
    })
  },
})

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Number
        name="linkage"
        label="联动选择框"
        x-decorator="FormItem"
        x-component="Select"
        enum={[
          { label: '发请求1', value: 1 },
          { label: '发请求2', value: 2 },
        ]}
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
      <SchemaField.String
        name="select"
        label="异步选择框"
        x-decorator="FormItem"
        x-component="TreeSelect"
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 同步数据源案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    select: {
      type: 'string',
      label: '选择框',
      'x-decorator': 'FormItem',
      'x-component': 'TreeSelect',
      enum: [
        {
          label: '选项1',
          value: 1,
          children: [
            {
              label: 'Child Node1',
              value: '0-0-0',
              key: '0-0-0',
            },
            {
              label: 'Child Node2',
              value: '0-0-1',
              key: '0-0-1',
            },
            {
              label: 'Child Node3',
              value: '0-0-2',
              key: '0-0-2',
            },
          ],
        },
        {
          label: '选项2',
          value: 2,
          children: [
            {
              label: 'Child Node1',
              value: '0-1-0',
              key: '0-1-0',
            },
            {
              label: 'Child Node2',
              value: '0-1-1',
              key: '0-1-1',
            },
            {
              label: 'Child Node3',
              value: '0-1-2',
              key: '0-1-2',
            },
          ],
        },
      ],
      'x-component-props': {
        style: {
          width: 200,
        },
      },
    },
  },
}

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

## JSON Schema 异步联动数据源案例

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

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

const loadData = async (field) => {
  const linkage = field.query('linkage').get('value')
  if (!linkage) return []
  return new Promise((resolve) => {
    setTimeout(() => {
      if (linkage === 1) {
        resolve([
          {
            label: 'AAA',
            value: 'aaa',
            children: [
              {
                label: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                label: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                label: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'BBB',
            value: 'ccc',
            children: [
              {
                label: 'Child Node1',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                label: 'Child Node2',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                label: 'Child Node3',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ])
      } else if (linkage === 2) {
        resolve([
          {
            label: 'CCC',
            value: 'ccc',
            children: [
              {
                label: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                label: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                label: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'DDD',
            value: 'ddd',
            children: [
              {
                label: 'Child Node1',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                label: 'Child Node2',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                label: 'Child Node3',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ])
      }
    }, 1500)
  })
}

const useAsyncDataSource = (service) => (field) => {
  field.loading = true
  service(field).then(
    action.bound((data) => {
      field.dataSource = data
      field.loading = false
    })
  )
}

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    linkage: {
      type: 'string',
      label: '联动选择框',
      enum: [
        { label: '发请求1', value: 1 },
        { label: '发请求2', value: 2 },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Select',
      'x-component-props': {
        style: {
          width: 200,
        },
      },
    },
    select: {
      type: 'string',
      label: '异步选择框',
      'x-decorator': 'FormItem',
      'x-component': 'TreeSelect',
      'x-component-props': {
        style: {
          width: 200,
        },
      },
      'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
    },
  },
}

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

## 纯 JSX 同步数据源案例

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="select"
      label="选择框"
      dataSource={[
        {
          label: '选项1',
          value: 1,
          children: [
            {
              label: 'Child Node1',
              value: '0-0-0',
              key: '0-0-0',
            },
            {
              label: 'Child Node2',
              value: '0-0-1',
              key: '0-0-1',
            },
            {
              label: 'Child Node3',
              value: '0-0-2',
              key: '0-0-2',
            },
          ],
        },
        {
          label: '选项2',
          value: 2,
          children: [
            {
              label: 'Child Node3',
              value: '0-1-0',
              key: '0-1-0',
            },
            {
              label: 'Child Node4',
              value: '0-1-1',
              key: '0-1-1',
            },
            {
              label: 'Child Node5',
              value: '0-1-2',
              key: '0-1-2',
            },
          ],
        },
      ]}
      decorator={[FormItem]}
      component={[
        TreeSelect,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 异步联动数据源案例

```tsx
import React from 'react'
import {
  TreeSelect,
  Select,
  FormItem,
  FormButtonGroup,
  Submit,
} from '@formily/next'
import {
  createForm,
  onFieldReact,
  FormPathPattern,
  FieldType,
} from '@formily/core'
import { FormProvider, Field } from '@formily/react'
import { action } from '@formily/reactive'

const useAsyncDataSource = (
  pattern: FormPathPattern,
  service: (field: FieldType) => Promise<{ label: string; value: any }[]>
) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}

const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'BBB',
                value: 'ccc',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'DDD',
                value: 'ddd',
                children: [
                  {
                    label: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    label: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    label: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          }
        }, 1500)
      })
    })
  },
})

export default () => (
  <FormProvider form={form}>
    <Field
      name="linkage"
      label="联动选择框"
      dataSource={[
        { label: '发请求1', value: 1 },
        { label: '发请求2', value: 2 },
      ]}
      decorator={[FormItem]}
      component={[
        Select,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <Field
      name="select"
      label="异步选择框"
      decorator={[FormItem]}
      component={[
        TreeSelect,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://fusion.design/pc/component/basic/tree-select

```

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

```typescript
import { createForm } from '@formily/core'
import { useFieldSchema, useField, Schema } from '../'
import {
  FormProvider,
  RecursionField,
  createSchemaField,
} from '../vue2-components'
import { render } from '@testing-library/vue'
import { mount, createLocalVue } from '@vue/test-utils'
import Vue, { CreateElement } from 'vue'
import { defineComponent, h } from '@vue/composition-api'

Vue.component('FormProvider', FormProvider)
Vue.component('RecursionField', RecursionField)

const Input = defineComponent({
  props: ['value'],
  setup(props, { attrs, listeners }) {
    return () => {
      return h('input', {
        attrs: {
          ...attrs,
          value: props.value,
          'data-testid': 'input',
        },
        on: {
          ...listeners,
          input: listeners.change,
        },
      })
    }
  },
})

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

  test('boolean', () => {
    const form = createForm()
    const { SchemaField, SchemaBooleanField } = createSchemaField({
      components: {
        Input,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField, SchemaBooleanField },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaBooleanField x-component="Input" />
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeVisible()
  })

  test('number', () => {
    const form = createForm()
    const { SchemaField, SchemaNumberField } = createSchemaField({
      components: {
        Input,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField, SchemaNumberField },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaNumberField x-component="Input" />
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeVisible()
  })

  test('date', () => {
    const form = createForm()
    const { SchemaField, SchemaDateField } = createSchemaField({
      components: {
        Input,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField, SchemaDateField },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaDateField x-component="Input" />
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeVisible()
  })

  test('datetime', () => {
    const form = createForm()
    const { SchemaField, SchemaDateTimeField } = createSchemaField({
      components: {
        Input,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField, SchemaDateTimeField },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaDateTimeField x-component="Input" />
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeVisible()
  })

  test('void', () => {
    const form = createForm()
    const VoidComponent = {
      render(h: CreateElement) {
        return h(
          'div',
          { attrs: { 'data-testid': 'void-component' } },
          this.$slots.default
        )
      },
    }
    const { SchemaField, SchemaVoidField } = createSchemaField({
      components: {
        VoidComponent,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField, SchemaVoidField },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaVoidField x-component="VoidComponent" />
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('void-component')).toBeVisible()
  })

  test('array', () => {
    const form = createForm()
    const components = createSchemaField({
      components: {
        Input,
      },
    })
    render({
      components: { ...components },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaArrayField>
            <SchemaObjectField>
              <SchemaStringField x-component="Input" />
            </SchemaObjectField>
            <SchemaVoidField />
          </SchemaArrayField>
        </SchemaField>
      </FormProvider>`,
    })
  })

  test('other', () => {
    const form = createForm()
    const components = createSchemaField({
      components: {
        Input,
      },
    })
    render({
      components: { ...components },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaMarkupField type="other">
            <SchemaMarkupField />
          </SchemaMarkupField>
        </SchemaField>
      </FormProvider>`,
    })
  })

  test('no parent', () => {
    const form = createForm()
    const components = createSchemaField({
      components: {
        Input,
      },
    })
    render({
      components: { ...components },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaMarkupField type="other">
          <SchemaMarkupField />
        </SchemaMarkupField>
      </FormProvider>`,
    })
  })
})

describe('recursion field', () => {
  test('onlyRenderProperties', () => {
    const form = createForm()

    const CustomObject = defineComponent({
      setup() {
        const schemaRef = useFieldSchema()
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', { props: { schema: schemaRef.value } }),
          ])
        }
      },
    })

    const CustomObject2 = defineComponent({
      setup() {
        const fieldRef = useField()
        const schemaRef = useFieldSchema()
        return () => {
          const schema = schemaRef.value
          const field = fieldRef.value
          return h('div', { attrs: { 'data-testid': 'only-properties' } }, [
            h('RecursionField', {
              props: {
                name: schema.name,
                basePath: field.address,
                schema,
                onlyRenderProperties: true,
              },
            }),
          ])
        }
      },
    })

    const components = createSchemaField({
      components: {
        Input,
        CustomObject,
        CustomObject2,
      },
    })

    const { queryAllByTestId } = render({
      components: components,
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaObjectField x-component="CustomObject">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
          <SchemaObjectField x-component="CustomObject2">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
          <SchemaVoidField x-component="CustomObject2">
            <SchemaStringField x-component="Input" />
          </SchemaVoidField>
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryAllByTestId('input').length).toEqual(3)
    expect(queryAllByTestId('object').length).toEqual(1)
    expect(queryAllByTestId('only-properties').length).toEqual(2)
  })

  test('mapProperties', () => {
    const form = createForm()

    const CustomObject = defineComponent({
      setup() {
        const schemaRef = useFieldSchema()
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema: schemaRef.value,
                mapProperties: (schema) => {
                  schema.default = '123'
                  return schema
                },
              },
            }),
          ])
        }
      },
    })

    const CustomObject2 = defineComponent({
      setup() {
        const schemaRef = useFieldSchema()
        return () => {
          const schema = schemaRef.value
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema,
                mapProperties: () => {
                  return null
                },
              },
            }),
          ])
        }
      },
    })

    const components = createSchemaField({
      components: {
        Input,
        CustomObject,
        CustomObject2,
      },
    })

    const { queryAllByTestId } = render({
      components: components,
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaObjectField x-component="CustomObject">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
          <SchemaObjectField x-component="CustomObject2">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryAllByTestId('input').length).toEqual(2)
    expect(queryAllByTestId('input')[0].getAttribute('value')).toEqual('123')
    expect(queryAllByTestId('input')[1].getAttribute('value')).toBeFalsy()
  })

  test('filterProperties', () => {
    const form = createForm()

    const CustomObject = defineComponent({
      setup() {
        const schemaRef = useFieldSchema()
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema: schemaRef.value,
                filterProperties: (schema: Schema) => {
                  if (schema['x-component'] === 'Input') return false
                  return true
                },
              },
            }),
          ])
        }
      },
    })

    const CustomObject2 = defineComponent({
      setup() {
        const schemaRef = useFieldSchema()
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema: schemaRef.value,
                filterProperties: (schema: Schema) => {
                  if (schema['x-component'] === 'Input') return
                  return true
                },
              },
            }),
          ])
        }
      },
    })

    const components = createSchemaField({
      components: {
        Input,
        CustomObject,
        CustomObject2,
      },
    })

    const { queryAllByTestId } = render({
      components: components,
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaObjectField x-component="CustomObject">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
          <SchemaObjectField x-component="CustomObject2">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryAllByTestId('input').length).toEqual(1)
    expect(queryAllByTestId('object').length).toEqual(2)
  })

  test('onlyRenderSelf', () => {
    const form = createForm()

    const CustomObject = defineComponent({
      setup() {
        const schemaRef = useFieldSchema()
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema: schemaRef.value,
                onlyRenderSelf: true,
              },
            }),
          ])
        }
      },
    })

    const components = createSchemaField({
      components: {
        Input,
        CustomObject,
      },
    })

    const { queryAllByTestId } = render({
      components: components,
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaObjectField x-component="CustomObject">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryAllByTestId('input').length).toEqual(0)
    expect(queryAllByTestId('object').length).toEqual(1)
  })

  test('illegal schema', () => {
    const form = createForm()

    const CustomObject = defineComponent({
      setup() {
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema: null,
              },
            }),
          ])
        }
      },
    })

    const CustomObject2 = defineComponent({
      setup() {
        return () => {
          return h('div', { attrs: { 'data-testid': 'object' } }, [
            h('RecursionField', {
              props: {
                schema: {},
              },
            }),
          ])
        }
      },
    })

    const components = createSchemaField({
      components: {
        Input,
        CustomObject,
        CustomObject2,
      },
    })

    const { queryByTestId } = render({
      components: components,
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaObjectField x-component="CustomObject">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
          <SchemaObjectField x-component="CustomObject2">
            <SchemaStringField x-component="Input" />
          </SchemaObjectField>
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('input')).toBeNull()
  })

  test('schema reactions', async () => {
    const div = document.createElement('div')
    document.body.appendChild(div)
    const form = createForm()
    const components = createSchemaField({
      components: {
        Input,
      },
    })
    const localVue = createLocalVue()
    localVue.component('FormProvider', FormProvider)
    const TestComponent = {
      components: components,
      data() {
        return {
          form,
          reactions: [
            {
              when: '{{$form.values.aaa === "123"}}',
              fulfill: {
                state: {
                  visible: true,
                },
              },
              otherwise: {
                state: {
                  visible: false,
                },
              },
            },
            {
              when: '{{$self.value === "123"}}',
              target: 'ccc',
              fulfill: {
                schema: {
                  'x-visible': true,
                },
              },
              otherwise: {
                schema: {
                  'x-visible': false,
                },
              },
            },
          ],
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaStringField
            name="aaa"
            x-component="Input"
            :x-component-props="{
              'class': 'aaa',
            }"
          />
          <SchemaStringField
            name="bbb"
            x-component="Input"
            :x-component-props="{
              'class': 'bbb',
            }"
            :x-reactions="reactions"
          />
          <SchemaStringField
            name="ccc"
            x-component="Input"
            :x-component-props="{
              'class': 'ccc',
            }"
          />
        </SchemaField>
      </FormProvider>`,
    } as any
    const wrapper = mount(TestComponent, {
      // attachTo: div,
      attachToDocument: true,
      localVue,
    })
    expect(wrapper.find('.bbb').exists()).toBeFalsy()
    wrapper.find('.aaa').setValue('123')
    expect(form.query('aaa').get('value')).toEqual('123')
    await wrapper.vm.$forceUpdate()
    expect(wrapper.find('.bbb').exists()).toBeTruthy()
    expect(wrapper.find('.ccc').exists()).toBeFalsy()
    wrapper.find('.bbb').setValue('123')
    expect(form.query('bbb').get('value')).toEqual('123')
    await wrapper.vm.$forceUpdate()
    expect(wrapper.find('.ccc').exists()).toBeTruthy()
    wrapper.destroy()
  })

  test('void field children', () => {
    const form = createForm()
    const VoidComponent = {
      render(h: CreateElement) {
        return h('div', this.$slots.default || 'placeholder')
      },
    }
    const { SchemaField, SchemaVoidField } = createSchemaField({
      components: {
        VoidComponent,
      },
    })
    const { queryByTestId } = render({
      components: { SchemaField, SchemaVoidField },
      data() {
        return {
          form,
        }
      },
      template: `<FormProvider :form="form">
        <SchemaField>
          <SchemaVoidField x-component="VoidComponent" :x-component-props="{ 'data-testid': 'void-component-1' }" />
          <SchemaVoidField x-component="VoidComponent" :x-component-props="{ 'data-testid': 'void-component-2' }" x-content="content" />
        </SchemaField>
      </FormProvider>`,
    })
    expect(queryByTestId('void-component-1').textContent).toBe('placeholder')
    expect(queryByTestId('void-component-2').textContent).toBe('content')
  })
})

```

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

```markdown
# SelectTable

> 表格选择组件

## Markup Schema 单选案例

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

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

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Object
          type="string"
          name="selectTable"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            bordered: false,
            mode: 'single',
          }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </FormProvider>
  )
}
```

## Markup Schema 筛选案例

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

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

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Array
          type="array"
          name="selectTable"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            bordered: false,
            showSearch: true,
            optionAsValue: true,
          }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
        >
          <SchemaField.Object>
            <SchemaField.Void
              name="name"
              title="标题"
              x-component="SelectTable.Column"
            />
            <SchemaField.Void
              name="description"
              title="描述"
              x-component="SelectTable.Column"
            />
          </SchemaField.Object>
        </SchemaField.Array>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </FormProvider>
  )
}
```

## Markup Schema 异步数据源案例

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

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

const form = createForm()

export default () => {
  const onSearch = (value) => {
    const field = form.query('selectTable').take()
    field.loading = true
    setTimeout(() => {
      field.setState({
        dataSource: [
          {
            key: '3',
            name: 'AAA' + value,
            description: 'aaa',
          },
          {
            key: '4',
            name: 'BBB' + value,
            description: 'bbb',
          },
        ],
        loading: false,
      })
    }, 1500)
  }

  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Object
          type="object"
          name="selectTable"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            showSearch: true,
            filterOption: false,
            onSearch,
          }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </FormProvider>
  )
}
```

## Markup Schema 阅读态案例

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

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

const form = createForm()

export default () => {
  return (
    <Form form={form} layout="vertical">
      <SchemaField>
        <SchemaField.Object
          title="单选"
          type="string"
          name="selectTable1"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            mode: 'single',
          }}
          default="1"
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
        <SchemaField.Object
          title="单选 + optionAsValue"
          type="string"
          name="selectTable2"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            mode: 'single',
            optionAsValue: true,
          }}
          default={{ key: '1', name: '标题1', description: '描述1' }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
        <SchemaField.Array
          title="多选"
          type="array"
          name="selectTable3"
          x-decorator="FormItem"
          x-component="SelectTable"
          default={['1', '3']}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
            { key: '3', name: '标题3', description: '描述3' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Object>
            <SchemaField.Void
              name="name"
              title="标题"
              x-component="SelectTable.Column"
            />
            <SchemaField.Void
              name="description"
              title="描述"
              x-component="SelectTable.Column"
            />
          </SchemaField.Object>
        </SchemaField.Array>
        <SchemaField.Array
          title="多选 + optionAsValue"
          type="array"
          name="selectTable4"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            optionAsValue: true,
          }}
          default={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '3', name: '标题3', description: '描述3' },
          ]}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
            { key: '3', name: '标题3', description: '描述3' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Object>
            <SchemaField.Void
              name="name"
              title="标题"
              x-component="SelectTable.Column"
            />
            <SchemaField.Void
              name="description"
              title="描述"
              x-component="SelectTable.Column"
            />
          </SchemaField.Object>
        </SchemaField.Array>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </Form>
  )
}
```

## JSON Schema 多选案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    selectTable: {
      type: 'array',
      'x-decorator': 'FormItem',
      'x-component': 'SelectTable',
      'x-component-props': {
        bordered: false,
        mode: 'multiple',
      },
      enum: [
        { key: '1', name: '标题1', description: '描述1' },
        { key: '2', name: '标题2', description: '描述2' },
      ],
      properties: {
        name: {
          title: '标题',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '40%',
          },
        },
        description: {
          title: '描述',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '60%',
          },
        },
      },
    },
  },
}

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

## JSON Schema 自定义筛选案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    selectTable: {
      type: 'array',
      'x-decorator': 'FormItem',
      'x-component': 'SelectTable',
      'x-component-props': {
        bordered: false,
        showSearch: true,
        primaryKey: 'key',
        isTree: true,
        filterOption: (input, option) =>
          option.description.toLowerCase().indexOf(input.toLowerCase()) >= 0,
        filterSort: (optionA, optionB) =>
          optionA.description
            .toLowerCase()
            .localeCompare(optionB.description.toLowerCase()),
        optionAsValue: true,
        rowSelection: {
          checkStrictly: false,
        },
      },
      enum: [
        { key: '1', name: '标题1', description: 'A-描述' },
        {
          key: '2',
          name: '标题2',
          description: 'X-描述',
          children: [
            {
              key: '2-1',
              name: '标题2-1',
              description: 'Y-描述',
              children: [
                { key: '2-1-1', name: '标题2-1-1', description: 'Z-描述' },
              ],
            },
            {
              key: '2-2',
              name: '标题2-2',
              description: 'YY-描述',
            },
          ],
        },
        { key: '3', name: '标题3', description: 'C-描述' },
      ],
      properties: {
        name: {
          title: '标题',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '40%',
          },
        },
        description: {
          title: '描述',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '60%',
          },
        },
      },
    },
  },
}

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

## JSON Schema 异步数据源案例

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

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

const loadData = async (value) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve([
        { key: '3', name: 'AAA' + value, description: 'aaa' },
        { key: '4', name: 'BBB' + value, description: 'bbb' },
      ])
    }, 1500)
  })
}

const useAsyncDataSource = (service, field) => (value) => {
  field.loading = true
  service(value).then((data) => {
    field.setState({
      dataSource: data,
      loading: false,
    })
  })
}

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    selectTable: {
      type: 'array',
      'x-decorator': 'FormItem',
      'x-component': 'SelectTable',
      'x-component-props': {
        showSearch: true,
        filterOption: false,
        onSearch: '{{useAsyncDataSource(loadData,$self)}}',
      },
      enum: [
        { key: '1', name: '标题1', description: '描述1' },
        { key: '2', name: '标题2', description: '描述2' },
      ],
      properties: {
        name: {
          title: '标题',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '40%',
          },
        },
        description: {
          title: '描述',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '60%',
          },
        },
      },
    },
  },
}

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

## 纯 JSX 案例

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="SelectTable"
      dataSource={[
        { key: '1', name: '标题1', description: '描述1' },
        { key: '2', name: '标题2', description: '描述2' },
      ]}
      decorator={[FormItem]}
      component={[
        SelectTable,
        {
          columns: [
            { dataIndex: 'name', title: '标题' },
            { dataIndex: 'description', title: '描述' },
          ],
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

### SelectTable

| 属性名        | 类型                                         | 描述                                                                                                                                 | 默认值       |
| ------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
| mode          | `'multiple' \| 'single'`                     | 设置 SelectTable 模式为单选或多选                                                                                                    | `'multiple'` |
| valueType     | `'all' \| 'parent' \| 'child' \| 'path'`     | 返回值类型,checkStrictly 设置为 `false` 时有效                                                                                      | `'all'`      |
| optionAsValue | boolean                                      | 使用表格行数据作为值,valueType 值为 `'path'` 时无效                                                                                 | false        |
| showSearch    | boolean                                      | 是否显示搜索组件                                                                                                                     | false        |
| searchProps   | object                                       | Search 组件属性                                                                                                                      | -            |
| primaryKey    | `string \| (record) => string`               | 表格行 key 的取值                                                                                                                    | `'key'`      |
| filterOption  | `boolean \| (inputValue, option) => boolean` | 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 false | true         |
| filterSort    | (optionA, optionB) => number                 | 搜索时对筛选结果项的排序函数, 类似 Array.sort 里的 compareFunction                                                                   | -            |
| onSearch      | 文本框值变化时回调                           | (inputValue) => void                                                                                                                 | -            |

参考 https://ant.design/components/table-cn/

### rowSelection

| 属性名        | 类型    | 描述                                                         | 默认值 |
| ------------- | ------- | ------------------------------------------------------------ | ------ |
| checkStrictly | boolean | checkable 状态下节点选择完全受控(父子数据选中状态不再关联) | true   |

参考 https://ant.design/components/table/#rowSelection

### SelectTable.Column

参考 https://ant.design/components/table-cn/ Table.Column 属性

```

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

```markdown
# TreeSelect

> Tree selector

## Markup Schema synchronization data source case

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

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Number
        name="select"
        title="select box"
        x-decorator="FormItem"
        x-component="TreeSelect"
        enum={[
          {
            label: 'Option 1',
            value: 1,
            children: [
              {
                title: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                title: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                title: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'Option 2',
            value: 2,
            children: [
              {
                title: 'Child Node3',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                title: 'Child Node4',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                title: 'Child Node5',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ]}
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Markup Schema Asynchronous Linkage Data Source Case

```tsx
import React from 'react'
import {
  TreeSelect,
  Select,
  FormItem,
  FormButtonGroup,
  Submit,
} from '@formily/antd'
import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { action } from '@formily/reactive'

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

const useAsyncDataSource = (
  pattern: FormPathPattern,
  service: (field: Field) => Promise<{ label: string; value: any }[]>
) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}

const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'BBB',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'DDD',
                value: 'ddd',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          }
        }, 1500)
      })
    })
  },
})

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Number
        name="linkage"
        title="Linkage selection box"
        x-decorator="FormItem"
        x-component="Select"
        enum={[
          { label: 'Request 1', value: 1 },
          { label: 'Request 2', value: 2 },
        ]}
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
      <SchemaField.String
        name="select"
        title="Asynchronous select box"
        x-decorator="FormItem"
        x-component="TreeSelect"
        x-component-props={{
          style: {
            width: 200,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema synchronization data source case

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    select: {
      type: 'string',
      title: 'Select box',
      'x-decorator': 'FormItem',
      'x-component': 'TreeSelect',
      enum: [
        {
          label: 'Option 1',
          value: 1,
          children: [
            {
              title: 'Child Node1',
              value: '0-0-0',
              key: '0-0-0',
            },
            {
              title: 'Child Node2',
              value: '0-0-1',
              key: '0-0-1',
            },
            {
              title: 'Child Node3',
              value: '0-0-2',
              key: '0-0-2',
            },
          ],
        },
        {
          label: 'Option 2',
          value: 2,
          children: [
            {
              title: 'Child Node1',
              value: '0-1-0',
              key: '0-1-0',
            },
            {
              title: 'Child Node2',
              value: '0-1-1',
              key: '0-1-1',
            },
            {
              title: 'Child Node3',
              value: '0-1-2',
              key: '0-1-2',
            },
          ],
        },
      ],
      'x-component-props': {
        style: {
          width: 200,
        },
      },
    },
  },
}

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

## JSON Schema asynchronous linkage data source case

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

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

const loadData = async (field) => {
  const linkage = field.query('linkage').get('value')
  if (!linkage) return []
  return new Promise((resolve) => {
    setTimeout(() => {
      if (linkage === 1) {
        resolve([
          {
            label: 'AAA',
            value: 'aaa',
            children: [
              {
                title: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                title: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                title: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'BBB',
            value: 'ccc',
            children: [
              {
                title: 'Child Node1',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                title: 'Child Node2',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                title: 'Child Node3',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ])
      } else if (linkage === 2) {
        resolve([
          {
            label: 'CCC',
            value: 'ccc',
            children: [
              {
                title: 'Child Node1',
                value: '0-0-0',
                key: '0-0-0',
              },
              {
                title: 'Child Node2',
                value: '0-0-1',
                key: '0-0-1',
              },
              {
                title: 'Child Node3',
                value: '0-0-2',
                key: '0-0-2',
              },
            ],
          },
          {
            label: 'DDD',
            value: 'ddd',
            children: [
              {
                title: 'Child Node1',
                value: '0-1-0',
                key: '0-1-0',
              },
              {
                title: 'Child Node2',
                value: '0-1-1',
                key: '0-1-1',
              },
              {
                title: 'Child Node3',
                value: '0-1-2',
                key: '0-1-2',
              },
            ],
          },
        ])
      }
    }, 1500)
  })
}

const useAsyncDataSource = (service) => (field) => {
  field.loading = true
  service(field).then(
    action.bound((data) => {
      field.dataSource = data
      field.loading = false
    })
  )
}

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    linkage: {
      type: 'string',
      title: 'Linkage selection box',
      enum: [
        { label: 'Request 1', value: 1 },
        { label: 'Request 2', value: 2 },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Select',
      'x-component-props': {
        style: {
          width: 200,
        },
      },
    },
    select: {
      type: 'string',
      title: 'Asynchronous selection box',
      'x-decorator': 'FormItem',
      'x-component': 'TreeSelect',
      'x-component-props': {
        style: {
          width: 200,
        },
      },
      'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
    },
  },
}

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

## Pure JSX synchronization data source case

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="select"
      title="select box"
      dataSource={[
        {
          label: 'Option 1',
          value: 1,
          children: [
            {
              title: 'Child Node1',
              value: '0-0-0',
              key: '0-0-0',
            },
            {
              title: 'Child Node2',
              value: '0-0-1',
              key: '0-0-1',
            },
            {
              title: 'Child Node3',
              value: '0-0-2',
              key: '0-0-2',
            },
          ],
        },
        {
          label: 'Option 2',
          value: 2,
          children: [
            {
              title: 'Child Node3',
              value: '0-1-0',
              key: '0-1-0',
            },
            {
              title: 'Child Node4',
              value: '0-1-1',
              key: '0-1-1',
            },
            {
              title: 'Child Node5',
              value: '0-1-2',
              key: '0-1-2',
            },
          ],
        },
      ]}
      decorator={[FormItem]}
      component={[TreeSelect]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Pure JSX asynchronous linkage data source case

```tsx
import React from 'react'
import {
  TreeSelect,
  Select,
  FormItem,
  FormButtonGroup,
  Submit,
} from '@formily/antd'
import {
  createForm,
  onFieldReact,
  FormPathPattern,
  Field as FieldType,
} from '@formily/core'
import { FormProvider, Field } from '@formily/react'
import { action } from '@formily/reactive'

const useAsyncDataSource = (
  pattern: FormPathPattern,
  service: (field: FieldType) => Promise<{ label: string; value: any }[]>
) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}

const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'BBB',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-0-0',
                    key: '0-0-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-0-1',
                    key: '0-0-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-0-2',
                    key: '0-0-2',
                  },
                ],
              },
              {
                label: 'DDD',
                value: 'ddd',
                children: [
                  {
                    title: 'Child Node1',
                    value: '0-1-0',
                    key: '0-1-0',
                  },
                  {
                    title: 'Child Node2',
                    value: '0-1-1',
                    key: '0-1-1',
                  },
                  {
                    title: 'Child Node3',
                    value: '0-1-2',
                    key: '0-1-2',
                  },
                ],
              },
            ])
          }
        }, 1500)
      })
    })
  },
})

export default () => (
  <FormProvider form={form}>
    <Field
      name="linkage"
      title="Linkage selection box"
      dataSource={[
        { label: 'Request 1', value: 1 },
        { label: 'Request 2', value: 2 },
      ]}
      decorator={[FormItem]}
      component={[
        Select,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <Field
      name="select"
      title="Asynchronous select box"
      decorator={[FormItem]}
      component={[
        TreeSelect,
        {
          style: {
            width: 200,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

Reference https://ant.design/components/tree-select-cn/

```

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

```markdown
# SelectTable

> 表格选择组件

## Markup Schema 单选案例

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

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

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Object
          type="string"
          name="selectTable"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
            mode: 'single',
          }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </FormProvider>
  )
}
```

## Markup Schema 筛选案例

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

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

const form = createForm()

export default () => {
  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Array
          type="array"
          name="selectTable"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
            showSearch: true,
            optionAsValue: true,
          }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
        >
          <SchemaField.Object>
            <SchemaField.Void
              name="name"
              title="标题"
              x-component="SelectTable.Column"
            />
            <SchemaField.Void
              name="description"
              title="描述"
              x-component="SelectTable.Column"
            />
          </SchemaField.Object>
        </SchemaField.Array>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </FormProvider>
  )
}
```

## Markup Schema 异步数据源案例

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

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

const form = createForm()

export default () => {
  const onSearch = (value) => {
    const field = form.query('selectTable').take()
    field.loading = true
    setTimeout(() => {
      field.setState({
        dataSource: [
          {
            key: '3',
            name: 'AAA' + value,
            description: 'aaa',
          },
          {
            key: '4',
            name: 'BBB' + value,
            description: 'bbb',
          },
        ],
        loading: false,
      })
    }, 1500)
  }

  return (
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.Object
          type="object"
          name="selectTable"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
            showSearch: true,
            filterOption: false,
            onSearch,
          }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </FormProvider>
  )
}
```

## Markup Schema 阅读态案例

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

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

const form = createForm()

export default () => {
  return (
    <Form form={form} layout="vertical">
      <SchemaField>
        <SchemaField.Object
          title="单选"
          type="string"
          name="selectTable1"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
            mode: 'single',
          }}
          default="1"
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
        <SchemaField.Object
          title="单选 + optionAsValue"
          type="string"
          name="selectTable2"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
            mode: 'single',
            optionAsValue: true,
          }}
          default={{ key: '1', name: '标题1', description: '描述1' }}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Void
            name="name"
            title="标题"
            x-component="SelectTable.Column"
          />
          <SchemaField.Void
            name="description"
            title="描述"
            x-component="SelectTable.Column"
          />
        </SchemaField.Object>
        <SchemaField.Array
          title="多选"
          type="array"
          name="selectTable3"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
          }}
          default={['1', '3']}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
            { key: '3', name: '标题3', description: '描述3' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Object>
            <SchemaField.Void
              name="name"
              title="标题"
              x-component="SelectTable.Column"
            />
            <SchemaField.Void
              name="description"
              title="描述"
              x-component="SelectTable.Column"
            />
          </SchemaField.Object>
        </SchemaField.Array>
        <SchemaField.Array
          title="多选 + optionAsValue"
          type="array"
          name="selectTable4"
          x-decorator="FormItem"
          x-component="SelectTable"
          x-component-props={{
            hasBorder: false,
            optionAsValue: true,
          }}
          default={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '3', name: '标题3', description: '描述3' },
          ]}
          enum={[
            { key: '1', name: '标题1', description: '描述1' },
            { key: '2', name: '标题2', description: '描述2' },
            { key: '3', name: '标题3', description: '描述3' },
          ]}
          x-read-pretty={true}
        >
          <SchemaField.Object>
            <SchemaField.Void
              name="name"
              title="标题"
              x-component="SelectTable.Column"
            />
            <SchemaField.Void
              name="description"
              title="描述"
              x-component="SelectTable.Column"
            />
          </SchemaField.Object>
        </SchemaField.Array>
      </SchemaField>
      <FormButtonGroup.FormItem>
        <Submit onSubmit={console.log}>提交</Submit>
      </FormButtonGroup.FormItem>
    </Form>
  )
}
```

## JSON Schema 多选案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    selectTable: {
      type: 'array',
      'x-decorator': 'FormItem',
      'x-component': 'SelectTable',
      'x-component-props': {
        hasBorder: false,
        mode: 'multiple',
      },
      enum: [
        { key: '1', name: '标题1', description: '描述1' },
        { key: '2', name: '标题2', description: '描述2' },
      ],
      properties: {
        name: {
          title: '标题',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '40%',
          },
        },
        description: {
          title: '描述',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '60%',
          },
        },
      },
    },
  },
}

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

## JSON Schema 自定义筛选案例

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

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

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    selectTable: {
      type: 'array',
      'x-decorator': 'FormItem',
      'x-component': 'SelectTable',
      'x-component-props': {
        hasBorder: false,
        showSearch: true,
        primaryKey: 'key',
        isTree: true,
        filterOption: (input, option) =>
          option.description.toLowerCase().indexOf(input.toLowerCase()) >= 0,
        filterSort: (optionA, optionB) =>
          optionA.description
            .toLowerCase()
            .localeCompare(optionB.description.toLowerCase()),
        optionAsValue: true,
        rowSelection: {
          checkStrictly: false,
        },
      },
      enum: [
        { key: '1', name: '标题1', description: 'A-描述' },
        {
          key: '2',
          name: '标题2',
          description: 'X-描述',
          children: [
            {
              key: '2-1',
              name: '标题2-1',
              description: 'Y-描述',
              children: [
                { key: '2-1-1', name: '标题2-1-1', description: 'Z-描述' },
              ],
            },
            {
              key: '2-2',
              name: '标题2-2',
              description: 'YY-描述',
            },
          ],
        },
        { key: '3', name: '标题3', description: 'C-描述' },
      ],
      properties: {
        name: {
          title: '标题',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '40%',
          },
        },
        description: {
          title: '描述',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '60%',
          },
        },
      },
    },
  },
}

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

## JSON Schema 异步数据源案例

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

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

const loadData = async (value) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve([
        { key: '3', name: 'AAA' + value, description: 'aaa' },
        { key: '4', name: 'BBB' + value, description: 'bbb' },
      ])
    }, 1500)
  })
}

const useAsyncDataSource = (service, field) => (value) => {
  field.loading = true
  service(value).then((data) => {
    field.setState({
      dataSource: data,
      loading: false,
    })
  })
}

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    selectTable: {
      type: 'array',
      'x-decorator': 'FormItem',
      'x-component': 'SelectTable',
      'x-component-props': {
        hasBorder: false,
        showSearch: true,
        filterOption: false,
        onSearch: '{{useAsyncDataSource(loadData,$self)}}',
      },
      enum: [
        { key: '1', name: '标题1', description: '描述1' },
        { key: '2', name: '标题2', description: '描述2' },
      ],
      properties: {
        name: {
          title: '标题',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '40%',
          },
        },
        description: {
          title: '描述',
          type: 'string',
          'x-component': 'SelectTable.Column',
          'x-component-props': {
            width: '60%',
          },
        },
      },
    },
  },
}

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

## 纯 JSX 案例

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

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="SelectTable"
      dataSource={[
        { key: '1', name: '标题1', description: '描述1' },
        { key: '2', name: '标题2', description: '描述2' },
      ]}
      decorator={[FormItem]}
      component={[
        SelectTable,
        {
          hasBorder: false,
          columns: [
            { dataIndex: 'name', title: '标题' },
            { dataIndex: 'description', title: '描述' },
          ],
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

### SelectTable

| 属性名        | 类型                                         | 描述                                                                                                                                 | 默认值       |
| ------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
| mode          | `'multiple' \| 'single'`                     | 设置 SelectTable 模式为单选或多选                                                                                                    | `'multiple'` |
| valueType     | `'all' \| 'parent' \| 'child' \| 'path'`     | 返回值类型,checkStrictly 设置为 `false` 时有效                                                                                      | `'all'`      |
| optionAsValue | boolean                                      | 使用表格行数据作为值,valueType 值为 `'path'` 时无效                                                                                 | false        |
| showSearch    | boolean                                      | 是否显示搜索组件                                                                                                                     | false        |
| searchProps   | object                                       | Search 组件属性                                                                                                                      | -            |
| primaryKey    | `string \| (record) => string`               | 表格行 key 的取值                                                                                                                    | `'key'`      |
| filterOption  | `boolean \| (inputValue, option) => boolean` | 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 false | true         |
| filterSort    | (optionA, optionB) => number                 | 搜索时对筛选结果项的排序函数, 类似 Array.sort 里的 compareFunction                                                                   | -            |
| onSearch      | 文本框值变化时回调                           | (inputValue) => void                                                                                                                 | -            |

参考 https://fusion.design/pc/component/basic/table

### rowSelection

| 属性名        | 类型    | 描述                                                         | 默认值 |
| ------------- | ------- | ------------------------------------------------------------ | ------ |
| checkStrictly | boolean | checkable 状态下节点选择完全受控(父子数据选中状态不再关联) | true   |

参考 https://fusion.design/pc/component/basic/table rowSelection

### SelectTable.Column

参考 https://fusion.design/pc/component/basic/table Table.Column 属性

```
Page 24/35FirstPrevNextLast