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

# Directory Structure

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

# Files

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

```typescript
  1 | import expect from 'expect'
  2 | import { Parser } from '../parser'
  3 | import { Path } from '../'
  4 | const parse = (string: string, json: any, index: number) => {
  5 |   test('test ' + string + ` : ${index}`, () => {
  6 |     const parser = new Parser(string)
  7 |     expect(parser.parse()).toEqual(json)
  8 |   })
  9 | }
 10 | 
 11 | const batchTest = (obj) => {
 12 |   let i = 0
 13 |   for (let key in obj) {
 14 |     i++
 15 |     parse(key, obj[key], i)
 16 |   }
 17 | }
 18 | 
 19 | test('relative', () => {
 20 |   const parser = new Parser('..[ + 1 ].dd.bb', new Path(['aa', '1', 'cc']))
 21 |   const parser2 = new Parser('.ee', new Path(['aa', '1', 'cc']))
 22 |   const parser3 = new Parser('.', new Path(['aa', '1', 'cc']))
 23 |   const parser4 = new Parser('..', new Path(['aa', '1', 'cc']))
 24 |   const parser5 = new Parser('.[].dd', new Path(['aa', '1']))
 25 |   const parser6 = new Parser('.[].[]', new Path(['aa', '1']))
 26 |   const parser7 = new Parser('.[].[aa]', new Path(['aa', '1']))
 27 |   parser2.parse()
 28 |   parser3.parse()
 29 |   parser4.parse()
 30 |   parser5.parse()
 31 |   parser6.parse()
 32 |   parser7.parse()
 33 |   expect(parser.parse()).toEqual({
 34 |     type: 'Identifier',
 35 |     value: 'aa',
 36 |     after: {
 37 |       type: 'DotOperator',
 38 |       after: {
 39 |         type: 'DestructorExpression',
 40 |         value: {
 41 |           type: 'ArrayPattern',
 42 |           elements: [
 43 |             {
 44 |               type: 'Identifier',
 45 |               value: '+',
 46 |               after: {
 47 |                 type: 'Identifier',
 48 |                 value: '1',
 49 |               },
 50 |             },
 51 |           ],
 52 |         },
 53 |         source: '2',
 54 |         after: {
 55 |           type: 'DotOperator',
 56 |           after: {
 57 |             type: 'Identifier',
 58 |             value: 'dd',
 59 |             after: {
 60 |               type: 'DotOperator',
 61 |               after: {
 62 |                 type: 'Identifier',
 63 |                 value: 'bb',
 64 |               },
 65 |             },
 66 |           },
 67 |         },
 68 |       },
 69 |     },
 70 |   })
 71 |   expect(parser.data.segments).toEqual(['aa', '2', 'dd', 'bb'])
 72 |   expect(parser2.data.segments).toEqual(['aa', '1', 'ee'])
 73 |   expect(parser3.data.segments).toEqual(['aa', '1'])
 74 |   expect(parser4.data.segments).toEqual(['aa'])
 75 |   expect(parser5.data.segments).toEqual(['aa', '1', 'dd'])
 76 |   expect(parser6.data.segments).toEqual(['aa', '1', '[]'])
 77 |   expect(parser7.data.segments).toEqual(['aa', '1', '[aa]'])
 78 | })
 79 | 
 80 | test('calculate', () => {
 81 |   const parser0 = new Parser('..[+].dd.bb', new Path(['aa', '1', 'cc']))
 82 |   parser0.parse()
 83 |   expect(parser0.data.segments).toEqual(['aa', '2', 'dd', 'bb'])
 84 | 
 85 |   const parser = new Parser('..[ -1 ].dd.bb', new Path(['aa', '1', 'cc']))
 86 |   parser.parse()
 87 |   expect(parser.data.segments).toEqual(['aa', '0', 'dd', 'bb'])
 88 | 
 89 |   // TODO support
 90 |   // const parser2 = new Parser('..[ *2 ].dd.bb', new Path(['aa', '2', 'cc']))
 91 |   // parser2.parse()
 92 |   // expect(parser2.data.segments).toEqual(['aa', '4', 'dd', 'bb'])
 93 | 
 94 |   const parser3 = new Parser('..[ /2 ].dd.bb', new Path(['aa', '2', 'cc']))
 95 |   parser3.parse()
 96 |   expect(parser3.data.segments).toEqual(['aa', '1', 'dd', 'bb'])
 97 | 
 98 |   const parser4 = new Parser('..[ +1 ].dd.bb', new Path(['aa', 'a', 'cc']))
 99 |   parser4.parse()
100 |   expect(parser4.data.segments).toEqual(['aa', 'a1', 'dd', 'bb'])
101 | 
102 |   const parser5 = new Parser('..[ -1 ].dd.bb', new Path(['aa', 'a', 'cc']))
103 |   parser5.parse()
104 |   expect(parser5.data.segments).toEqual(['aa', 'NaN', 'dd', 'bb'])
105 | 
106 |   // TODO support
107 |   // const parser6 = new Parser('..[ *1 ].dd.bb', new Path(['aa', 'a', 'cc']))
108 |   // parser6.parse()
109 |   // expect(parser6.data.segments).toEqual(['aa', 'NaN', 'dd', 'bb'])
110 | 
111 |   const parser7 = new Parser('..[ /1 ].dd.bb', new Path(['aa', 'a', 'cc']))
112 |   parser7.parse()
113 |   expect(parser7.data.segments).toEqual(['aa', 'NaN', 'dd', 'bb'])
114 | 
115 |   const parser8 = new Parser('..[1].dd.bb', new Path(['aa', '1', 'cc']))
116 |   parser8.parse()
117 |   expect(parser8.data.segments).toEqual(['aa', '2', 'dd', 'bb'])
118 |   const parser9 = new Parser('')
119 |   parser9.next()
120 |   expect(parser9.parseObjectProperties()).toEqual([])
121 | })
122 | 
123 | test('parser unexpected', () => {
124 |   const parser = new Parser('array[]')
125 |   expect(() => parser.parse()).toThrowError()
126 | 
127 |   const parser2 = new Parser('array[0.')
128 |   expect(() => parser2.parse()).toThrowError()
129 | 
130 |   const parser3 = new Parser('.[+]', new Path('*.1.cc'))
131 |   expect(() => parser3.parse()).toThrowError()
132 | 
133 |   const parser4 = new Parser('[:,4]')
134 |   expect(() => parser4.parse()).toThrowError()
135 | })
136 | 
137 | test('tokenizer', () => {
138 |   const originFromCharCode = String.fromCharCode
139 |   String.fromCharCode = null
140 | 
141 |   const parser = new Parser('aa.bb')
142 |   parser.parse()
143 |   expect(parser.data.segments).toEqual(['aa', 'bb'])
144 | 
145 |   const parser2 = new Parser('array.0.[aa,bb]')
146 |   parser2.parse()
147 |   expect(parser2.data.segments).toEqual(['array', '0', '[aa,bb]'])
148 | 
149 |   String.fromCharCode = originFromCharCode
150 | 
151 |   const char13 = String.fromCharCode(13)
152 |   const parser3 = new Parser(`${char13} aa.bb`)
153 |   parser3.parse()
154 | 
155 |   const char11 = String.fromCharCode(11)
156 |   const parser4 = new Parser(`${char11} aa.bb`)
157 |   parser4.parse()
158 | 
159 |   const parser5 = new Parser('')
160 |   parser5.next()
161 |   parser5.parse()
162 |   expect(parser5.data.segments).toEqual([])
163 | 
164 |   const char10 = String.fromCharCode(10)
165 |   const parser6 = new Parser(`{
166 |                 c${char13}${char10}: kk,
167 |                 d : mm
168 |           }`)
169 |   parser6.parse()
170 |   expect(parser6.data.segments).toEqual(['{c:kk,d:mm}'])
171 | 
172 |   const parser7 = new Parser(`{
173 |                 c${char13}${char11}: kk,
174 |                 d : mm
175 |           }`)
176 |   parser7.parse()
177 |   expect(parser7.data.segments).toEqual(['{c:kk,d:mm}'])
178 | 
179 |   const parser8 = new Parser(`\\name`)
180 |   parser8.state.pos++
181 |   parser8.parse()
182 |   expect(parser8.data.segments).toEqual(['name'])
183 | 
184 |   const parser9 = new Parser(`[a,{b}]`)
185 |   parser9.parse()
186 |   expect(parser9.data.segments).toEqual(['[a,{b}]'])
187 | 
188 |   const parser10 = new Parser(`*(a.b.c.*(aa,bb))`)
189 |   parser10.parse()
190 |   expect(parser10.data.segments).toEqual([])
191 | 
192 |   const parser11 = new Parser(`{a,[b,{c}]. }`)
193 |   expect(() => parser11.parse()).toThrowError()
194 | 
195 |   const parser12 = new Parser(`*(a.*[1:3])`)
196 |   parser12.parse()
197 |   expect(parser12.data.segments).toEqual([])
198 | 
199 |   const parser13 = new Parser(`*(a.*[1:3]])`)
200 |   expect(() => parser13.parse()).toThrowError()
201 | })
202 | 
203 | batchTest({
204 |   '*': {
205 |     type: 'WildcardOperator',
206 |   },
207 |   'a.b.c': {
208 |     type: 'Identifier',
209 |     value: 'a',
210 |     after: {
211 |       type: 'DotOperator',
212 |       after: {
213 |         type: 'Identifier',
214 |         value: 'b',
215 |         after: {
216 |           type: 'DotOperator',
217 |           after: {
218 |             type: 'Identifier',
219 |             value: 'c',
220 |           },
221 |         },
222 |       },
223 |     },
224 |   },
225 |   'a.b.*': {
226 |     type: 'Identifier',
227 |     value: 'a',
228 |     after: {
229 |       type: 'DotOperator',
230 |       after: {
231 |         type: 'Identifier',
232 |         value: 'b',
233 |         after: {
234 |           type: 'DotOperator',
235 |           after: {
236 |             type: 'WildcardOperator',
237 |           },
238 |         },
239 |       },
240 |     },
241 |   },
242 |   'a.b.*(111,222,aaa)': {
243 |     type: 'Identifier',
244 |     value: 'a',
245 |     after: {
246 |       type: 'DotOperator',
247 |       after: {
248 |         type: 'Identifier',
249 |         value: 'b',
250 |         after: {
251 |           type: 'DotOperator',
252 |           after: {
253 |             type: 'WildcardOperator',
254 |             filter: {
255 |               type: 'GroupExpression',
256 |               value: [
257 |                 {
258 |                   type: 'Identifier',
259 |                   value: '111',
260 |                 },
261 |                 {
262 |                   type: 'Identifier',
263 |                   value: '222',
264 |                 },
265 |                 {
266 |                   type: 'Identifier',
267 |                   value: 'aaa',
268 |                 },
269 |               ],
270 |             },
271 |           },
272 |         },
273 |       },
274 |     },
275 |   },
276 |   'a.b.*(!111,222,aaa)': {
277 |     type: 'Identifier',
278 |     value: 'a',
279 |     after: {
280 |       type: 'DotOperator',
281 |       after: {
282 |         type: 'Identifier',
283 |         value: 'b',
284 |         after: {
285 |           type: 'DotOperator',
286 |           after: {
287 |             type: 'WildcardOperator',
288 |             filter: {
289 |               type: 'GroupExpression',
290 |               isExclude: true,
291 |               value: [
292 |                 {
293 |                   type: 'Identifier',
294 |                   value: '111',
295 |                 },
296 |                 {
297 |                   type: 'Identifier',
298 |                   value: '222',
299 |                 },
300 |                 {
301 |                   type: 'Identifier',
302 |                   value: 'aaa',
303 |                 },
304 |               ],
305 |             },
306 |           },
307 |         },
308 |       },
309 |     },
310 |   },
311 |   'a.b. * [  11 :  22  ]': {
312 |     type: 'Identifier',
313 |     value: 'a',
314 |     after: {
315 |       type: 'DotOperator',
316 |       after: {
317 |         type: 'Identifier',
318 |         value: 'b',
319 |         after: {
320 |           type: 'DotOperator',
321 |           after: {
322 |             type: 'WildcardOperator',
323 |             filter: {
324 |               type: 'RangeExpression',
325 |               start: {
326 |                 type: 'Identifier',
327 |                 value: '11',
328 |               },
329 |               end: {
330 |                 type: 'Identifier',
331 |                 value: '22',
332 |               },
333 |             },
334 |           },
335 |         },
336 |       },
337 |     },
338 |   },
339 |   'a.b.*([[123123!,()]],[[aaa]])': {
340 |     type: 'Identifier',
341 |     value: 'a',
342 |     after: {
343 |       type: 'DotOperator',
344 |       after: {
345 |         type: 'Identifier',
346 |         value: 'b',
347 |         after: {
348 |           type: 'DotOperator',
349 |           after: {
350 |             type: 'WildcardOperator',
351 |             filter: {
352 |               type: 'GroupExpression',
353 |               value: [
354 |                 {
355 |                   type: 'IgnoreExpression',
356 |                   value: '123123!,()',
357 |                 },
358 |                 {
359 |                   type: 'IgnoreExpression',
360 |                   value: 'aaa',
361 |                 },
362 |               ],
363 |             },
364 |           },
365 |         },
366 |       },
367 |     },
368 |   },
369 |   'a.b.*([[123123!,()]],aaa)': {
370 |     type: 'Identifier',
371 |     value: 'a',
372 |     after: {
373 |       type: 'DotOperator',
374 |       after: {
375 |         type: 'Identifier',
376 |         value: 'b',
377 |         after: {
378 |           type: 'DotOperator',
379 |           after: {
380 |             type: 'WildcardOperator',
381 |             filter: {
382 |               type: 'GroupExpression',
383 |               value: [
384 |                 {
385 |                   type: 'IgnoreExpression',
386 |                   value: '123123!,()',
387 |                 },
388 |                 {
389 |                   type: 'Identifier',
390 |                   value: 'aaa',
391 |                 },
392 |               ],
393 |             },
394 |           },
395 |         },
396 |       },
397 |     },
398 |   },
399 |   'a.b.*(![[123123!,()]],aaa)': {
400 |     type: 'Identifier',
401 |     value: 'a',
402 |     after: {
403 |       type: 'DotOperator',
404 |       after: {
405 |         type: 'Identifier',
406 |         value: 'b',
407 |         after: {
408 |           type: 'DotOperator',
409 |           after: {
410 |             type: 'WildcardOperator',
411 |             filter: {
412 |               type: 'GroupExpression',
413 |               value: [
414 |                 {
415 |                   type: 'IgnoreExpression',
416 |                   value: '123123!,()',
417 |                 },
418 |                 {
419 |                   type: 'Identifier',
420 |                   value: 'aaa',
421 |                 },
422 |               ],
423 |               isExclude: true,
424 |             },
425 |           },
426 |         },
427 |       },
428 |     },
429 |   },
430 |   'a.b  . *   (![[123123!,()]],aaa,bbb)': {
431 |     type: 'Identifier',
432 |     value: 'a',
433 |     after: {
434 |       type: 'DotOperator',
435 |       after: {
436 |         type: 'Identifier',
437 |         value: 'b',
438 |         after: {
439 |           type: 'DotOperator',
440 |           after: {
441 |             type: 'WildcardOperator',
442 |             filter: {
443 |               type: 'GroupExpression',
444 |               value: [
445 |                 {
446 |                   type: 'IgnoreExpression',
447 |                   value: '123123!,()',
448 |                 },
449 |                 {
450 |                   type: 'Identifier',
451 |                   value: 'aaa',
452 |                 },
453 |                 {
454 |                   type: 'Identifier',
455 |                   value: 'bbb',
456 |                 },
457 |               ],
458 |               isExclude: true,
459 |             },
460 |           },
461 |         },
462 |       },
463 |     },
464 |   },
465 |   'a.b.[[123123!,()]]   ': {
466 |     type: 'Identifier',
467 |     value: 'a',
468 |     after: {
469 |       type: 'DotOperator',
470 |       after: {
471 |         type: 'Identifier',
472 |         value: 'b',
473 |         after: {
474 |           type: 'DotOperator',
475 |           after: {
476 |             type: 'IgnoreExpression',
477 |             value: '123123!,()',
478 |           },
479 |         },
480 |       },
481 |     },
482 |   },
483 |   [`a .  
484 |      b .  
485 |        [[123123!,()]]
486 |     
487 |     .aaaa`]: {
488 |     type: 'Identifier',
489 |     value: 'a',
490 |     after: {
491 |       type: 'DotOperator',
492 |       after: {
493 |         type: 'Identifier',
494 |         value: 'b',
495 |         after: {
496 |           type: 'DotOperator',
497 |           after: {
498 |             type: 'IgnoreExpression',
499 |             value: '123123!,()',
500 |             after: {
501 |               type: 'DotOperator',
502 |               after: {
503 |                 type: 'Identifier',
504 |                 value: 'aaaa',
505 |               },
506 |             },
507 |           },
508 |         },
509 |       },
510 |     },
511 |   },
512 |   'a.*(aaa.d.*(!sss),ddd,bbb).c.b': {
513 |     type: 'Identifier',
514 |     value: 'a',
515 |     after: {
516 |       type: 'DotOperator',
517 |       after: {
518 |         type: 'WildcardOperator',
519 |         filter: {
520 |           type: 'GroupExpression',
521 |           value: [
522 |             {
523 |               type: 'Identifier',
524 |               value: 'aaa',
525 |               after: {
526 |                 type: 'DotOperator',
527 |                 after: {
528 |                   type: 'Identifier',
529 |                   value: 'd',
530 |                   after: {
531 |                     type: 'DotOperator',
532 |                     after: {
533 |                       type: 'WildcardOperator',
534 |                       filter: {
535 |                         type: 'GroupExpression',
536 |                         isExclude: true,
537 |                         value: [
538 |                           {
539 |                             type: 'Identifier',
540 |                             value: 'sss',
541 |                           },
542 |                         ],
543 |                       },
544 |                     },
545 |                   },
546 |                 },
547 |               },
548 |             },
549 |             {
550 |               type: 'Identifier',
551 |               value: 'ddd',
552 |             },
553 |             {
554 |               type: 'Identifier',
555 |               value: 'bbb',
556 |             },
557 |           ],
558 |         },
559 |         after: {
560 |           type: 'DotOperator',
561 |           after: {
562 |             type: 'Identifier',
563 |             value: 'c',
564 |             after: {
565 |               type: 'DotOperator',
566 |               after: {
567 |                 type: 'Identifier',
568 |                 value: 'b',
569 |               },
570 |             },
571 |           },
572 |         },
573 |       },
574 |     },
575 |   },
576 |   'aa.bb.cc.{aa,bb,cc:kk}': {
577 |     type: 'Identifier',
578 |     value: 'aa',
579 |     after: {
580 |       type: 'DotOperator',
581 |       after: {
582 |         type: 'Identifier',
583 |         value: 'bb',
584 |         after: {
585 |           type: 'DotOperator',
586 |           after: {
587 |             type: 'Identifier',
588 |             value: 'cc',
589 |             after: {
590 |               type: 'DotOperator',
591 |               after: {
592 |                 type: 'DestructorExpression',
593 |                 value: {
594 |                   type: 'ObjectPattern',
595 |                   properties: [
596 |                     {
597 |                       type: 'ObjectPatternProperty',
598 |                       key: { type: 'Identifier', value: 'aa' },
599 |                     },
600 |                     {
601 |                       type: 'ObjectPatternProperty',
602 |                       key: { type: 'Identifier', value: 'bb' },
603 |                     },
604 |                     {
605 |                       type: 'ObjectPatternProperty',
606 |                       key: { type: 'Identifier', value: 'cc' },
607 |                       value: { type: 'Identifier', value: 'kk' },
608 |                     },
609 |                   ],
610 |                 },
611 |                 source: '{aa,bb,cc:kk}',
612 |               },
613 |             },
614 |           },
615 |         },
616 |       },
617 |     },
618 |   },
619 |   'aa.bb.cc.[ [aa,bb,cc,[ [{aa:bb}] ]] ]': {
620 |     type: 'Identifier',
621 |     value: 'aa',
622 |     after: {
623 |       type: 'DotOperator',
624 |       after: {
625 |         type: 'Identifier',
626 |         value: 'bb',
627 |         after: {
628 |           type: 'DotOperator',
629 |           after: {
630 |             type: 'Identifier',
631 |             value: 'cc',
632 |             after: {
633 |               type: 'DotOperator',
634 |               after: {
635 |                 type: 'DestructorExpression',
636 |                 value: {
637 |                   type: 'ArrayPattern',
638 |                   elements: [
639 |                     {
640 |                       type: 'ArrayPattern',
641 |                       elements: [
642 |                         {
643 |                           type: 'Identifier',
644 |                           value: 'aa',
645 |                         },
646 |                         {
647 |                           type: 'Identifier',
648 |                           value: 'bb',
649 |                         },
650 |                         {
651 |                           type: 'Identifier',
652 |                           value: 'cc',
653 |                         },
654 |                         {
655 |                           type: 'ArrayPattern',
656 |                           elements: [
657 |                             {
658 |                               type: 'ArrayPattern',
659 |                               elements: [
660 |                                 {
661 |                                   type: 'ObjectPattern',
662 |                                   properties: [
663 |                                     {
664 |                                       type: 'ObjectPatternProperty',
665 |                                       key: {
666 |                                         type: 'Identifier',
667 |                                         value: 'aa',
668 |                                       },
669 |                                       value: {
670 |                                         type: 'Identifier',
671 |                                         value: 'bb',
672 |                                       },
673 |                                     },
674 |                                   ],
675 |                                 },
676 |                               ],
677 |                             },
678 |                           ],
679 |                         },
680 |                       ],
681 |                     },
682 |                   ],
683 |                 },
684 |                 source: '[[aa,bb,cc,[[{aa:bb}]]]]',
685 |               },
686 |             },
687 |           },
688 |         },
689 |       },
690 |     },
691 |   },
692 | })
693 | 
```

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

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

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

