#
tokens: 48046/50000 16/1152 files (page 16/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 16 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/reactive/docs/guide/concept.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Core idea
 2 | 
 3 | ## Observable
 4 | 
 5 | Observable is the most important part of the reactive programming model. Its core concepts are:
 6 | 
 7 | An observable object, literally means a subscribable object, **we create a subscribable object, each time we manipulate the attribute data of the object, we will automatically notify the subscriber**, @formily/reactive creates an observable object mainly It is created by ES Proxy, which can perfectly hijack data operations
 8 | 
 9 | We mainly use the following APIs to create observable objects in @formily/reactive:
10 | 
11 | - The observable function creates a deep observable object
12 |   - The observable.deep function creates a deep hijacking observable object
13 |   - The observable.shallow function creates shallow hijacked observable objects
14 |   - The observable.computed function creates a cache calculator
15 |   - The observable.box function creates observable objects with get/set methods
16 |   - The observable.ref function creates a reference-level observable object
17 | - The define function defines the observable domain model, which can be combined with the observable function and its static attribute (such as observable.computed) function to complete the definition of the domain model
18 | - The model function defines an automatic observable domain model. It will wrap the getter setter attribute as a computed attribute, wrap the function as an action, and wrap other data attributes with observable (note that this is a deep hijacking)
19 | 
20 | ## Reaction
21 | 
22 | In the reactive programming model, reaction is equivalent to the subscriber of the subscribeable object. It receives a tracker function. When this function is executed, if there is a **read operation* on an attribute in the observable object inside the function. * (Dependency collection), then the current reaction will be bound to the attribute (dependency tracking), until the attribute has a **write operation\*\* in other places, it will trigger the tracker function to repeat execution, using a picture Means:
23 | 
24 | ![](https://img.alicdn.com/imgextra/i4/O1CN01DQMGUL22mFICDsKfY_!!6000000007162-2-tps-1234-614.png)
25 | 
26 | You can see that from subscribing to dispatching subscriptions, it is actually a closed loop state machine. Each time the tracker function is executed, the dependencies are re-collected, and the tracker execution is re-triggered when the dependencies change. So, if we don't want to subscribe to the reaction anymore, we must manually dispose, otherwise there will be memory leaks.
27 | 
28 | In @formily/reactive, we mainly use the following APIs to create reactions:
29 | 
30 | - autorun creates an automatically executed responder
31 | - reaction creates a responder that can implement dirty checks
32 | - Tracker creates a dependency tracker that requires users to manually perform tracking
33 | 
34 | ## Computed
35 | 
36 | Computed is also a relatively important concept in the reactive programming model. In one sentence, **computed is a Reaction that can cache calculation results**
37 | 
38 | Its caching strategy is: as long as the observable data that the computed function relies on changes, the function will re-execute the calculation, otherwise the cached result will always be read
39 | 
40 | The requirement here is that the computed function must be a pure function. The internally dependent data is either observable data or external constant data. If it is external variable data (non-observable), then if the external variable data changes, the computed will not be re-executed computational.
41 | 
42 | ## Batch
43 | 
44 | As mentioned earlier, @formily/reactive is a reactive programming model based on Proxy hijacking. Therefore, any atomic operation will trigger the execution of Reaction, which is obviously a waste of computing resources. For example, we have a function for multiple observables. Property to operate:
45 | 
46 | ```ts
47 | import { observable, autorun } from '@formily/reactive'
48 | const obs = observable({})
49 | const handler = () => {
50 |   obs.aa = 123
51 |   obs.bb = 321
52 | }
53 | 
54 | autorun(() => {
55 |   console.log(obs.aa, obs.bb)
56 | })
57 | 
58 | handler()
59 | ```
60 | 
61 | This will execute 3 prints, autorun is executed once by default, plus the assignment of obs.aa is executed once, and the assignment of obs.bb is executed once. If there are more atomic operations, the number of executions will be more. Therefore, we recommend using batch mode To merge the updates:
62 | 
63 | ```ts
64 | import { observable, autorun, batch } from '@formily/reactive'
65 | const obs = observable({})
66 | const handler = () => {
67 |   obs.aa = 123
68 |   obs.bb = 321
69 | }
70 | 
71 | autorun(() => {
72 |   console.log(obs.aa, obs.bb)
73 | })
74 | 
75 | batch(() => {
76 |   handler()
77 | })
78 | ```
79 | 
80 | Of course, we can also use action for high-level packaging:
81 | 
82 | ```ts
83 | import { observable, autorun, action } from '@formily/reactive'
84 | const obs = observable({})
85 | const handler = action.bound(() => {
86 |   obs.aa = 123
87 |   obs.bb = 321
88 | })
89 | 
90 | autorun(() => {
91 |   console.log(obs.aa, obs.bb)
92 | })
93 | 
94 | handler()
95 | ```
96 | 
97 | The final number of executions is 2 times, even if there are more operations inside the handler, it is still 2 times
98 | 
```

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

```typescript
  1 | import React, { Fragment, useMemo } from 'react'
  2 | import { Collapse, Badge } from 'antd'
  3 | import { model, markRaw } from '@formily/reactive'
  4 | import { CollapseProps, CollapsePanelProps } from 'antd/lib/collapse'
  5 | import {
  6 |   useField,
  7 |   observer,
  8 |   useFieldSchema,
  9 |   RecursionField,
 10 | } from '@formily/react'
 11 | import { Schema, SchemaKey } from '@formily/json-schema'
 12 | import cls from 'classnames'
 13 | import { usePrefixCls } from '../__builtins__'
 14 | import { toArr } from '@formily/shared'
 15 | 
 16 | type ActiveKeys = string | number | Array<string | number>
 17 | 
 18 | type ActiveKey = string | number
 19 | export interface IFormCollapse {
 20 |   activeKeys: ActiveKeys
 21 |   hasActiveKey(key: ActiveKey): boolean
 22 |   setActiveKeys(key: ActiveKeys): void
 23 |   addActiveKey(key: ActiveKey): void
 24 |   removeActiveKey(key: ActiveKey): void
 25 |   toggleActiveKey(key: ActiveKey): void
 26 | }
 27 | 
 28 | export interface IFormCollapseProps extends CollapseProps {
 29 |   formCollapse?: IFormCollapse
 30 | }
 31 | 
 32 | type ComposedFormCollapse = React.FC<
 33 |   React.PropsWithChildren<IFormCollapseProps>
 34 | > & {
 35 |   CollapsePanel?: React.FC<React.PropsWithChildren<CollapsePanelProps>>
 36 |   createFormCollapse?: (defaultActiveKeys?: ActiveKeys) => IFormCollapse
 37 | }
 38 | 
 39 | const usePanels = () => {
 40 |   const collapseField = useField()
 41 |   const schema = useFieldSchema()
 42 |   const panels: { name: SchemaKey; props: any; schema: Schema }[] = []
 43 |   schema.mapProperties((schema, name) => {
 44 |     const field = collapseField.query(collapseField.address.concat(name)).take()
 45 |     if (field?.display === 'none' || field?.display === 'hidden') return
 46 |     if (schema['x-component']?.indexOf('CollapsePanel') > -1) {
 47 |       const componentProps = field?.componentProps
 48 |       panels.push({
 49 |         name,
 50 |         props: {
 51 |           ...componentProps,
 52 |           key: componentProps?.key || name,
 53 |         },
 54 |         schema,
 55 |       })
 56 |     }
 57 |   })
 58 |   return panels
 59 | }
 60 | 
 61 | const createFormCollapse = (defaultActiveKeys?: ActiveKeys) => {
 62 |   const formCollapse = model({
 63 |     activeKeys: defaultActiveKeys,
 64 |     setActiveKeys(keys: ActiveKeys) {
 65 |       formCollapse.activeKeys = keys
 66 |     },
 67 |     hasActiveKey(key: ActiveKey) {
 68 |       if (Array.isArray(formCollapse.activeKeys)) {
 69 |         if (formCollapse.activeKeys.includes(key)) {
 70 |           return true
 71 |         }
 72 |       } else if (formCollapse.activeKeys == key) {
 73 |         return true
 74 |       }
 75 |       return false
 76 |     },
 77 |     addActiveKey(key: ActiveKey) {
 78 |       if (formCollapse.hasActiveKey(key)) return
 79 |       formCollapse.activeKeys = toArr(formCollapse.activeKeys).concat(key)
 80 |     },
 81 |     removeActiveKey(key: ActiveKey) {
 82 |       if (Array.isArray(formCollapse.activeKeys)) {
 83 |         formCollapse.activeKeys = formCollapse.activeKeys.filter(
 84 |           (item) => item != key
 85 |         )
 86 |       } else {
 87 |         formCollapse.activeKeys = ''
 88 |       }
 89 |     },
 90 |     toggleActiveKey(key: ActiveKey) {
 91 |       if (formCollapse.hasActiveKey(key)) {
 92 |         formCollapse.removeActiveKey(key)
 93 |       } else {
 94 |         formCollapse.addActiveKey(key)
 95 |       }
 96 |     },
 97 |   })
 98 |   return markRaw(formCollapse)
 99 | }
100 | 
101 | export const FormCollapse: ComposedFormCollapse = observer(
102 |   ({ formCollapse, ...props }) => {
103 |     const field = useField()
104 |     const panels = usePanels()
105 |     const prefixCls = usePrefixCls('formily-collapse', props)
106 |     const _formCollapse = useMemo(() => {
107 |       return formCollapse
108 |         ? formCollapse
109 |         : createFormCollapse(props.defaultActiveKey)
110 |     }, [])
111 | 
112 |     const takeActiveKeys = () => {
113 |       if (props.activeKey) return props.activeKey
114 |       if (_formCollapse?.activeKeys) return _formCollapse?.activeKeys
115 |       if (props.accordion) return panels[0]?.name
116 |       return panels.map((item) => item.name)
117 |     }
118 | 
119 |     const badgedHeader = (key: SchemaKey, props: any) => {
120 |       const errors = field.form.queryFeedbacks({
121 |         type: 'error',
122 |         address: `${field.address.concat(key)}.*`,
123 |       })
124 |       if (errors.length) {
125 |         return (
126 |           <Badge size="small" className="errors-badge" count={errors.length}>
127 |             {props.header}
128 |           </Badge>
129 |         )
130 |       }
131 |       return props.header
132 |     }
133 |     return (
134 |       <Collapse
135 |         {...props}
136 |         className={cls(prefixCls, props.className)}
137 |         activeKey={takeActiveKeys()}
138 |         onChange={(key) => {
139 |           props?.onChange?.(key)
140 |           _formCollapse?.setActiveKeys?.(key)
141 |         }}
142 |       >
143 |         {panels.map(({ props, schema, name }, index) => (
144 |           <Collapse.Panel
145 |             key={index}
146 |             {...props}
147 |             header={badgedHeader(name, props)}
148 |             forceRender
149 |           >
150 |             <RecursionField schema={schema} name={name} />
151 |           </Collapse.Panel>
152 |         ))}
153 |       </Collapse>
154 |     )
155 |   }
156 | )
157 | 
158 | const CollapsePanel: React.FC<React.PropsWithChildren<CollapsePanelProps>> = ({
159 |   children,
160 | }) => {
161 |   return <Fragment>{children}</Fragment>
162 | }
163 | 
164 | FormCollapse.CollapsePanel = CollapsePanel
165 | FormCollapse.createFormCollapse = createFormCollapse
166 | 
167 | export default FormCollapse
168 | 
```

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

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField :schema="schema" />
  4 |     <Submit @submit="log">提交</Submit>
  5 |   </FormProvider>
  6 | </template>
  7 | 
  8 | <script>
  9 | import { createForm } from '@formily/core'
 10 | import { FormProvider, createSchemaField } from '@formily/vue'
 11 | import {
 12 |   FormItem,
 13 |   FormButtonGroup,
 14 |   Submit,
 15 |   Input,
 16 |   ArrayCollapse,
 17 | } from '@formily/element'
 18 | import { Button } from 'element-ui'
 19 | 
 20 | const SchemaField = createSchemaField({
 21 |   components: {
 22 |     FormItem,
 23 |     Input,
 24 |     ArrayCollapse,
 25 |   },
 26 | })
 27 | 
 28 | export default {
 29 |   components: {
 30 |     FormProvider,
 31 |     FormButtonGroup,
 32 |     Button,
 33 |     Submit,
 34 |     ...SchemaField,
 35 |   },
 36 | 
 37 |   data() {
 38 |     const form = createForm()
 39 |     const schema = {
 40 |       type: 'object',
 41 |       properties: {
 42 |         string_array: {
 43 |           type: 'array',
 44 |           'x-component': 'ArrayCollapse',
 45 |           maxItems: 3,
 46 |           'x-decorator': 'FormItem',
 47 |           items: {
 48 |             type: 'object',
 49 |             'x-component': 'ArrayCollapse.Item',
 50 |             'x-component-props': {
 51 |               title: '字符串数组',
 52 |             },
 53 |             properties: {
 54 |               index: {
 55 |                 type: 'void',
 56 |                 'x-component': 'ArrayCollapse.Index',
 57 |               },
 58 |               input: {
 59 |                 type: 'string',
 60 |                 'x-decorator': 'FormItem',
 61 |                 title: 'Input',
 62 |                 required: true,
 63 |                 'x-component': 'Input',
 64 |               },
 65 |               remove: {
 66 |                 type: 'void',
 67 |                 'x-component': 'ArrayCollapse.Remove',
 68 |               },
 69 |               moveUp: {
 70 |                 type: 'void',
 71 |                 'x-component': 'ArrayCollapse.MoveUp',
 72 |               },
 73 |               moveDown: {
 74 |                 type: 'void',
 75 |                 'x-component': 'ArrayCollapse.MoveDown',
 76 |               },
 77 |             },
 78 |           },
 79 |           properties: {
 80 |             addition: {
 81 |               type: 'void',
 82 |               title: '添加条目',
 83 |               'x-component': 'ArrayCollapse.Addition',
 84 |             },
 85 |           },
 86 |         },
 87 |         array: {
 88 |           type: 'array',
 89 |           'x-component': 'ArrayCollapse',
 90 |           maxItems: 3,
 91 |           'x-decorator': 'FormItem',
 92 |           items: {
 93 |             type: 'object',
 94 |             'x-component': 'ArrayCollapse.Item',
 95 |             'x-component-props': {
 96 |               title: '对象数组',
 97 |             },
 98 |             properties: {
 99 |               index: {
100 |                 type: 'void',
101 |                 'x-component': 'ArrayCollapse.Index',
102 |               },
103 |               input: {
104 |                 type: 'string',
105 |                 'x-decorator': 'FormItem',
106 |                 title: 'Input',
107 |                 required: true,
108 |                 'x-component': 'Input',
109 |               },
110 |               remove: {
111 |                 type: 'void',
112 |                 'x-component': 'ArrayCollapse.Remove',
113 |               },
114 |               moveUp: {
115 |                 type: 'void',
116 |                 'x-component': 'ArrayCollapse.MoveUp',
117 |               },
118 |               moveDown: {
119 |                 type: 'void',
120 |                 'x-component': 'ArrayCollapse.MoveDown',
121 |               },
122 |             },
123 |           },
124 |           properties: {
125 |             addition: {
126 |               type: 'void',
127 |               title: '添加条目',
128 |               'x-component': 'ArrayCollapse.Addition',
129 |             },
130 |           },
131 |         },
132 |         array_unshift: {
133 |           type: 'array',
134 |           'x-component': 'ArrayCollapse',
135 |           maxItems: 3,
136 |           'x-decorator': 'FormItem',
137 |           items: {
138 |             type: 'object',
139 |             'x-component': 'ArrayCollapse.Item',
140 |             'x-component-props': {
141 |               title: '对象数组',
142 |             },
143 |             properties: {
144 |               index: {
145 |                 type: 'void',
146 |                 'x-component': 'ArrayCollapse.Index',
147 |               },
148 |               input: {
149 |                 type: 'string',
150 |                 'x-decorator': 'FormItem',
151 |                 title: 'Input',
152 |                 required: true,
153 |                 'x-component': 'Input',
154 |               },
155 |               remove: {
156 |                 type: 'void',
157 |                 'x-component': 'ArrayCollapse.Remove',
158 |               },
159 |               moveUp: {
160 |                 type: 'void',
161 |                 'x-component': 'ArrayCollapse.MoveUp',
162 |               },
163 |               moveDown: {
164 |                 type: 'void',
165 |                 'x-component': 'ArrayCollapse.MoveDown',
166 |               },
167 |             },
168 |           },
169 |           properties: {
170 |             addition: {
171 |               type: 'void',
172 |               title: '添加条目(unshift)',
173 |               'x-component': 'ArrayCollapse.Addition',
174 |               'x-component-props': {
175 |                 method: 'unshift',
176 |               },
177 |             },
178 |           },
179 |         },
180 |       },
181 |     }
182 | 
183 |     return {
184 |       form,
185 |       schema,
186 |     }
187 |   },
188 |   methods: {
189 |     log(values) {
190 |       console.log(values)
191 |     },
192 |   },
193 | }
194 | </script>
195 | 
196 | <style lang="scss" scoped></style>
197 | 
```

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

```typescript
  1 | import { ArrayField } from '@formily/core'
  2 | import { ISchema } from '@formily/json-schema'
  3 | import { observer } from '@formily/reactive-vue'
  4 | import { h, RecursionField, useField, useFieldSchema } from '@formily/vue'
  5 | import { defineComponent } from 'vue-demi'
  6 | import { SlickItem, SlickList } from 'vue-slicksort'
  7 | import { ArrayBase } from '../array-base'
  8 | import { stylePrefix } from '../__builtins__/configs'
  9 | import { composeExport } from '../__builtins__/shared'
 10 | 
 11 | const isAdditionComponent = (schema: ISchema) => {
 12 |   return schema['x-component']?.indexOf('Addition') > -1
 13 | }
 14 | 
 15 | export interface IArrayItemsItemProps {
 16 |   type?: 'card' | 'divide'
 17 | }
 18 | 
 19 | const ArrayItemsInner = observer(
 20 |   defineComponent({
 21 |     name: 'FArrayItems',
 22 |     setup() {
 23 |       const fieldRef = useField<ArrayField>()
 24 |       const schemaRef = useFieldSchema()
 25 | 
 26 |       const prefixCls = `${stylePrefix}-array-items`
 27 |       const { getKey, keyMap } = ArrayBase.useKey(schemaRef.value)
 28 | 
 29 |       return () => {
 30 |         const field = fieldRef.value
 31 |         const schema = schemaRef.value
 32 |         const dataSource = Array.isArray(field.value) ? field.value.slice() : []
 33 | 
 34 |         const renderItems = () => {
 35 |           const items = dataSource?.map((item, index) => {
 36 |             const items = Array.isArray(schema.items)
 37 |               ? schema.items[index] || schema.items[0]
 38 |               : schema.items
 39 |             const key = getKey(item, index)
 40 |             return h(
 41 |               ArrayBase.Item,
 42 |               {
 43 |                 key,
 44 |                 props: {
 45 |                   index,
 46 |                   record: item,
 47 |                 },
 48 |               },
 49 |               {
 50 |                 default: () =>
 51 |                   h(
 52 |                     SlickItem,
 53 |                     {
 54 |                       class: [`${prefixCls}-item-inner`],
 55 |                       props: {
 56 |                         index,
 57 |                       },
 58 |                       key,
 59 |                     },
 60 |                     {
 61 |                       default: () =>
 62 |                         h(
 63 |                           RecursionField,
 64 |                           {
 65 |                             props: {
 66 |                               schema: items,
 67 |                               name: index,
 68 |                             },
 69 |                           },
 70 |                           {}
 71 |                         ),
 72 |                     }
 73 |                   ),
 74 |               }
 75 |             )
 76 |           })
 77 | 
 78 |           return h(
 79 |             SlickList,
 80 |             {
 81 |               class: [`${prefixCls}-list`],
 82 |               props: {
 83 |                 useDragHandle: true,
 84 |                 lockAxis: 'y',
 85 |                 helperClass: `${prefixCls}-sort-helper`,
 86 |                 value: [],
 87 |               },
 88 |               on: {
 89 |                 'sort-end': ({ oldIndex, newIndex }) => {
 90 |                   if (Array.isArray(keyMap)) {
 91 |                     keyMap.splice(newIndex, 0, keyMap.splice(oldIndex, 1)[0])
 92 |                   }
 93 |                   field.move(oldIndex, newIndex)
 94 |                 },
 95 |               },
 96 |             },
 97 |             { default: () => items }
 98 |           )
 99 |         }
100 |         const renderAddition = () => {
101 |           return schema.reduceProperties((addition, schema) => {
102 |             if (isAdditionComponent(schema)) {
103 |               return h(
104 |                 RecursionField,
105 |                 {
106 |                   props: {
107 |                     schema,
108 |                     name: 'addition',
109 |                   },
110 |                 },
111 |                 {}
112 |               )
113 |             }
114 |             return addition
115 |           }, null)
116 |         }
117 | 
118 |         return h(
119 |           ArrayBase,
120 |           {
121 |             props: {
122 |               keyMap,
123 |             },
124 |           },
125 |           {
126 |             default: () =>
127 |               h(
128 |                 'div',
129 |                 {
130 |                   class: [prefixCls],
131 |                   on: {
132 |                     change: () => {},
133 |                   },
134 |                 },
135 |                 {
136 |                   default: () => [renderItems(), renderAddition()],
137 |                 }
138 |               ),
139 |           }
140 |         )
141 |       }
142 |     },
143 |   })
144 | )
145 | 
146 | const ArrayItemsItem = defineComponent<IArrayItemsItemProps>({
147 |   name: 'FArrayItemsItem',
148 |   props: ['type'],
149 |   setup(props, { attrs, slots }) {
150 |     const prefixCls = `${stylePrefix}-array-items`
151 | 
152 |     return () =>
153 |       h(
154 |         'div',
155 |         {
156 |           class: [`${prefixCls}-${props.type || 'card'}`],
157 |           attrs: {
158 |             ...attrs,
159 |           },
160 |           on: {
161 |             change: () => {},
162 |           },
163 |         },
164 |         slots
165 |       )
166 |   },
167 | })
168 | 
169 | export const ArrayItems = composeExport(ArrayItemsInner, {
170 |   Item: ArrayItemsItem,
171 |   Index: ArrayBase.Index,
172 |   SortHandle: ArrayBase.SortHandle,
173 |   Addition: ArrayBase.Addition,
174 |   Remove: ArrayBase.Remove,
175 |   MoveDown: ArrayBase.MoveDown,
176 |   MoveUp: ArrayBase.MoveUp,
177 |   useArray: ArrayBase.useArray,
178 |   useIndex: ArrayBase.useIndex,
179 |   useRecord: ArrayBase.useRecord,
180 | })
181 | 
182 | export default ArrayItems
183 | 
```

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

```typescript
  1 | import React, { Fragment, useMemo } from 'react'
  2 | import { Collapse, Badge } from '@alifd/next'
  3 | import { model, markRaw } from '@formily/reactive'
  4 | import {
  5 |   CollapseProps,
  6 |   PanelProps as CollapsePanelProps,
  7 | } from '@alifd/next/lib/collapse'
  8 | import {
  9 |   useField,
 10 |   observer,
 11 |   useFieldSchema,
 12 |   RecursionField,
 13 | } from '@formily/react'
 14 | import { Schema, SchemaKey } from '@formily/json-schema'
 15 | import { toArr } from '@formily/shared'
 16 | import cls from 'classnames'
 17 | import { usePrefixCls } from '../__builtins__'
 18 | 
 19 | type ActiveKeys = string | number | Array<string | number>
 20 | 
 21 | type ActiveKey = string | number
 22 | 
 23 | export interface IFormCollapse {
 24 |   activeKeys: ActiveKeys
 25 |   hasActiveKey(key: ActiveKey): boolean
 26 |   setActiveKeys(key: ActiveKeys): void
 27 |   addActiveKey(key: ActiveKey): void
 28 |   removeActiveKey(key: ActiveKey): void
 29 |   toggleActiveKey(key: ActiveKey): void
 30 | }
 31 | 
 32 | export interface IFormCollapseProps extends CollapseProps {
 33 |   formCollapse?: IFormCollapse
 34 | }
 35 | 
 36 | type ComposedFormCollapse = React.FC<
 37 |   React.PropsWithChildren<IFormCollapseProps>
 38 | > & {
 39 |   CollapsePanel?: React.FC<React.PropsWithChildren<CollapsePanelProps>>
 40 |   createFormCollapse?: (
 41 |     defaultActiveKeys?: CollapseProps['expandedKeys']
 42 |   ) => IFormCollapse
 43 | }
 44 | 
 45 | const usePanels = () => {
 46 |   const collapseField = useField()
 47 |   const schema = useFieldSchema()
 48 |   const panels: { name: SchemaKey; props: any; schema: Schema }[] = []
 49 |   schema.mapProperties((schema, name) => {
 50 |     const field = collapseField.query(collapseField.address.concat(name)).take()
 51 |     if (field?.display === 'none' || field?.display === 'hidden') return
 52 |     if (schema['x-component']?.indexOf('CollapsePanel') > -1) {
 53 |       panels.push({
 54 |         name,
 55 |         props: {
 56 |           ...schema?.['x-component-props'],
 57 |           title: schema?.['x-component-props']?.title || schema?.title,
 58 |           key: schema?.['x-component-props']?.key || name,
 59 |         },
 60 |         schema,
 61 |       })
 62 |     }
 63 |   })
 64 |   return panels
 65 | }
 66 | 
 67 | const createFormCollapse = (defaultActiveKeys?: ActiveKeys) => {
 68 |   const formCollapse = model({
 69 |     activeKeys: defaultActiveKeys,
 70 |     setActiveKeys(keys: ActiveKeys) {
 71 |       formCollapse.activeKeys = keys
 72 |     },
 73 |     hasActiveKey(key: ActiveKey) {
 74 |       if (Array.isArray(formCollapse.activeKeys)) {
 75 |         if (formCollapse.activeKeys.includes(key)) {
 76 |           return true
 77 |         }
 78 |       } else if (formCollapse.activeKeys == key) {
 79 |         return true
 80 |       }
 81 |       return false
 82 |     },
 83 |     addActiveKey(key: ActiveKey) {
 84 |       if (formCollapse.hasActiveKey(key)) return
 85 |       formCollapse.activeKeys = toArr(formCollapse.activeKeys).concat(key)
 86 |     },
 87 |     removeActiveKey(key: ActiveKey) {
 88 |       if (Array.isArray(formCollapse.activeKeys)) {
 89 |         formCollapse.activeKeys = formCollapse.activeKeys.filter(
 90 |           (item) => item != key
 91 |         )
 92 |       } else {
 93 |         formCollapse.activeKeys = []
 94 |       }
 95 |     },
 96 |     toggleActiveKey(key: ActiveKey) {
 97 |       if (formCollapse.hasActiveKey(key)) {
 98 |         formCollapse.removeActiveKey(key)
 99 |       } else {
100 |         formCollapse.addActiveKey(key)
101 |       }
102 |     },
103 |   })
104 |   return markRaw(formCollapse)
105 | }
106 | 
107 | export const FormCollapse: ComposedFormCollapse = observer(
108 |   ({ formCollapse, ...props }) => {
109 |     const field = useField()
110 |     const panels = usePanels()
111 |     const prefixCls = usePrefixCls('formily-collapse', props)
112 |     const _formCollapse = useMemo(() => {
113 |       return formCollapse
114 |         ? formCollapse
115 |         : createFormCollapse(props.defaultExpandedKeys)
116 |     }, [])
117 | 
118 |     const takeExpandedKeys = () => {
119 |       if (props.expandedKeys) return props.expandedKeys
120 |       if (_formCollapse?.activeKeys) return _formCollapse?.activeKeys
121 |       if (props.accordion) return panels[0]?.name
122 |       return panels.map((item) => item.name)
123 |     }
124 | 
125 |     const badgedHeader = (key: SchemaKey, props: any) => {
126 |       const errors = field.form.queryFeedbacks({
127 |         type: 'error',
128 |         address: `${field.address.concat(key)}.*`,
129 |       })
130 |       if (errors.length) {
131 |         return (
132 |           <Badge className="errors-badge" count={errors.length}>
133 |             {props.title}
134 |           </Badge>
135 |         )
136 |       }
137 |       return props.title
138 |     }
139 |     return (
140 |       <Collapse
141 |         {...props}
142 |         className={cls(prefixCls, props.className)}
143 |         expandedKeys={takeExpandedKeys() as any}
144 |         onExpand={(keys) => {
145 |           props?.onExpand?.(keys)
146 |           _formCollapse?.setActiveKeys?.(keys)
147 |         }}
148 |       >
149 |         {panels.map(({ props, schema, name }, index) => (
150 |           <Collapse.Panel
151 |             key={index}
152 |             {...props}
153 |             title={badgedHeader(name, props)}
154 |           >
155 |             <RecursionField schema={schema} name={name} />
156 |           </Collapse.Panel>
157 |         ))}
158 |       </Collapse>
159 |     )
160 |   }
161 | )
162 | 
163 | const CollapsePanel: React.FC<React.PropsWithChildren<CollapsePanelProps>> = ({
164 |   children,
165 | }) => {
166 |   return <Fragment>{children}</Fragment>
167 | }
168 | 
169 | FormCollapse.CollapsePanel = CollapsePanel
170 | FormCollapse.createFormCollapse = createFormCollapse
171 | 
172 | export default FormCollapse
173 | 
```

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

```typescript
  1 | import React from 'react'
  2 | import {
  3 |   Form,
  4 |   Field as FieldType,
  5 |   VoidField,
  6 |   ObjectField,
  7 |   GeneralField,
  8 |   IFieldFactoryProps,
  9 |   IVoidFieldFactoryProps,
 10 |   FormPatternTypes,
 11 |   FieldDisplayTypes,
 12 |   FieldValidator,
 13 | } from '@formily/core'
 14 | import { ReactFC } from '@formily/reactive-react'
 15 | import { ISchema, Schema, SchemaKey } from '@formily/json-schema'
 16 | import { FormPathPattern } from '@formily/shared'
 17 | 
 18 | export type JSXComponent =
 19 |   | keyof JSX.IntrinsicElements
 20 |   | React.JSXElementConstructor<any>
 21 | 
 22 | export type IProviderProps = {
 23 |   form: Form
 24 | }
 25 | 
 26 | export interface IFormSpyProps {
 27 |   children?: (form: Form) => ReactChild
 28 | }
 29 | 
 30 | export type RenderPropsChildren<Payload> =
 31 |   | ((field: Payload, form: Form) => React.ReactNode)
 32 |   | React.ReactNode
 33 | 
 34 | export interface IFieldProps<
 35 |   D extends JSXComponent,
 36 |   C extends JSXComponent,
 37 |   Field = FieldType
 38 | > extends IFieldFactoryProps<D, C> {
 39 |   children?: RenderPropsChildren<Field>
 40 |   decorator?: [] | [D] | [D, React.ComponentProps<D>] | any[]
 41 |   component?: [] | [C] | [C, React.ComponentProps<C>] | any[]
 42 | }
 43 | 
 44 | export interface IVoidFieldProps<
 45 |   D extends JSXComponent,
 46 |   C extends JSXComponent,
 47 |   Field = VoidField
 48 | > extends IVoidFieldFactoryProps<D, C> {
 49 |   children?: RenderPropsChildren<Field>
 50 |   decorator?: [] | [D] | [D, React.ComponentProps<D>] | any[]
 51 |   component?: [] | [C] | [C, React.ComponentProps<C>] | any[]
 52 | }
 53 | 
 54 | export interface IComponentMapper<T extends JSXComponent> {
 55 |   (target: T): JSXComponent
 56 | }
 57 | 
 58 | export type IStateMapper<Props> =
 59 |   | {
 60 |       [key in keyof FieldType]?: keyof Props | boolean
 61 |     }
 62 |   | ((props: Props, field: GeneralField) => Props)
 63 | 
 64 | export type SchemaReactComponents = Record<string, JSXComponent>
 65 | 
 66 | export interface ISchemaFieldReactFactoryOptions<
 67 |   Components extends SchemaReactComponents = any
 68 | > {
 69 |   components?: Components
 70 |   scope?: any
 71 | }
 72 | 
 73 | export interface ISchemaFieldOptionContext {
 74 |   components: SchemaReactComponents
 75 | }
 76 | 
 77 | export interface ISchemaFieldProps<
 78 |   Decorator extends JSXComponent = any,
 79 |   Component extends JSXComponent = any,
 80 |   InnerField = ObjectField<Decorator, Component>
 81 | > extends Omit<IFieldFactoryProps<Decorator, Component, InnerField>, 'name'> {
 82 |   schema?: ISchema
 83 |   components?: {
 84 |     [key: string]: JSXComponent
 85 |   }
 86 |   scope?: any
 87 |   name?: SchemaKey
 88 |   children?: React.ReactNode
 89 | }
 90 | 
 91 | export interface ISchemaMapper {
 92 |   (schema: Schema, name: SchemaKey): Schema
 93 | }
 94 | 
 95 | export interface ISchemaFilter {
 96 |   (schema: Schema, name: SchemaKey): boolean
 97 | }
 98 | export interface IRecursionFieldProps {
 99 |   schema: ISchema
100 |   name?: SchemaKey
101 |   basePath?: FormPathPattern
102 |   propsRecursion?: boolean
103 |   onlyRenderProperties?: boolean
104 |   onlyRenderSelf?: boolean
105 |   mapProperties?: ISchemaMapper
106 |   filterProperties?: ISchemaFilter
107 | }
108 | 
109 | export type ObjectKey = string | number | boolean | symbol
110 | 
111 | export type Path<T, Key extends keyof T = keyof T> = Key extends string
112 |   ? T[Key] extends Record<string, any>
113 |     ?
114 |         | `${Key}.${Path<T[Key], Exclude<keyof T[Key], keyof Array<any>>> &
115 |             string}`
116 |         | `${Key}.${Exclude<keyof T[Key], keyof Array<any>> & string}`
117 |         | Key
118 |     : Key
119 |   : never
120 | 
121 | export type PathValue<
122 |   T,
123 |   P extends Path<T>
124 | > = P extends `${infer Key}.${infer Rest}`
125 |   ? Key extends keyof T
126 |     ? Rest extends Path<T[Key]>
127 |       ? PathValue<T[Key], Rest>
128 |       : never
129 |     : never
130 |   : P extends keyof T
131 |   ? T[P]
132 |   : never
133 | 
134 | export type KeyOfReactComponent<T> = Exclude<
135 |   keyof T,
136 |   'contextTypes' | 'displayName' | 'propTypes' | 'defaultProps'
137 | >
138 | 
139 | export type ReactComponentPath<
140 |   T,
141 |   Key extends KeyOfReactComponent<T> = KeyOfReactComponent<T>
142 | > = Key extends string
143 |   ? T[Key] extends Record<string, any>
144 |     ?
145 |         | `${Key}.${Exclude<KeyOfReactComponent<T[Key]>, keyof Array<any>> &
146 |             string}`
147 |         | Key
148 |     : Key
149 |   : never
150 | 
151 | export type ReactComponentPropsByPathValue<
152 |   T extends Record<string, any>,
153 |   P extends ReactComponentPath<T>
154 | > = P extends `${infer Key}.${infer Rest}`
155 |   ? Key extends keyof T
156 |     ? Rest extends ReactComponentPath<T[Key]>
157 |       ? ReactComponentPropsByPathValue<T[Key], Rest>
158 |       : never
159 |     : React.ComponentProps<T[P]>
160 |   : P extends keyof T
161 |   ? React.ComponentProps<T[P]>
162 |   : never
163 | export interface ISchemaMarkupFieldProps<
164 |   Components extends SchemaReactComponents,
165 |   Decorator extends ReactComponentPath<Components>,
166 |   Component extends ReactComponentPath<Components>
167 | > extends ISchema<
168 |     Decorator,
169 |     Component,
170 |     ReactComponentPropsByPathValue<Components, Decorator>,
171 |     ReactComponentPropsByPathValue<Components, Component>,
172 |     FormPatternTypes,
173 |     FieldDisplayTypes,
174 |     FieldValidator,
175 |     React.ReactNode,
176 |     GeneralField
177 |   > {
178 |   children?: React.ReactNode
179 | }
180 | 
181 | export type ISchemaTypeFieldProps<
182 |   Components extends SchemaReactComponents,
183 |   Decorator extends ReactComponentPath<Components>,
184 |   Component extends ReactComponentPath<Components>
185 | > = ISchemaMarkupFieldProps<Components, Decorator, Component>
186 | 
187 | export interface IExpressionScopeProps {
188 |   value?: any
189 | }
190 | 
191 | export interface IRecordScopeProps {
192 |   getIndex?(): number
193 |   getRecord(): any
194 | }
195 | 
196 | export interface IRecordsScopeProps {
197 |   getRecords(): any[]
198 | }
199 | 
200 | export type ReactChild = React.ReactElement | string | number
201 | 
202 | export { ReactFC }
203 | 
```

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

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField>
  4 |       <SchemaObjectField x-component="QueryForm">
  5 |         <SchemaStringField
  6 |           name="input1"
  7 |           title="Input 1"
  8 |           x-component="Input"
  9 |           x-decorator="FormItem"
 10 |         />
 11 |         <SchemaStringField
 12 |           name="input2"
 13 |           title="Input 2"
 14 |           x-component="Input"
 15 |           x-decorator="FormItem"
 16 |         />
 17 | 
 18 |         <SchemaStringField
 19 |           name="select1"
 20 |           title="Select 1"
 21 |           x-component="Select"
 22 |           x-decorator="FormItem"
 23 |         />
 24 |         <SchemaStringField
 25 |           name="select2"
 26 |           title="Select 2"
 27 |           x-component="Select"
 28 |           x-decorator="FormItem"
 29 |         />
 30 |         <SchemaStringField
 31 |           name="date"
 32 |           title="DatePicker"
 33 |           x-component="DatePicker"
 34 |           x-decorator="FormItem"
 35 |         />
 36 |         <SchemaStringField
 37 |           name="dateRange"
 38 |           title="DatePicker"
 39 |           x-component="DatePicker"
 40 |           x-decorator="FormItem"
 41 |           :x-decorator-props="{
 42 |             gridSpan: 2,
 43 |           }"
 44 |           :x-component-props="{
 45 |             type: 'daterange',
 46 |           }"
 47 |         />
 48 |         <SchemaStringField
 49 |           name="select3"
 50 |           title="Select 3"
 51 |           x-component="Select"
 52 |           x-decorator="FormItem"
 53 |         />
 54 |       </SchemaObjectField>
 55 |     </SchemaField>
 56 |   </FormProvider>
 57 | </template>
 58 | 
 59 | <script>
 60 | import { defineComponent, ref, onUnmounted } from 'vue-demi'
 61 | import { createForm } from '@formily/core'
 62 | import {
 63 |   createSchemaField,
 64 |   FormProvider,
 65 |   FragmentComponent,
 66 | } from '@formily/vue'
 67 | import { autorun } from '@formily/reactive'
 68 | import { observer } from '@formily/reactive-vue'
 69 | import {
 70 |   Form,
 71 |   Input,
 72 |   Select,
 73 |   DatePicker,
 74 |   FormItem,
 75 |   FormGrid,
 76 |   Submit,
 77 |   Reset,
 78 |   FormButtonGroup,
 79 | } from '@formily/element'
 80 | 
 81 | const useCollapseGrid = (maxRows) => {
 82 |   const grid = FormGrid.createFormGrid({
 83 |     maxColumns: 4,
 84 |     maxWidth: 240,
 85 |     maxRows: maxRows,
 86 |     shouldVisible: (node, grid) => {
 87 |       if (node.index === grid.childSize - 1) return true
 88 |       if (grid.maxRows === Infinity) return true
 89 |       return node.shadowRow < maxRows + 1
 90 |     },
 91 |   })
 92 | 
 93 |   const expanded = ref(false)
 94 |   const type = ref('')
 95 | 
 96 |   const takeType = (realRows, computeRows) => {
 97 |     if (realRows < maxRows + 1) return 'incomplete-wrap'
 98 |     if (computeRows > maxRows) return 'collapsible'
 99 |     return 'complete-wrap'
100 |   }
101 | 
102 |   const dispose = autorun(() => {
103 |     expanded.value = grid.maxRows === Infinity
104 | 
105 |     const realRows = grid.shadowRows
106 |     const computeRows = grid.fullnessLastColumn
107 |       ? grid.shadowRows - 1
108 |       : grid.shadowRows
109 | 
110 |     type.value = takeType(realRows, computeRows)
111 |   })
112 | 
113 |   onUnmounted(dispose)
114 | 
115 |   const toggle = () => {
116 |     if (grid.maxRows === Infinity) {
117 |       grid.maxRows = maxRows
118 |     } else {
119 |       grid.maxRows = Infinity
120 |     }
121 |   }
122 |   return {
123 |     grid,
124 |     expanded,
125 |     toggle,
126 |     type,
127 |   }
128 | }
129 | 
130 | const QueryForm = observer(
131 |   defineComponent({
132 |     setup(props, { slots }) {
133 |       const { grid, expanded, toggle, type } = useCollapseGrid(1)
134 | 
135 |       const renderActions = () => {
136 |         return (
137 |           <FragmentComponent>
138 |             <Submit onSubmit={console.log}>查询</Submit>
139 |             <Reset>重置</Reset>
140 |           </FragmentComponent>
141 |         )
142 |       }
143 | 
144 |       const renderButtonGroup = () => {
145 |         if (type.value === 'incomplete-wrap') {
146 |           return (
147 |             <FormButtonGroup.FormItem>
148 |               <FormButtonGroup>{renderActions()}</FormButtonGroup>
149 |             </FormButtonGroup.FormItem>
150 |           )
151 |         }
152 |         if (type.value === 'collapsible') {
153 |           return (
154 |             <FragmentComponent>
155 |               <FormButtonGroup>
156 |                 <a
157 |                   href=""
158 |                   onClick={(e) => {
159 |                     e.preventDefault()
160 |                     toggle()
161 |                   }}
162 |                 >
163 |                   {expanded.value ? '收起' : '展开'}
164 |                 </a>
165 |               </FormButtonGroup>
166 |               <FormButtonGroup align="right">{renderActions()}</FormButtonGroup>
167 |             </FragmentComponent>
168 |           )
169 |         }
170 |         return (
171 |           <FormButtonGroup
172 |             align="right"
173 |             style={{ display: 'flex', width: '100%' }}
174 |           >
175 |             {renderActions()}
176 |           </FormButtonGroup>
177 |         )
178 |       }
179 | 
180 |       return () => {
181 |         return (
182 |           <Form {...props} layout="vertical" feedbackLayout="terse">
183 |             <FormGrid grid={grid}>
184 |               {slots.default()}
185 |               <FormGrid.GridColumn
186 |                 gridSpan={-1}
187 |                 style={{ display: 'flex', justifyContent: 'space-between' }}
188 |               >
189 |                 {renderButtonGroup()}
190 |               </FormGrid.GridColumn>
191 |             </FormGrid>
192 |           </Form>
193 |         )
194 |       }
195 |     },
196 |   })
197 | )
198 | 
199 | const form = createForm()
200 | const fields = createSchemaField({
201 |   components: {
202 |     QueryForm,
203 |     Input,
204 |     Select,
205 |     DatePicker,
206 |     FormItem,
207 |   },
208 | })
209 | 
210 | export default {
211 |   components: { FormProvider, ...fields, Submit },
212 |   data() {
213 |     return {
214 |       form,
215 |     }
216 |   },
217 |   methods: {
218 |     onSubmit(value) {
219 |       console.log(value)
220 |     },
221 |   },
222 | }
223 | </script>
224 | 
```

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

```typescript
  1 | import { isFn, each, isPlainObj, isArr, toArr, FormPath } from '@formily/shared'
  2 | import { isObservable, untracked } from '@formily/reactive'
  3 | import { Schema } from './schema'
  4 | import { ISchema } from './types'
  5 | 
  6 | const REVA_ACTIONS_KEY = Symbol.for('__REVA_ACTIONS')
  7 | 
  8 | export const SchemaNestedMap = {
  9 |   parent: true,
 10 |   root: true,
 11 |   properties: true,
 12 |   patternProperties: true,
 13 |   additionalProperties: true,
 14 |   items: true,
 15 |   additionalItems: true,
 16 |   'x-linkages': true,
 17 |   'x-reactions': true,
 18 | }
 19 | 
 20 | export const SchemaStateMap = {
 21 |   title: 'title',
 22 |   description: 'description',
 23 |   default: 'initialValue',
 24 |   enum: 'dataSource',
 25 |   readOnly: 'readOnly',
 26 |   writeOnly: 'editable',
 27 |   'x-content': 'content',
 28 |   'x-data': 'data',
 29 |   'x-value': 'value',
 30 |   'x-editable': 'editable',
 31 |   'x-disabled': 'disabled',
 32 |   'x-read-pretty': 'readPretty',
 33 |   'x-read-only': 'readOnly',
 34 |   'x-visible': 'visible',
 35 |   'x-hidden': 'hidden',
 36 |   'x-display': 'display',
 37 |   'x-pattern': 'pattern',
 38 |   'x-validator': 'validator',
 39 |   'x-decorator': 'decoratorType',
 40 |   'x-component': 'componentType',
 41 |   'x-decorator-props': 'decoratorProps',
 42 |   'x-component-props': 'componentProps',
 43 | }
 44 | 
 45 | export const SchemaValidatorMap = {
 46 |   required: true,
 47 |   format: true,
 48 |   maxItems: true,
 49 |   minItems: true,
 50 |   maxLength: true,
 51 |   minLength: true,
 52 |   maximum: true,
 53 |   minimum: true,
 54 |   exclusiveMaximum: true,
 55 |   exclusiveMinimum: true,
 56 |   pattern: true,
 57 |   const: true,
 58 |   multipleOf: true,
 59 |   maxProperties: true,
 60 |   minProperties: true,
 61 |   uniqueItems: true,
 62 | }
 63 | 
 64 | export const SchemaNormalKeys = Object.keys(SchemaStateMap)
 65 | 
 66 | export const SchemaValidatorKeys = Object.keys(SchemaValidatorMap)
 67 | 
 68 | export const hasOwnProperty = Object.prototype.hasOwnProperty
 69 | 
 70 | export const traverse = (
 71 |   target: any,
 72 |   visitor: (value: any, path: Array<string | number>) => void
 73 | ) => {
 74 |   const seenObjects = []
 75 |   const root = target
 76 |   const traverse = (target: any, path = []) => {
 77 |     if (isPlainObj(target)) {
 78 |       const seenIndex = seenObjects.indexOf(target)
 79 |       if (seenIndex > -1) {
 80 |         return
 81 |       }
 82 |       const addIndex = seenObjects.length
 83 |       seenObjects.push(target)
 84 |       if (isNoNeedCompileObject(target) && root !== target) {
 85 |         visitor(target, path)
 86 |         return
 87 |       }
 88 |       each(target, (value, key) => {
 89 |         traverse(value, path.concat(key))
 90 |       })
 91 |       seenObjects.splice(addIndex, 1)
 92 |     } else {
 93 |       visitor(target, path)
 94 |     }
 95 |   }
 96 |   traverse(target)
 97 | }
 98 | 
 99 | export const traverseSchema = (
100 |   schema: ISchema,
101 |   visitor: (value: any, path: any[], omitCompile?: boolean) => void
102 | ) => {
103 |   if (schema['x-validator'] !== undefined) {
104 |     visitor(
105 |       schema['x-validator'],
106 |       ['x-validator'],
107 |       schema['x-compile-omitted']?.includes('x-validator')
108 |     )
109 |   }
110 |   const seenObjects = []
111 |   const root = schema
112 |   const traverse = (target: any, path = []) => {
113 |     if (
114 |       path[0] === 'x-compile-omitted' ||
115 |       path[0] === 'x-validator' ||
116 |       path[0] === 'version' ||
117 |       path[0] === '_isJSONSchemaObject'
118 |     )
119 |       return
120 |     if (String(path[0]).indexOf('x-') == -1 && isFn(target)) return
121 |     if (SchemaNestedMap[path[0]]) return
122 |     if (schema['x-compile-omitted']?.indexOf(path[0]) > -1) {
123 |       visitor(target, path, true)
124 |       return
125 |     }
126 |     if (isPlainObj(target)) {
127 |       if (path[0] === 'default' || path[0] === 'x-value') {
128 |         visitor(target, path)
129 |         return
130 |       }
131 |       const seenIndex = seenObjects.indexOf(target)
132 |       if (seenIndex > -1) {
133 |         return
134 |       }
135 |       const addIndex = seenObjects.length
136 |       seenObjects.push(target)
137 |       if (isNoNeedCompileObject(target) && root !== target) {
138 |         visitor(target, path)
139 |         return
140 |       }
141 |       each(target, (value, key) => {
142 |         traverse(value, path.concat(key))
143 |       })
144 |       seenObjects.splice(addIndex, 1)
145 |     } else {
146 |       visitor(target, path)
147 |     }
148 |   }
149 |   traverse(schema)
150 | }
151 | 
152 | export const isNoNeedCompileObject = (source: any) => {
153 |   if ('$$typeof' in source && '_owner' in source) {
154 |     return true
155 |   }
156 |   if (source['_isAMomentObject']) {
157 |     return true
158 |   }
159 |   if (Schema.isSchemaInstance(source)) {
160 |     return true
161 |   }
162 |   if (source[REVA_ACTIONS_KEY]) {
163 |     return true
164 |   }
165 |   if (isFn(source['toJS'])) {
166 |     return true
167 |   }
168 |   if (isFn(source['toJSON'])) {
169 |     return true
170 |   }
171 |   if (isObservable(source)) {
172 |     return true
173 |   }
174 |   return false
175 | }
176 | 
177 | export const createDataSource = (source: any[]) => {
178 |   return toArr(source).map((item) => {
179 |     if (typeof item === 'object') {
180 |       return item
181 |     } else {
182 |       return {
183 |         label: item,
184 |         value: item,
185 |       }
186 |     }
187 |   })
188 | }
189 | 
190 | export const patchStateFormSchema = (
191 |   targetState: any,
192 |   pattern: any[],
193 |   compiled: any
194 | ) => {
195 |   untracked(() => {
196 |     const path = FormPath.parse(pattern)
197 |     const segments = path.segments
198 |     const key = segments[0]
199 |     const isEnum = key === 'enum' && isArr(compiled)
200 |     const schemaMapKey = SchemaStateMap[key]
201 |     if (schemaMapKey) {
202 |       FormPath.setIn(
203 |         targetState,
204 |         [schemaMapKey].concat(segments.slice(1)),
205 |         isEnum ? createDataSource(compiled) : compiled
206 |       )
207 |     } else {
208 |       const isValidatorKey = SchemaValidatorMap[key]
209 |       if (isValidatorKey) {
210 |         targetState['setValidatorRule']?.(key, compiled)
211 |       }
212 |     }
213 |   })
214 | }
215 | 
```

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

```markdown
  1 | # DatePicker
  2 | 
  3 | > 日期选择器
  4 | 
  5 | ## Markup Schema 案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { DatePicker, 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 |     DatePicker,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.String
 26 |         name="date"
 27 |         title="普通日期"
 28 |         x-decorator="FormItem"
 29 |         x-component="DatePicker"
 30 |       />
 31 |       <SchemaField.String
 32 |         name="week"
 33 |         title="周选择"
 34 |         x-decorator="FormItem"
 35 |         x-component="DatePicker.WeekPicker"
 36 |       />
 37 |       <SchemaField.String
 38 |         name="month"
 39 |         title="月选择"
 40 |         x-decorator="FormItem"
 41 |         x-component="DatePicker.MonthPicker"
 42 |       />
 43 |       <SchemaField.String
 44 |         name="year"
 45 |         title="年选择"
 46 |         x-decorator="FormItem"
 47 |         x-component="DatePicker.YearPicker"
 48 |       />
 49 |       <SchemaField.String
 50 |         name="[startDate,endDate]"
 51 |         title="日期范围"
 52 |         x-decorator="FormItem"
 53 |         x-component="DatePicker.RangePicker"
 54 |         x-component-props={{
 55 |           showTime: true,
 56 |         }}
 57 |       />
 58 |       <SchemaField.String
 59 |         name="range_month"
 60 |         title="月范围选择"
 61 |         x-decorator="FormItem"
 62 |         x-component="DatePicker.RangePicker"
 63 |         x-component-props={{
 64 |           type: 'month',
 65 |         }}
 66 |       />
 67 |       <SchemaField.String
 68 |         name="range_year"
 69 |         title="年范围选择"
 70 |         x-decorator="FormItem"
 71 |         x-component="DatePicker.RangePicker"
 72 |         x-component-props={{
 73 |           type: 'year',
 74 |         }}
 75 |       />
 76 |     </SchemaField>
 77 |     <FormButtonGroup>
 78 |       <Submit onSubmit={console.log}>提交</Submit>
 79 |     </FormButtonGroup>
 80 |   </FormProvider>
 81 | )
 82 | ```
 83 | 
 84 | ## JSON Schema 案例
 85 | 
 86 | ```tsx
 87 | import React from 'react'
 88 | import { DatePicker, FormItem, FormButtonGroup, Submit } from '@formily/next'
 89 | import { createForm } from '@formily/core'
 90 | import { FormProvider, createSchemaField } from '@formily/react'
 91 | 
 92 | const SchemaField = createSchemaField({
 93 |   components: {
 94 |     DatePicker,
 95 |     FormItem,
 96 |   },
 97 | })
 98 | 
 99 | const form = createForm()
