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

# Directory Structure

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

# Files

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

```markdown
  1 | # FormDialog
  2 | 
  3 | > Pop-up form, mainly used in simple event to open the form scene
  4 | 
  5 | ## Markup Schema example
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { FormDialog, FormItem, FormLayout, Input } from '@formily/antd'
 10 | import { createSchemaField } from '@formily/react'
 11 | import { Button } from 'antd'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     FormItem,
 16 |     Input,
 17 |   },
 18 | })
 19 | 
 20 | export default () => {
 21 |   return (
 22 |     <Button
 23 |       onClick={() => {
 24 |         const dialog = FormDialog('Pop-up form', () => {
 25 |           return (
 26 |             <FormLayout labelCol={6} wrapperCol={10}>
 27 |               <SchemaField>
 28 |                 <SchemaField.String
 29 |                   name="aaa"
 30 |                   required
 31 |                   title="input box 1"
 32 |                   x-decorator="FormItem"
 33 |                   x-component="Input"
 34 |                 />
 35 |                 <SchemaField.String
 36 |                   name="bbb"
 37 |                   required
 38 |                   title="input box 2"
 39 |                   x-decorator="FormItem"
 40 |                   x-component="Input"
 41 |                 />
 42 |                 <SchemaField.String
 43 |                   name="ccc"
 44 |                   required
 45 |                   title="input box 3"
 46 |                   x-decorator="FormItem"
 47 |                   x-component="Input"
 48 |                 />
 49 |                 <SchemaField.String
 50 |                   name="ddd"
 51 |                   required
 52 |                   title="input box 4"
 53 |                   x-decorator="FormItem"
 54 |                   x-component="Input"
 55 |                 />
 56 |               </SchemaField>
 57 |               <FormDialog.Footer>
 58 |                 <span
 59 |                   onClick={() => {
 60 |                     dialog.close()
 61 |                   }}
 62 |                   style={{ marginLeft: 4 }}
 63 |                 >
 64 |                   Extended copywriting(Click me to close the form)
 65 |                 </span>
 66 |               </FormDialog.Footer>
 67 |             </FormLayout>
 68 |           )
 69 |         })
 70 |         dialog
 71 |           .forOpen((payload, next) => {
 72 |             setTimeout(() => {
 73 |               next({
 74 |                 initialValues: {
 75 |                   aaa: '123',
 76 |                 },
 77 |               })
 78 |             }, 1000)
 79 |           })
 80 |           .forConfirm((payload, next) => {
 81 |             setTimeout(() => {
 82 |               console.log(payload)
 83 |               next(payload)
 84 |             }, 1000)
 85 |           })
 86 |           .forCancel((payload, next) => {
 87 |             setTimeout(() => {
 88 |               console.log(payload)
 89 |               next(payload)
 90 |             }, 1000)
 91 |           })
 92 |           .open({
 93 |             initialValues: {
 94 |               aaa: '123',
 95 |             },
 96 |           })
 97 |           .then(console.log)
 98 |       }}
 99 |     >
100 |       Click me to open the form
101 |     </Button>
102 |   )
103 | }
104 | ```
105 | 
106 | ## JSON Schema case
107 | 
108 | ```tsx
109 | import React from 'react'
110 | import { FormDialog, FormItem, FormLayout, Input } from '@formily/antd'
111 | import { createSchemaField } from '@formily/react'
112 | import { Button } from 'antd'
113 | 
114 | const SchemaField = createSchemaField({
115 |   components: {
116 |     FormItem,
117 |     Input,
118 |   },
119 | })
120 | 
121 | const schema = {
122 |   type: 'object',
123 |   properties: {
124 |     aaa: {
125 |       type: 'string',
126 |       title: 'input box 1',
127 |       required: true,
128 |       'x-decorator': 'FormItem',
129 |       'x-component': 'Input',
130 |     },
131 |     bbb: {
132 |       type: 'string',
133 |       title: 'input box 2',
134 |       required: true,
135 |       'x-decorator': 'FormItem',
136 |       'x-component': 'Input',
137 |     },
138 |     ccc: {
139 |       type: 'string',
140 |       title: 'input box 3',
141 |       required: true,
142 |       'x-decorator': 'FormItem',
143 |       'x-component': 'Input',
144 |     },
145 |     ddd: {
146 |       type: 'string',
147 |       title: 'input box 4',
148 |       required: true,
149 |       'x-decorator': 'FormItem',
150 |       'x-component': 'Input',
151 |     },
152 |   },
153 | }
154 | 
155 | export default () => {
156 |   return (
157 |     <Button
158 |       onClick={() => {
159 |         const dialog = FormDialog('Pop-up form', () => {
160 |           return (
161 |             <FormLayout labelCol={6} wrapperCol={10}>
162 |               <SchemaField schema={schema} />
163 |               <FormDialog.Footer>
164 |                 <span
165 |                   onClick={() => {
166 |                     dialog.close()
167 |                   }}
168 |                   style={{ marginLeft: 4 }}
169 |                 >
170 |                   Extended copywriting(Click me to close the form)
171 |                 </span>
172 |               </FormDialog.Footer>
173 |             </FormLayout>
174 |           )
175 |         })
176 |         dialog
177 |           .forOpen((payload, next) => {
178 |             setTimeout(() => {
179 |               next({
180 |                 initialValues: {
181 |                   aaa: '123',
182 |                 },
183 |               })
184 |             }, 1000)
185 |           })
186 |           .forConfirm((payload, next) => {
187 |             setTimeout(() => {
188 |               console.log(payload)
189 |               next(payload)
190 |             }, 1000)
191 |           })
192 |           .forCancel((payload, next) => {
193 |             setTimeout(() => {
194 |               console.log(payload)
195 |               next(payload)
196 |             }, 1000)
197 |           })
198 |           .open({
199 |             initialValues: {
200 |               aaa: '123',
201 |             },
202 |           })
203 |           .then(console.log)
204 |       }}
205 |     >
206 |       Click me to open the form
207 |     </Button>
208 |   )
209 | }
210 | ```
211 | 
212 | ## Pure JSX case
213 | 
214 | ```tsx
215 | import React from 'react'
216 | import { FormDialog, FormItem, FormLayout, Input } from '@formily/antd'
217 | import { Field } from '@formily/react'
218 | import { Button } from 'antd'
219 | 
220 | export default () => {
221 |   return (
222 |     <Button
223 |       onClick={() => {
224 |         const dialog = FormDialog('Pop-up form', () => {
225 |           return (
226 |             <FormLayout labelCol={6} wrapperCol={10}>
227 |               <Field
228 |                 name="aaa"
229 |                 required
230 |                 title="input box 1"
231 |                 decorator={[FormItem]}
232 |                 component={[Input]}
233 |               />
234 |               <Field
235 |                 name="bbb"
236 |                 required
237 |                 title="input box 2"
238 |                 decorator={[FormItem]}
239 |                 component={[Input]}
240 |               />
241 |               <Field
242 |                 name="ccc"
243 |                 required
244 |                 title="input box 3"
245 |                 decorator={[FormItem]}
246 |                 component={[Input]}
247 |               />
248 |               <Field
249 |                 name="ddd"
250 |                 required
251 |                 title="input box 4"
252 |                 decorator={[FormItem]}
253 |                 component={[Input]}
254 |               />
255 |               <FormDialog.Footer>
256 |                 <span
257 |                   onClick={() => {
258 |                     dialog.close()
259 |                   }}
260 |                   style={{ marginLeft: 4 }}
261 |                 >
262 |                   Extended copywriting(Click me to close the form)
263 |                 </span>
264 |               </FormDialog.Footer>
265 |             </FormLayout>
266 |           )
267 |         })
268 |         dialog
269 |           .forOpen((payload, next) => {
270 |             setTimeout(() => {
271 |               next({
272 |                 initialValues: {
273 |                   aaa: '123',
274 |                 },
275 |               })
276 |             }, 1000)
277 |           })
278 |           .forConfirm((payload, next) => {
279 |             setTimeout(() => {
280 |               console.log(payload)
281 |               next(payload)
282 |             }, 1000)
283 |           })
284 |           .forCancel((payload, next) => {
285 |             setTimeout(() => {
286 |               console.log(payload)
287 |               next(payload)
288 |             }, 1000)
289 |           })
290 |           .open({
291 |             initialValues: {
292 |               aaa: '123',
293 |             },
294 |           })
295 |           .then(console.log)
296 |       }}
297 |     >
298 |       Click me to open the form
299 |     </Button>
300 |   )
301 | }
302 | ```
303 | 
304 | ## API
305 | 
306 | ### FormDialog
307 | 
308 | ```ts pure
309 | import { IFormProps, Form } from '@formily/core'
310 | 
311 | type FormDialogRenderer =
312 |   | React.ReactElement
313 |   | ((form: Form) => React.ReactElement)
314 | 
315 | type ModalTitle = string | number | React.ReactElement
316 | 
317 | interface IFormDialog {
318 |   forOpen(
319 |     middleware: (
320 |       props: IFormProps,
321 |       next: (props?: IFormProps) => Promise<any>
322 |     ) => any
323 |   ): any //Middleware interceptor, can intercept Dialog to open
324 |   forConfirm(
325 |     middleware: (props: Form, next: (props?: Form) => Promise<any>) => any
326 |   ): any //Middleware interceptor, which can intercept Dialog confirmation
327 |   forCancel(
328 |     middleware: (props: Form, next: (props?: Form) => Promise<any>) => any
329 |   ): any //Middleware interceptor, can intercept Dialog to cancel
330 |   //Open the pop-up window to receive form attributes, you can pass in initialValues/values/effects etc.
331 |   open(props: IFormProps): Promise<any> //return form data
332 |   //Close the pop-up window
333 |   close(): void
334 | }
335 | 
336 | interface IModalProps extends ModalProps {
337 |   onOk?: (event: React.MouseEvent<HTMLElement>) => void | boolean // return false can prevent onOk
338 |   onCancel?: (event: React.MouseEvent<HTMLElement>) => void | boolean // return false can prevent onCancel
339 |   loadingText?: React.ReactNode
340 | }
341 | 
342 | interface FormDialog {
343 |   (title: IModalProps, id: string, renderer: FormDialogRenderer): IFormDialog
344 |   (title: IModalProps, renderer: FormDialogRenderer): IFormDialog
345 |   (title: ModalTitle, id: string, renderer: FormDialogRenderer): IFormDialog
346 |   (title: ModalTitle, renderer: FormDialogRenderer): IFormDialog
347 | }
348 | ```
349 | 
350 | `ModalProps` type definition reference ant design [Modal API](https://ant.design/components/modal-cn/#API)
351 | 
352 | ### FormDialog.Footer
353 | 
354 | No attributes, only child nodes are received
355 | 
356 | ### FormDialog.Portal
357 | 
358 | Receive the optional id attribute, the default value is `form-dialog`, if there are multiple prefixCls in an application, and the prefixCls in the pop-up window of different regions are different, then it is recommended to specify the id as the region-level id
359 | 
```

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

```markdown
  1 | # FormDialog
  2 | 
  3 | > 弹窗表单,主要用在简单的事件打开表单场景
  4 | 
  5 | ## Markup Schema 案例
  6 | 
  7 | ```tsx
  8 | import React, { createContext, useContext } from 'react'
  9 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
 10 | import { createSchemaField } from '@formily/react'
 11 | import { Button } from '@alifd/next'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     FormItem,
 16 |     Input,
 17 |   },
 18 | })
 19 | 
 20 | const Context = createContext()
 21 | 
 22 | const PortalId = '可以传,也可以不传的ID,默认是form-dialog'
 23 | 
 24 | export default () => {
 25 |   return (
 26 |     <Context.Provider value="自定义上下文可以直接传到弹窗内部,只需要ID一致即可">
 27 |       <FormDialog.Portal id={PortalId}>
 28 |         <Button
 29 |           onClick={() => {
 30 |             FormDialog('弹窗表单', PortalId, (form) => {
 31 |               console.log(useContext(Context))
 32 |               return (
 33 |                 <FormLayout labelCol={6} wrapperCol={10}>
 34 |                   <SchemaField>
 35 |                     <SchemaField.String
 36 |                       name="aaa"
 37 |                       required
 38 |                       title="输入框1"
 39 |                       x-decorator="FormItem"
 40 |                       x-component="Input"
 41 |                     />
 42 |                     <SchemaField.String
 43 |                       name="bbb"
 44 |                       required
 45 |                       title="输入框2"
 46 |                       x-decorator="FormItem"
 47 |                       x-component="Input"
 48 |                     />
 49 |                     <SchemaField.String
 50 |                       name="ccc"
 51 |                       required
 52 |                       title="输入框3"
 53 |                       x-decorator="FormItem"
 54 |                       x-component="Input"
 55 |                     />
 56 |                     <SchemaField.String
 57 |                       name="ddd"
 58 |                       required
 59 |                       title="输入框4"
 60 |                       x-decorator="FormItem"
 61 |                       x-component="Input"
 62 |                     />
 63 |                   </SchemaField>
 64 |                   <FormDialog.Footer>
 65 |                     <span style={{ marginLeft: 4 }}>
 66 |                       扩展文案:{form.values.aaa}
 67 |                     </span>
 68 |                   </FormDialog.Footer>
 69 |                 </FormLayout>
 70 |               )
 71 |             })
 72 |               .forOpen((payload, next) => {
 73 |                 setTimeout(() => {
 74 |                   next({
 75 |                     initialValues: {
 76 |                       aaa: '123',
 77 |                     },
 78 |                   })
 79 |                 }, 1000)
 80 |               })
 81 |               .forConfirm((payload, next) => {
 82 |                 setTimeout(() => {
 83 |                   console.log(payload)
 84 |                   next(payload)
 85 |                 }, 1000)
 86 |               })
 87 |               .forCancel((payload, next) => {
 88 |                 setTimeout(() => {
 89 |                   console.log(payload)
 90 |                   next(payload)
 91 |                 }, 1000)
 92 |               })
 93 |               .open()
 94 |               .then(console.log)
 95 |               .catch(console.error)
 96 |           }}
 97 |         >
 98 |           点我打开表单
 99 |         </Button>
100 |       </FormDialog.Portal>
101 |     </Context.Provider>
102 |   )
103 | }
104 | ```
105 | 
106 | ## JSON Schema 案例
107 | 
108 | ```tsx
109 | import React from 'react'
110 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
111 | import { createSchemaField } from '@formily/react'
112 | import { Button } from '@alifd/next'
113 | 
114 | const SchemaField = createSchemaField({
115 |   components: {
116 |     FormItem,
117 |     Input,
118 |   },
119 | })
120 | 
121 | const schema = {
122 |   type: 'object',
123 |   properties: {
124 |     aaa: {
125 |       type: 'string',
126 |       title: '输入框1',
127 |       required: true,
128 |       'x-decorator': 'FormItem',
129 |       'x-component': 'Input',
130 |     },
131 |     bbb: {
132 |       type: 'string',
133 |       title: '输入框2',
134 |       required: true,
135 |       'x-decorator': 'FormItem',
136 |       'x-component': 'Input',
137 |     },
138 |     ccc: {
139 |       type: 'string',
140 |       title: '输入框3',
141 |       required: true,
142 |       'x-decorator': 'FormItem',
143 |       'x-component': 'Input',
144 |     },
145 |     ddd: {
146 |       type: 'string',
147 |       title: '输入框4',
148 |       required: true,
149 |       'x-decorator': 'FormItem',
150 |       'x-component': 'Input',
151 |     },
152 |   },
153 | }
154 | 
155 | export default () => {
156 |   return (
157 |     <Button
158 |       onClick={() => {
159 |         FormDialog('弹窗表单', () => {
160 |           return (
161 |             <FormLayout labelCol={6} wrapperCol={14}>
162 |               <SchemaField schema={schema} />
163 |               <FormDialog.Footer>
164 |                 <span style={{ marginLeft: 4 }}>扩展文案</span>
165 |               </FormDialog.Footer>
166 |             </FormLayout>
167 |           )
168 |         })
169 |           .open({
170 |             initialValues: {
171 |               aaa: '123',
172 |             },
173 |           })
174 |           .then(console.log)
175 |       }}
176 |     >
177 |       点我打开表单
178 |     </Button>
179 |   )
180 | }
181 | ```
182 | 
183 | ## 纯 JSX 案例
184 | 
185 | ```tsx
186 | import React from 'react'
187 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
188 | import { Field } from '@formily/react'
189 | import { Button } from '@alifd/next'
190 | 
191 | export default () => {
192 |   return (
193 |     <Button
194 |       onClick={() => {
195 |         FormDialog('弹窗表单', () => {
196 |           return (
197 |             <FormLayout labelCol={6} wrapperCol={14}>
198 |               <Field
199 |                 name="aaa"
200 |                 required
201 |                 title="输入框1"
202 |                 decorator={[FormItem]}
203 |                 component={[Input]}
204 |               />
205 |               <Field
206 |                 name="bbb"
207 |                 required
208 |                 title="输入框2"
209 |                 decorator={[FormItem]}
210 |                 component={[Input]}
211 |               />
212 |               <Field
213 |                 name="ccc"
214 |                 required
215 |                 title="输入框3"
216 |                 decorator={[FormItem]}
217 |                 component={[Input]}
218 |               />
219 |               <Field
220 |                 name="ddd"
221 |                 required
222 |                 title="输入框4"
223 |                 decorator={[FormItem]}
224 |                 component={[Input]}
225 |               />
226 |               <FormDialog.Footer>
227 |                 <span style={{ marginLeft: 4 }}>扩展文案</span>
228 |               </FormDialog.Footer>
229 |             </FormLayout>
230 |           )
231 |         })
232 |           .open({
233 |             initialValues: {
234 |               aaa: '123',
235 |             },
236 |           })
237 |           .then(console.log)
238 |       }}
239 |     >
240 |       点我打开表单
241 |     </Button>
242 |   )
243 | }
244 | ```
245 | 
246 | ## 使用 Fusion Context
247 | 
248 | ```tsx
249 | import React from 'react'
250 | import { FormDialog, FormItem, Input, FormLayout } from '@formily/next'
251 | import { Field } from '@formily/react'
252 | import { Button, ConfigProvider } from '@alifd/next'
253 | 
254 | export default () => {
255 |   return (
256 |     <ConfigProvider
257 |       locale={{
258 |         Dialog: {
259 |           ok: 'OK',
260 |           cancel: 'Cancel',
261 |         },
262 |       }}
263 |       defaultPropsConfig={{
264 |         Dialog: {
265 |           isFullScreen: true,
266 |           footerActions: ['cancel', 'ok'],
267 |         },
268 |       }}
269 |     >
270 |       <Button
271 |         onClick={() => {
272 |           FormDialog('弹窗表单', () => {
273 |             return (
274 |               <FormLayout labelCol={6} wrapperCol={14}>
275 |                 <Field
276 |                   name="aaa"
277 |                   required
278 |                   title="输入框1"
279 |                   decorator={[FormItem]}
280 |                   component={[Input]}
281 |                 />
282 |                 <Field
283 |                   name="bbb"
284 |                   required
285 |                   title="输入框2"
286 |                   decorator={[FormItem]}
287 |                   component={[Input]}
288 |                 />
289 |                 <Field
290 |                   name="ccc"
291 |                   required
292 |                   title="输入框3"
293 |                   decorator={[FormItem]}
294 |                   component={[Input]}
295 |                 />
296 |                 <Field
297 |                   name="ddd"
298 |                   required
299 |                   title="输入框4"
300 |                   decorator={[FormItem]}
301 |                   component={[Input]}
302 |                 />
303 |                 <FormDialog.Footer>
304 |                   <span style={{ marginLeft: 4 }}>扩展文案</span>
305 |                 </FormDialog.Footer>
306 |               </FormLayout>
307 |             )
308 |           })
309 |             .open({
310 |               initialValues: {
311 |                 aaa: '123',
312 |               },
313 |             })
314 |             .then(console.log)
315 |         }}
316 |       >
317 |         点我打开表单
318 |       </Button>
319 |     </ConfigProvider>
320 |   )
321 | }
322 | ```
323 | 
324 | ## API
325 | 
326 | ### FormDialog
327 | 
328 | ```ts pure
329 | import { IFormProps, Form } from '@formily/core'
330 | 
331 | type FormDialogRenderer =
332 |   | React.ReactElement
333 |   | ((form: Form) => React.ReactElement)
334 | 
335 | interface IFormDialog {
336 |   forOpen(
337 |     middleware: (
338 |       props: IFormProps,
339 |       next: (props?: IFormProps) => Promise<any>
340 |     ) => any
341 |   ): any //中间件拦截器,可以拦截Dialog打开
342 |   forConfirm(
343 |     middleware: (props: Form, next: (props?: Form) => Promise<any>) => any
344 |   ): any //中间件拦截器,可以拦截Dialog确认
345 |   forCancel(
346 |     middleware: (props: Form, next: (props?: Form) => Promise<any>) => any
347 |   ): any //中间件拦截器,可以拦截Dialog取消
348 |   //打开弹窗,接收表单属性,可以传入initialValues/values/effects etc.
349 |   open(props: IFormProps): Promise<any> //返回表单数据
350 |   //关闭弹窗
351 |   close(): void
352 | }
353 | 
354 | interface IDialogProps extends DialogProps {
355 |   onOk?: (event: React.MouseEvent) => void | boolean // return false can prevent onOk
356 |   onCancel?: (event: React.MouseEvent) => void | boolean // return false can prevent onCancel
357 |   loadingText?: React.ReactText
358 | }
359 | 
360 | interface FormDialog {
361 |   (title: IDialogProps, id: string, renderer: FormDialogRenderer): IFormDialog
362 |   (title: IDialogProps, renderer: FormDialogRenderer): IFormDialog
363 |   (title: ModalTitle, id: string, renderer: FormDialogRenderer): IFormDialog
364 |   (title: ModalTitle, renderer: FormDialogRenderer): IFormDialog
365 | }
366 | ```
367 | 
368 | `DialogProps` 类型定义参考 fusion [Dialog API](https://fusion.design/pc/component/dialog?themeid=2#API)
369 | 
370 | ### FormDialog.Footer
371 | 
372 | 无属性,只接收子节点
373 | 
374 | ### FormDialog.Portal
375 | 
376 | 接收可选的 id 属性,默认值为`form-dialog`,如果一个应用存在多个 prefixCls,不同区域的弹窗内部 prefixCls 不一样,那推荐指定 id 为区域级 id
377 | 
```

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

```markdown
  1 | # FormDrawer
  2 | 
  3 | > 抽屉表单,主要用在简单的事件打开表单场景
  4 | 
  5 | ## Markup Schema 案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   FormDrawer,
 11 |   FormItem,
 12 |   Input,
 13 |   Submit,
 14 |   Reset,
 15 |   FormButtonGroup,
 16 |   FormLayout,
 17 | } from '@formily/next'
 18 | import { createSchemaField } from '@formily/react'
 19 | import { Button } from '@alifd/next'
 20 | 
 21 | const SchemaField = createSchemaField({
 22 |   components: {
 23 |     FormItem,
 24 |     Input,
 25 |   },
 26 | })
 27 | 
 28 | export default () => {
 29 |   return (
 30 |     <Button
 31 |       onClick={() => {
 32 |         FormDrawer('抽屉表单', () => {
 33 |           return (
 34 |             <FormLayout labelCol={6} wrapperCol={10}>
 35 |               <SchemaField>
 36 |                 <SchemaField.String
 37 |                   name="aaa"
 38 |                   required
 39 |                   title="输入框1"
 40 |                   x-decorator="FormItem"
 41 |                   x-component="Input"
 42 |                 />
 43 |                 <SchemaField.String
 44 |                   name="bbb"
 45 |                   required
 46 |                   title="输入框2"
 47 |                   x-decorator="FormItem"
 48 |                   x-component="Input"
 49 |                 />
 50 |                 <SchemaField.String
 51 |                   name="ccc"
 52 |                   required
 53 |                   title="输入框3"
 54 |                   x-decorator="FormItem"
 55 |                   x-component="Input"
 56 |                 />
 57 |                 <SchemaField.String
 58 |                   name="ddd"
 59 |                   required
 60 |                   title="输入框4"
 61 |                   x-decorator="FormItem"
 62 |                   x-component="Input"
 63 |                 />
 64 |               </SchemaField>
 65 |               <FormDrawer.Footer>
 66 |                 <FormButtonGroup align="right">
 67 |                   <Submit
 68 |                     onSubmit={() => {
 69 |                       return new Promise((resolve) => {
 70 |                         setTimeout(resolve, 1000)
 71 |                       })
 72 |                     }}
 73 |                   >
 74 |                     提交
 75 |                   </Submit>
 76 |                   <Reset>重置</Reset>
 77 |                 </FormButtonGroup>
 78 |               </FormDrawer.Footer>
 79 |             </FormLayout>
 80 |           )
 81 |         })
 82 |           .forOpen((props, next) => {
 83 |             setTimeout(() => {
 84 |               next()
 85 |             }, 1000)
 86 |           })
 87 |           .open({
 88 |             initialValues: {
 89 |               aaa: '123',
 90 |             },
 91 |           })
 92 |           .then(console.log)
 93 |       }}
 94 |     >
 95 |       点我打开表单
 96 |     </Button>
 97 |   )
 98 | }
 99 | ```
100 | 
101 | ## JSON Schema 案例
102 | 
103 | ```tsx
104 | import React from 'react'
105 | import {
106 |   FormDrawer,
107 |   FormItem,
108 |   Input,
109 |   Submit,
110 |   Reset,
111 |   FormButtonGroup,
112 |   FormLayout,
113 | } from '@formily/next'
114 | import { createSchemaField } from '@formily/react'
115 | import { Button } from '@alifd/next'
116 | 
117 | const SchemaField = createSchemaField({
118 |   components: {
119 |     FormItem,
120 |     Input,
121 |   },
122 | })
123 | 
124 | const schema = {
125 |   type: 'object',
126 |   properties: {
127 |     aaa: {
128 |       type: 'string',
129 |       title: '输入框1',
130 |       required: true,
131 |       'x-decorator': 'FormItem',
132 |       'x-component': 'Input',
133 |     },
134 |     bbb: {
135 |       type: 'string',
136 |       title: '输入框2',
137 |       required: true,
138 |       'x-decorator': 'FormItem',
139 |       'x-component': 'Input',
140 |     },
141 |     ccc: {
142 |       type: 'string',
143 |       title: '输入框3',
144 |       required: true,
145 |       'x-decorator': 'FormItem',
146 |       'x-component': 'Input',
147 |     },
148 |     ddd: {
149 |       type: 'string',
150 |       title: '输入框4',
151 |       required: true,
152 |       'x-decorator': 'FormItem',
153 |       'x-component': 'Input',
154 |     },
155 |   },
156 | }
157 | 
158 | export default () => {
159 |   return (
160 |     <Button
161 |       onClick={() => {
162 |         FormDrawer('弹窗表单', () => {
163 |           return (
164 |             <FormLayout labelCol={6} wrapperCol={14}>
165 |               <SchemaField schema={schema} />
166 |               <FormDrawer.Footer>
167 |                 <FormButtonGroup align="right">
168 |                   <Submit
169 |                     onSubmit={() => {
170 |                       return new Promise((resolve) => {
171 |                         setTimeout(resolve, 1000)
172 |                       })
173 |                     }}
174 |                   >
175 |                     提交
176 |                   </Submit>
177 |                   <Reset>重置</Reset>
178 |                 </FormButtonGroup>
179 |               </FormDrawer.Footer>
180 |             </FormLayout>
181 |           )
182 |         })
183 |           .open({
184 |             initialValues: {
185 |               aaa: '123',
186 |             },
187 |           })
188 |           .then(console.log)
189 |       }}
190 |     >
191 |       点我打开表单
192 |     </Button>
193 |   )
194 | }
195 | ```
196 | 
197 | ## 纯 JSX 案例
198 | 
199 | ```tsx
200 | import React from 'react'
201 | import {
202 |   FormDrawer,
203 |   FormItem,
204 |   Input,
205 |   Submit,
206 |   Reset,
207 |   FormButtonGroup,
208 |   FormLayout,
209 | } from '@formily/next'
210 | import { Field } from '@formily/react'
211 | import { Button } from '@alifd/next'
212 | 
213 | export default () => {
214 |   return (
215 |     <Button
216 |       onClick={() => {
217 |         FormDrawer('弹窗表单', () => {
218 |           return (
219 |             <FormLayout labelCol={6} wrapperCol={14}>
220 |               <Field
221 |                 name="aaa"
222 |                 required
223 |                 title="输入框1"
224 |                 decorator={[FormItem]}
225 |                 component={[Input]}
226 |               />
227 |               <Field
228 |                 name="bbb"
229 |                 required
230 |                 title="输入框2"
231 |                 decorator={[FormItem]}
232 |                 component={[Input]}
233 |               />
234 |               <Field
235 |                 name="ccc"
236 |                 required
237 |                 title="输入框3"
238 |                 decorator={[FormItem]}
239 |                 component={[Input]}
240 |               />
241 |               <Field
242 |                 name="ddd"
243 |                 required
244 |                 title="输入框4"
245 |                 decorator={[FormItem]}
246 |                 component={[Input]}
247 |               />
248 |               <FormDrawer.Footer>
249 |                 <FormButtonGroup align="right">
250 |                   <Submit
251 |                     onSubmit={() => {
252 |                       return new Promise((resolve) => {
253 |                         setTimeout(resolve, 1000)
254 |                       })
255 |                     }}
256 |                   >
257 |                     提交
258 |                   </Submit>
259 |                   <Reset>重置</Reset>
260 |                 </FormButtonGroup>
261 |               </FormDrawer.Footer>
262 |             </FormLayout>
263 |           )
264 |         })
265 |           .open({
266 |             initialValues: {
267 |               aaa: '123',
268 |             },
269 |           })
270 |           .then(console.log)
271 |       }}
272 |     >
273 |       点我打开表单
274 |     </Button>
275 |   )
276 | }
277 | ```
278 | 
279 | ## 使用 Fusion Context
280 | 
281 | ```tsx
282 | import React from 'react'
283 | import {
284 |   FormDrawer,
285 |   FormItem,
286 |   Input,
287 |   Submit,
288 |   Reset,
289 |   FormButtonGroup,
290 |   FormLayout,
291 | } from '@formily/next'
292 | import { Field } from '@formily/react'
293 | import { Button, ConfigProvider } from '@alifd/next'
294 | 
295 | export default () => {
296 |   return (
297 |     <ConfigProvider
298 |       defaultPropsConfig={{
299 |         Drawer: {},
300 |       }}
301 |     >
302 |       <Button
303 |         onClick={() => {
304 |           FormDrawer('弹窗表单', () => {
305 |             return (
306 |               <FormLayout labelCol={6} wrapperCol={14}>
307 |                 <Field
308 |                   name="aaa"
309 |                   required
310 |                   title="输入框1"
311 |                   decorator={[FormItem]}
312 |                   component={[Input]}
313 |                 />
314 |                 <Field
315 |                   name="bbb"
316 |                   required
317 |                   title="输入框2"
318 |                   decorator={[FormItem]}
319 |                   component={[Input]}
320 |                 />
321 |                 <Field
322 |                   name="ccc"
323 |                   required
324 |                   title="输入框3"
325 |                   decorator={[FormItem]}
326 |                   component={[Input]}
327 |                 />
328 |                 <Field
329 |                   name="ddd"
330 |                   required
331 |                   title="输入框4"
332 |                   decorator={[FormItem]}
333 |                   component={[Input]}
334 |                 />
335 |                 <FormDrawer.Footer>
336 |                   <FormButtonGroup align="right">
337 |                     <Submit
338 |                       onSubmit={() => {
339 |                         return new Promise((resolve) => {
340 |                           setTimeout(resolve, 1000)
341 |                         })
342 |                       }}
343 |                     >
344 |                       提交
345 |                     </Submit>
346 |                     <Reset>重置</Reset>
347 |                   </FormButtonGroup>
348 |                 </FormDrawer.Footer>
349 |               </FormLayout>
350 |             )
351 |           })
352 |             .open({
353 |               initialValues: {
354 |                 aaa: '123',
355 |               },
356 |             })
357 |             .then(console.log)
358 |         }}
359 |       >
360 |         点我打开表单
361 |       </Button>
362 |     </ConfigProvider>
363 |   )
364 | }
365 | ```
366 | 
367 | ## API
368 | 
369 | ### FormDrawer
370 | 
371 | ## API
372 | 
373 | ### FormDrawer
374 | 
375 | ```ts pure
376 | import { IFormProps, Form } from '@formily/core'
377 | 
378 | type FormDrawerRenderer =
379 |   | React.ReactElement
380 |   | ((form: Form) => React.ReactElement)
381 | 
382 | interface IFormDrawer {
383 |   forOpen(
384 |     middleware: (
385 |       props: IFormProps,
386 |       next: (props?: IFormProps) => Promise<any>
387 |     ) => any
388 |   ): any //中间件拦截器,可以拦截Drawer打开
389 |   //打开弹窗,接收表单属性,可以传入initialValues/values/effects etc.
390 |   open(props: IFormProps): Promise<any> //返回表单数据
391 |   //关闭弹窗
392 |   close(): void
393 | }
394 | 
395 | interface IDrawerProps extends DrawerProps {
396 |   onClose?: (reason: string, e: React.MouseEvent) => void | boolean // return false can prevent onClose
397 |   loadingText?: React.ReactNode
398 | }
399 | 
400 | interface FormDrawer {
401 |   (title: IDrawerProps, id: string, renderer: FormDrawerRenderer): IFormDrawer
402 |   (title: IDrawerProps, renderer: FormDrawerRenderer): IFormDrawer
403 |   (title: ModalTitle, id: string, renderer: FormDrawerRenderer): IFormDrawer
404 |   (title: ModalTitle, renderer: FormDrawerRenderer): IFormDrawer
405 | }
406 | ```
407 | 
408 | `DrawerProps` 类型定义参考 fusion [Drawer API](https://fusion.design/pc/component/drawer?themeid=2#API)
409 | 
410 | ### FormDrawer.Footer
411 | 
412 | 无属性,只接收子节点
413 | 
414 | ### FormDrawer.Portal
415 | 
416 | 接收可选的 id 属性,默认值为`form-drawer`,如果一个应用存在多个 prefixCls,不同区域的弹窗内部 prefixCls 不一样,那推荐指定 id 为区域级 id
417 | 
```

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

```markdown
  1 | # Select
  2 | 
  3 | > Drop-down box components
  4 | 
  5 | ## Markup Schema synchronization data source case
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { Select, 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 |     Select,
 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="Select"
 30 |         enum={[
 31 |           { label: 'Option 1', value: 1 },
 32 |           { label: 'Option 2', value: 2 },
 33 |         ]}
 34 |         x-component-props={{
 35 |           style: {
 36 |             width: 120,
 37 |           },
 38 |         }}
 39 |       />
 40 |     </SchemaField>
 41 |     <FormButtonGroup>
 42 |       <Submit onSubmit={console.log}>Submit</Submit>
 43 |     </FormButtonGroup>
 44 |   </FormProvider>
 45 | )
 46 | ```
 47 | 
 48 | ## Markup Schema Asynchronous Linkage Data Source Case
 49 | 
 50 | ```tsx
 51 | import React from 'react'
 52 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
 53 | import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'
 54 | import { FormProvider, createSchemaField } from '@formily/react'
 55 | import { action } from '@formily/reactive'
 56 | 
 57 | const SchemaField = createSchemaField({
 58 |   components: {
 59 |     Select,
 60 |     FormItem,
 61 |   },
 62 | })
 63 | 
 64 | const useAsyncDataSource = (
 65 |   pattern: FormPathPattern,
 66 |   service: (field: Field) => Promise<{ label: string; value: any }[]>
 67 | ) => {
 68 |   onFieldReact(pattern, (field) => {
 69 |     field.loading = true
 70 |     service(field).then(
 71 |       action.bound((data) => {
 72 |         field.dataSource = data
 73 |         field.loading = false
 74 |       })
 75 |     )
 76 |   })
 77 | }
 78 | 
 79 | const form = createForm({
 80 |   effects: () => {
 81 |     useAsyncDataSource('select', async (field) => {
 82 |       const linkage = field.query('linkage').get('value')
 83 |       if (!linkage) return []
 84 |       return new Promise((resolve) => {
 85 |         setTimeout(() => {
 86 |           if (linkage === 1) {
 87 |             resolve([
 88 |               {
 89 |                 label: 'AAA',
 90 |                 value: 'aaa',
 91 |               },
 92 |               {
 93 |                 label: 'BBB',
 94 |                 value: 'ccc',
 95 |               },
 96 |             ])
 97 |           } else if (linkage === 2) {
 98 |             resolve([
 99 |               {
100 |                 label: 'CCC',
101 |                 value: 'ccc',
102 |               },
103 |               {
104 |                 label: 'DDD',
105 |                 value: 'ddd',
106 |               },
107 |             ])
108 |           }
109 |         }, 1500)
110 |       })
111 |     })
112 |   },
113 | })
114 | 
115 | export default () => (
116 |   <FormProvider form={form}>
117 |     <SchemaField>
118 |       <SchemaField.Number
119 |         name="linkage"
120 |         title="Linkage selection box"
121 |         x-decorator="FormItem"
122 |         x-component="Select"
123 |         enum={[
124 |           { label: 'Request 1', value: 1 },
125 |           { label: 'Request 2', value: 2 },
126 |         ]}
127 |         x-component-props={{
128 |           style: {
129 |             width: 120,
130 |           },
131 |         }}
132 |       />
133 |       <SchemaField.String
134 |         name="select"
135 |         title="Asynchronous select box"
136 |         x-decorator="FormItem"
137 |         x-component="Select"
138 |         x-component-props={{
139 |           style: {
140 |             width: 120,
141 |           },
142 |         }}
143 |       />
144 |     </SchemaField>
145 |     <FormButtonGroup>
146 |       <Submit onSubmit={console.log}>Submit</Submit>
147 |     </FormButtonGroup>
148 |   </FormProvider>
149 | )
150 | ```
151 | 
152 | ## JSON Schema synchronization data source case
153 | 
154 | ```tsx
155 | import React from 'react'
156 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
157 | import { createForm } from '@formily/core'
158 | import { FormProvider, createSchemaField } from '@formily/react'
159 | 
160 | const SchemaField = createSchemaField({
161 |   components: {
162 |     Select,
163 |     FormItem,
164 |   },
165 | })
166 | 
167 | const form = createForm()
168 | 
169 | const schema = {
170 |   type: 'object',
171 |   properties: {
172 |     select: {
173 |       type: 'string',
174 |       title: 'Select box',
175 |       'x-decorator': 'FormItem',
176 |       'x-component': 'Select',
177 |       enum: [
178 |         { label: 'Option 1', value: 1 },
179 |         { label: 'Option 2', value: 2 },
180 |       ],
181 |       'x-component-props': {
182 |         style: {
183 |           width: 120,
184 |         },
185 |       },
186 |     },
187 |   },
188 | }
189 | 
190 | export default () => (
191 |   <FormProvider form={form}>
192 |     <SchemaField schema={schema} />
193 |     <FormButtonGroup>
194 |       <Submit onSubmit={console.log}>Submit</Submit>
195 |     </FormButtonGroup>
196 |   </FormProvider>
197 | )
198 | ```
199 | 
200 | ## JSON Schema asynchronous linkage data source case
201 | 
202 | ```tsx
203 | import React from 'react'
204 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
205 | import { createForm } from '@formily/core'
206 | import { FormProvider, createSchemaField } from '@formily/react'
207 | import { action } from '@formily/reactive'
208 | 
209 | const SchemaField = createSchemaField({
210 |   components: {
211 |     Select,
212 |     FormItem,
213 |   },
214 | })
215 | 
216 | const loadData = async (field) => {
217 |   const linkage = field.query('linkage').get('value')
218 |   if (!linkage) return []
219 |   return new Promise((resolve) => {
220 |     setTimeout(() => {
221 |       if (linkage === 1) {
222 |         resolve([
223 |           {
224 |             label: 'AAA',
225 |             value: 'aaa',
226 |           },
227 |           {
228 |             label: 'BBB',
229 |             value: 'ccc',
230 |           },
231 |         ])
232 |       } else if (linkage === 2) {
233 |         resolve([
234 |           {
235 |             label: 'CCC',
236 |             value: 'ccc',
237 |           },
238 |           {
239 |             label: 'DDD',
240 |             value: 'ddd',
241 |           },
242 |         ])
243 |       }
244 |     }, 1500)
245 |   })
246 | }
247 | 
248 | const useAsyncDataSource = (service) => (field) => {
249 |   field.loading = true
250 |   service(field).then(
251 |     action.bound((data) => {
252 |       field.dataSource = data
253 |       field.loading = false
254 |     })
255 |   )
256 | }
257 | 
258 | const form = createForm()
259 | 
260 | const schema = {
261 |   type: 'object',
262 |   properties: {
263 |     linkage: {
264 |       type: 'string',
265 |       title: 'Linkage selection box',
266 |       enum: [
267 |         { label: 'Request 1', value: 1 },
268 |         { label: 'Request 2', value: 2 },
269 |       ],
270 |       'x-decorator': 'FormItem',
271 |       'x-component': 'Select',
272 |       'x-component-props': {
273 |         style: {
274 |           width: 120,
275 |         },
276 |       },
277 |     },
278 |     select: {
279 |       type: 'string',
280 |       title: 'Asynchronous selection box',
281 |       'x-decorator': 'FormItem',
282 |       'x-component': 'Select',
283 |       'x-component-props': {
284 |         style: {
285 |           width: 120,
286 |         },
287 |       },
288 |       'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
289 |     },
290 |   },
291 | }
292 | 
293 | export default () => (
294 |   <FormProvider form={form}>
295 |     <SchemaField schema={schema} scope={{ useAsyncDataSource, loadData }} />
296 |     <FormButtonGroup>
297 |       <Submit onSubmit={console.log}>Submit</Submit>
298 |     </FormButtonGroup>
299 |   </FormProvider>
300 | )
301 | ```
302 | 
303 | ## Pure JSX synchronization data source case
304 | 
305 | ```tsx
306 | import React from 'react'
307 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
308 | import { createForm } from '@formily/core'
309 | import { FormProvider, Field } from '@formily/react'
310 | 
311 | const form = createForm()
312 | 
313 | export default () => (
314 |   <FormProvider form={form}>
315 |     <Field
316 |       name="select"
317 |       title="select box"
318 |       dataSource={[
319 |         { label: 'Option 1', value: 1 },
320 |         { label: 'Option 2', value: 2 },
321 |       ]}
322 |       decorator={[FormItem]}
323 |       component={[
324 |         Select,
325 |         {
326 |           style: {
327 |             width: 120,
328 |           },
329 |         },
330 |       ]}
331 |     />
332 |     <FormButtonGroup>
333 |       <Submit onSubmit={console.log}>Submit</Submit>
334 |     </FormButtonGroup>
335 |   </FormProvider>
336 | )
337 | ```
338 | 
339 | ## Pure JSX asynchronous linkage data source case
340 | 
341 | ```tsx
342 | import React from 'react'
343 | import { Select, FormItem, FormButtonGroup, Submit } from '@formily/next'
344 | import {
345 |   createForm,
346 |   onFieldReact,
347 |   FormPathPattern,
348 |   FieldType,
349 | } from '@formily/core'
350 | import { FormProvider, Field } from '@formily/react'
351 | import { action } from '@formily/reactive'
352 | 
353 | const useAsyncDataSource = (
354 |   pattern: FormPathPattern,
355 |   service: (field: FieldType) => Promise<{ label: string; value: any }[]>
356 | ) => {
357 |   onFieldReact(pattern, (field) => {
358 |     field.loading = true
359 |     service(field).then(
360 |       action.bound((data) => {
361 |         field.dataSource = data
362 |         field.loading = false
363 |       })
364 |     )
365 |   })
366 | }
367 | 
368 | const form = createForm({
369 |   effects: () => {
370 |     useAsyncDataSource('select', async (field) => {
371 |       const linkage = field.query('linkage').get('value')
372 |       if (!linkage) return []
373 |       return new Promise((resolve) => {
374 |         setTimeout(() => {
375 |           if (linkage === 1) {
376 |             resolve([
377 |               {
378 |                 label: 'AAA',
379 |                 value: 'aaa',
380 |               },
381 |               {
382 |                 label: 'BBB',
383 |                 value: 'ccc',
384 |               },
385 |             ])
386 |           } else if (linkage === 2) {
387 |             resolve([
388 |               {
389 |                 label: 'CCC',
390 |                 value: 'ccc',
391 |               },
392 |               {
393 |                 label: 'DDD',
394 |                 value: 'ddd',
395 |               },
396 |             ])
397 |           }
398 |         }, 1500)
399 |       })
400 |     })
401 |   },
402 | })
403 | 
404 | export default () => (
405 |   <FormProvider form={form}>
406 |     <Field
407 |       name="linkage"
408 |       title="Linkage selection box"
409 |       dataSource={[
410 |         { label: 'Request 1', value: 1 },
411 |         { label: 'Request 2', value: 2 },
412 |       ]}
413 |       decorator={[FormItem]}
414 |       component={[
415 |         Select,
416 |         {
417 |           style: {
418 |             width: 120,
419 |           },
420 |         },
421 |       ]}
422 |     />
423 |     <Field
424 |       name="select"
425 |       title="Asynchronous select box"
426 |       decorator={[FormItem]}
427 |       component={[
428 |         Select,
429 |         {
430 |           style: {
431 |             width: 120,
432 |           },
433 |         },
434 |       ]}
435 |     />
436 |     <FormButtonGroup>
437 |       <Submit onSubmit={console.log}>Submit</Submit>
438 |     </FormButtonGroup>
439 |   </FormProvider>
440 | )
441 | ```
442 | 
443 | ## API
444 | 
445 | Reference https://fusion.design/pc/component/basic/select
446 | 
```

--------------------------------------------------------------------------------
/packages/antd/src/preview-text/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { createContext, useContext } from 'react'
  2 | import { isArr, toArr, isValid } from '@formily/shared'
  3 | import { Field } from '@formily/core'
  4 | import { observer, useField } from '@formily/react'
  5 | import { InputProps } from 'antd/lib/input'
  6 | import { InputNumberProps } from 'antd/lib/input-number'
  7 | import { SelectProps } from 'antd/lib/select'
  8 | import { TreeSelectProps } from 'antd/lib/tree-select'
  9 | import { CascaderProps, DefaultOptionType } from 'antd/lib/cascader'
 10 | import {
 11 |   DatePickerProps,
 12 |   RangePickerProps as DateRangePickerProps,
 13 | } from 'antd/lib/date-picker'
 14 | import { TimePickerProps, TimeRangePickerProps } from 'antd/lib/time-picker'
 15 | import { Tag, Space } from 'antd'
 16 | import cls from 'classnames'
 17 | import { formatMomentValue, usePrefixCls } from '../__builtins__'
 18 | 
 19 | const PlaceholderContext = createContext<React.ReactNode>('N/A')
 20 | 
 21 | const Placeholder = PlaceholderContext.Provider
 22 | 
 23 | const usePlaceholder = (value?: any) => {
 24 |   const placeholder = useContext(PlaceholderContext) || 'N/A'
 25 |   return isValid(value) && value !== '' ? value : placeholder
 26 | }
 27 | 
 28 | const Input: React.FC<React.PropsWithChildren<InputProps>> = (props) => {
 29 |   const prefixCls = usePrefixCls('form-text', props)
 30 |   return (
 31 |     <Space className={cls(prefixCls, props.className)} style={props.style}>
 32 |       {props.addonBefore}
 33 |       {props.prefix}
 34 |       {usePlaceholder(props.value)}
 35 |       {props.suffix}
 36 |       {props.addonAfter}
 37 |     </Space>
 38 |   )
 39 | }
 40 | 
 41 | const NumberPicker: React.FC<React.PropsWithChildren<InputNumberProps>> = (
 42 |   props
 43 | ) => {
 44 |   const prefixCls = usePrefixCls('form-text', props)
 45 |   return (
 46 |     <Space className={cls(prefixCls, props.className)} style={props.style}>
 47 |       {props.addonBefore}
 48 |       {props.prefix}
 49 |       {usePlaceholder(
 50 |         props.formatter
 51 |           ? props.formatter(String(props.value), {
 52 |               userTyping: false,
 53 |               input: '',
 54 |             })
 55 |           : props.value
 56 |       )}
 57 |       {props['suffix']}
 58 |       {props.addonAfter}
 59 |     </Space>
 60 |   )
 61 | }
 62 | 
 63 | const Select: React.FC<React.PropsWithChildren<SelectProps<any>>> = observer(
 64 |   (props) => {
 65 |     const field = useField<Field>()
 66 |     const prefixCls = usePrefixCls('form-text', props)
 67 |     const dataSource: any[] = field?.dataSource?.length
 68 |       ? field.dataSource
 69 |       : props?.options?.length
 70 |       ? props.options
 71 |       : []
 72 |     const placeholder = usePlaceholder()
 73 |     const getSelected = () => {
 74 |       const value = props.value
 75 |       if (props.mode === 'multiple' || props.mode === 'tags') {
 76 |         if (props.labelInValue) {
 77 |           return isArr(value) ? value : []
 78 |         } else {
 79 |           return isArr(value)
 80 |             ? value.map((val) => ({ label: val, value: val }))
 81 |             : []
 82 |         }
 83 |       } else {
 84 |         if (props.labelInValue) {
 85 |           return isValid(value) ? [value] : []
 86 |         } else {
 87 |           return isValid(value) ? [{ label: value, value }] : []
 88 |         }
 89 |       }
 90 |     }
 91 | 
 92 |     const getLabel = (target: any) => {
 93 |       const labelKey = props.fieldNames?.label || 'label'
 94 |       return (
 95 |         dataSource?.find((item) => {
 96 |           const valueKey = props.fieldNames?.value || 'value'
 97 |           return item[valueKey] == target?.value
 98 |         })?.[labelKey] ||
 99 |         target.label ||
100 |         placeholder
101 |       )
102 |     }
103 | 
104 |     const getLabels = () => {
105 |       const selected = getSelected()
106 |       if (!selected.length) return placeholder
107 |       if (selected.length === 1) return getLabel(selected[0])
108 |       return selected.map((item, key) => {
109 |         return <Tag key={key}>{getLabel(item)}</Tag>
110 |       })
111 |     }
112 |     return (
113 |       <div className={cls(prefixCls, props.className)} style={props.style}>
114 |         {getLabels()}
115 |       </div>
116 |     )
117 |   }
118 | )
119 | 
120 | const TreeSelect: React.FC<React.PropsWithChildren<TreeSelectProps<any>>> =
121 |   observer((props) => {
122 |     const field = useField<Field>()
123 |     const placeholder = usePlaceholder()
124 |     const prefixCls = usePrefixCls('form-text', props)
125 |     const dataSource = field?.dataSource?.length
126 |       ? field.dataSource
127 |       : props?.treeData?.length
128 |       ? props.treeData
129 |       : []
130 |     const getSelected = () => {
131 |       const value = props.value
132 |       if (props.multiple) {
133 |         if (props.labelInValue) {
134 |           return isArr(value) ? value : []
135 |         } else {
136 |           return isArr(value)
137 |             ? value.map((val) => ({ label: val, value: val }))
138 |             : []
139 |         }
140 |       } else {
141 |         if (props.labelInValue) {
142 |           return value ? [value] : []
143 |         } else {
144 |           return value ? [{ label: value, value }] : []
145 |         }
146 |       }
147 |     }
148 | 
149 |     const findLabel = (
150 |       value: any,
151 |       dataSource: any[],
152 |       treeNodeLabelProp?: string
153 |     ) => {
154 |       for (let i = 0; i < dataSource?.length; i++) {
155 |         const item = dataSource[i]
156 |         if (item?.value === value) {
157 |           return item?.label ?? item[treeNodeLabelProp]
158 |         } else {
159 |           const childLabel = findLabel(value, item?.children, treeNodeLabelProp)
160 |           if (childLabel) return childLabel
161 |         }
162 |       }
163 |     }
164 | 
165 |     const getLabels = () => {
166 |       const selected = getSelected()
167 |       if (!selected?.length) return <Tag>{placeholder}</Tag>
168 |       return selected.map(({ value, label }, key) => {
169 |         return (
170 |           <Tag key={key}>
171 |             {findLabel(value, dataSource, props.treeNodeLabelProp) ||
172 |               label ||
173 |               placeholder}
174 |           </Tag>
175 |         )
176 |       })
177 |     }
178 |     return (
179 |       <div className={cls(prefixCls, props.className)} style={props.style}>
180 |         {getLabels()}
181 |       </div>
182 |     )
183 |   })
184 | 
185 | const Cascader: React.FC<React.PropsWithChildren<CascaderProps<any>>> =
186 |   observer((props) => {
187 |     const field = useField<Field>()
188 |     const placeholder = usePlaceholder()
189 |     const prefixCls = usePrefixCls('form-text', props)
190 |     const dataSource: any[] = field?.dataSource?.length
191 |       ? field.dataSource
192 |       : props?.options?.length
193 |       ? props.options
194 |       : []
195 |     const findSelectedItem = (
196 |       items: DefaultOptionType[],
197 |       val: string | number
198 |     ) => {
199 |       return items.find((item) => item.value == val)
200 |     }
201 |     const findSelectedItems = (
202 |       sources: DefaultOptionType[],
203 |       selectedValues: Array<string[] | number[]>
204 |     ): Array<any[]> => {
205 |       return selectedValues.map((value) => {
206 |         const result: Array<DefaultOptionType> = []
207 |         let items = sources
208 |         value.forEach((val) => {
209 |           const selectedItem = findSelectedItem(items, val)
210 |           result.push({
211 |             label: selectedItem?.label ?? '',
212 |             value: selectedItem?.value,
213 |           })
214 |           items = selectedItem?.children ?? []
215 |         })
216 |         return result
217 |       })
218 |     }
219 |     const getSelected = () => {
220 |       const val = toArr(props.value)
221 |       // unified conversion to multi selection mode
222 |       return props.multiple ? val : [val]
223 |     }
224 |     const getLabels = () => {
225 |       const selected = getSelected()
226 |       const values = findSelectedItems(dataSource, selected)
227 |       const labels = values
228 |         .map((val: Array<DefaultOptionType>) => {
229 |           return val.map((item) => item.label).join('/')
230 |         })
231 |         .join(' ')
232 |       return labels || placeholder
233 |     }
234 |     return (
235 |       <div className={cls(prefixCls, props.className)} style={props.style}>
236 |         {getLabels()}
237 |       </div>
238 |     )
239 |   })
240 | 
241 | const DatePicker: React.FC<React.PropsWithChildren<DatePickerProps>> = (
242 |   props
243 | ) => {
244 |   const placeholder = usePlaceholder()
245 |   const prefixCls = usePrefixCls('form-text', props)
246 |   const getLabels = () => {
247 |     const labels = formatMomentValue(props.value, props.format, placeholder)
248 |     return isArr(labels) ? labels.join('~') : labels
249 |   }
250 |   return <div className={cls(prefixCls, props.className)}>{getLabels()}</div>
251 | }
252 | 
253 | const DateRangePicker: React.FC<
254 |   React.PropsWithChildren<DateRangePickerProps>
255 | > = (props) => {
256 |   const placeholder = usePlaceholder()
257 |   const prefixCls = usePrefixCls('form-text', props)
258 |   const getLabels = () => {
259 |     const labels = formatMomentValue(props.value, props.format, placeholder)
260 |     return isArr(labels) ? labels.join('~') : labels
261 |   }
262 |   return (
263 |     <div className={cls(prefixCls, props.className)} style={props.style}>
264 |       {getLabels()}
265 |     </div>
266 |   )
267 | }
268 | 
269 | const TimePicker: React.FC<React.PropsWithChildren<TimePickerProps>> = (
270 |   props
271 | ) => {
272 |   const placeholder = usePlaceholder()
273 |   const prefixCls = usePrefixCls('form-text', props)
274 |   const getLabels = () => {
275 |     const labels = formatMomentValue(props.value, props.format, placeholder)
276 |     return isArr(labels) ? labels.join('~') : labels
277 |   }
278 |   return (
279 |     <div className={cls(prefixCls, props.className)} style={props.style}>
280 |       {getLabels()}
281 |     </div>
282 |   )
283 | }
284 | 
285 | const TimeRangePicker: React.FC<
286 |   React.PropsWithChildren<TimeRangePickerProps>
287 | > = (props) => {
288 |   const placeholder = usePlaceholder()
289 |   const prefixCls = usePrefixCls('form-text', props)
290 |   const getLabels = () => {
291 |     const labels = formatMomentValue(props.value, props.format, placeholder)
292 |     return isArr(labels) ? labels.join('~') : labels
293 |   }
294 |   return (
295 |     <div className={cls(prefixCls, props.className)} style={props.style}>
296 |       {getLabels()}
297 |     </div>
298 |   )
299 | }
300 | 
301 | const Text = (props: React.PropsWithChildren<any>) => {
302 |   const prefixCls = usePrefixCls('form-text', props)
303 | 
304 |   return (
305 |     <div className={cls(prefixCls, props.className)} style={props.style}>
306 |       {usePlaceholder(props.value)}
307 |     </div>
308 |   )
309 | }
310 | 
311 | Text.Input = Input
312 | Text.Select = Select
313 | Text.TreeSelect = TreeSelect
314 | Text.Cascader = Cascader
315 | Text.DatePicker = DatePicker
316 | Text.DateRangePicker = DateRangePicker
317 | Text.TimePicker = TimePicker
318 | Text.TimeRangePicker = TimeRangePicker
319 | Text.Placeholder = Placeholder
320 | Text.usePlaceholder = usePlaceholder
321 | Text.NumberPicker = NumberPicker
322 | 
323 | export const PreviewText = Text
324 | 
325 | export default PreviewText
326 | 
```

--------------------------------------------------------------------------------
/docs/guide/advanced/calculator.zh-CN.md:
--------------------------------------------------------------------------------

```markdown
  1 | # 实现联动计算器
  2 | 
  3 | 联动计算器,主要用于在填写表单的过程中做求值汇总,在 Formily1.x 中实现这类需求的成本非常非常高,在 2.x 中,我们可以借助 reactions 轻松实现
  4 | 
  5 | ## Markup Schema 案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   Form,
 11 |   FormItem,
 12 |   NumberPicker,
 13 |   ArrayTable,
 14 |   Editable,
 15 |   Input,
 16 |   FormButtonGroup,
 17 |   Submit,
 18 | } from '@formily/antd'
 19 | import { createForm } from '@formily/core'
 20 | import { createSchemaField } from '@formily/react'
 21 | 
 22 | const SchemaField = createSchemaField({
 23 |   components: {
 24 |     FormItem,
 25 |     Editable,
 26 |     Input,
 27 |     NumberPicker,
 28 |     ArrayTable,
 29 |   },
 30 | })
 31 | 
 32 | const form = createForm()
 33 | 
 34 | export default () => {
 35 |   return (
 36 |     <Form form={form} layout="vertical">
 37 |       <SchemaField>
 38 |         <SchemaField.Array
 39 |           name="projects"
 40 |           title="Projects"
 41 |           x-decorator="FormItem"
 42 |           x-component="ArrayTable"
 43 |         >
 44 |           <SchemaField.Object>
 45 |             <SchemaField.Void
 46 |               x-component="ArrayTable.Column"
 47 |               x-component-props={{ width: 50, title: 'Sort', align: 'center' }}
 48 |             >
 49 |               <SchemaField.Void
 50 |                 x-decorator="FormItem"
 51 |                 x-component="ArrayTable.SortHandle"
 52 |               />
 53 |             </SchemaField.Void>
 54 |             <SchemaField.Void
 55 |               x-component="ArrayTable.Column"
 56 |               x-component-props={{ width: 80, title: 'Index', align: 'center' }}
 57 |             >
 58 |               <SchemaField.String
 59 |                 x-decorator="FormItem"
 60 |                 x-component="ArrayTable.Index"
 61 |               />
 62 |             </SchemaField.Void>
 63 |             <SchemaField.Void
 64 |               x-component="ArrayTable.Column"
 65 |               x-component-props={{ title: 'Price' }}
 66 |             >
 67 |               <SchemaField.Number
 68 |                 name="price"
 69 |                 x-decorator="Editable"
 70 |                 required
 71 |                 x-component="NumberPicker"
 72 |                 x-component-props={{
 73 |                   addonAfter: '$',
 74 |                 }}
 75 |                 default={0}
 76 |               />
 77 |             </SchemaField.Void>
 78 |             <SchemaField.Void
 79 |               x-component="ArrayTable.Column"
 80 |               x-component-props={{ title: 'Count' }}
 81 |             >
 82 |               <SchemaField.Number
 83 |                 name="count"
 84 |                 x-decorator="Editable"
 85 |                 required
 86 |                 x-component="NumberPicker"
 87 |                 default={0}
 88 |               />
 89 |             </SchemaField.Void>
 90 |             <SchemaField.Void
 91 |               x-component="ArrayTable.Column"
 92 |               x-component-props={{ title: 'Total' }}
 93 |             >
 94 |               <SchemaField.Number
 95 |                 x-decorator="FormItem"
 96 |                 name="total"
 97 |                 x-component="NumberPicker"
 98 |                 x-pattern="readPretty"
 99 |                 x-component-props={{
100 |                   addonAfter: '$',
101 |                 }}
102 |                 x-reactions={{
103 |                   dependencies: ['.price', '.count'],
104 |                   when: '{{$deps[0] && $deps[1]}}',
105 |                   fulfill: {
106 |                     state: {
107 |                       value: '{{$deps[0] * $deps[1]}}',
108 |                     },
109 |                   },
110 |                 }}
111 |               />
112 |             </SchemaField.Void>
113 |             <SchemaField.Void
114 |               x-component="ArrayTable.Column"
115 |               x-component-props={{
116 |                 title: 'Operations',
117 |                 dataIndex: 'operations',
118 |                 width: 200,
119 |                 fixed: 'right',
120 |               }}
121 |             >
122 |               <SchemaField.Void x-component="FormItem">
123 |                 <SchemaField.Void x-component="ArrayTable.Remove" />
124 |                 <SchemaField.Void x-component="ArrayTable.MoveDown" />
125 |                 <SchemaField.Void x-component="ArrayTable.MoveUp" />
126 |               </SchemaField.Void>
127 |             </SchemaField.Void>
128 |           </SchemaField.Object>
129 |           <SchemaField.Void x-component="ArrayTable.Addition" title="Add" />
130 |         </SchemaField.Array>
131 |         <SchemaField.Number
132 |           name="total"
133 |           title="Total"
134 |           x-decorator="FormItem"
135 |           x-component="NumberPicker"
136 |           x-component-props={{
137 |             addonAfter: '$',
138 |           }}
139 |           x-pattern="readPretty"
140 |           x-reactions={{
141 |             dependencies: ['.projects'],
142 |             when: '{{$deps[0].length > 0}}',
143 |             fulfill: {
144 |               state: {
145 |                 value:
146 |                   '{{$deps[0].reduce((total,item)=>item.total ? total+item.total : total,0)}}',
147 |               },
148 |             },
149 |           }}
150 |         />
151 |       </SchemaField>
152 |       <FormButtonGroup>
153 |         <Submit onSubmit={console.log}>提交</Submit>
154 |       </FormButtonGroup>
155 |     </Form>
156 |   )
157 | }
158 | ```
159 | 
160 | ## JSON Schema 案例
161 | 
162 | ```tsx
163 | import React from 'react'
164 | import {
165 |   Form,
166 |   FormItem,
167 |   NumberPicker,
168 |   ArrayTable,
169 |   Editable,
170 |   Input,
171 |   FormButtonGroup,
172 |   Submit,
173 | } from '@formily/antd'
174 | import { createForm } from '@formily/core'
175 | import { createSchemaField } from '@formily/react'
176 | 
177 | const SchemaField = createSchemaField({
178 |   components: {
179 |     FormItem,
180 |     Editable,
181 |     Input,
182 |     NumberPicker,
183 |     ArrayTable,
184 |   },
185 | })
186 | 
187 | const form = createForm()
188 | 
189 | const schema = {
190 |   type: 'object',
191 |   properties: {
192 |     projects: {
193 |       type: 'array',
194 |       title: 'Projects',
195 |       'x-decorator': 'FormItem',
196 |       'x-component': 'ArrayTable',
197 |       items: {
198 |         type: 'object',
199 |         properties: {
200 |           column_1: {
201 |             type: 'void',
202 |             'x-component': 'ArrayTable.Column',
203 |             'x-component-props': {
204 |               width: 50,
205 |               title: 'Sort',
206 |               align: 'center',
207 |             },
208 |             properties: {
209 |               sortable: {
210 |                 type: 'void',
211 |                 'x-component': 'ArrayTable.SortHandle',
212 |               },
213 |             },
214 |           },
215 |           column_2: {
216 |             type: 'void',
217 |             'x-component': 'ArrayTable.Column',
218 |             'x-component-props': {
219 |               width: 50,
220 |               title: 'Index',
221 |               align: 'center',
222 |             },
223 |             properties: {
224 |               index: {
225 |                 type: 'void',
226 |                 'x-component': 'ArrayTable.Index',
227 |               },
228 |             },
229 |           },
230 |           column_3: {
231 |             type: 'void',
232 |             'x-component': 'ArrayTable.Column',
233 |             'x-component-props': {
234 |               title: 'Price',
235 |             },
236 |             properties: {
237 |               price: {
238 |                 type: 'number',
239 |                 default: 0,
240 |                 'x-decorator': 'Editable',
241 |                 'x-component': 'NumberPicker',
242 |                 'x-component-props': {
243 |                   addonAfter: '$',
244 |                 },
245 |               },
246 |             },
247 |           },
248 |           column_4: {
249 |             type: 'void',
250 |             'x-component': 'ArrayTable.Column',
251 |             'x-component-props': {
252 |               title: 'Count',
253 |             },
254 |             properties: {
255 |               count: {
256 |                 type: 'number',
257 |                 default: 0,
258 |                 'x-decorator': 'Editable',
259 |                 'x-component': 'NumberPicker',
260 |                 'x-component-props': {
261 |                   addonAfter: '$',
262 |                 },
263 |               },
264 |             },
265 |           },
266 |           column_5: {
267 |             type: 'void',
268 |             'x-component': 'ArrayTable.Column',
269 |             'x-component-props': {
270 |               title: 'Total',
271 |             },
272 |             properties: {
273 |               total: {
274 |                 type: 'number',
275 |                 'x-read-pretty': true,
276 |                 'x-decorator': 'FormItem',
277 |                 'x-component': 'NumberPicker',
278 |                 'x-component-props': {
279 |                   addonAfter: '$',
280 |                 },
281 |                 'x-reactions': {
282 |                   dependencies: ['.price', '.count'],
283 |                   when: '{{$deps[0] && $deps[1]}}',
284 |                   fulfill: {
285 |                     state: {
286 |                       value: '{{$deps[0] * $deps[1]}}',
287 |                     },
288 |                   },
289 |                 },
290 |               },
291 |             },
292 |           },
293 |           column_6: {
294 |             type: 'void',
295 |             'x-component': 'ArrayTable.Column',
296 |             'x-component-props': {
297 |               title: 'Operations',
298 |             },
299 |             properties: {
300 |               item: {
301 |                 type: 'void',
302 |                 'x-component': 'FormItem',
303 |                 properties: {
304 |                   remove: {
305 |                     type: 'void',
306 |                     'x-component': 'ArrayTable.Remove',
307 |                   },
308 |                   moveDown: {
309 |                     type: 'void',
310 |                     'x-component': 'ArrayTable.MoveDown',
311 |                   },
312 |                   moveUp: {
313 |                     type: 'void',
314 |                     'x-component': 'ArrayTable.MoveUp',
315 |                   },
316 |                 },
317 |               },
318 |             },
319 |           },
320 |         },
321 |       },
322 |       properties: {
323 |         add: {
324 |           type: 'void',
325 |           title: 'Add',
326 |           'x-component': 'ArrayTable.Addition',
327 |         },
328 |       },
329 |     },
330 |     total: {
331 |       type: 'number',
332 |       title: 'Total',
333 |       'x-decorator': 'FormItem',
334 |       'x-component': 'NumberPicker',
335 |       'x-component-props': {
336 |         addonAfter: '$',
337 |       },
338 |       'x-pattern': 'readPretty',
339 |       'x-reactions': {
340 |         dependencies: ['.projects'],
341 |         when: '{{$deps[0].length > 0}}',
342 |         fulfill: {
343 |           state: {
344 |             value:
345 |               '{{$deps[0].reduce((total,item)=>item.total ? total+item.total : total,0)}}',
346 |           },
347 |         },
348 |       },
349 |     },
350 |   },
351 | }
352 | 
353 | export default () => {
354 |   return (
355 |     <Form form={form} layout="vertical">
356 |       <SchemaField schema={schema} />
357 |       <FormButtonGroup>
358 |         <Submit onSubmit={console.log}>提交</Submit>
359 |       </FormButtonGroup>
360 |     </Form>
361 |   )
362 | }
363 | ```
364 | 
```

--------------------------------------------------------------------------------
/docs/guide/advanced/calculator.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Calculator
  2 | 
  3 | Linkage calculator is mainly used for evaluation and summarization in the process of filling in the form. In Formily 1.x, the cost of realizing this kind of demand is very high. In 2.x, we can easily implement it with the help of reactions.
  4 | 
  5 | ## Markup Schema Case
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   Form,
 11 |   FormItem,
 12 |   NumberPicker,
 13 |   ArrayTable,
 14 |   Editable,
 15 |   Input,
 16 |   FormButtonGroup,
 17 |   Submit,
 18 | } from '@formily/antd'
 19 | import { createForm } from '@formily/core'
 20 | import { createSchemaField } from '@formily/react'
 21 | 
 22 | const SchemaField = createSchemaField({
 23 |   components: {
 24 |     FormItem,
 25 |     Editable,
 26 |     Input,
 27 |     NumberPicker,
 28 |     ArrayTable,
 29 |   },
 30 | })
 31 | 
 32 | const form = createForm()
 33 | 
 34 | export default () => {
 35 |   return (
 36 |     <Form form={form} layout="vertical">
 37 |       <SchemaField>
 38 |         <SchemaField.Array
 39 |           name="projects"
 40 |           title="Projects"
 41 |           x-decorator="FormItem"
 42 |           x-component="ArrayTable"
 43 |         >
 44 |           <SchemaField.Object>
 45 |             <SchemaField.Void
 46 |               x-component="ArrayTable.Column"
 47 |               x-component-props={{ width: 50, title: 'Sort', align: 'center' }}
 48 |             >
 49 |               <SchemaField.Void
 50 |                 x-decorator="FormItem"
 51 |                 x-component="ArrayTable.SortHandle"
 52 |               />
 53 |             </SchemaField.Void>
 54 |             <SchemaField.Void
 55 |               x-component="ArrayTable.Column"
 56 |               x-component-props={{ width: 80, title: 'Index', align: 'center' }}
 57 |             >
 58 |               <SchemaField.String
 59 |                 x-decorator="FormItem"
 60 |                 x-component="ArrayTable.Index"
 61 |               />
 62 |             </SchemaField.Void>
 63 |             <SchemaField.Void
 64 |               x-component="ArrayTable.Column"
 65 |               x-component-props={{ title: 'Price' }}
 66 |             >
 67 |               <SchemaField.Number
 68 |                 name="price"
 69 |                 x-decorator="Editable"
 70 |                 required
 71 |                 x-component="NumberPicker"
 72 |                 x-component-props={{
 73 |                   addonAfter: '$',
 74 |                 }}
 75 |                 default={0}
 76 |               />
 77 |             </SchemaField.Void>
 78 |             <SchemaField.Void
 79 |               x-component="ArrayTable.Column"
 80 |               x-component-props={{ title: 'Count' }}
 81 |             >
 82 |               <SchemaField.Number
 83 |                 name="count"
 84 |                 x-decorator="Editable"
 85 |                 required
 86 |                 x-component="NumberPicker"
 87 |                 default={0}
 88 |               />
 89 |             </SchemaField.Void>
 90 |             <SchemaField.Void
 91 |               x-component="ArrayTable.Column"
 92 |               x-component-props={{ title: 'Total' }}
 93 |             >
 94 |               <SchemaField.Number
 95 |                 x-decorator="FormItem"
 96 |                 name="total"
 97 |                 x-component="NumberPicker"
 98 |                 x-pattern="readPretty"
 99 |                 x-component-props={{
100 |                   addonAfter: '$',
101 |                 }}
102 |                 x-reactions={{
103 |                   dependencies: ['.price', '.count'],
104 |                   when: '{{$deps[0] && $deps[1]}}',
105 |                   fulfill: {
106 |                     state: {
107 |                       value: '{{$deps[0] * $deps[1]}}',
108 |                     },
109 |                   },
110 |                 }}
111 |               />
112 |             </SchemaField.Void>
113 |             <SchemaField.Void
114 |               x-component="ArrayTable.Column"
115 |               x-component-props={{
116 |                 title: 'Operations',
117 |                 dataIndex: 'operations',
118 |                 width: 200,
119 |                 fixed: 'right',
120 |               }}
121 |             >
122 |               <SchemaField.Void x-component="FormItem">
123 |                 <SchemaField.Void x-component="ArrayTable.Remove" />
124 |                 <SchemaField.Void x-component="ArrayTable.MoveDown" />
125 |                 <SchemaField.Void x-component="ArrayTable.MoveUp" />
126 |               </SchemaField.Void>
127 |             </SchemaField.Void>
128 |           </SchemaField.Object>
129 |           <SchemaField.Void x-component="ArrayTable.Addition" title="Add" />
130 |         </SchemaField.Array>
131 |         <SchemaField.Number
132 |           name="total"
133 |           title="Total"
134 |           x-decorator="FormItem"
135 |           x-component="NumberPicker"
136 |           x-component-props={{
137 |             addonAfter: '$',
138 |           }}
139 |           x-pattern="readPretty"
140 |           x-reactions={{
141 |             dependencies: ['.projects'],
142 |             when: '{{$deps[0].length > 0}}',
143 |             fulfill: {
144 |               state: {
145 |                 value:
146 |                   '{{$deps[0].reduce((total,item)=>item.total ? total+item.total : total,0)}}',
147 |               },
148 |             },
149 |           }}
150 |         />
151 |       </SchemaField>
152 |       <FormButtonGroup>
153 |         <Submit onSubmit={console.log}>提交</Submit>
154 |       </FormButtonGroup>
155 |     </Form>
156 |   )
157 | }
158 | ```
159 | 
160 | ## JSON Schema Case
161 | 
162 | ```tsx
163 | import React from 'react'
164 | import {
165 |   Form,
166 |   FormItem,
167 |   NumberPicker,
168 |   ArrayTable,
169 |   Editable,
170 |   Input,
171 |   FormButtonGroup,
172 |   Submit,
173 | } from '@formily/antd'
174 | import { createForm } from '@formily/core'
175 | import { createSchemaField } from '@formily/react'
176 | 
177 | const SchemaField = createSchemaField({
178 |   components: {
179 |     FormItem,
180 |     Editable,
181 |     Input,
182 |     NumberPicker,
183 |     ArrayTable,
184 |   },
185 | })
186 | 
187 | const form = createForm()
188 | 
189 | const schema = {
190 |   type: 'object',
191 |   properties: {
192 |     projects: {
193 |       type: 'array',
194 |       title: 'Projects',
195 |       'x-decorator': 'FormItem',
196 |       'x-component': 'ArrayTable',
197 |       items: {
198 |         type: 'object',
199 |         properties: {
200 |           column_1: {
201 |             type: 'void',
202 |             'x-component': 'ArrayTable.Column',
203 |             'x-component-props': {
204 |               width: 50,
205 |               title: 'Sort',
206 |               align: 'center',
207 |             },
208 |             properties: {
209 |               sortable: {
210 |                 type: 'void',
211 |                 'x-component': 'ArrayTable.SortHandle',
212 |               },
213 |             },
214 |           },
215 |           column_2: {
216 |             type: 'void',
217 |             'x-component': 'ArrayTable.Column',
218 |             'x-component-props': {
219 |               width: 50,
220 |               title: 'Index',
221 |               align: 'center',
222 |             },
223 |             properties: {
224 |               index: {
225 |                 type: 'void',
226 |                 'x-component': 'ArrayTable.Index',
227 |               },
228 |             },
229 |           },
230 |           column_3: {
231 |             type: 'void',
232 |             'x-component': 'ArrayTable.Column',
233 |             'x-component-props': {
234 |               title: 'Price',
235 |             },
236 |             properties: {
237 |               price: {
238 |                 type: 'number',
239 |                 default: 0,
240 |                 'x-decorator': 'Editable',
241 |                 'x-component': 'NumberPicker',
242 |                 'x-component-props': {
243 |                   addonAfter: '$',
244 |                 },
245 |               },
246 |             },
247 |           },
248 |           column_4: {
249 |             type: 'void',
250 |             'x-component': 'ArrayTable.Column',
251 |             'x-component-props': {
252 |               title: 'Count',
253 |             },
254 |             properties: {
255 |               count: {
256 |                 type: 'number',
257 |                 default: 0,
258 |                 'x-decorator': 'Editable',
259 |                 'x-component': 'NumberPicker',
260 |                 'x-component-props': {
261 |                   addonAfter: '$',
262 |                 },
263 |               },
264 |             },
265 |           },
266 |           column_5: {
267 |             type: 'void',
268 |             'x-component': 'ArrayTable.Column',
269 |             'x-component-props': {
270 |               title: 'Total',
271 |             },
272 |             properties: {
273 |               total: {
274 |                 type: 'number',
275 |                 'x-read-pretty': true,
276 |                 'x-decorator': 'FormItem',
277 |                 'x-component': 'NumberPicker',
278 |                 'x-component-props': {
279 |                   addonAfter: '$',
280 |                 },
281 |                 'x-reactions': {
282 |                   dependencies: ['.price', '.count'],
283 |                   when: '{{$deps[0] && $deps[1]}}',
284 |                   fulfill: {
285 |                     state: {
286 |                       value: '{{$deps[0] * $deps[1]}}',
287 |                     },
288 |                   },
289 |                 },
290 |               },
291 |             },
292 |           },
293 |           column_6: {
294 |             type: 'void',
295 |             'x-component': 'ArrayTable.Column',
296 |             'x-component-props': {
297 |               title: 'Operations',
298 |             },
299 |             properties: {
300 |               item: {
301 |                 type: 'void',
302 |                 'x-component': 'FormItem',
303 |                 properties: {
304 |                   remove: {
305 |                     type: 'void',
306 |                     'x-component': 'ArrayTable.Remove',
307 |                   },
308 |                   moveDown: {
309 |                     type: 'void',
310 |                     'x-component': 'ArrayTable.MoveDown',
311 |                   },
312 |                   moveUp: {
313 |                     type: 'void',
314 |                     'x-component': 'ArrayTable.MoveUp',
315 |                   },
316 |                 },
317 |               },
318 |             },
319 |           },
320 |         },
321 |       },
322 |       properties: {
323 |         add: {
324 |           type: 'void',
325 |           title: 'Add',
326 |           'x-component': 'ArrayTable.Addition',
327 |         },
328 |       },
329 |     },
330 |     total: {
331 |       type: 'number',
332 |       title: 'Total',
333 |       'x-decorator': 'FormItem',
334 |       'x-component': 'NumberPicker',
335 |       'x-component-props': {
336 |         addonAfter: '$',
337 |       },
338 |       'x-pattern': 'readPretty',
339 |       'x-reactions': {
340 |         dependencies: ['.projects'],
341 |         when: '{{$deps[0].length > 0}}',
342 |         fulfill: {
343 |           state: {
344 |             value:
345 |               '{{$deps[0].reduce((total,item)=>item.total ? total+item.total : total,0)}}',
346 |           },
347 |         },
348 |       },
349 |     },
350 |   },
351 | }
352 | 
353 | export default () => {
354 |   return (
355 |     <Form form={form} layout="vertical">
356 |       <SchemaField schema={schema} />
357 |       <FormButtonGroup>
358 |         <Submit onSubmit={console.log}>submit</Submit>
359 |       </FormButtonGroup>
360 |     </Form>
361 |   )
362 | }
363 | ```
364 | 
```

--------------------------------------------------------------------------------
/packages/next/src/array-base/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { createContext, useContext } from 'react'
  2 | import { Button } from '@alifd/next'
  3 | import { isValid, isUndef, clone } from '@formily/shared'
  4 | import { ButtonProps } from '@alifd/next/lib/button'
  5 | import { ArrayField } from '@formily/core'
  6 | import { useField, useFieldSchema, Schema, JSXComponent } from '@formily/react'
  7 | import { SortableHandle } from 'react-sortable-hoc'
  8 | import {
  9 |   usePrefixCls,
 10 |   PlusOutlinedIcon,
 11 |   DeleteOutlinedIcon,
 12 |   DownOutlinedIcon,
 13 |   UpOutlinedIcon,
 14 |   MenuOutlinedIcon,
 15 |   CopyOutlinedIcon,
 16 | } from '../__builtins__'
 17 | import cls from 'classnames'
 18 | 
 19 | export interface IArrayBaseAdditionProps extends ButtonProps {
 20 |   title?: string
 21 |   method?: 'push' | 'unshift'
 22 |   defaultValue?: any
 23 |   icon?: React.ReactNode
 24 | }
 25 | 
 26 | export interface IArrayBaseOperationProps extends ButtonProps {
 27 |   title?: string
 28 |   index?: number
 29 |   ref?: React.Ref<Button>
 30 |   icon?: React.ReactNode
 31 | }
 32 | 
 33 | export interface IArrayBaseContext {
 34 |   props: IArrayBaseProps
 35 |   field: ArrayField
 36 |   schema: Schema
 37 | }
 38 | 
 39 | export interface IArrayBaseItemProps {
 40 |   index: number
 41 |   record: ((index: number) => Record<string, any>) | Record<string, any>
 42 | }
 43 | 
 44 | export type ArrayBaseMixins = {
 45 |   Addition?: React.FC<React.PropsWithChildren<IArrayBaseAdditionProps>>
 46 |   Remove?: React.FC<
 47 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 48 |   >
 49 |   Copy?: React.FC<
 50 |     React.PropsWithChildren<
 51 |       IArrayBaseAdditionProps & IArrayBaseOperationProps & { index?: number }
 52 |     >
 53 |   >
 54 |   MoveUp?: React.FC<
 55 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 56 |   >
 57 |   MoveDown?: React.FC<
 58 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 59 |   >
 60 |   SortHandle?: React.FC<
 61 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 62 |   >
 63 |   Index?: React.FC
 64 |   useArray?: () => IArrayBaseContext
 65 |   useIndex?: (index?: number) => number
 66 |   useRecord?: (record?: number) => any
 67 | }
 68 | 
 69 | export interface IArrayBaseProps {
 70 |   disabled?: boolean
 71 |   onCopy?: (index: number) => void
 72 |   onAdd?: (index: number) => void
 73 |   onRemove?: (index: number) => void
 74 |   onMoveDown?: (index: number) => void
 75 |   onMoveUp?: (index: number) => void
 76 | }
 77 | 
 78 | type ComposedArrayBase = React.FC<React.PropsWithChildren<IArrayBaseProps>> &
 79 |   ArrayBaseMixins & {
 80 |     Item?: React.FC<React.PropsWithChildren<IArrayBaseItemProps>>
 81 |     mixin?: <T extends JSXComponent>(target: T) => T & ArrayBaseMixins
 82 |   }
 83 | 
 84 | const ArrayBaseContext = createContext<IArrayBaseContext>(null)
 85 | 
 86 | const ItemContext = createContext<IArrayBaseItemProps>(null)
 87 | 
 88 | const takeRecord = (val: any, index?: number) =>
 89 |   typeof val === 'function' ? val(index) : val
 90 | 
 91 | const useArray = () => {
 92 |   return useContext(ArrayBaseContext)
 93 | }
 94 | 
 95 | const useIndex = (index?: number) => {
 96 |   const ctx = useContext(ItemContext)
 97 |   return ctx ? ctx.index : index
 98 | }
 99 | 
100 | const useRecord = (record?: number) => {
101 |   const ctx = useContext(ItemContext)
102 |   return takeRecord(ctx ? ctx.record : record, ctx?.index)
103 | }
104 | 
105 | const getSchemaDefaultValue = (schema: Schema) => {
106 |   if (schema?.type === 'array') return []
107 |   if (schema?.type === 'object') return {}
108 |   if (schema?.type === 'void') {
109 |     for (let key in schema.properties) {
110 |       const value = getSchemaDefaultValue(schema.properties[key])
111 |       if (isValid(value)) return value
112 |     }
113 |   }
114 | }
115 | 
116 | const getDefaultValue = (defaultValue: any, schema: Schema) => {
117 |   if (isValid(defaultValue)) return clone(defaultValue)
118 |   if (Array.isArray(schema?.items))
119 |     return getSchemaDefaultValue(schema?.items[0])
120 |   return getSchemaDefaultValue(schema?.items)
121 | }
122 | 
123 | export const ArrayBase: ComposedArrayBase = (props) => {
124 |   const field = useField<ArrayField>()
125 |   const schema = useFieldSchema()
126 |   return (
127 |     <ArrayBaseContext.Provider value={{ field, schema, props }}>
128 |       {props.children}
129 |     </ArrayBaseContext.Provider>
130 |   )
131 | }
132 | 
133 | ArrayBase.Item = ({ children, ...props }) => {
134 |   return <ItemContext.Provider value={props}>{children}</ItemContext.Provider>
135 | }
136 | 
137 | const SortHandle = SortableHandle((props: any) => {
138 |   const prefixCls = usePrefixCls('formily-array-base')
139 |   return (
140 |     <MenuOutlinedIcon
141 |       {...props}
142 |       className={cls(`${prefixCls}-sort-handle`, props.className)}
143 |       style={{ ...props.style }}
144 |     />
145 |   )
146 | }) as any
147 | 
148 | ArrayBase.SortHandle = () => {
149 |   const array = useArray()
150 |   if (!array) return null
151 |   if (array.field?.pattern !== 'editable') return null
152 |   return <SortHandle />
153 | }
154 | 
155 | ArrayBase.Index = (props) => {
156 |   const index = useIndex()
157 |   const prefixCls = usePrefixCls('formily-array-base')
158 |   return (
159 |     <span {...props} className={`${prefixCls}-index`}>
160 |       #{index + 1}.
161 |     </span>
162 |   )
163 | }
164 | 
165 | ArrayBase.Addition = (props) => {
166 |   const self = useField()
167 |   const array = useArray()
168 |   const prefixCls = usePrefixCls('formily-array-base')
169 |   if (!array) return null
170 |   if (
171 |     array.field?.pattern !== 'editable' &&
172 |     array.field?.pattern !== 'disabled'
173 |   )
174 |     return null
175 |   return (
176 |     <Button
177 |       {...props}
178 |       disabled={self?.disabled}
179 |       className={cls(`${prefixCls}-addition`, props.className)}
180 |       style={{ display: 'block', width: '100%', ...props.style }}
181 |       onClick={(e) => {
182 |         if (array.props?.disabled) return
183 |         e.stopPropagation()
184 |         const defaultValue = getDefaultValue(props.defaultValue, array.schema)
185 |         if (props.method === 'unshift') {
186 |           array.field?.unshift?.(defaultValue)
187 |           array.props?.onAdd?.(0)
188 |         } else {
189 |           array.field?.push?.(defaultValue)
190 |           array.props?.onAdd?.(array?.field?.value?.length - 1)
191 |         }
192 |         if (props.onClick) {
193 |           props.onClick(e)
194 |         }
195 |       }}
196 |     >
197 |       {isUndef(props.icon) ? <PlusOutlinedIcon /> : props.icon}
198 |       {props.title || self.title}
199 |     </Button>
200 |   )
201 | }
202 | 
203 | ArrayBase.Remove = React.forwardRef((props, ref) => {
204 |   const index = useIndex(props.index)
205 |   const self = useField()
206 |   const array = useArray()
207 |   const prefixCls = usePrefixCls('formily-array-base')
208 |   if (!array) return null
209 |   if (array.field?.pattern !== 'editable') return null
210 |   return (
211 |     <Button
212 |       text
213 |       {...props}
214 |       disabled={self?.disabled}
215 |       className={cls(
216 |         `${prefixCls}-remove`,
217 |         self?.disabled ? `${prefixCls}-remove-disabled` : '',
218 |         props.className
219 |       )}
220 |       ref={ref}
221 |       onClick={(e) => {
222 |         if (self?.disabled) return
223 |         e.stopPropagation()
224 |         array.field?.remove?.(index)
225 |         array.props?.onRemove?.(index)
226 |         if (props.onClick) {
227 |           props.onClick(e)
228 |         }
229 |       }}
230 |     >
231 |       {isUndef(props.icon) ? <DeleteOutlinedIcon /> : props.icon}
232 |       {props.title || self.title}
233 |     </Button>
234 |   )
235 | })
236 | 
237 | ArrayBase.Copy = React.forwardRef((props, ref) => {
238 |   const index = useIndex(props.index)
239 |   const self = useField()
240 |   const array = useArray()
241 |   const prefixCls = usePrefixCls('formily-array-base')
242 |   if (!array) return null
243 |   if (array.field?.pattern !== 'editable') return null
244 |   return (
245 |     <Button
246 |       text
247 |       {...props}
248 |       disabled={self?.disabled}
249 |       className={cls(
250 |         `${prefixCls}-copy`,
251 |         self?.disabled ? `${prefixCls}-copy-disabled` : '',
252 |         props.className
253 |       )}
254 |       ref={ref}
255 |       onClick={(e) => {
256 |         if (self?.disabled) return
257 |         e.stopPropagation()
258 |         if (array.props?.disabled) return
259 |         const value = clone(array?.field?.value[index])
260 |         const distIndex = index + 1
261 |         array.field?.insert?.(distIndex, value)
262 |         array.props?.onCopy?.(distIndex)
263 |         if (props.onClick) {
264 |           props.onClick(e)
265 |         }
266 |       }}
267 |     >
268 |       {isUndef(props.icon) ? <CopyOutlinedIcon /> : props.icon}
269 |       {props.title || self.title}
270 |     </Button>
271 |   )
272 | })
273 | 
274 | ArrayBase.MoveDown = React.forwardRef((props, ref) => {
275 |   const index = useIndex(props.index)
276 |   const self = useField()
277 |   const array = useArray()
278 |   const prefixCls = usePrefixCls('formily-array-base')
279 |   if (!array) return null
280 |   if (array.field?.pattern !== 'editable') return null
281 |   return (
282 |     <Button
283 |       text
284 |       {...props}
285 |       disabled={self?.disabled}
286 |       className={cls(
287 |         `${prefixCls}-move-down`,
288 |         self?.disabled ? `${prefixCls}-move-down-disabled` : '',
289 |         props.className
290 |       )}
291 |       ref={ref}
292 |       onClick={(e) => {
293 |         if (self?.disabled) return
294 |         e.stopPropagation()
295 |         array.field?.moveDown?.(index)
296 |         array.props?.onMoveDown?.(index)
297 |         if (props.onClick) {
298 |           props.onClick(e)
299 |         }
300 |       }}
301 |     >
302 |       {isUndef(props.icon) ? <DownOutlinedIcon /> : props.icon}
303 |       {props.title || self.title}
304 |     </Button>
305 |   )
306 | })
307 | 
308 | ArrayBase.MoveUp = React.forwardRef((props, ref) => {
309 |   const index = useIndex(props.index)
310 |   const self = useField()
311 |   const array = useArray()
312 |   const prefixCls = usePrefixCls('formily-array-base')
313 |   if (!array) return null
314 |   if (array.field?.pattern !== 'editable') return null
315 |   return (
316 |     <Button
317 |       text
318 |       {...props}
319 |       disabled={self?.disabled}
320 |       className={cls(
321 |         `${prefixCls}-move-up`,
322 |         self?.disabled ? `${prefixCls}-move-up-disabled` : '',
323 |         props.className
324 |       )}
325 |       ref={ref}
326 |       onClick={(e) => {
327 |         if (self?.disabled) return
328 |         e.stopPropagation()
329 |         array?.field?.moveUp(index)
330 |         array?.props?.onMoveUp?.(index)
331 |         if (props.onClick) {
332 |           props.onClick(e)
333 |         }
334 |       }}
335 |     >
336 |       {isUndef(props.icon) ? <UpOutlinedIcon /> : props.icon}
337 |       {props.title || self.title}
338 |     </Button>
339 |   )
340 | })
341 | 
342 | ArrayBase.useArray = useArray
343 | ArrayBase.useIndex = useIndex
344 | ArrayBase.useRecord = useRecord
345 | ArrayBase.mixin = (target: any) => {
346 |   target.Index = ArrayBase.Index
347 |   target.SortHandle = ArrayBase.SortHandle
348 |   target.Addition = ArrayBase.Addition
349 |   target.Copy = ArrayBase.Copy
350 |   target.Remove = ArrayBase.Remove
351 |   target.MoveDown = ArrayBase.MoveDown
352 |   target.MoveUp = ArrayBase.MoveUp
353 |   target.useArray = ArrayBase.useArray
354 |   target.useIndex = ArrayBase.useIndex
355 |   target.useRecord = ArrayBase.useRecord
356 |   return target
357 | }
358 | 
359 | export default ArrayBase
360 | 
```

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

```typescript
  1 | import {
  2 |   CopyOutlined,
  3 |   DeleteOutlined,
  4 |   DownOutlined,
  5 |   MenuOutlined,
  6 |   PlusOutlined,
  7 |   UpOutlined,
  8 | } from '@ant-design/icons'
  9 | import { ArrayField } from '@formily/core'
 10 | import { JSXComponent, Schema, useField, useFieldSchema } from '@formily/react'
 11 | import { clone, isUndef, isValid } from '@formily/shared'
 12 | import { Button } from 'antd'
 13 | import { ButtonProps } from 'antd/lib/button'
 14 | import cls from 'classnames'
 15 | import React, { createContext, useContext } from 'react'
 16 | import { SortableHandle, usePrefixCls } from '../__builtins__'
 17 | 
 18 | export interface IArrayBaseAdditionProps extends ButtonProps {
 19 |   title?: string
 20 |   method?: 'push' | 'unshift'
 21 |   defaultValue?: any
 22 | }
 23 | export interface IArrayBaseOperationProps extends ButtonProps {
 24 |   title?: string
 25 |   index?: number
 26 |   ref?: React.Ref<HTMLElement>
 27 | }
 28 | 
 29 | export interface IArrayBaseContext {
 30 |   props: IArrayBaseProps
 31 |   field: ArrayField
 32 |   schema: Schema
 33 | }
 34 | 
 35 | export interface IArrayBaseItemProps {
 36 |   index: number
 37 |   record: ((index: number) => Record<string, any>) | Record<string, any>
 38 | }
 39 | 
 40 | export type ArrayBaseMixins = {
 41 |   Addition?: React.FC<React.PropsWithChildren<IArrayBaseAdditionProps>>
 42 |   Copy?: React.FC<
 43 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 44 |   >
 45 |   Remove?: React.FC<
 46 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 47 |   >
 48 |   MoveUp?: React.FC<
 49 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 50 |   >
 51 |   MoveDown?: React.FC<
 52 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 53 |   >
 54 |   SortHandle?: React.FC<
 55 |     React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>
 56 |   >
 57 |   Index?: React.FC
 58 |   useArray?: () => IArrayBaseContext
 59 |   useIndex?: (index?: number) => number
 60 |   useRecord?: (record?: number) => any
 61 | }
 62 | 
 63 | export interface IArrayBaseProps {
 64 |   disabled?: boolean
 65 |   onAdd?: (index: number) => void
 66 |   onCopy?: (index: number) => void
 67 |   onRemove?: (index: number) => void
 68 |   onMoveDown?: (index: number) => void
 69 |   onMoveUp?: (index: number) => void
 70 | }
 71 | 
 72 | type ComposedArrayBase = React.FC<React.PropsWithChildren<IArrayBaseProps>> &
 73 |   ArrayBaseMixins & {
 74 |     Item?: React.FC<React.PropsWithChildren<IArrayBaseItemProps>>
 75 |     mixin?: <T extends JSXComponent>(target: T) => T & ArrayBaseMixins
 76 |   }
 77 | 
 78 | const ArrayBaseContext = createContext<IArrayBaseContext>(null)
 79 | 
 80 | const ItemContext = createContext<IArrayBaseItemProps>(null)
 81 | 
 82 | const takeRecord = (val: any, index?: number) =>
 83 |   typeof val === 'function' ? val(index) : val
 84 | 
 85 | const useArray = () => {
 86 |   return useContext(ArrayBaseContext)
 87 | }
 88 | 
 89 | const useIndex = (index?: number) => {
 90 |   const ctx = useContext(ItemContext)
 91 |   return ctx ? ctx.index : index
 92 | }
 93 | 
 94 | const useRecord = (record?: number) => {
 95 |   const ctx = useContext(ItemContext)
 96 |   return takeRecord(ctx ? ctx.record : record, ctx?.index)
 97 | }
 98 | 
 99 | const getSchemaDefaultValue = (schema: Schema) => {
100 |   if (schema?.type === 'array') return []
101 |   if (schema?.type === 'object') return {}
102 |   if (schema?.type === 'void') {
103 |     for (let key in schema.properties) {
104 |       const value = getSchemaDefaultValue(schema.properties[key])
105 |       if (isValid(value)) return value
106 |     }
107 |   }
108 | }
109 | 
110 | const getDefaultValue = (defaultValue: any, schema: Schema) => {
111 |   if (isValid(defaultValue)) return clone(defaultValue)
112 |   if (Array.isArray(schema?.items))
113 |     return getSchemaDefaultValue(schema?.items[0])
114 |   return getSchemaDefaultValue(schema?.items)
115 | }
116 | 
117 | export const ArrayBase: ComposedArrayBase = (props) => {
118 |   const field = useField<ArrayField>()
119 |   const schema = useFieldSchema()
120 |   return (
121 |     <ArrayBaseContext.Provider value={{ field, schema, props }}>
122 |       {props.children}
123 |     </ArrayBaseContext.Provider>
124 |   )
125 | }
126 | 
127 | ArrayBase.Item = ({ children, ...props }) => {
128 |   return <ItemContext.Provider value={props}>{children}</ItemContext.Provider>
129 | }
130 | 
131 | const SortHandle = SortableHandle((props: any) => {
132 |   const prefixCls = usePrefixCls('formily-array-base')
133 |   return (
134 |     <MenuOutlined
135 |       {...props}
136 |       className={cls(`${prefixCls}-sort-handle`, props.className)}
137 |       style={{ ...props.style }}
138 |     />
139 |   )
140 | }) as any
141 | 
142 | ArrayBase.SortHandle = (props) => {
143 |   const array = useArray()
144 |   if (!array) return null
145 |   if (array.field?.pattern !== 'editable') return null
146 |   return <SortHandle {...props} />
147 | }
148 | 
149 | ArrayBase.Index = (props) => {
150 |   const index = useIndex()
151 |   const prefixCls = usePrefixCls('formily-array-base')
152 |   return (
153 |     <span {...props} className={`${prefixCls}-index`}>
154 |       #{index + 1}.
155 |     </span>
156 |   )
157 | }
158 | 
159 | ArrayBase.Addition = (props) => {
160 |   const self = useField()
161 |   const array = useArray()
162 |   const prefixCls = usePrefixCls('formily-array-base')
163 |   if (!array) return null
164 |   if (
165 |     array.field?.pattern !== 'editable' &&
166 |     array.field?.pattern !== 'disabled'
167 |   )
168 |     return null
169 |   return (
170 |     <Button
171 |       type="dashed"
172 |       block
173 |       {...props}
174 |       disabled={self?.disabled}
175 |       className={cls(`${prefixCls}-addition`, props.className)}
176 |       onClick={(e) => {
177 |         if (array.props?.disabled) return
178 |         if (props.onClick) {
179 |           props.onClick(e)
180 |           if (e.defaultPrevented) return
181 |         }
182 |         const defaultValue = getDefaultValue(props.defaultValue, array.schema)
183 |         if (props.method === 'unshift') {
184 |           array.field?.unshift?.(defaultValue)
185 |           array.props?.onAdd?.(0)
186 |         } else {
187 |           array.field?.push?.(defaultValue)
188 |           array.props?.onAdd?.(array?.field?.value?.length - 1)
189 |         }
190 |       }}
191 |       icon={isUndef(props.icon) ? <PlusOutlined /> : props.icon}
192 |     >
193 |       {props.title || self.title}
194 |     </Button>
195 |   )
196 | }
197 | 
198 | ArrayBase.Copy = React.forwardRef((props, ref) => {
199 |   const self = useField()
200 |   const array = useArray()
201 |   const index = useIndex(props.index)
202 |   const prefixCls = usePrefixCls('formily-array-base')
203 |   if (!array) return null
204 |   if (array.field?.pattern !== 'editable') return null
205 |   return (
206 |     <Button
207 |       type="text"
208 |       {...props}
209 |       disabled={self?.disabled}
210 |       className={cls(
211 |         `${prefixCls}-copy`,
212 |         self?.disabled ? `${prefixCls}-copy-disabled` : '',
213 |         props.className
214 |       )}
215 |       ref={ref}
216 |       onClick={(e) => {
217 |         if (self?.disabled) return
218 |         e.stopPropagation()
219 |         if (array.props?.disabled) return
220 |         if (props.onClick) {
221 |           props.onClick(e)
222 |           if (e.defaultPrevented) return
223 |         }
224 |         const value = clone(array?.field?.value[index])
225 |         const distIndex = index + 1
226 |         array.field?.insert?.(distIndex, value)
227 |         array.props?.onCopy?.(distIndex)
228 |       }}
229 |       icon={isUndef(props.icon) ? <CopyOutlined /> : props.icon}
230 |     >
231 |       {props.title || self.title}
232 |     </Button>
233 |   )
234 | })
235 | 
236 | ArrayBase.Remove = React.forwardRef((props, ref) => {
237 |   const index = useIndex(props.index)
238 |   const self = useField()
239 |   const array = useArray()
240 |   const prefixCls = usePrefixCls('formily-array-base')
241 |   if (!array) return null
242 |   if (array.field?.pattern !== 'editable') return null
243 |   return (
244 |     <Button
245 |       type="text"
246 |       {...props}
247 |       disabled={self?.disabled}
248 |       className={cls(
249 |         `${prefixCls}-remove`,
250 |         self?.disabled ? `${prefixCls}-remove-disabled` : '',
251 |         props.className
252 |       )}
253 |       ref={ref}
254 |       onClick={(e) => {
255 |         if (self?.disabled) return
256 |         e.stopPropagation()
257 |         if (props.onClick) {
258 |           props.onClick(e)
259 |           if (e.defaultPrevented) return
260 |         }
261 |         array.field?.remove?.(index)
262 |         array.props?.onRemove?.(index)
263 |       }}
264 |       icon={isUndef(props.icon) ? <DeleteOutlined /> : props.icon}
265 |     >
266 |       {props.title || self.title}
267 |     </Button>
268 |   )
269 | })
270 | 
271 | ArrayBase.MoveDown = React.forwardRef((props, ref) => {
272 |   const index = useIndex(props.index)
273 |   const self = useField()
274 |   const array = useArray()
275 |   const prefixCls = usePrefixCls('formily-array-base')
276 |   if (!array) return null
277 |   if (array.field?.pattern !== 'editable') return null
278 |   return (
279 |     <Button
280 |       type="text"
281 |       {...props}
282 |       disabled={self?.disabled}
283 |       className={cls(
284 |         `${prefixCls}-move-down`,
285 |         self?.disabled ? `${prefixCls}-move-down-disabled` : '',
286 |         props.className
287 |       )}
288 |       ref={ref}
289 |       onClick={(e) => {
290 |         if (self?.disabled) return
291 |         e.stopPropagation()
292 |         if (props.onClick) {
293 |           props.onClick(e)
294 |           if (e.defaultPrevented) return
295 |         }
296 |         array.field?.moveDown?.(index)
297 |         array.props?.onMoveDown?.(index)
298 |       }}
299 |       icon={isUndef(props.icon) ? <DownOutlined /> : props.icon}
300 |     >
301 |       {props.title || self.title}
302 |     </Button>
303 |   )
304 | })
305 | 
306 | ArrayBase.MoveUp = React.forwardRef((props, ref) => {
307 |   const index = useIndex(props.index)
308 |   const self = useField()
309 |   const array = useArray()
310 |   const prefixCls = usePrefixCls('formily-array-base')
311 |   if (!array) return null
312 |   if (array.field?.pattern !== 'editable') return null
313 |   return (
314 |     <Button
315 |       type="text"
316 |       {...props}
317 |       disabled={self?.disabled}
318 |       className={cls(
319 |         `${prefixCls}-move-up`,
320 |         self?.disabled ? `${prefixCls}-move-up-disabled` : '',
321 |         props.className
322 |       )}
323 |       ref={ref}
324 |       onClick={(e) => {
325 |         if (self?.disabled) return
326 |         e.stopPropagation()
327 |         if (props.onClick) {
328 |           props.onClick(e)
329 |           if (e.defaultPrevented) return
330 |         }
331 |         array?.field?.moveUp(index)
332 |         array?.props?.onMoveUp?.(index)
333 |       }}
334 |       icon={isUndef(props.icon) ? <UpOutlined /> : props.icon}
335 |     >
336 |       {props.title || self.title}
337 |     </Button>
338 |   )
339 | })
340 | 
341 | ArrayBase.useArray = useArray
342 | ArrayBase.useIndex = useIndex
343 | ArrayBase.useRecord = useRecord
344 | ArrayBase.mixin = (target: any) => {
345 |   target.Index = ArrayBase.Index
346 |   target.SortHandle = ArrayBase.SortHandle
347 |   target.Addition = ArrayBase.Addition
348 |   target.Copy = ArrayBase.Copy
349 |   target.Remove = ArrayBase.Remove
350 |   target.MoveDown = ArrayBase.MoveDown
351 |   target.MoveUp = ArrayBase.MoveUp
352 |   target.useArray = ArrayBase.useArray
353 |   target.useIndex = ArrayBase.useIndex
354 |   target.useRecord = ArrayBase.useRecord
355 |   return target
356 | }
357 | 
358 | export default ArrayBase
359 | 
```
Page 25/52FirstPrevNextLast