```typescript
  1 | import { createForm } from '@formily/core'
  2 | import { useFieldSchema, useField, Schema } from '../'
  3 | import {
  4 |   FormProvider,
  5 |   RecursionField,
  6 |   createSchemaField,
  7 | } from '../vue2-components'
  8 | import { render } from '@testing-library/vue'
  9 | import { mount, createLocalVue } from '@vue/test-utils'
 10 | import Vue, { CreateElement } from 'vue'
 11 | import { defineComponent, h } from '@vue/composition-api'
 12 | 
 13 | Vue.component('FormProvider', FormProvider)
 14 | Vue.component('RecursionField', RecursionField)
 15 | 
 16 | const Input = defineComponent({
 17 |   props: ['value'],
 18 |   setup(props, { attrs, listeners }) {
 19 |     return () => {
 20 |       return h('input', {
 21 |         attrs: {
 22 |           ...attrs,
 23 |           value: props.value,
 24 |           'data-testid': 'input',
 25 |         },
 26 |         on: {
 27 |           ...listeners,
 28 |           input: listeners.change,
 29 |         },
 30 |       })
 31 |     }
 32 |   },
 33 | })
 34 | 
 35 | describe('markup schema field', () => {
 36 |   test('string', () => {
 37 |     const form = createForm()
 38 |     const { SchemaField, SchemaStringField } = createSchemaField({
 39 |       components: {
 40 |         Input,
 41 |       },
 42 |     })
 43 |     const { queryByTestId } = render({
 44 |       components: { SchemaField, SchemaStringField },
 45 |       data() {
 46 |         return {
 47 |           form,
 48 |         }
 49 |       },
 50 |       template: `<FormProvider :form="form">
 51 |         <SchemaField>
 52 |           <SchemaStringField x-component="Input" />
 53 |         </SchemaField>
 54 |       </FormProvider>`,
 55 |     })
 56 |     expect(queryByTestId('input')).toBeVisible()
 57 |   })
 58 | 
 59 |   test('boolean', () => {
 60 |     const form = createForm()
 61 |     const { SchemaField, SchemaBooleanField } = createSchemaField({
 62 |       components: {
 63 |         Input,
 64 |       },
 65 |     })
 66 |     const { queryByTestId } = render({
 67 |       components: { SchemaField, SchemaBooleanField },
 68 |       data() {
 69 |         return {
 70 |           form,
 71 |         }
 72 |       },
 73 |       template: `<FormProvider :form="form">
 74 |         <SchemaField>
 75 |           <SchemaBooleanField x-component="Input" />
 76 |         </SchemaField>
 77 |       </FormProvider>`,
 78 |     })
 79 |     expect(queryByTestId('input')).toBeVisible()
 80 |   })
 81 | 
 82 |   test('number', () => {
 83 |     const form = createForm()
 84 |     const { SchemaField, SchemaNumberField } = createSchemaField({
 85 |       components: {
 86 |         Input,
 87 |       },
 88 |     })
 89 |     const { queryByTestId } = render({
 90 |       components: { SchemaField, SchemaNumberField },
 91 |       data() {
 92 |         return {
 93 |           form,
 94 |         }
 95 |       },
 96 |       template: `<FormProvider :form="form">
 97 |         <SchemaField>
 98 |           <SchemaNumberField x-component="Input" />
 99 |         </SchemaField>