100 | 
101 | const schema = {
102 |   type: 'object',
103 |   properties: {
104 |     date: {
105 |       title: '普通日期',
106 |       'x-decorator': 'FormItem',
107 |       'x-component': 'DatePicker',
108 |       type: 'string',
109 |     },
110 |     week: {
111 |       title: '周选择',
112 |       'x-decorator': 'FormItem',
113 |       'x-component': 'DatePicker.WeekPicker',
114 |       type: 'string',
115 |     },
116 |     month: {
117 |       title: '月选择',
118 |       'x-decorator': 'FormItem',
119 |       'x-component': 'DatePicker.MonthPicker',
120 |       type: 'string',
121 |     },
122 |     year: {
123 |       title: '年选择',
124 |       'x-decorator': 'FormItem',
125 |       'x-component': 'DatePicker.YearPicker',
126 |       type: 'string',
127 |     },
128 |     '[startDate,endDate]': {
129 |       title: '日期范围',
130 |       'x-decorator': 'FormItem',
131 |       'x-component': 'DatePicker.RangePicker',
132 |       'x-component-props': {
133 |         showTime: true,
134 |       },
135 |       type: 'string',
136 |     },
137 |     range_month: {
138 |       title: '月范围选择',
139 |       'x-decorator': 'FormItem',
140 |       'x-component': 'DatePicker.RangePicker',
141 |       'x-component-props': {
142 |         type: 'month',
143 |       },
144 |       type: 'string',
145 |     },
146 |     range_year: {
147 |       name: 'range_year',
148 |       title: '年范围选择',
149 |       'x-decorator': 'FormItem',
150 |       'x-component': 'DatePicker.RangePicker',
151 |       'x-component-props': {
152 |         type: 'year',
153 |       },
154 |       type: 'string',
155 |     },
156 |   },
157 | }
158 | 
159 | export default () => (
160 |   <FormProvider form={form}>
161 |     <SchemaField schema={schema} />
162 |     <FormButtonGroup>
163 |       <Submit onSubmit={console.log}>提交</Submit>
164 |     </FormButtonGroup>
165 |   </FormProvider>
166 | )
167 | ```
168 | 
169 | ## 纯 JSX 案例
170 | 
171 | ```tsx
172 | import React from 'react'
173 | import { DatePicker, FormItem, FormButtonGroup, Submit } from '@formily/next'
174 | import { createForm } from '@formily/core'
175 | import { FormProvider, Field } from '@formily/react'
176 | 
177 | const form = createForm()
178 | 
179 | export default () => (
180 |   <FormProvider form={form}>
181 |     <Field
182 |       name="date"
183 |       title="日期选择"
184 |       decorator={[FormItem]}
185 |       component={[DatePicker]}
186 |     />
187 |     <Field
188 |       name="week"
189 |       title="周选择"
190 |       decorator={[FormItem]}
191 |       component={[DatePicker.WeekPicker]}
192 |     />
193 |     <Field
194 |       name="quarter"
195 |       title="财年选择"
196 |       decorator={[FormItem]}
197 |       component={[DatePicker.MonthPicker]}
198 |     />
199 |     <Field
200 |       name="year"
201 |       title="年选择"
202 |       decorator={[FormItem]}
203 |       component={[DatePicker.YearPicker]}
204 |     />
205 |     <Field
206 |       name="[startDate,endDate]"
207 |       title="日期范围选择"
208 |       decorator={[FormItem]}
209 |       component={[DatePicker.RangePicker]}
210 |     />
211 |     <Field
212 |       name="range_month"
213 |       title="月范围选择"
214 |       decorator={[FormItem]}
215 |       component={[
216 |         DatePicker.RangePicker,
217 |         {
218 |           type: 'month',
219 |         },
220 |       ]}
221 |     />
222 |     <Field
223 |       name="range_year"
224 |       title="年范围选择"
225 |       decorator={[FormItem]}
226 |       component={[
227 |         DatePicker.RangePicker,
228 |         {
229 |           type: 'year',
230 |         },
231 |       ]}
232 |     />
233 |     <FormButtonGroup>
234 |       <Submit onSubmit={console.log}>提交</Submit>
235 |     </FormButtonGroup>
236 |   </FormProvider>
237 | )
238 | ```
239 | 
240 | ## API
241 | 
242 | 参考 https://fusion.design/pc/component/basic/date-picker
243 | 
```

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