100 |       </FormProvider>`,
101 |     })
102 |     expect(queryByTestId('input')).toBeVisible()
103 |   })
104 | 
105 |   test('date', () => {
106 |     const form = createForm()
107 |     const { SchemaField, SchemaDateField } = createSchemaField({
108 |       components: {
109 |         Input,
110 |       },
111 |     })
112 |     const { queryByTestId } = render({
113 |       components: { SchemaField, SchemaDateField },
114 |       data() {
115 |         return {
116 |           form,
117 |         }
118 |       },
119 |       template: `<FormProvider :form="form">
120 |         <SchemaField>
121 |           <SchemaDateField x-component="Input" />
122 |         </SchemaField>
123 |       </FormProvider>`,
124 |     })
125 |     expect(queryByTestId('input')).toBeVisible()
126 |   })
127 | 
128 |   test('datetime', () => {
129 |     const form = createForm()
130 |     const { SchemaField, SchemaDateTimeField } = createSchemaField({
131 |       components: {
132 |         Input,
133 |       },
134 |     })
135 |     const { queryByTestId } = render({
136 |       components: { SchemaField, SchemaDateTimeField },
137 |       data() {
138 |         return {
139 |           form,
140 |         }
141 |       },
142 |       template: `<FormProvider :form="form">
143 |         <SchemaField>
144 |           <SchemaDateTimeField x-component="Input" />
145 |         </SchemaField>
146 |       </FormProvider>`,
147 |     })
148 |     expect(queryByTestId('input')).toBeVisible()
149 |   })
150 | 
151 |   test('void', () => {
152 |     const form = createForm()
153 |     const VoidComponent = {
154 |       render(h: CreateElement) {
155 |         return h(
156 |           'div',
157 |           { attrs: { 'data-testid': 'void-component' } },
158 |           this.$slots.default
159 |         )
160 |       },
161 |     }
162 |     const { SchemaField, SchemaVoidField } = createSchemaField({
163 |       components: {
164 |         VoidComponent,
165 |       },
166 |     })
167 |     const { queryByTestId } = render({
168 |       components: { SchemaField, SchemaVoidField },
169 |       data() {
170 |         return {
171 |           form,
172 |         }
173 |       },
174 |       template: `<FormProvider :form="form">
175 |         <SchemaField>
176 |           <SchemaVoidField x-component="VoidComponent" />
177 |         </SchemaField>
178 |       </FormProvider>`,
179 |     })
180 |     expect(queryByTestId('void-component')).toBeVisible()
181 |   })
182 | 
183 |   test('array', () => {
184 |     const form = createForm()
185 |     const components = createSchemaField({
186 |       components: {
187 |         Input,
188 |       },
189 |     })
190 |     render({
191 |       components: { ...components },
192 |       data() {
193 |         return {
194 |           form,
195 |         }
196 |       },
197 |       template: `<FormProvider :form="form">
198 |         <SchemaField>
199 |           <SchemaArrayField>
200 |             <SchemaObjectField>
201 |               <SchemaStringField x-component="Input" />
202 |             </SchemaObjectField>
203 |             <SchemaVoidField />
204 |           </SchemaArrayField>
205 |         </SchemaField>
206 |       </FormProvider>`,
207 |     })
208 |   })
209 | 
210 |   test('other', () => {
211 |     const form = createForm()
212 |     const components = createSchemaField({
213 |       components: {
214 |         Input,
215 |       },
216 |     })
217 |     render({
218 |       components: { ...components },
219 |       data() {
220 |         return {
221 |           form,
222 |         }
223 |       },
224 |       template: `<FormProvider :form="form">
225 |         <SchemaField>
226 |           <SchemaMarkupField type="other">
227 |             <SchemaMarkupField />
228 |           </SchemaMarkupField>
229 |         </SchemaField>
230 |       </FormProvider>`,
231 |     })
232 |   })
233 | 
234 |   test('no parent', () => {
235 |     const form = createForm()
236 |     const components = createSchemaField({
237 |       components: {
238 |         Input,
239 |       },
240 |     })
241 |     render({
242 |       components: { ...components },
243 |       data() {
244 |         return {
245 |           form,
246 |         }
247 |       },
248 |       template: `<FormProvider :form="form">
249 |         <SchemaMarkupField type="other">
250 |           <SchemaMarkupField />
251 |         </SchemaMarkupField>
252 |       </FormProvider>`,
253 |     })
254 |   })
255 | })
256 | 
257 | describe('recursion field', () => {
258 |   test('onlyRenderProperties', () => {
259 |     const form = createForm()
260 | 
261 |     const CustomObject = defineComponent({
262 |       setup() {
263 |         const schemaRef = useFieldSchema()
264 |         return () => {
265 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
266 |             h('RecursionField', { props: { schema: schemaRef.value } }),
267 |           ])
268 |         }
269 |       },
270 |     })
271 | 
272 |     const CustomObject2 = defineComponent({
273 |       setup() {
274 |         const fieldRef = useField()
275 |         const schemaRef = useFieldSchema()
276 |         return () => {
277 |           const schema = schemaRef.value
278 |           const field = fieldRef.value
279 |           return h('div', { attrs: { 'data-testid': 'only-properties' } }, [
280 |             h('RecursionField', {
281 |               props: {
282 |                 name: schema.name,
283 |                 basePath: field.address,
284 |                 schema,
285 |                 onlyRenderProperties: true,
286 |               },
287 |             }),
288 |           ])
289 |         }
290 |       },
291 |     })
292 | 
293 |     const components = createSchemaField({
294 |       components: {
295 |         Input,
296 |         CustomObject,
297 |         CustomObject2,
298 |       },
299 |     })
300 | 
301 |     const { queryAllByTestId } = render({
302 |       components: components,
303 |       data() {
304 |         return {
305 |           form,
306 |         }
307 |       },
308 |       template: `<FormProvider :form="form">
309 |         <SchemaField>
310 |           <SchemaObjectField x-component="CustomObject">
311 |             <SchemaStringField x-component="Input" />
312 |           </SchemaObjectField>
313 |           <SchemaObjectField x-component="CustomObject2">
314 |             <SchemaStringField x-component="Input" />
315 |           </SchemaObjectField>
316 |           <SchemaVoidField x-component="CustomObject2">
317 |             <SchemaStringField x-component="Input" />
318 |           </SchemaVoidField>
319 |         </SchemaField>
320 |       </FormProvider>`,
321 |     })
322 |     expect(queryAllByTestId('input').length).toEqual(3)
323 |     expect(queryAllByTestId('object').length).toEqual(1)
324 |     expect(queryAllByTestId('only-properties').length).toEqual(2)
325 |   })
326 | 
327 |   test('mapProperties', () => {
328 |     const form = createForm()
329 | 
330 |     const CustomObject = defineComponent({
331 |       setup() {
332 |         const schemaRef = useFieldSchema()
333 |         return () => {
334 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
335 |             h('RecursionField', {
336 |               props: {
337 |                 schema: schemaRef.value,
338 |                 mapProperties: (schema) => {
339 |                   schema.default = '123'
340 |                   return schema
341 |                 },
342 |               },
343 |             }),
344 |           ])
345 |         }
346 |       },
347 |     })
348 | 
349 |     const CustomObject2 = defineComponent({
350 |       setup() {
351 |         const schemaRef = useFieldSchema()
352 |         return () => {
353 |           const schema = schemaRef.value
354 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
355 |             h('RecursionField', {
356 |               props: {
357 |                 schema,
358 |                 mapProperties: () => {
359 |                   return null
360 |                 },
361 |               },
362 |             }),
363 |           ])
364 |         }
365 |       },
366 |     })
367 | 
368 |     const components = createSchemaField({
369 |       components: {
370 |         Input,
371 |         CustomObject,
372 |         CustomObject2,
373 |       },
374 |     })
375 | 
376 |     const { queryAllByTestId } = render({
377 |       components: components,
378 |       data() {
379 |         return {
380 |           form,
381 |         }
382 |       },
383 |       template: `<FormProvider :form="form">
384 |         <SchemaField>
385 |           <SchemaObjectField x-component="CustomObject">
386 |             <SchemaStringField x-component="Input" />
387 |           </SchemaObjectField>
388 |           <SchemaObjectField x-component="CustomObject2">
389 |             <SchemaStringField x-component="Input" />
390 |           </SchemaObjectField>
391 |         </SchemaField>
392 |       </FormProvider>`,
393 |     })
394 |     expect(queryAllByTestId('input').length).toEqual(2)
395 |     expect(queryAllByTestId('input')[0].getAttribute('value')).toEqual('123')
396 |     expect(queryAllByTestId('input')[1].getAttribute('value')).toBeFalsy()
397 |   })
398 | 
399 |   test('filterProperties', () => {
400 |     const form = createForm()
401 | 
402 |     const CustomObject = defineComponent({
403 |       setup() {
404 |         const schemaRef = useFieldSchema()
405 |         return () => {
406 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
407 |             h('RecursionField', {
408 |               props: {
409 |                 schema: schemaRef.value,
410 |                 filterProperties: (schema: Schema) => {
411 |                   if (schema['x-component'] === 'Input') return false
412 |                   return true
413 |                 },
414 |               },
415 |             }),
416 |           ])
417 |         }
418 |       },
419 |     })
420 | 
421 |     const CustomObject2 = defineComponent({
422 |       setup() {
423 |         const schemaRef = useFieldSchema()
424 |         return () => {
425 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
426 |             h('RecursionField', {
427 |               props: {
428 |                 schema: schemaRef.value,
429 |                 filterProperties: (schema: Schema) => {
430 |                   if (schema['x-component'] === 'Input') return
431 |                   return true
432 |                 },
433 |               },
434 |             }),
435 |           ])
436 |         }
437 |       },
438 |     })
439 | 
440 |     const components = createSchemaField({
441 |       components: {
442 |         Input,
443 |         CustomObject,
444 |         CustomObject2,
445 |       },
446 |     })
447 | 
448 |     const { queryAllByTestId } = render({
449 |       components: components,
450 |       data() {
451 |         return {
452 |           form,
453 |         }
454 |       },
455 |       template: `<FormProvider :form="form">
456 |         <SchemaField>
457 |           <SchemaObjectField x-component="CustomObject">
458 |             <SchemaStringField x-component="Input" />
459 |           </SchemaObjectField>
460 |           <SchemaObjectField x-component="CustomObject2">
461 |             <SchemaStringField x-component="Input" />
462 |           </SchemaObjectField>
463 |         </SchemaField>
464 |       </FormProvider>`,
465 |     })
466 |     expect(queryAllByTestId('input').length).toEqual(1)
467 |     expect(queryAllByTestId('object').length).toEqual(2)
468 |   })
469 | 
470 |   test('onlyRenderSelf', () => {
471 |     const form = createForm()
472 | 
473 |     const CustomObject = defineComponent({
474 |       setup() {
475 |         const schemaRef = useFieldSchema()
476 |         return () => {
477 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
478 |             h('RecursionField', {
479 |               props: {
480 |                 schema: schemaRef.value,
481 |                 onlyRenderSelf: true,
482 |               },
483 |             }),
484 |           ])
485 |         }
486 |       },
487 |     })
488 | 
489 |     const components = createSchemaField({
490 |       components: {
491 |         Input,
492 |         CustomObject,
493 |       },
494 |     })
495 | 
496 |     const { queryAllByTestId } = render({
497 |       components: components,
498 |       data() {
499 |         return {
500 |           form,
501 |         }
502 |       },
503 |       template: `<FormProvider :form="form">
504 |         <SchemaField>
505 |           <SchemaObjectField x-component="CustomObject">
506 |             <SchemaStringField x-component="Input" />
507 |           </SchemaObjectField>
508 |         </SchemaField>
509 |       </FormProvider>`,
510 |     })
511 |     expect(queryAllByTestId('input').length).toEqual(0)
512 |     expect(queryAllByTestId('object').length).toEqual(1)
513 |   })
514 | 
515 |   test('illegal schema', () => {
516 |     const form = createForm()
517 | 
518 |     const CustomObject = defineComponent({
519 |       setup() {
520 |         return () => {
521 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
522 |             h('RecursionField', {
523 |               props: {
524 |                 schema: null,
525 |               },
526 |             }),
527 |           ])
528 |         }
529 |       },
530 |     })
531 | 
532 |     const CustomObject2 = defineComponent({
533 |       setup() {
534 |         return () => {
535 |           return h('div', { attrs: { 'data-testid': 'object' } }, [
536 |             h('RecursionField', {
537 |               props: {
538 |                 schema: {},
539 |               },
540 |             }),
541 |           ])
542 |         }
543 |       },
544 |     })
545 | 
546 |     const components = createSchemaField({
547 |       components: {
548 |         Input,
549 |         CustomObject,
550 |         CustomObject2,
551 |       },
552 |     })
553 | 
554 |     const { queryByTestId } = render({
555 |       components: components,
556 |       data() {
557 |         return {
558 |           form,
559 |         }
560 |       },
561 |       template: `<FormProvider :form="form">
562 |         <SchemaField>
563 |           <SchemaObjectField x-component="CustomObject">
564 |             <SchemaStringField x-component="Input" />
565 |           </SchemaObjectField>
566 |           <SchemaObjectField x-component="CustomObject2">
567 |             <SchemaStringField x-component="Input" />
568 |           </SchemaObjectField>
569 |         </SchemaField>
570 |       </FormProvider>`,
571 |     })
572 |     expect(queryByTestId('input')).toBeNull()
573 |   })
574 | 
575 |   test('schema reactions', async () => {
576 |     const div = document.createElement('div')
577 |     document.body.appendChild(div)
578 |     const form = createForm()
579 |     const components = createSchemaField({
580 |       components: {
581 |         Input,
582 |       },
583 |     })
584 |     const localVue = createLocalVue()
585 |     localVue.component('FormProvider', FormProvider)
586 |     const TestComponent = {
587 |       components: components,
588 |       data() {
589 |         return {
590 |           form,
591 |           reactions: [
592 |             {
593 |               when: '{{$form.values.aaa === "123"}}',
594 |               fulfill: {
595 |                 state: {
596 |                   visible: true,
597 |                 },
598 |               },
599 |               otherwise: {
600 |                 state: {
601 |                   visible: false,
602 |                 },
603 |               },
604 |             },
605 |             {
606 |               when: '{{$self.value === "123"}}',
607 |               target: 'ccc',
608 |               fulfill: {
609 |                 schema: {
610 |                   'x-visible': true,
611 |                 },
612 |               },
613 |               otherwise: {
614 |                 schema: {
615 |                   'x-visible': false,
616 |                 },
617 |               },
618 |             },
619 |           ],
620 |         }
621 |       },
622 |       template: `<FormProvider :form="form">
623 |         <SchemaField>
624 |           <SchemaStringField
625 |             name="aaa"
626 |             x-component="Input"
627 |             :x-component-props="{
628 |               'class': 'aaa',
629 |             }"
630 |           />
631 |           <SchemaStringField
632 |             name="bbb"
633 |             x-component="Input"
634 |             :x-component-props="{
635 |               'class': 'bbb',
636 |             }"
637 |             :x-reactions="reactions"
638 |           />
639 |           <SchemaStringField
640 |             name="ccc"
641 |             x-component="Input"
642 |             :x-component-props="{
643 |               'class': 'ccc',
644 |             }"
645 |           />
646 |         </SchemaField>
647 |       </FormProvider>`,
648 |     } as any
649 |     const wrapper = mount(TestComponent, {
650 |       // attachTo: div,
651 |       attachToDocument: true,
652 |       localVue,
653 |     })
654 |     expect(wrapper.find('.bbb').exists()).toBeFalsy()
655 |     wrapper.find('.aaa').setValue('123')
656 |     expect(form.query('aaa').get('value')).toEqual('123')
657 |     await wrapper.vm.$forceUpdate()
658 |     expect(wrapper.find('.bbb').exists()).toBeTruthy()
659 |     expect(wrapper.find('.ccc').exists()).toBeFalsy()
660 |     wrapper.find('.bbb').setValue('123')
661 |     expect(form.query('bbb').get('value')).toEqual('123')
662 |     await wrapper.vm.$forceUpdate()
663 |     expect(wrapper.find('.ccc').exists()).toBeTruthy()
664 |     wrapper.destroy()
665 |   })
666 | 
667 |   test('void field children', () => {
668 |     const form = createForm()
669 |     const VoidComponent = {
670 |       render(h: CreateElement) {
671 |         return h('div', this.$slots.default || 'placeholder')
672 |       },
673 |     }
674 |     const { SchemaField, SchemaVoidField } = createSchemaField({
675 |       components: {
676 |         VoidComponent,
677 |       },
678 |     })
679 |     const { queryByTestId } = render({
680 |       components: { SchemaField, SchemaVoidField },
681 |       data() {
682 |         return {
683 |           form,
684 |         }
685 |       },
686 |       template: `<FormProvider :form="form">
687 |         <SchemaField>
688 |           <SchemaVoidField x-component="VoidComponent" :x-component-props="{ 'data-testid': 'void-component-1' }" />
689 |           <SchemaVoidField x-component="VoidComponent" :x-component-props="{ 'data-testid': 'void-component-2' }" x-content="content" />
690 |         </SchemaField>
691 |       </FormProvider>`,
692 |     })
693 |     expect(queryByTestId('void-component-1').textContent).toBe('placeholder')
694 |     expect(queryByTestId('void-component-2').textContent).toBe('content')
695 |   })
696 | })
697 | 
```

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