```markdown
  1 | # DatePicker2
  2 | 
  3 | > 日期选择器
  4 | 
  5 | ## Markup Schema 案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { DatePicker2, 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 |     DatePicker2,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.String
 26 |         name="date"
 27 |         title="普通日期"
 28 |         x-decorator="FormItem"
 29 |         x-component="DatePicker2"
 30 |       />
 31 |       <SchemaField.String
 32 |         name="week"
 33 |         title="周选择"
 34 |         x-decorator="FormItem"
 35 |         x-component="DatePicker2.WeekPicker"
 36 |       />
 37 |       <SchemaField.String
 38 |         name="month"
 39 |         title="月选择"
 40 |         x-decorator="FormItem"
 41 |         x-component="DatePicker2.MonthPicker"
 42 |       />
 43 |       <SchemaField.String
 44 |         name="year"
 45 |         title="年选择"
 46 |         x-decorator="FormItem"
 47 |         x-component="DatePicker2.YearPicker"
 48 |       />
 49 |       <SchemaField.String
 50 |         name="[startDate,endDate]"
 51 |         title="日期范围"
 52 |         x-decorator="FormItem"
 53 |         x-component="DatePicker2.RangePicker"
 54 |         x-component-props={{
 55 |           showTime: true,
 56 |         }}
 57 |       />
 58 |       <SchemaField.String
 59 |         name="range_month"
 60 |         title="月范围选择"
 61 |         x-decorator="FormItem"
 62 |         x-component="DatePicker2.RangePicker"
 63 |         x-component-props={{
 64 |           mode: 'month',
 65 |         }}
 66 |       />
 67 |       <SchemaField.String
 68 |         name="range_year"
 69 |         title="年范围选择"
 70 |         x-decorator="FormItem"
 71 |         x-component="DatePicker2.RangePicker"
 72 |         x-component-props={{
 73 |           mode: 'year',
 74 |         }}
 75 |       />
 76 |     </SchemaField>
 77 |     <FormButtonGroup>
 78 |       <Submit onSubmit={console.log}>提交</Submit>
 79 |     </FormButtonGroup>
 80 |   </FormProvider>
 81 | )
 82 | ```
 83 | 
 84 | ## JSON Schema 案例
 85 | 
 86 | ```tsx
 87 | import React from 'react'
 88 | import { DatePicker2, FormItem, FormButtonGroup, Submit } from '@formily/next'
 89 | import { createForm } from '@formily/core'
 90 | import { FormProvider, createSchemaField } from '@formily/react'
 91 | 
 92 | const SchemaField = createSchemaField({
 93 |   components: {
 94 |     DatePicker2,
 95 |     FormItem,
 96 |   },
 97 | })
 98 | 
 99 | const form = createForm()
100 | 
101 | const schema = {
102 |   type: 'object',
103 |   properties: {
104 |     date: {
105 |       title: '普通日期',
106 |       'x-decorator': 'FormItem',
107 |       'x-component': 'DatePicker2',
108 |       type: 'string',
109 |     },
110 |     week: {
111 |       title: '周选择',
112 |       'x-decorator': 'FormItem',
113 |       'x-component': 'DatePicker2.WeekPicker',
114 |       type: 'string',
115 |     },
116 |     month: {
117 |       title: '月选择',
118 |       'x-decorator': 'FormItem',
119 |       'x-component': 'DatePicker2.MonthPicker',
120 |       type: 'string',
121 |     },
122 |     year: {
123 |       title: '年选择',
124 |       'x-decorator': 'FormItem',
125 |       'x-component': 'DatePicker2.YearPicker',
126 |       type: 'string',
127 |     },
128 |     '[startDate,endDate]': {
129 |       title: '日期范围',
130 |       'x-decorator': 'FormItem',
131 |       'x-component': 'DatePicker2.RangePicker',
132 |       'x-component-props': {
133 |         showTime: true,
134 |       },
135 |       type: 'string',
136 |     },
137 |     range_month: {
138 |       title: '月范围选择',
139 |       'x-decorator': 'FormItem',
140 |       'x-component': 'DatePicker2.RangePicker',
141 |       'x-component-props': {
142 |         mode: 'month',
143 |       },
144 |       type: 'string',
145 |     },
146 |     range_year: {
147 |       name: 'range_year',
148 |       title: '年范围选择',
149 |       'x-decorator': 'FormItem',
150 |       'x-component': 'DatePicker2.RangePicker',
151 |       'x-component-props': {
152 |         mode: 'year',
153 |       },
154 |       type: 'string',
155 |     },
156 |   },
157 | }
158 | 
159 | export default () => (
160 |   <FormProvider form={form}>
161 |     <SchemaField schema={schema} />
162 |     <FormButtonGroup>
163 |       <Submit onSubmit={console.log}>提交</Submit>
164 |     </FormButtonGroup>
165 |   </FormProvider>
166 | )
167 | ```
168 | 
169 | ## 纯 JSX 案例
170 | 
171 | ```tsx
172 | import React from 'react'
173 | import { DatePicker2, FormItem, FormButtonGroup, Submit } from '@formily/next'
174 | import { createForm } from '@formily/core'
175 | import { FormProvider, Field } from '@formily/react'
176 | 
177 | const form = createForm()
178 | 
179 | export default () => (
180 |   <FormProvider form={form}>
181 |     <Field
182 |       name="date"
183 |       title="日期选择"
184 |       decorator={[FormItem]}
185 |       component={[DatePicker2]}
186 |     />
187 |     <Field
188 |       name="week"
189 |       title="周选择"
190 |       decorator={[FormItem]}
191 |       component={[DatePicker2.WeekPicker]}
192 |     />
193 |     <Field
194 |       name="quarter"
195 |       title="财年选择"
196 |       decorator={[FormItem]}
197 |       component={[DatePicker2.MonthPicker]}
198 |     />
199 |     <Field
200 |       name="year"
201 |       title="年选择"
202 |       decorator={[FormItem]}
203 |       component={[DatePicker2.YearPicker]}
204 |     />
205 |     <Field
206 |       name="[startDate,endDate]"
207 |       title="日期范围选择"
208 |       decorator={[FormItem]}
209 |       component={[DatePicker2.RangePicker]}
210 |     />
211 |     <Field
212 |       name="range_month"
213 |       title="月范围选择"
214 |       decorator={[FormItem]}
215 |       component={[
216 |         DatePicker2.RangePicker,
217 |         {
218 |           mode: 'month',
219 |         },
220 |       ]}
221 |     />
222 |     <Field
223 |       name="range_year"
224 |       title="年范围选择"
225 |       decorator={[FormItem]}
226 |       component={[
227 |         DatePicker2.RangePicker,
228 |         {
229 |           mode: 'year',
230 |         },
231 |       ]}
232 |     />
233 |     <FormButtonGroup>
234 |       <Submit onSubmit={console.log}>提交</Submit>
235 |     </FormButtonGroup>
236 |   </FormProvider>
237 | )
238 | ```
239 | 
240 | ## API
241 | 
242 | 参考 https://fusion.design/pc/component/basic/date-picker2
243 | 
```

--------------------------------------------------------------------------------
/packages/next/src/upload/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { useEffect } from 'react'
  2 | import { Field } from '@formily/core'
  3 | import { useField } from '@formily/react'
  4 | import { reaction } from '@formily/reactive'
  5 | import { Upload as NextUpload, Button, Icon } from '@alifd/next'
  6 | import {
  7 |   UploadProps as NextUploadProps,
  8 |   CardProps,
  9 | } from '@alifd/next/lib/upload'
 10 | import { isArr, toArr } from '@formily/shared'
 11 | import { UPLOAD_PLACEHOLDER } from './placeholder'
 12 | 
 13 | type ExtendsUploadProps = NextUploadProps & {
 14 |   textContent?: React.ReactNode
 15 |   serviceErrorMessage?: string
 16 | }
 17 | 
 18 | type FileList = Parameters<ExtendsUploadProps['onChange']>[0]
 19 | 
 20 | type ComposedUpload = React.FC<React.PropsWithChildren<IUploadProps>> & {
 21 |   Card?: React.FC<React.PropsWithChildren<ICardUploadProps>>
 22 |   Dragger?: React.FC<React.PropsWithChildren<IUploadProps>>
 23 | }
 24 | 
 25 | type IExtendsUploadProps = {
 26 |   value?: any[]
 27 |   serviceErrorMessage?: string
 28 |   onChange?: (...args: any) => void
 29 |   formatter?: (...args: any) => any
 30 | }
 31 | 
 32 | export type IUploadProps = ExtendsUploadProps & { serviceErrorMessage?: string }
 33 | 
 34 | export type ICardUploadProps = CardProps & { serviceErrorMessage?: string }
 35 | 
 36 | const testOpts = (
 37 |   ext: RegExp,
 38 |   options: { exclude?: string[]; include?: string[] }
 39 | ) => {
 40 |   if (options && isArr(options.include)) {
 41 |     return options.include.some((url) => ext.test(url))
 42 |   }
 43 | 
 44 |   if (options && isArr(options.exclude)) {
 45 |     return !options.exclude.some((url) => ext.test(url))
 46 |   }
 47 | 
 48 |   return true
 49 | }
 50 | 
 51 | const getImageByUrl = (url: string, options: any) => {
 52 |   for (let i = 0; i < UPLOAD_PLACEHOLDER.length; i++) {
 53 |     if (
 54 |       UPLOAD_PLACEHOLDER[i].ext.test(url) &&
 55 |       testOpts(UPLOAD_PLACEHOLDER[i].ext, options)
 56 |     ) {
 57 |       return UPLOAD_PLACEHOLDER[i].icon || url
 58 |     }
 59 |   }
 60 | 
 61 |   return url
 62 | }
 63 | 
 64 | const getURL = (target: any) => {
 65 |   return target?.['url'] || target?.['downloadURL'] || target?.['imgURL']
 66 | }
 67 | 
 68 | const getThumbURL = (target: any) => {
 69 |   return (
 70 |     target?.['thumbUrl'] ||
 71 |     target?.['url'] ||
 72 |     target?.['downloadURL'] ||
 73 |     target?.['imgURL']
 74 |   )
 75 | }
 76 | 
 77 | const getSuccess = (target: any) => {
 78 |   return (
 79 |     target?.success ||
 80 |     target?.status === 'done' ||
 81 |     target?.status === 'success' ||
 82 |     target?.state === 'done' ||
 83 |     target?.state === 'success'
 84 |   )
 85 | }
 86 | 
 87 | const getErrorMessage = (target: any) => {
 88 |   return (
 89 |     target?.errorMessage ||
 90 |     target?.errMsg ||
 91 |     target?.errorMsg ||
 92 |     target?.message ||
 93 |     (typeof target?.error === 'string' ? target.error : '')
 94 |   )
 95 | }
 96 | 
 97 | const getState = (target: any) => {
 98 |   if (target?.success === false) return 'error'
 99 |   if (target?.failed === true) return 'error'
100 |   if (target?.error) return 'error'
101 |   return target?.state || target?.status
102 | }
103 | 
104 | const normalizeFileList = (fileList: IUploadProps['value']) => {
105 |   if (fileList && fileList.length) {
106 |     return fileList.map(({ ...file }, index) => {
107 |       delete file['originFileObj']
108 |       return {
109 |         ...file,
110 |         uid: file.uid || index,
111 |         state: getState(file?.response) || getState(file),
112 |         downloadURL: getURL(file) || getURL(file?.response),
113 |         imgURL: getImageByUrl(
114 |           getThumbURL(file) || getThumbURL(file?.response),
115 |           {
116 |             exclude: ['.png', '.jpg', '.jpeg', '.gif'],
117 |           }
118 |         ),
119 |       }
120 |     })
121 |   }
122 |   return []
123 | }
124 | 
125 | const useValidator = (validator: (value: any) => string) => {
126 |   const field = useField<Field>()
127 |   useEffect(() => {
128 |     const dispose = reaction(
129 |       () => field.value,
130 |       (value) => {
131 |         const message = validator(value)
132 |         field.setFeedback({
133 |           type: 'error',
134 |           code: 'UploadError',
135 |           messages: message ? [message] : [],
136 |         })
137 |       }
138 |     )
139 |     return () => {
140 |       dispose()
141 |     }
142 |   }, [])
143 | }
144 | 
145 | const useUploadValidator = (serviceErrorMessage = 'Upload Service Error') => {
146 |   useValidator((value) => {
147 |     const list = toArr(value)
148 |     for (let i = 0; i < list.length; i++) {
149 |       if (list[i]?.state === 'error') {
150 |         return (
151 |           getErrorMessage(list[i]?.response) ||
152 |           getErrorMessage(list[i]) ||
153 |           serviceErrorMessage
154 |         )
155 |       }
156 |     }
157 |   })
158 | }
159 | 
160 | function useUploadProps<T extends IExtendsUploadProps = IUploadProps>({
161 |   serviceErrorMessage,
162 |   ...props
163 | }: T) {
164 |   useUploadValidator(serviceErrorMessage)
165 |   const onChange = (fileList: FileList) => {
166 |     props.onChange?.(normalizeFileList([...fileList]))
167 |   }
168 | 
169 |   const formatter = (res: any, file: any) => {
170 |     const response = props?.formatter?.(res, file) as any
171 |     return {
172 |       ...res,
173 |       success: getSuccess(res),
174 |       ...response,
175 |     }
176 |   }
177 |   return {
178 |     ...props,
179 |     value: normalizeFileList(props.value),
180 |     onChange,
181 |     formatter,
182 |   }
183 | }
184 | 
185 | const getPlaceholder = (props: IUploadProps) => {
186 |   if (props.shape !== 'card') {
187 |     return (
188 |       <Button>
189 |         <Icon type="upload" />
190 |         {props.textContent}
191 |       </Button>
192 |     )
193 |   }
194 |   return <Icon type="upload" style={{ fontSize: 20 }} />
195 | }
196 | 
197 | export const Upload: ComposedUpload = (props) => {
198 |   return (
199 |     <NextUpload listType="text" {...useUploadProps(props)}>
200 |       {props.children || getPlaceholder(props)}
201 |     </NextUpload>
202 |   )
203 | }
204 | 
205 | Upload.Dragger = (props) => {
206 |   return <NextUpload.Dragger listType="text" {...useUploadProps(props)} />
207 | }
208 | 
209 | Upload.Card = (props) => {
210 |   return <NextUpload.Card listType="card" {...useUploadProps(props)} />
211 | }
212 | 
213 | export default Upload
214 | 
```

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