```markdown
  1 | # SelectTable
  2 | 
  3 | > 表格选择组件
  4 | 
  5 | ## Markup Schema 单选案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
 10 | import { createForm } from '@formily/core'
 11 | import { FormProvider, createSchemaField } from '@formily/react'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     FormItem,
 16 |     SelectTable,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => {
 23 |   return (
 24 |     <FormProvider form={form}>
 25 |       <SchemaField>
 26 |         <SchemaField.Object
 27 |           type="string"
 28 |           name="selectTable"
 29 |           x-decorator="FormItem"
 30 |           x-component="SelectTable"
 31 |           x-component-props={{
 32 |             bordered: false,
 33 |             mode: 'single',
 34 |           }}
 35 |           enum={[
 36 |             { key: '1', name: '标题1', description: '描述1' },
 37 |             { key: '2', name: '标题2', description: '描述2' },
 38 |           ]}
 39 |         >
 40 |           <SchemaField.Void
 41 |             name="name"
 42 |             title="标题"
 43 |             x-component="SelectTable.Column"
 44 |           />
 45 |           <SchemaField.Void
 46 |             name="description"
 47 |             title="描述"
 48 |             x-component="SelectTable.Column"
 49 |           />
 50 |         </SchemaField.Object>
 51 |       </SchemaField>
 52 |       <FormButtonGroup.FormItem>
 53 |         <Submit onSubmit={console.log}>提交</Submit>
 54 |       </FormButtonGroup.FormItem>
 55 |     </FormProvider>
 56 |   )
 57 | }
 58 | ```
 59 | 
 60 | ## Markup Schema 筛选案例
 61 | 
 62 | ```tsx
 63 | import React from 'react'
 64 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
 65 | import { createForm } from '@formily/core'
 66 | import { FormProvider, createSchemaField } from '@formily/react'
 67 | 
 68 | const SchemaField = createSchemaField({
 69 |   components: {
 70 |     FormItem,
 71 |     SelectTable,
 72 |   },
 73 | })
 74 | 
 75 | const form = createForm()
 76 | 
 77 | export default () => {
 78 |   return (
 79 |     <FormProvider form={form}>
 80 |       <SchemaField>
 81 |         <SchemaField.Array
 82 |           type="array"
 83 |           name="selectTable"
 84 |           x-decorator="FormItem"
 85 |           x-component="SelectTable"
 86 |           x-component-props={{
 87 |             bordered: false,
 88 |             showSearch: true,
 89 |             optionAsValue: true,
 90 |           }}
 91 |           enum={[
 92 |             { key: '1', name: '标题1', description: '描述1' },
 93 |             { key: '2', name: '标题2', description: '描述2' },
 94 |           ]}
 95 |         >
 96 |           <SchemaField.Object>
 97 |             <SchemaField.Void
 98 |               name="name"
 99 |               title="标题"
100 |               x-component="SelectTable.Column"
101 |             />
102 |             <SchemaField.Void
103 |               name="description"
104 |               title="描述"
105 |               x-component="SelectTable.Column"
106 |             />
107 |           </SchemaField.Object>
108 |         </SchemaField.Array>
109 |       </SchemaField>
110 |       <FormButtonGroup.FormItem>
111 |         <Submit onSubmit={console.log}>提交</Submit>
112 |       </FormButtonGroup.FormItem>
113 |     </FormProvider>
114 |   )
115 | }
116 | ```
117 | 
118 | ## Markup Schema 异步数据源案例
119 | 
120 | ```tsx
121 | import React from 'react'
122 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
123 | import { createForm } from '@formily/core'
124 | import { FormProvider, createSchemaField } from '@formily/react'
125 | 
126 | const SchemaField = createSchemaField({
127 |   components: {
128 |     FormItem,
129 |     SelectTable,
130 |   },
131 | })
132 | 
133 | const form = createForm()
134 | 
135 | export default () => {
136 |   const onSearch = (value) => {
137 |     const field = form.query('selectTable').take()
138 |     field.loading = true
139 |     setTimeout(() => {
140 |       field.setState({
141 |         dataSource: [
142 |           {
143 |             key: '3',
144 |             name: 'AAA' + value,
145 |             description: 'aaa',
146 |           },
147 |           {
148 |             key: '4',
149 |             name: 'BBB' + value,
150 |             description: 'bbb',
151 |           },
152 |         ],
153 |         loading: false,
154 |       })
155 |     }, 1500)
156 |   }
157 | 
158 |   return (
159 |     <FormProvider form={form}>
160 |       <SchemaField>
161 |         <SchemaField.Object
162 |           type="object"
163 |           name="selectTable"
164 |           x-decorator="FormItem"
165 |           x-component="SelectTable"
166 |           x-component-props={{
167 |             showSearch: true,
168 |             filterOption: false,
169 |             onSearch,
170 |           }}
171 |           enum={[
172 |             { key: '1', name: '标题1', description: '描述1' },
173 |             { key: '2', name: '标题2', description: '描述2' },
174 |           ]}
175 |         >
176 |           <SchemaField.Void
177 |             name="name"
178 |             title="标题"
179 |             x-component="SelectTable.Column"
180 |           />
181 |           <SchemaField.Void
182 |             name="description"
183 |             title="描述"
184 |             x-component="SelectTable.Column"
185 |           />
186 |         </SchemaField.Object>
187 |       </SchemaField>
188 |       <FormButtonGroup.FormItem>
189 |         <Submit onSubmit={console.log}>提交</Submit>
190 |       </FormButtonGroup.FormItem>
191 |     </FormProvider>
192 |   )
193 | }
194 | ```
195 | 
196 | ## Markup Schema 阅读态案例
197 | 
198 | ```tsx
199 | import React from 'react'
200 | import {
201 |   Form,
202 |   FormItem,
203 |   FormButtonGroup,
204 |   Submit,
205 |   SelectTable,
206 | } from '@formily/antd'
207 | import { createForm } from '@formily/core'
208 | import { createSchemaField } from '@formily/react'
209 | 
210 | const SchemaField = createSchemaField({
211 |   components: {
212 |     FormItem,
213 |     SelectTable,
214 |   },
215 | })
216 | 
217 | const form = createForm()
218 | 
219 | export default () => {
220 |   return (
221 |     <Form form={form} layout="vertical">
222 |       <SchemaField>
223 |         <SchemaField.Object
224 |           title="单选"
225 |           type="string"
226 |           name="selectTable1"
227 |           x-decorator="FormItem"
228 |           x-component="SelectTable"
229 |           x-component-props={{
230 |             mode: 'single',
231 |           }}
232 |           default="1"
233 |           enum={[
234 |             { key: '1', name: '标题1', description: '描述1' },
235 |             { key: '2', name: '标题2', description: '描述2' },
236 |           ]}
237 |           x-read-pretty={true}
238 |         >
239 |           <SchemaField.Void
240 |             name="name"
241 |             title="标题"
242 |             x-component="SelectTable.Column"
243 |           />
244 |           <SchemaField.Void
245 |             name="description"
246 |             title="描述"
247 |             x-component="SelectTable.Column"
248 |           />
249 |         </SchemaField.Object>
250 |         <SchemaField.Object
251 |           title="单选 + optionAsValue"
252 |           type="string"
253 |           name="selectTable2"
254 |           x-decorator="FormItem"
255 |           x-component="SelectTable"
256 |           x-component-props={{
257 |             mode: 'single',
258 |             optionAsValue: true,
259 |           }}
260 |           default={{ key: '1', name: '标题1', description: '描述1' }}
261 |           enum={[
262 |             { key: '1', name: '标题1', description: '描述1' },
263 |             { key: '2', name: '标题2', description: '描述2' },
264 |           ]}
265 |           x-read-pretty={true}
266 |         >
267 |           <SchemaField.Void
268 |             name="name"
269 |             title="标题"
270 |             x-component="SelectTable.Column"
271 |           />
272 |           <SchemaField.Void
273 |             name="description"
274 |             title="描述"
275 |             x-component="SelectTable.Column"
276 |           />
277 |         </SchemaField.Object>
278 |         <SchemaField.Array
279 |           title="多选"
280 |           type="array"
281 |           name="selectTable3"
282 |           x-decorator="FormItem"
283 |           x-component="SelectTable"
284 |           default={['1', '3']}
285 |           enum={[
286 |             { key: '1', name: '标题1', description: '描述1' },
287 |             { key: '2', name: '标题2', description: '描述2' },
288 |             { key: '3', name: '标题3', description: '描述3' },
289 |           ]}
290 |           x-read-pretty={true}
291 |         >
292 |           <SchemaField.Object>
293 |             <SchemaField.Void
294 |               name="name"
295 |               title="标题"
296 |               x-component="SelectTable.Column"
297 |             />
298 |             <SchemaField.Void
299 |               name="description"
300 |               title="描述"
301 |               x-component="SelectTable.Column"
302 |             />
303 |           </SchemaField.Object>
304 |         </SchemaField.Array>
305 |         <SchemaField.Array
306 |           title="多选 + optionAsValue"
307 |           type="array"
308 |           name="selectTable4"
309 |           x-decorator="FormItem"
310 |           x-component="SelectTable"
311 |           x-component-props={{
312 |             optionAsValue: true,
313 |           }}
314 |           default={[
315 |             { key: '1', name: '标题1', description: '描述1' },
316 |             { key: '3', name: '标题3', description: '描述3' },
317 |           ]}
318 |           enum={[
319 |             { key: '1', name: '标题1', description: '描述1' },
320 |             { key: '2', name: '标题2', description: '描述2' },
321 |             { key: '3', name: '标题3', description: '描述3' },
322 |           ]}
323 |           x-read-pretty={true}
324 |         >
325 |           <SchemaField.Object>
326 |             <SchemaField.Void
327 |               name="name"
328 |               title="标题"
329 |               x-component="SelectTable.Column"
330 |             />
331 |             <SchemaField.Void
332 |               name="description"
333 |               title="描述"
334 |               x-component="SelectTable.Column"
335 |             />
336 |           </SchemaField.Object>
337 |         </SchemaField.Array>
338 |       </SchemaField>
339 |       <FormButtonGroup.FormItem>
340 |         <Submit onSubmit={console.log}>提交</Submit>
341 |       </FormButtonGroup.FormItem>
342 |     </Form>
343 |   )
344 | }
345 | ```
346 | 
347 | ## JSON Schema 多选案例
348 | 
349 | ```tsx
350 | import React from 'react'
351 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
352 | import { createForm } from '@formily/core'
353 | import { FormProvider, createSchemaField } from '@formily/react'
354 | 
355 | const SchemaField = createSchemaField({
356 |   components: {
357 |     SelectTable,
358 |     FormItem,
359 |   },
360 | })
361 | 
362 | const form = createForm()
363 | 
364 | const schema = {
365 |   type: 'object',
366 |   properties: {
367 |     selectTable: {
368 |       type: 'array',
369 |       'x-decorator': 'FormItem',
370 |       'x-component': 'SelectTable',
371 |       'x-component-props': {
372 |         bordered: false,
373 |         mode: 'multiple',
374 |       },
375 |       enum: [
376 |         { key: '1', name: '标题1', description: '描述1' },
377 |         { key: '2', name: '标题2', description: '描述2' },
378 |       ],
379 |       properties: {
380 |         name: {
381 |           title: '标题',
382 |           type: 'string',
383 |           'x-component': 'SelectTable.Column',
384 |           'x-component-props': {
385 |             width: '40%',
386 |           },
387 |         },
388 |         description: {
389 |           title: '描述',
390 |           type: 'string',
391 |           'x-component': 'SelectTable.Column',
392 |           'x-component-props': {
393 |             width: '60%',
394 |           },
395 |         },
396 |       },
397 |     },
398 |   },
399 | }
400 | 
401 | export default () => (
402 |   <FormProvider form={form}>
403 |     <SchemaField schema={schema} />
404 |     <FormButtonGroup>
405 |       <Submit onSubmit={console.log}>提交</Submit>
406 |     </FormButtonGroup>
407 |   </FormProvider>
408 | )
409 | ```
410 | 
411 | ## JSON Schema 自定义筛选案例
412 | 
413 | ```tsx
414 | import React from 'react'
415 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
416 | import { createForm } from '@formily/core'
417 | import { FormProvider, createSchemaField } from '@formily/react'
418 | 
419 | const SchemaField = createSchemaField({
420 |   components: {
421 |     SelectTable,
422 |     FormItem,
423 |   },
424 | })
425 | 
426 | const form = createForm()
427 | 
428 | const schema = {
429 |   type: 'object',
430 |   properties: {
431 |     selectTable: {
432 |       type: 'array',
433 |       'x-decorator': 'FormItem',
434 |       'x-component': 'SelectTable',
435 |       'x-component-props': {
436 |         bordered: false,
437 |         showSearch: true,
438 |         primaryKey: 'key',
439 |         isTree: true,
440 |         filterOption: (input, option) =>
441 |           option.description.toLowerCase().indexOf(input.toLowerCase()) >= 0,
442 |         filterSort: (optionA, optionB) =>
443 |           optionA.description
444 |             .toLowerCase()
445 |             .localeCompare(optionB.description.toLowerCase()),
446 |         optionAsValue: true,
447 |         rowSelection: {
448 |           checkStrictly: false,
449 |         },
450 |       },
451 |       enum: [
452 |         { key: '1', name: '标题1', description: 'A-描述' },
453 |         {
454 |           key: '2',
455 |           name: '标题2',
456 |           description: 'X-描述',
457 |           children: [
458 |             {
459 |               key: '2-1',
460 |               name: '标题2-1',
461 |               description: 'Y-描述',
462 |               children: [
463 |                 { key: '2-1-1', name: '标题2-1-1', description: 'Z-描述' },
464 |               ],
465 |             },
466 |             {
467 |               key: '2-2',
468 |               name: '标题2-2',
469 |               description: 'YY-描述',
470 |             },
471 |           ],
472 |         },
473 |         { key: '3', name: '标题3', description: 'C-描述' },
474 |       ],
475 |       properties: {
476 |         name: {
477 |           title: '标题',
478 |           type: 'string',
479 |           'x-component': 'SelectTable.Column',
480 |           'x-component-props': {
481 |             width: '40%',
482 |           },
483 |         },
484 |         description: {
485 |           title: '描述',
486 |           type: 'string',
487 |           'x-component': 'SelectTable.Column',
488 |           'x-component-props': {
489 |             width: '60%',
490 |           },
491 |         },
492 |       },
493 |     },
494 |   },
495 | }
496 | 
497 | export default () => (
498 |   <FormProvider form={form}>
499 |     <SchemaField schema={schema} />
500 |     <FormButtonGroup>
501 |       <Submit onSubmit={console.log}>提交</Submit>
502 |     </FormButtonGroup>
503 |   </FormProvider>
504 | )
505 | ```
506 | 
507 | ## JSON Schema 异步数据源案例
508 | 
509 | ```tsx
510 | import React from 'react'
511 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
512 | import { createForm } from '@formily/core'
513 | import { FormProvider, createSchemaField } from '@formily/react'
514 | 
515 | const SchemaField = createSchemaField({
516 |   components: {
517 |     SelectTable,
518 |     FormItem,
519 |   },
520 | })
521 | 
522 | const loadData = async (value) => {
523 |   return new Promise((resolve) => {
524 |     setTimeout(() => {
525 |       resolve([
526 |         { key: '3', name: 'AAA' + value, description: 'aaa' },
527 |         { key: '4', name: 'BBB' + value, description: 'bbb' },
528 |       ])
529 |     }, 1500)
530 |   })
531 | }
532 | 
533 | const useAsyncDataSource = (service, field) => (value) => {
534 |   field.loading = true
535 |   service(value).then((data) => {
536 |     field.setState({
537 |       dataSource: data,
538 |       loading: false,
539 |     })
540 |   })
541 | }
542 | 
543 | const form = createForm()
544 | 
545 | const schema = {
546 |   type: 'object',
547 |   properties: {
548 |     selectTable: {
549 |       type: 'array',
550 |       'x-decorator': 'FormItem',
551 |       'x-component': 'SelectTable',
552 |       'x-component-props': {
553 |         showSearch: true,
554 |         filterOption: false,
555 |         onSearch: '{{useAsyncDataSource(loadData,$self)}}',
556 |       },
557 |       enum: [
558 |         { key: '1', name: '标题1', description: '描述1' },
559 |         { key: '2', name: '标题2', description: '描述2' },
560 |       ],
561 |       properties: {
562 |         name: {
563 |           title: '标题',
564 |           type: 'string',
565 |           'x-component': 'SelectTable.Column',
566 |           'x-component-props': {
567 |             width: '40%',
568 |           },
569 |         },
570 |         description: {
571 |           title: '描述',
572 |           type: 'string',
573 |           'x-component': 'SelectTable.Column',
574 |           'x-component-props': {
575 |             width: '60%',
576 |           },
577 |         },
578 |       },
579 |     },
580 |   },
581 | }
582 | 
583 | export default () => (
584 |   <FormProvider form={form}>
585 |     <SchemaField schema={schema} scope={{ useAsyncDataSource, loadData }} />
586 |     <FormButtonGroup>
587 |       <Submit onSubmit={console.log}>提交</Submit>
588 |     </FormButtonGroup>
589 |   </FormProvider>
590 | )
591 | ```
592 | 
593 | ## 纯 JSX 案例
594 | 
595 | ```tsx
596 | import React from 'react'
597 | import { FormItem, FormButtonGroup, Submit, SelectTable } from '@formily/antd'
598 | import { createForm } from '@formily/core'
599 | import { FormProvider, Field } from '@formily/react'
600 | 
601 | const form = createForm()
602 | 
603 | export default () => (
604 |   <FormProvider form={form}>
605 |     <Field
606 |       name="SelectTable"
607 |       dataSource={[
608 |         { key: '1', name: '标题1', description: '描述1' },
609 |         { key: '2', name: '标题2', description: '描述2' },
610 |       ]}
611 |       decorator={[FormItem]}
612 |       component={[
613 |         SelectTable,
614 |         {
615 |           columns: [
616 |             { dataIndex: 'name', title: '标题' },
617 |             { dataIndex: 'description', title: '描述' },
618 |           ],
619 |         },
620 |       ]}
621 |     />
622 |     <FormButtonGroup>
623 |       <Submit onSubmit={console.log}>提交</Submit>
624 |     </FormButtonGroup>
625 |   </FormProvider>
626 | )
627 | ```
628 | 
629 | ## API
630 | 
631 | ### SelectTable
632 | 
633 | | 属性名        | 类型                                         | 描述                                                                                                                                 | 默认值       |
634 | | ------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
635 | | mode          | `'multiple' \| 'single'`                     | 设置 SelectTable 模式为单选或多选                                                                                                    | `'multiple'` |
636 | | valueType     | `'all' \| 'parent' \| 'child' \| 'path'`     | 返回值类型,checkStrictly 设置为 `false` 时有效                                                                                      | `'all'`      |
637 | | optionAsValue | boolean                                      | 使用表格行数据作为值,valueType 值为 `'path'` 时无效                                                                                 | false        |
638 | | showSearch    | boolean                                      | 是否显示搜索组件                                                                                                                     | false        |
639 | | searchProps   | object                                       | Search 组件属性                                                                                                                      | -            |
640 | | primaryKey    | `string \| (record) => string`               | 表格行 key 的取值                                                                                                                    | `'key'`      |
641 | | filterOption  | `boolean \| (inputValue, option) => boolean` | 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 false | true         |
642 | | filterSort    | (optionA, optionB) => number                 | 搜索时对筛选结果项的排序函数, 类似 Array.sort 里的 compareFunction                                                                   | -            |
643 | | onSearch      | 文本框值变化时回调                           | (inputValue) => void                                                                                                                 | -            |
644 | 
645 | 参考 https://ant.design/components/table-cn/
646 | 
647 | ### rowSelection
648 | 
649 | | 属性名        | 类型    | 描述                                                         | 默认值 |
650 | | ------------- | ------- | ------------------------------------------------------------ | ------ |
651 | | checkStrictly | boolean | checkable 状态下节点选择完全受控(父子数据选中状态不再关联) | true   |
652 | 
653 | 参考 https://ant.design/components/table/#rowSelection
654 | 
655 | ### SelectTable.Column
656 | 
657 | 参考 https://ant.design/components/table-cn/ Table.Column 属性
658 | 
```

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

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