```markdown
  1 | # PreviewText
  2 | 
  3 | > 阅读态组件,主要用来实现类 Input,类 DatePicker 这些组件的阅读态
  4 | 
  5 | ## 简单用例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { PreviewText, FormItem, FormLayout } from '@formily/next'
 10 | import { createForm } from '@formily/core'
 11 | import { FormProvider, createSchemaField } from '@formily/react'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     FormItem,
 16 |     PreviewText,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => {
 23 |   return (
 24 |     <FormLayout labelCol={8} wrapperCol={16}>
 25 |       <FormProvider form={form}>
 26 |         <SchemaField>
 27 |           <SchemaField.String
 28 |             x-decorator="FormItem"
 29 |             title="文本预览"
 30 |             x-component="PreviewText.Input"
 31 |             default={'Hello world'}
 32 |           />
 33 |           <SchemaField.String
 34 |             x-decorator="FormItem"
 35 |             title="选择项预览"
 36 |             x-component="PreviewText.Select"
 37 |             x-component-props={{
 38 |               mode: 'multiple',
 39 |             }}
 40 |             default={['123', '222']}
 41 |             enum={[
 42 |               { label: 'A111', value: '123' },
 43 |               { label: 'A222', value: '222' },
 44 |             ]}
 45 |           />
 46 |           <SchemaField.String
 47 |             x-decorator="FormItem"
 48 |             title="日期预览"
 49 |             x-component="PreviewText.DatePicker"
 50 |             default={'2020-11-23 22:15:20'}
 51 |           />
 52 |           <SchemaField.String
 53 |             x-decorator="FormItem"
 54 |             title="Cascader预览"
 55 |             x-component="PreviewText.Cascader"
 56 |             default={'yuhang'}
 57 |             enum={[
 58 |               {
 59 |                 label: '杭州',
 60 |                 value: 'hangzhou',
 61 |                 children: [
 62 |                   {
 63 |                     label: '余杭',
 64 |                     value: 'yuhang',
 65 |                   },
 66 |                 ],
 67 |               },
 68 |             ]}
 69 |           />
 70 |         </SchemaField>
 71 |       </FormProvider>
 72 |     </FormLayout>
 73 |   )
 74 | }
 75 | ```
 76 | 
 77 | ## 扩展阅读态
 78 | 
 79 | ```tsx
 80 | import React from 'react'
 81 | import {
 82 |   PreviewText,
 83 |   FormItem,
 84 |   FormButtonGroup,
 85 |   FormLayout,
 86 | } from '@formily/next'
 87 | import { createForm } from '@formily/core'
 88 | import {
 89 |   FormProvider,
 90 |   mapReadPretty,
 91 |   connect,
 92 |   createSchemaField,
 93 | } from '@formily/react'
 94 | import { Button, Input as NextInput } from '@alifd/next'
 95 | 
 96 | const Input = connect(NextInput, mapReadPretty(PreviewText.Input))
 97 | 
 98 | const SchemaField = createSchemaField({
 99 |   components: {
100 |     Input,
101 |     FormItem,
102 |     PreviewText,
103 |   },
104 | })
105 | 
106 | const form = createForm()
107 | 
108 | export default () => {
109 |   return (
110 |     <PreviewText.Placeholder value="暂无数据">
111 |       <FormLayout labelCol={8} wrapperCol={16}>
112 |         <FormProvider form={form}>
113 |           <SchemaField>
114 |             <SchemaField.Markup
115 |               type="string"
116 |               x-decorator="FormItem"
117 |               title="文本预览"
118 |               required
119 |               x-component="Input"
120 |               default={'Hello world'}
121 |             />
122 |             <SchemaField.Markup
123 |               type="string"
124 |               x-decorator="FormItem"
125 |               title="选择项预览"
126 |               x-component="PreviewText.Select"
127 |               x-component-props={{
128 |                 mode: 'multiple',
129 |               }}
130 |               default={['123']}
131 |               enum={[
132 |                 { label: 'A111', value: '123' },
133 |                 { label: 'A222', value: '222' },
134 |               ]}
135 |             />
136 |             <SchemaField.Markup
137 |               type="string"
138 |               x-decorator="FormItem"
139 |               title="日期预览"
140 |               x-component="PreviewText.DatePicker"
141 |             />
142 |             <SchemaField.Markup
143 |               type="string"
144 |               x-decorator="FormItem"
145 |               title="Cascader预览"
146 |               x-component="PreviewText.Cascader"
147 |               default={'yuhang'}
148 |               enum={[
149 |                 {
150 |                   label: '杭州',
151 |                   value: 'hangzhou',
152 |                   children: [
153 |                     {
154 |                       label: '余杭',
155 |                       value: 'yuhang',
156 |                     },
157 |                   ],
158 |                 },
159 |               ]}
160 |             />
161 |           </SchemaField>
162 |           <FormButtonGroup.FormItem>
163 |             <Button
164 |               onClick={() => {
165 |                 form.setState((state) => {
166 |                   state.editable = !state.editable
167 |                 })
168 |               }}
169 |             >
170 |               切换阅读态
171 |             </Button>
172 |           </FormButtonGroup.FormItem>
173 |         </FormProvider>
174 |       </FormLayout>
175 |     </PreviewText.Placeholder>
176 |   )
177 | }
178 | ```
179 | 
180 | ## API
181 | 
182 | ### PreviewText.Input
183 | 
184 | 参考 https://fusion.design/pc/component/basic/input
185 | 
186 | ### PreviewText.Select
187 | 
188 | 参考 https://fusion.design/pc/component/basic/select
189 | 
190 | ### PreviewText.TreeSelect
191 | 
192 | 参考 https://fusion.design/pc/component/basic/tree-select
193 | 
194 | ### PreviewText.Cascader
195 | 
196 | 参考 https://fusion.design/pc/component/basic/cascader-select
197 | 
198 | ### PreviewText.DatePicker
199 | 
200 | 参考 https://fusion.design/pc/component/basic/date-picker
201 | 
202 | ### PreviewText.DateRangePicker
203 | 
204 | 参考 https://fusion.design/pc/component/basic/date-picker
205 | 
206 | ### PreviewText.TimePicker
207 | 
208 | 参考 https://fusion.design/pc/component/basic/time-picker
209 | 
210 | ### PreviewText.NumberPicker
211 | 
212 | 参考 https://fusion.design/pc/component/basic/number-picker
213 | 
214 | ### PreviewText.Placeholder
215 | 
216 | | 属性名 | 类型   | 描述       | 默认值 |
217 | | ------ | ------ | ---------- | ------ |
218 | | value  | stirng | 缺省占位符 | N/A    |
219 | 
220 | ### PreviewText.usePlaceholder
221 | 
222 | ```ts pure
223 | interface usePlaceholder {
224 |   (): string
225 | }
226 | ```
227 | 
```

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

```typescript
  1 | import React, { Fragment, useLayoutEffect, useRef, useState } from 'react'
  2 | import { createPortal } from 'react-dom'
  3 | import {
  4 |   createForm,
  5 |   onFormSubmitSuccess,
  6 |   IFormProps,
  7 |   Form,
  8 | } from '@formily/core'
  9 | import { toJS } from '@formily/reactive'
 10 | import { FormProvider, observer, Observer, ReactFC } from '@formily/react'
 11 | import {
 12 |   isNum,
 13 |   isStr,
 14 |   isBool,
 15 |   isFn,
 16 |   applyMiddleware,
 17 |   IMiddleware,
 18 | } from '@formily/shared'
 19 | import { ConfigProvider, Drawer } from '@alifd/next'
 20 | import { DrawerProps } from '@alifd/next/lib/drawer'
 21 | import {
 22 |   usePrefixCls,
 23 |   loading,
 24 |   createPortalProvider,
 25 |   createPortalRoot,
 26 | } from '../__builtins__'
 27 | 
 28 | type FormDrawerRenderer =
 29 |   | React.ReactElement
 30 |   | ((form: Form) => React.ReactElement)
 31 | 
 32 | type DrawerTitle = string | number | React.ReactElement
 33 | 
 34 | const getContext: () => any = ConfigProvider['getContext']
 35 | 
 36 | const isDrawerTitle = (props: any): props is DrawerTitle => {
 37 |   return (
 38 |     isNum(props) || isStr(props) || isBool(props) || React.isValidElement(props)
 39 |   )
 40 | }
 41 | 
 42 | const getDrawerProps = (props: any): IDrawerProps => {
 43 |   if (isDrawerTitle(props)) {
 44 |     return {
 45 |       title: props,
 46 |     }
 47 |   } else {
 48 |     return props
 49 |   }
 50 | }
 51 | 
 52 | export interface IDrawerProps extends DrawerProps {
 53 |   onClose?: (reason: string, e: React.MouseEvent) => void | boolean
 54 |   loadingText?: React.ReactNode
 55 | }
 56 | 
 57 | export interface IFormDrawer {
 58 |   forOpen(middleware: IMiddleware<IFormProps>): IFormDrawer
 59 |   open(props?: IFormProps): Promise<any>
 60 |   close(): void
 61 | }
 62 | 
 63 | export function FormDrawer(
 64 |   title: IDrawerProps,
 65 |   id: string,
 66 |   renderer: FormDrawerRenderer
 67 | ): IFormDrawer
 68 | export function FormDrawer(
 69 |   title: IDrawerProps,
 70 |   renderer: FormDrawerRenderer
 71 | ): IFormDrawer
 72 | export function FormDrawer(
 73 |   title: DrawerTitle,
 74 |   id: string,
 75 |   renderer: FormDrawerRenderer
 76 | ): IFormDrawer
 77 | export function FormDrawer(
 78 |   title: DrawerTitle,
 79 |   renderer: FormDrawerRenderer
 80 | ): IFormDrawer
 81 | export function FormDrawer(title: any, id: any, renderer?: any): IFormDrawer {
 82 |   if (isFn(id) || React.isValidElement(id)) {
 83 |     renderer = id
 84 |     id = 'form-drawer'
 85 |   }
 86 |   const env = {
 87 |     host: document.createElement('div'),
 88 |     form: null,
 89 |     promise: null,
 90 |     openMiddlewares: [],
 91 |   }
 92 |   const root = createPortalRoot(env.host, id)
 93 |   const props = getDrawerProps(title)
 94 |   const drawer = {
 95 |     width: '40%',
 96 |     ...props,
 97 |     onClose: (reason: string, e: any) => {
 98 |       if (props?.onClose?.(reason, e) !== false) {
 99 |         formDrawer.close()
100 |       }
101 |     },
102 |     afterClose() {
103 |       props?.afterClose?.()
104 |       root.unmount()
105 |     },
106 |   }
107 |   const DrawerContent = observer(() => {
108 |     return <Fragment>{isFn(renderer) ? renderer(env.form) : renderer}</Fragment>
109 |   })
110 |   const renderDrawer = (visible = true) => {
111 |     return (
112 |       <ConfigProvider {...getContext()}>
113 |         <Observer>
114 |           {() => (
115 |             <Drawer {...drawer} visible={visible}>
116 |               <FormProvider form={env.form}>
117 |                 <DrawerContent />
118 |               </FormProvider>
119 |             </Drawer>
120 |           )}
121 |         </Observer>
122 |       </ConfigProvider>
123 |     )
124 |   }
125 |   document.body.appendChild(env.host)
126 |   const formDrawer = {
127 |     forOpen: (middleware: IMiddleware<IFormProps>) => {
128 |       if (isFn(middleware)) {
129 |         env.openMiddlewares.push(middleware)
130 |       }
131 |       return formDrawer
132 |     },
133 |     open: (props: IFormProps) => {
134 |       if (env.promise) return env.promise
135 |       env.promise = new Promise(async (resolve, reject) => {
136 |         try {
137 |           props = await loading(drawer.loadingText, () =>
138 |             applyMiddleware(props, env.openMiddlewares)
139 |           )
140 |           env.form =
141 |             env.form ||
142 |             createForm({
143 |               ...props,
144 |               effects(form) {
145 |                 onFormSubmitSuccess(() => {
146 |                   resolve(toJS(form.values))
147 |                   formDrawer.close()
148 |                 })
149 |                 props?.effects?.(form)
150 |               },
151 |             })
152 |         } catch (e) {
153 |           reject(e)
154 |         }
155 |         root.render(() => renderDrawer(false))
156 |         setTimeout(() => {
157 |           root.render(() => renderDrawer(true))
158 |         }, 16)
159 |       })
160 |       return env.promise
161 |     },
162 |     close: () => {
163 |       if (!env.host) return
164 |       root.render(() => renderDrawer(false))
165 |     },
166 |   }
167 |   return formDrawer
168 | }
169 | 
170 | const DrawerFooter: ReactFC = (props) => {
171 |   const ref = useRef<HTMLDivElement>()
172 |   const [footer, setFooter] = useState<HTMLDivElement>()
173 |   const footerRef = useRef<HTMLDivElement>()
174 |   const prefixCls = usePrefixCls('drawer')
175 |   useLayoutEffect(() => {
176 |     const content = ref.current?.closest(`.${prefixCls}`)
177 |     if (content) {
178 |       if (!footerRef.current) {
179 |         footerRef.current = content.querySelector(`.${prefixCls}-footer`)
180 |         const body = content.querySelector(`.${prefixCls}-body`)
181 |         if (!footerRef.current && body) {
182 |           footerRef.current = document.createElement('div')
183 |           footerRef.current.classList.add(`${prefixCls}-footer`)
184 |           footerRef.current.style.padding = '20px'
185 |           footerRef.current.style.borderTop = '1px solid #eee'
186 |           body.after(footerRef.current)
187 |         }
188 |       }
189 |       setFooter(footerRef.current)
190 |     }
191 |   })
192 | 
193 |   footerRef.current = footer
194 | 
195 |   return (
196 |     <div ref={ref} style={{ display: 'none' }}>
197 |       {footer && createPortal(props.children, footer)}
198 |     </div>
199 |   )
200 | }
201 | 
202 | FormDrawer.Footer = DrawerFooter
203 | 
204 | FormDrawer.Portal = createPortalProvider('form-drawer')
205 | 
206 | export default FormDrawer
207 | 
```

--------------------------------------------------------------------------------
/packages/next/src/editable/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { useLayoutEffect, useRef, useState } from 'react'
  2 | import { isVoidField, Field } from '@formily/core'
  3 | import { useField, observer } from '@formily/react'
  4 | import { Balloon } from '@alifd/next'
  5 | import { BalloonProps as PopoverProps } from '@alifd/next/lib/balloon'
  6 | import { BaseItem, IFormItemProps } from '../form-item'
  7 | import {
  8 |   useClickAway,
  9 |   usePrefixCls,
 10 |   EditOutlinedIcon,
 11 |   CloseOutlinedIcon,
 12 |   MessageOutlinedIcon,
 13 | } from '../__builtins__'
 14 | /**
 15 |  * 默认Inline展示
 16 |  */
 17 | 
 18 | type IPopoverProps = PopoverProps
 19 | 
 20 | type ComposedEditable = React.FC<React.PropsWithChildren<IFormItemProps>> & {
 21 |   Popover?: React.FC<
 22 |     React.PropsWithChildren<IPopoverProps & { title?: React.ReactNode }>
 23 |   >
 24 | }
 25 | 
 26 | const useParentPattern = () => {
 27 |   const field = useField<Field>()
 28 |   return field?.parent?.pattern || field?.form?.pattern
 29 | }
 30 | 
 31 | const useEditable = (): [boolean, (payload: boolean) => void] => {
 32 |   const pattern = useParentPattern()
 33 |   const field = useField<Field>()
 34 |   useLayoutEffect(() => {
 35 |     if (pattern === 'editable') {
 36 |       field.setPattern('readPretty')
 37 |     }
 38 |   }, [pattern])
 39 |   return [
 40 |     field.pattern === 'editable',
 41 |     (pyaload: boolean) => {
 42 |       if (pattern !== 'editable') return
 43 |       field.setPattern(pyaload ? 'editable' : 'readPretty')
 44 |     },
 45 |   ]
 46 | }
 47 | 
 48 | const useFormItemProps = (): IFormItemProps => {
 49 |   const field = useField()
 50 |   if (isVoidField(field)) return {}
 51 |   if (!field) return {}
 52 |   const takeMessage = () => {
 53 |     if (field.selfErrors.length) return field.selfErrors
 54 |     if (field.selfWarnings.length) return field.selfWarnings
 55 |     if (field.selfSuccesses.length) return field.selfSuccesses
 56 |   }
 57 | 
 58 |   return {
 59 |     feedbackStatus:
 60 |       field.validateStatus === 'validating' ? 'pending' : field.validateStatus,
 61 |     feedbackText: takeMessage(),
 62 |     extra: field.description,
 63 |   }
 64 | }
 65 | 
 66 | export const Editable: ComposedEditable = observer((props) => {
 67 |   const [editable, setEditable] = useEditable()
 68 |   const pattern = useParentPattern()
 69 |   const itemProps = useFormItemProps()
 70 |   const field = useField<Field>()
 71 |   const basePrefixCls = usePrefixCls()
 72 |   const prefixCls = usePrefixCls('formily-editable')
 73 |   const ref = useRef<boolean>()
 74 |   const innerRef = useRef<HTMLDivElement>()
 75 |   const recover = () => {
 76 |     if (ref.current && !field?.errors?.length) {
 77 |       setEditable(false)
 78 |     }
 79 |   }
 80 |   const renderEditHelper = () => {
 81 |     if (editable) return
 82 |     return (
 83 |       <BaseItem {...props} {...itemProps}>
 84 |         {pattern === 'editable' && (
 85 |           <EditOutlinedIcon className={`${prefixCls}-edit-btn`} />
 86 |         )}
 87 |         {pattern !== 'editable' && (
 88 |           <MessageOutlinedIcon className={`${prefixCls}-edit-btn`} />
 89 |         )}
 90 |       </BaseItem>
 91 |     )
 92 |   }
 93 | 
 94 |   const renderCloseHelper = () => {
 95 |     if (!editable) return
 96 |     return (
 97 |       <BaseItem {...props}>
 98 |         <CloseOutlinedIcon className={`${prefixCls}-close-btn`} />
 99 |       </BaseItem>
100 |     )
101 |   }
102 | 
103 |   useClickAway((e) => {
104 |     const target = e.target as HTMLElement
105 |     if (target?.closest(`.${basePrefixCls}-overlay-wrapper`)) return
106 |     recover()
107 |   }, innerRef)
108 | 
109 |   const onClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
110 |     const target = e.target as HTMLElement
111 |     const close = innerRef.current.querySelector(`.${prefixCls}-close-btn`)
112 |     if (target?.contains(close) || close?.contains(target)) {
113 |       recover()
114 |     } else if (!ref.current) {
115 |       setTimeout(() => {
116 |         setEditable(true)
117 |         setTimeout(() => {
118 |           innerRef.current.querySelector('input')?.focus()
119 |         })
120 |       })
121 |     }
122 |   }
123 | 
124 |   ref.current = editable
125 | 
126 |   return (
127 |     <div className={prefixCls} ref={innerRef} onClick={onClick}>
128 |       <div className={`${prefixCls}-content`}>
129 |         <BaseItem {...props} {...itemProps}>
130 |           {props.children}
131 |         </BaseItem>
132 |         {renderEditHelper()}
133 |         {renderCloseHelper()}
134 |       </div>
135 |     </div>
136 |   )
137 | })
138 | 
139 | Editable.Popover = observer((props) => {
140 |   const field = useField<Field>()
141 |   const pattern = useParentPattern()
142 |   const [visible, setVisible] = useState(false)
143 |   const prefixCls = usePrefixCls('formily-editable')
144 |   const closePopover = async () => {
145 |     try {
146 |       await field.form.validate(`${field.address}.*`)
147 |     } finally {
148 |       const errors = field.form.queryFeedbacks({
149 |         type: 'error',
150 |         address: `${field.address}.*`,
151 |       })
152 |       if (errors?.length) return
153 |       setVisible(false)
154 |     }
155 |   }
156 |   const openPopover = () => {
157 |     setVisible(true)
158 |   }
159 |   return (
160 |     <Balloon
161 |       {...props}
162 |       title={field.title}
163 |       visible={visible}
164 |       className={props.className}
165 |       onVisibleChange={(visible) => {
166 |         if (visible) {
167 |           openPopover()
168 |         } else {
169 |           closePopover()
170 |         }
171 |       }}
172 |       align="t"
173 |       triggerType="click"
174 |       closable={false}
175 |       trigger={
176 |         <div style={{ display: 'inline-flex' }}>
177 |           <BaseItem className={`${prefixCls}-trigger`}>
178 |             <div className={`${prefixCls}-content`}>
179 |               <span className={`${prefixCls}-preview`}>
180 |                 {props.title || field.title}
181 |               </span>
182 |               {pattern === 'editable' && (
183 |                 <EditOutlinedIcon className={`${prefixCls}-edit-btn`} />
184 |               )}
185 |               {pattern !== 'editable' && (
186 |                 <MessageOutlinedIcon className={`${prefixCls}-edit-btn`} />
187 |               )}
188 |             </div>
189 |           </BaseItem>
190 |         </div>
191 |       }
192 |     >
193 |       {props.children}
194 |     </Balloon>
195 |   )
196 | })
197 | 
198 | export default Editable
199 | 
```

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

```markdown
  1 | # DatePicker
  2 | 
  3 | > Date Picker
  4 | 
  5 | ## Markup Schema example
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { DatePicker, 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 |     DatePicker,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.String
 26 |         name="date"
 27 |         title="normal date"
 28 |         x-decorator="FormItem"
 29 |         x-component="DatePicker"
 30 |       />
 31 |       <SchemaField.String
 32 |         name="week"
 33 |         title="Week Selection"
 34 |         x-decorator="FormItem"
 35 |         x-component="DatePicker.WeekPicker"
 36 |       />
 37 |       <SchemaField.String
 38 |         name="month"
 39 |         title="Month Selection"
 40 |         x-decorator="FormItem"
 41 |         x-component="DatePicker.MonthPicker"
 42 |       />
 43 |       <SchemaField.String
 44 |         name="year"
 45 |         title="Year selection"
 46 |         x-decorator="FormItem"
 47 |         x-component="DatePicker.YearPicker"
 48 |       />
 49 |       <SchemaField.String
 50 |         name="[startDate,endDate]"
 51 |         title="Date Range"
 52 |         x-decorator="FormItem"
 53 |         x-component="DatePicker.RangePicker"
 54 |         x-component-props={{
 55 |           showTime: true,
 56 |         }}
 57 |       />
 58 |       <SchemaField.String
 59 |         name="range_month"
 60 |         title="Month Range Selection"
 61 |         x-decorator="FormItem"
 62 |         x-component="DatePicker.RangePicker"
 63 |         x-component-props={{
 64 |           type: 'month',
 65 |         }}
 66 |       />
 67 |       <SchemaField.String
 68 |         name="range_year"
 69 |         title="Year range selection"
 70 |         x-decorator="FormItem"
 71 |         x-component="DatePicker.RangePicker"
 72 |         x-component-props={{
 73 |           type: 'year',
 74 |         }}
 75 |       />
 76 |     </SchemaField>
 77 |     <FormButtonGroup>
 78 |       <Submit onSubmit={console.log}>Submit</Submit>
 79 |     </FormButtonGroup>
 80 |   </FormProvider>
 81 | )
 82 | ```
 83 | 
 84 | ## JSON Schema case
 85 | 
 86 | ```tsx
 87 | import React from 'react'
 88 | import { DatePicker, FormItem, FormButtonGroup, Submit } from '@formily/next'
 89 | import { createForm } from '@formily/core'
 90 | import { FormProvider, createSchemaField } from '@formily/react'
 91 | 
 92 | const SchemaField = createSchemaField({
 93 |   components: {
 94 |     DatePicker,
 95 |     FormItem,
 96 |   },
 97 | })
 98 | 
 99 | const form = createForm()
100 | 
101 | const schema = {
102 |   type: 'object',
103 |   properties: {
104 |     date: {
105 |       title: 'Normal date',
106 |       'x-decorator': 'FormItem',
107 |       'x-component': 'DatePicker',
108 |       type: 'string',
109 |     },
110 |     week: {
111 |       title: 'Week Selection',
112 |       'x-decorator': 'FormItem',
113 |       'x-component': 'DatePicker.WeekPicker',
114 |       type: 'string',
115 |     },
116 |     month: {
117 |       title: 'Month Selection',
118 |       'x-decorator': 'FormItem',
119 |       'x-component': 'DatePicker.MonthPicker',
120 |       type: 'string',
121 |     },
122 |     year: {
123 |       title: 'Year selection',
124 |       'x-decorator': 'FormItem',
125 |       'x-component': 'DatePicker.YearPicker',
126 |       type: 'string',
127 |     },
128 |     '[startDate,endDate]': {
129 |       title: 'Date range',
130 |       'x-decorator': 'FormItem',
131 |       'x-component': 'DatePicker.RangePicker',
132 |       'x-component-props': {
133 |         showTime: true,
134 |       },
135 |       type: 'string',
136 |     },
137 |     range_month: {
138 |       title: 'Month Range Selection',
139 |       'x-decorator': 'FormItem',
140 |       'x-component': 'DatePicker.RangePicker',
141 |       'x-component-props': {
142 |         type: 'month',
143 |       },
144 |       type: 'string',
145 |     },
146 |     range_year: {
147 |       name: 'range_year',
148 |       title: 'Year range selection',
149 |       'x-decorator': 'FormItem',
150 |       'x-component': 'DatePicker.RangePicker',
151 |       'x-component-props': {
152 |         type: 'year',
153 |       },
154 |       type: 'string',
155 |     },
156 |   },
157 | }
158 | 
159 | export default () => (
160 |   <FormProvider form={form}>
161 |     <SchemaField schema={schema} />
162 |     <FormButtonGroup>
163 |       <Submit onSubmit={console.log}>Submit</Submit>
164 |     </FormButtonGroup>
165 |   </FormProvider>
166 | )
167 | ```
168 | 
169 | ## Pure JSX case
170 | 
171 | ```tsx
172 | import React from 'react'
173 | import { DatePicker, FormItem, FormButtonGroup, Submit } from '@formily/next'
174 | import { createForm } from '@formily/core'
175 | import { FormProvider, Field } from '@formily/react'
176 | 
177 | const form = createForm()
178 | 
179 | export default () => (
180 |   <FormProvider form={form}>
181 |     <Field
182 |       name="date"
183 |       title="date selection"
184 |       decorator={[FormItem]}
185 |       component={[DatePicker]}
186 |     />
187 |     <Field
188 |       name="week"
189 |       title="Week Selection"
190 |       decorator={[FormItem]}
191 |       component={[DatePicker.WeekPicker]}
192 |     />
193 |     <Field
194 |       name="quarter"
195 |       title="Financial Year Selection"
196 |       decorator={[FormItem]}
197 |       component={[DatePicker.MonthPicker]}
198 |     />
199 |     <Field
200 |       name="year"
201 |       title="Year selection"
202 |       decorator={[FormItem]}
203 |       component={[DatePicker.YearPicker]}
204 |     />
205 |     <Field
206 |       name="[startDate,endDate]"
207 |       title="Date range selection"
208 |       decorator={[FormItem]}
209 |       component={[DatePicker.RangePicker]}
210 |     />
211 |     <Field
212 |       name="range_month"
213 |       title="Month Range Selection"
214 |       decorator={[FormItem]}
215 |       component={[
216 |         DatePicker.RangePicker,
217 |         {
218 |           type: 'month',
219 |         },
220 |       ]}
221 |     />
222 |     <Field
223 |       name="range_year"
224 |       title="Year range selection"
225 |       decorator={[FormItem]}
226 |       component={[
227 |         DatePicker.RangePicker,
228 |         {
229 |           type: 'year',
230 |         },
231 |       ]}
232 |     />
233 |     <FormButtonGroup>
234 |       <Submit onSubmit={console.log}>Submit</Submit>
235 |     </FormButtonGroup>
236 |   </FormProvider>
237 | )
238 | ```
239 | 
240 | ## API
241 | 
242 | Reference https://fusion.design/pc/component/basic/date-picker
243 | 
```

--------------------------------------------------------------------------------
/packages/antd/src/editable/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { useLayoutEffect, useRef, useState } from 'react'
  2 | import { isVoidField, Field } from '@formily/core'
  3 | import { useField, observer } from '@formily/react'
  4 | import { Popover } from 'antd'
  5 | import { EditOutlined, CloseOutlined, MessageOutlined } from '@ant-design/icons'
  6 | import { BaseItem, IFormItemProps } from '../form-item'
  7 | import { PopoverProps } from 'antd/lib/popover'
  8 | import { useClickAway, usePrefixCls } from '../__builtins__'
  9 | import cls from 'classnames'
 10 | /**
 11 |  * 默认Inline展示
 12 |  */
 13 | 
 14 | type IPopoverProps = PopoverProps
 15 | 
 16 | type ComposedEditable = React.FC<React.PropsWithChildren<IFormItemProps>> & {
 17 |   Popover?: React.FC<
 18 |     React.PropsWithChildren<IPopoverProps & { title?: React.ReactNode }>
 19 |   >
 20 | }
 21 | 
 22 | const useParentPattern = () => {
 23 |   const field = useField<Field>()
 24 |   return field?.parent?.pattern || field?.form?.pattern
 25 | }
 26 | 
 27 | const useEditable = (): [boolean, (payload: boolean) => void] => {
 28 |   const pattern = useParentPattern()
 29 |   const field = useField<Field>()
 30 |   useLayoutEffect(() => {
 31 |     if (pattern === 'editable') {
 32 |       return field.setPattern('readPretty')
 33 |     }
 34 |   }, [pattern])
 35 |   return [
 36 |     field.pattern === 'editable',
 37 |     (payload: boolean) => {
 38 |       if (pattern !== 'editable') return
 39 |       field.setPattern(payload ? 'editable' : 'readPretty')
 40 |     },
 41 |   ]
 42 | }
 43 | 
 44 | const useFormItemProps = (): IFormItemProps => {
 45 |   const field = useField()
 46 |   if (isVoidField(field)) return {}
 47 |   if (!field) return {}
 48 |   const takeMessage = () => {
 49 |     if (field.selfErrors.length) return field.selfErrors
 50 |     if (field.selfWarnings.length) return field.selfWarnings
 51 |     if (field.selfSuccesses.length) return field.selfSuccesses
 52 |   }
 53 | 
 54 |   return {
 55 |     feedbackStatus:
 56 |       field.validateStatus === 'validating' ? 'pending' : field.validateStatus,
 57 |     feedbackText: takeMessage(),
 58 |     extra: field.description,
 59 |   }
 60 | }
 61 | 
 62 | export const Editable: ComposedEditable = observer((props) => {
 63 |   const [editable, setEditable] = useEditable()
 64 |   const pattern = useParentPattern()
 65 |   const itemProps = useFormItemProps()
 66 |   const field = useField<Field>()
 67 |   const basePrefixCls = usePrefixCls()
 68 |   const prefixCls = usePrefixCls('formily-editable')
 69 |   const ref = useRef<boolean>()
 70 |   const innerRef = useRef<HTMLDivElement>()
 71 |   const recover = () => {
 72 |     if (ref.current && !field?.errors?.length) {
 73 |       setEditable(false)
 74 |     }
 75 |   }
 76 |   const renderEditHelper = () => {
 77 |     if (editable) return
 78 |     return (
 79 |       <BaseItem {...props} {...itemProps}>
 80 |         {pattern === 'editable' && (
 81 |           <EditOutlined className={`${prefixCls}-edit-btn`} />
 82 |         )}
 83 |         {pattern !== 'editable' && (
 84 |           <MessageOutlined className={`${prefixCls}-edit-btn`} />
 85 |         )}
 86 |       </BaseItem>
 87 |     )
 88 |   }
 89 | 
 90 |   const renderCloseHelper = () => {
 91 |     if (!editable) return
 92 |     return (
 93 |       <BaseItem {...props}>
 94 |         <CloseOutlined className={`${prefixCls}-close-btn`} />
 95 |       </BaseItem>
 96 |     )
 97 |   }
 98 | 
 99 |   useClickAway((e) => {
100 |     const target = e.target as HTMLElement
101 |     if (target?.closest(`.${basePrefixCls}-select-dropdown`)) return
102 |     if (target?.closest(`.${basePrefixCls}-picker-dropdown`)) return
103 |     if (target?.closest(`.${basePrefixCls}-cascader-menus`)) return
104 |     recover()
105 |   }, innerRef)
106 | 
107 |   const onClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
108 |     const target = e.target as HTMLElement
109 |     const close = innerRef.current.querySelector(`.${prefixCls}-close-btn`)
110 |     if (target?.contains(close) || close?.contains(target)) {
111 |       recover()
112 |     } else if (!ref.current) {
113 |       setTimeout(() => {
114 |         setEditable(true)
115 |         setTimeout(() => {
116 |           innerRef.current.querySelector('input')?.focus()
117 |         })
118 |       })
119 |     }
120 |   }
121 | 
122 |   ref.current = editable
123 | 
124 |   return (
125 |     <div className={prefixCls} ref={innerRef} onClick={onClick}>
126 |       <div className={`${prefixCls}-content`}>
127 |         <BaseItem {...props} {...itemProps}>
128 |           {props.children}
129 |         </BaseItem>
130 |         {renderEditHelper()}
131 |         {renderCloseHelper()}
132 |       </div>
133 |     </div>
134 |   )
135 | })
136 | 
137 | Editable.Popover = observer((props) => {
138 |   const field = useField<Field>()
139 |   const pattern = useParentPattern()
140 |   const [visible, setVisible] = useState(false)
141 |   const prefixCls = usePrefixCls('formily-editable')
142 |   const closePopover = async () => {
143 |     try {
144 |       await field.form.validate(`${field.address}.*`)
145 |     } finally {
146 |       const errors = field.form.queryFeedbacks({
147 |         type: 'error',
148 |         address: `${field.address}.*`,
149 |       })
150 |       if (errors?.length) return
151 |       setVisible(false)
152 |     }
153 |   }
154 |   const openPopover = () => {
155 |     setVisible(true)
156 |   }
157 |   return (
158 |     <Popover
159 |       {...props}
160 |       title={props.title || field.title}
161 |       visible={visible}
162 |       className={cls(prefixCls, props.className)}
163 |       content={props.children}
164 |       trigger="click"
165 |       destroyTooltipOnHide
166 |       onVisibleChange={(visible) => {
167 |         if (visible) {
168 |           openPopover()
169 |         } else {
170 |           closePopover()
171 |         }
172 |       }}
173 |     >
174 |       <div>
175 |         <BaseItem className={`${prefixCls}-trigger`}>
176 |           <div className={`${prefixCls}-content`}>
177 |             <span className={`${prefixCls}-preview`}>
178 |               {props.title || field.title}
179 |             </span>
180 |             {pattern === 'editable' && (
181 |               <EditOutlined className={`${prefixCls}-edit-btn`} />
182 |             )}
183 |             {pattern !== 'editable' && (
184 |               <MessageOutlined className={`${prefixCls}-edit-btn`} />
185 |             )}
186 |           </div>
187 |         </BaseItem>
188 |       </div>
189 |     </Popover>
190 |   )
191 | })
192 | 
193 | export default Editable
194 | 
```
Page 16/52FirstPrevNextLast