#
tokens: 48070/50000 12/1152 files (page 20/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 20 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/shared/src/array.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { isArr, isObj, isStr } from './checkers'
  2 | 
  3 | type EachArrayIterator<T> = (currentValue: T, key: number) => void | boolean
  4 | type EachStringIterator = (currentValue: string, key: number) => void | boolean
  5 | type EachObjectIterator<T = any> = (
  6 |   currentValue: T,
  7 |   key: string
  8 | ) => void | boolean
  9 | type MapArrayIterator<TItem, TResult> = (
 10 |   currentValue: TItem,
 11 |   key: number
 12 | ) => TResult
 13 | type MapStringIterator<TResult> = (currentValue: string, key: number) => TResult
 14 | type MapObjectIterator<TItem, TResult> = (
 15 |   currentValue: TItem,
 16 |   key: string
 17 | ) => TResult
 18 | type MemoArrayIterator<T, U> = (
 19 |   previousValue: U,
 20 |   currentValue: T,
 21 |   key: number
 22 | ) => U
 23 | type MemoStringIterator<T> = (
 24 |   previousValue: T,
 25 |   currentValue: string,
 26 |   key: number
 27 | ) => T
 28 | type MemoObjectIterator<TValue, TResult> = (
 29 |   previousValue: TResult,
 30 |   currentValue: TValue,
 31 |   key: string
 32 | ) => TResult
 33 | 
 34 | export const toArr = (val: any): any[] => (isArr(val) ? val : val ? [val] : [])
 35 | export function each(
 36 |   val: string,
 37 |   iterator: EachStringIterator,
 38 |   revert?: boolean
 39 | ): void
 40 | export function each<T>(
 41 |   val: T[],
 42 |   iterator: EachArrayIterator<T>,
 43 |   revert?: boolean
 44 | ): void
 45 | export function each<T extends {}, TValue extends T[keyof T]>(
 46 |   val: T,
 47 |   iterator: EachObjectIterator<TValue>,
 48 |   revert?: boolean
 49 | ): void
 50 | export function each(val: any, iterator: any, revert?: boolean): void {
 51 |   if (isArr(val) || isStr(val)) {
 52 |     if (revert) {
 53 |       for (let i: number = val.length - 1; i >= 0; i--) {
 54 |         if (iterator(val[i], i) === false) {
 55 |           return
 56 |         }
 57 |       }
 58 |     } else {
 59 |       for (let i = 0; i < val.length; i++) {
 60 |         if (iterator(val[i], i) === false) {
 61 |           return
 62 |         }
 63 |       }
 64 |     }
 65 |   } else if (isObj(val)) {
 66 |     let key: string
 67 |     for (key in val) {
 68 |       if (Object.hasOwnProperty.call(val, key)) {
 69 |         if (iterator(val[key], key) === false) {
 70 |           return
 71 |         }
 72 |       }
 73 |     }
 74 |   }
 75 | }
 76 | 
 77 | export function map<T>(
 78 |   val: string,
 79 |   iterator: MapStringIterator<T>,
 80 |   revert?: boolean
 81 | ): T[]
 82 | export function map<TItem, TResult>(
 83 |   val: TItem[],
 84 |   iterator: MapArrayIterator<TItem, TResult>,
 85 |   revert?: boolean
 86 | ): TResult[]
 87 | export function map<T extends {}, TResult>(
 88 |   val: T,
 89 |   iterator: MapObjectIterator<T[keyof T], TResult>,
 90 |   revert?: boolean
 91 | ): Record<keyof T, TResult>
 92 | export function map(val: any, iterator: any, revert?: any): any {
 93 |   const res = isArr(val) || isStr(val) ? [] : {}
 94 |   each(
 95 |     val,
 96 |     (item, key) => {
 97 |       const value = iterator(item, key)
 98 |       if (isArr(res)) {
 99 |         ;(res as any).push(value)
100 |       } else {
101 |         res[key] = value
102 |       }
103 |     },
104 |     revert
105 |   )
106 |   return res
107 | }
108 | 
109 | export function reduce<T, U>(
110 |   val: T[],
111 |   iterator: MemoArrayIterator<T, U>,
112 |   accumulator?: U,
113 |   revert?: boolean
114 | ): U
115 | export function reduce<T>(
116 |   val: string,
117 |   iterator: MemoStringIterator<T>,
118 |   accumulator?: T,
119 |   revert?: boolean
120 | ): T
121 | export function reduce<T extends {}, TValue extends T[keyof T], TResult = any>(
122 |   val: T,
123 |   iterator: MemoObjectIterator<TValue, TResult>,
124 |   accumulator?: TResult,
125 |   revert?: boolean
126 | ): TResult
127 | export function reduce(
128 |   val: any,
129 |   iterator: any,
130 |   accumulator?: any,
131 |   revert?: boolean
132 | ): any {
133 |   let result = accumulator
134 |   each(
135 |     val,
136 |     (item, key) => {
137 |       result = iterator(result, item, key)
138 |     },
139 |     revert
140 |   )
141 |   return result
142 | }
143 | 
144 | export function every<T extends string>(
145 |   val: T,
146 |   iterator: EachStringIterator,
147 |   revert?: boolean
148 | ): boolean
149 | export function every<T>(
150 |   val: T[],
151 |   iterator: EachArrayIterator<T>,
152 |   revert?: boolean
153 | ): boolean
154 | export function every<T extends {}>(
155 |   val: T,
156 |   iterator: EachObjectIterator,
157 |   revert?: boolean
158 | ): boolean
159 | export function every(val: any, iterator: any, revert?: boolean): boolean {
160 |   let res = true
161 |   each(
162 |     val,
163 |     (item, key) => {
164 |       if (!iterator(item, key)) {
165 |         res = false
166 |         return false
167 |       }
168 |     },
169 |     revert
170 |   )
171 |   return res
172 | }
173 | 
174 | export function some<T extends string>(
175 |   val: T,
176 |   iterator: EachStringIterator,
177 |   revert?: boolean
178 | ): boolean
179 | export function some<T>(
180 |   val: T[],
181 |   iterator: EachArrayIterator<T>,
182 |   revert?: boolean
183 | ): boolean
184 | export function some<T extends {}>(
185 |   val: T,
186 |   iterator: EachObjectIterator,
187 |   revert?: boolean
188 | ): boolean
189 | export function some(val: any, iterator: any, revert?: boolean): boolean {
190 |   let res = false
191 |   each(
192 |     val,
193 |     (item, key) => {
194 |       if (iterator(item, key)) {
195 |         res = true
196 |         return false
197 |       }
198 |     },
199 |     revert
200 |   )
201 |   return res
202 | }
203 | 
204 | export function findIndex<T extends string>(
205 |   val: T,
206 |   iterator: EachStringIterator,
207 |   revert?: boolean
208 | ): number
209 | export function findIndex<T>(
210 |   val: T[],
211 |   iterator: EachArrayIterator<T>,
212 |   revert?: boolean
213 | ): number
214 | export function findIndex<T extends {}>(
215 |   val: T,
216 |   iterator: EachObjectIterator,
217 |   revert?: boolean
218 | ): keyof T
219 | export function findIndex(
220 |   val: any,
221 |   iterator: any,
222 |   revert?: boolean
223 | ): string | number {
224 |   let res: number | string = -1
225 |   each(
226 |     val,
227 |     (item, key) => {
228 |       if (iterator(item, key)) {
229 |         res = key
230 |         return false
231 |       }
232 |     },
233 |     revert
234 |   )
235 |   return res
236 | }
237 | 
238 | export function find<T extends string>(
239 |   val: T,
240 |   iterator: EachStringIterator,
241 |   revert?: boolean
242 | ): any
243 | export function find<T>(
244 |   val: T[],
245 |   iterator: EachArrayIterator<T>,
246 |   revert?: boolean
247 | ): T
248 | export function find<T extends {}>(
249 |   val: T,
250 |   iterator: EachObjectIterator,
251 |   revert?: boolean
252 | ): T[keyof T]
253 | export function find(val: any, iterator: any, revert?: boolean): any {
254 |   let res: any
255 |   each(
256 |     val,
257 |     (item, key) => {
258 |       if (iterator(item, key)) {
259 |         res = item
260 |         return false
261 |       }
262 |     },
263 |     revert
264 |   )
265 |   return res
266 | }
267 | 
268 | export function includes<T extends string>(
269 |   val: T,
270 |   searchElement: string,
271 |   revert?: boolean
272 | ): boolean
273 | export function includes<T>(
274 |   val: T[],
275 |   searchElement: T,
276 |   revert?: boolean
277 | ): boolean
278 | export function includes(val: any, searchElement: any, revert?: boolean) {
279 |   if (isStr(val)) return val.includes(searchElement)
280 |   return some(val, (item) => item === searchElement, revert)
281 | }
282 | 
283 | export function move<T extends any>(
284 |   array: T[],
285 |   fromIndex: number,
286 |   toIndex: number
287 | ) {
288 |   if (fromIndex === toIndex) return array
289 | 
290 |   if (
291 |     toIndex < 0 ||
292 |     fromIndex < 0 ||
293 |     toIndex > array.length - 1 ||
294 |     fromIndex > array.length - 1
295 |   ) {
296 |     return array
297 |   }
298 | 
299 |   if (fromIndex < toIndex) {
300 |     const fromItem = array[fromIndex]
301 |     for (let index = fromIndex; index < toIndex; index++) {
302 |       array[index] = array[index + 1]
303 |     }
304 |     array[toIndex] = fromItem
305 |   } else {
306 |     const fromItem = array[fromIndex]
307 |     for (let index = fromIndex; index > toIndex; index--) {
308 |       array[index] = array[index - 1]
309 |     }
310 |     array[toIndex] = fromItem
311 |   }
312 |   return array
313 | }
314 | 
```

--------------------------------------------------------------------------------
/devtools/chrome-extension/src/app/components/FieldTree.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { useState, useEffect, useRef } from 'react'
  2 | import styled from 'styled-components'
  3 | import { FormPath, isObj } from '@formily/shared'
  4 | import { Treebeard, decorators } from 'react-treebeard'
  5 | import * as filters from './filter'
  6 | import SearchBox from './SearchBox'
  7 | 
  8 | const createTree = (dataSource: any, cursor?: any) => {
  9 |   const tree: any = {}
 10 |   const getParentPath = (key: string) => {
 11 |     let parentPath: FormPath = FormPath.parse(key)
 12 |     let i = 0
 13 |     while (true) {
 14 |       parentPath = parentPath.parent()
 15 |       if (dataSource[parentPath.toString()]) {
 16 |         return parentPath
 17 |       }
 18 |       if (i > parentPath.segments.length) return parentPath
 19 |       i++
 20 |     }
 21 |   }
 22 |   const findParent = (key: string): any => {
 23 |     const parentPath = getParentPath(key)
 24 |     const _findParent = (node: any) => {
 25 |       if (FormPath.parse(node.path).match(parentPath)) {
 26 |         return node
 27 |       } else {
 28 |         for (let i = 0; i < node?.children?.length; i++) {
 29 |           const parent = _findParent(node.children[i])
 30 |           if (parent) {
 31 |             return parent
 32 |           }
 33 |         }
 34 |       }
 35 |     }
 36 |     return _findParent(tree)
 37 |   }
 38 |   Object.keys(dataSource || {}).forEach((key) => {
 39 |     if (key == '') {
 40 |       tree.name = 'Form'
 41 |       tree.path = key
 42 |       tree.toggled = true
 43 |       tree.data = dataSource[key]
 44 |       if (cursor && cursor.current && cursor.current.path === key) {
 45 |         tree.active = true
 46 |         cursor.current = tree
 47 |       }
 48 |     } else {
 49 |       const node: any = {
 50 |         name: key,
 51 |         path: key,
 52 |         toggled: true,
 53 |         data: dataSource[key],
 54 |       }
 55 |       if (cursor && cursor.current && cursor.current.path === key) {
 56 |         node.active = true
 57 |         cursor.current = node
 58 |       }
 59 |       const parent = findParent(key)
 60 |       if (parent) {
 61 |         node.name = (node.path || '').slice(
 62 |           parent && parent.path ? parent.path.length + 1 : 0
 63 |         )
 64 |         parent.children = parent.children || []
 65 |         parent.children.push(node)
 66 |       }
 67 |     }
 68 |   })
 69 |   return tree
 70 | }
 71 | 
 72 | const theme = {
 73 |   tree: {
 74 |     base: {
 75 |       listStyle: 'none',
 76 |       margin: 0,
 77 |       padding: 0,
 78 |       color: '#9DA5AB',
 79 |       fontFamily: 'lucida grande ,tahoma,verdana,arial,sans-serif',
 80 |       fontSize: '8px',
 81 |       background: 'none',
 82 |       marginBottom: '50px',
 83 |     },
 84 |     node: {
 85 |       base: {
 86 |         position: 'relative',
 87 |         background: 'none',
 88 |       },
 89 |       link: {
 90 |         cursor: 'pointer',
 91 |         position: 'relative',
 92 |         padding: '0px 5px',
 93 |         display: 'block',
 94 |       },
 95 |       activeLink: {
 96 |         background: '#3D424A',
 97 |       },
 98 |       toggle: {
 99 |         base: {
100 |           position: 'relative',
101 |           display: 'inline-block',
102 |           verticalAlign: 'top',
103 |           marginLeft: '-5px',
104 |           height: '22px',
105 |           width: '20px',
106 |           zIndex: 2,
107 |         },
108 |         wrapper: {
109 |           position: 'absolute',
110 |           top: '50%',
111 |           left: '50%',
112 |           transform: 'translate(-50%,-50%)',
113 |           width: 4,
114 |           height: 6,
115 |           display: 'flex',
116 |           alignItems: 'center',
117 |           justifyContent: 'center',
118 |         },
119 |         height: 6,
120 |         width: 4,
121 |         arrow: {
122 |           fill: '#9DA5AB',
123 |           strokeWidth: 0,
124 |         },
125 |       },
126 |       header: {
127 |         base: {
128 |           display: 'inline-block',
129 |           verticalAlign: 'top',
130 |           color: '#9DA5AB',
131 |         },
132 |         connector: {
133 |           width: '2px',
134 |           height: '12px',
135 |           borderLeft: 'solid 2px black',
136 |           borderBottom: 'solid 2px black',
137 |           position: 'absolute',
138 |           top: '0px',
139 |           left: '-21px',
140 |         },
141 |         title: {
142 |           lineHeight: '24px',
143 |           verticalAlign: 'middle',
144 |         },
145 |       },
146 |       subtree: {
147 |         listStyle: 'none',
148 |         paddingLeft: '19px',
149 |       },
150 |       loading: {
151 |         color: '#E2C089',
152 |       },
153 |     },
154 |   },
155 | }
156 | 
157 | const Header = (props) => {
158 |   const { node, style, customStyles } = props
159 |   const title = node.data?.title ? node.data.title : ''
160 |   return (
161 |     <div
162 |       className="node-header"
163 |       style={style.base}
164 |       onClick={() => {
165 |         node.toggled = false
166 |       }}
167 |     >
168 |       <div
169 |         style={
170 |           node.selected
171 |             ? { ...style.title, ...customStyles.header.title }
172 |             : style.title
173 |         }
174 |       >
175 |         <span
176 |           style={{
177 |             zIndex: 1,
178 |             position: 'relative',
179 |             fontSize: 12,
180 |           }}
181 |         >
182 |           {node.name}
183 |         </span>
184 |         <span style={{ zIndex: 1, position: 'absolute', right: 12 }}>
185 |            {isObj(title) ? ((title as any).title ?? '') : title}
186 |         </span>
187 |         <div
188 |           className={`highlight ${node.active ? 'active' : ''}`}
189 |           style={{ transition: '.15s all ease-in' }}
190 |         ></div>
191 |       </div>
192 |     </div>
193 |   )
194 | }
195 | 
196 | const ToolBar = styled.div`
197 |   border-bottom: 1px solid #3d424a;
198 |   height: 20px;
199 |   padding: 10px 10px;
200 |   padding: 5px;
201 |   overflow: auto;
202 |   position: sticky;
203 |   top: 0;
204 |   background: #282c34;
205 |   z-index: 100;
206 | `
207 | 
208 | export const FieldTree = styled(({ className, dataSource, onSelect }) => {
209 |   const allDataRef = useRef(createTree(dataSource))
210 |   const cursor = useRef(allDataRef.current)
211 |   const [keyword, setKeyword] = useState('')
212 |   const searchTimer = useRef(null)
213 |   const [data, setData] = useState(allDataRef.current)
214 | 
215 |   const filterData = () => {
216 |     if (!keyword) return data
217 |     const finded = filters.filterTree(data, keyword)
218 |     return filters.expandFilteredNodes(finded, keyword)
219 |   }
220 | 
221 |   const onToggle = (node: any, toggled: boolean) => {
222 |     cursor.current.active = false
223 |     node.active = true
224 |     if (node.children && node.children.length) {
225 |       node.toggled = toggled
226 |     }
227 |     cursor.current = node
228 |     setData(data)
229 |     if (onSelect) {
230 |       onSelect(node)
231 |     }
232 |   }
233 | 
234 |   const onSearch = ({ target: { value } }) => {
235 |     clearTimeout(searchTimer.current)
236 |     searchTimer.current = setTimeout(() => {
237 |       setKeyword(value.trim())
238 |     }, 100)
239 |   }
240 | 
241 |   useEffect(() => {
242 |     allDataRef.current = createTree(dataSource, cursor)
243 |     setData(allDataRef.current)
244 |   }, [dataSource])
245 | 
246 |   return (
247 |     <div className={className}>
248 |       <ToolBar>
249 |         <SearchBox onSearch={onSearch} />
250 |       </ToolBar>
251 | 
252 |       <Treebeard
253 |         data={filterData()}
254 |         onToggle={onToggle}
255 |         decorators={{
256 |           ...decorators,
257 |           Header,
258 |         }}
259 |         style={theme}
260 |       />
261 |     </div>
262 |   )
263 | })`
264 |   position: relative;
265 |   overflow: auto;
266 |   height: calc(100% - 40px);
267 |   user-select: none;
268 |   .highlight {
269 |     position: absolute;
270 |     top: 0;
271 |     right: 0;
272 |     left: -100%;
273 |     height: 100%;
274 |     z-index: 0;
275 |     &.active {
276 |       background: #3d424a;
277 |     }
278 |   }
279 |   .node-header:hover .highlight {
280 |     background: #3d424a;
281 |   }
282 | `
283 | 
```

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

```markdown
  1 | # Editable
  2 | 
  3 | > 局部编辑器,对于一些空间要求较高的表单区域可以使用该组件
  4 | >
  5 | > Editable 组件相当于是 FormItem 组件的变体,所以通常放在 decorator 中
  6 | 
  7 | ## Markup Schema 案例
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   Input,
 13 |   DatePicker,
 14 |   Editable,
 15 |   FormItem,
 16 |   FormButtonGroup,
 17 |   Submit,
 18 | } from '@formily/next'
 19 | import { createForm } from '@formily/core'
 20 | import { FormProvider, createSchemaField } from '@formily/react'
 21 | 
 22 | const SchemaField = createSchemaField({
 23 |   components: {
 24 |     DatePicker,
 25 |     Editable,
 26 |     Input,
 27 |     FormItem,
 28 |   },
 29 | })
 30 | 
 31 | const form = createForm()
 32 | 
 33 | export default () => (
 34 |   <FormProvider form={form}>
 35 |     <SchemaField>
 36 |       <SchemaField.String
 37 |         name="date"
 38 |         title="日期"
 39 |         x-decorator="Editable"
 40 |         x-component="DatePicker"
 41 |       />
 42 |       <SchemaField.String
 43 |         name="input"
 44 |         title="输入框"
 45 |         x-decorator="Editable"
 46 |         x-component="Input"
 47 |       />
 48 |       <SchemaField.Void
 49 |         name="void"
 50 |         title="虚拟节点容器"
 51 |         x-component="Editable.Popover"
 52 |         x-reactions={(field) => {
 53 |           field.title = field.query('.void.date2').get('value') || field.title
 54 |         }}
 55 |       >
 56 |         <SchemaField.String
 57 |           name="date2"
 58 |           title="日期"
 59 |           x-decorator="FormItem"
 60 |           x-component="DatePicker"
 61 |           x-component-props={{
 62 |             followTrigger: true,
 63 |           }}
 64 |         />
 65 |         <SchemaField.String
 66 |           name="input2"
 67 |           title="输入框"
 68 |           x-decorator="FormItem"
 69 |           x-component="Input"
 70 |         />
 71 |       </SchemaField.Void>
 72 |       <SchemaField.Object
 73 |         name="iobject"
 74 |         title="对象节点容器"
 75 |         x-component="Editable.Popover"
 76 |         x-reactions={(field) => {
 77 |           field.title = field.value?.date || field.title
 78 |         }}
 79 |       >
 80 |         <SchemaField.String
 81 |           name="date"
 82 |           title="日期"
 83 |           x-decorator="FormItem"
 84 |           x-component="DatePicker"
 85 |           x-component-props={{
 86 |             followTrigger: true,
 87 |           }}
 88 |         />
 89 |         <SchemaField.String
 90 |           name="input"
 91 |           title="输入框"
 92 |           x-decorator="FormItem"
 93 |           x-component="Input"
 94 |         />
 95 |       </SchemaField.Object>
 96 |     </SchemaField>
 97 |     <FormButtonGroup>
 98 |       <Submit onSubmit={console.log}>提交</Submit>
 99 |     </FormButtonGroup>
100 |   </FormProvider>
101 | )
102 | ```
103 | 
104 | ## JSON Schema 案例
105 | 
106 | ```tsx
107 | import React from 'react'
108 | import {
109 |   Input,
110 |   DatePicker,
111 |   Editable,
112 |   FormItem,
113 |   FormButtonGroup,
114 |   Submit,
115 | } from '@formily/next'
116 | import { createForm } from '@formily/core'
117 | import { FormProvider, createSchemaField } from '@formily/react'
118 | 
119 | const SchemaField = createSchemaField({
120 |   components: {
121 |     DatePicker,
122 |     Editable,
123 |     Input,
124 |     FormItem,
125 |   },
126 | })
127 | 
128 | const form = createForm()
129 | 
130 | const schema = {
131 |   type: 'object',
132 |   properties: {
133 |     date: {
134 |       type: 'string',
135 |       title: '日期',
136 |       'x-decorator': 'Editable',
137 |       'x-component': 'DatePicker',
138 |     },
139 |     input: {
140 |       type: 'string',
141 |       title: '输入框',
142 |       'x-decorator': 'Editable',
143 |       'x-component': 'Input',
144 |     },
145 |     void: {
146 |       type: 'void',
147 |       title: '虚拟节点容器',
148 |       'x-component': 'Editable.Popover',
149 |       'x-reactions':
150 |         "{{(field) => field.title = field.query('.void.date2').get('value') || field.title}}",
151 |       properties: {
152 |         date2: {
153 |           type: 'string',
154 |           title: '日期',
155 |           'x-decorator': 'FormItem',
156 |           'x-component': 'DatePicker',
157 |           'x-component-props': {
158 |             followTrigger: true,
159 |           },
160 |         },
161 |         input2: {
162 |           type: 'string',
163 |           title: '输入框',
164 |           'x-decorator': 'FormItem',
165 |           'x-component': 'Input',
166 |         },
167 |       },
168 |     },
169 |     iobject: {
170 |       type: 'object',
171 |       title: '对象节点容器',
172 |       'x-component': 'Editable.Popover',
173 |       'x-reactions':
174 |         '{{(field) => field.title = field.value && field.value.date || field.title}}',
175 |       properties: {
176 |         date: {
177 |           type: 'string',
178 |           title: '日期',
179 |           'x-decorator': 'FormItem',
180 |           'x-component': 'DatePicker',
181 |           'x-component-props': {
182 |             followTrigger: true,
183 |           },
184 |         },
185 |         input: {
186 |           type: 'string',
187 |           title: '输入框',
188 |           'x-decorator': 'FormItem',
189 |           'x-component': 'Input',
190 |         },
191 |       },
192 |     },
193 |   },
194 | }
195 | 
196 | export default () => (
197 |   <FormProvider form={form}>
198 |     <SchemaField schema={schema} />
199 |     <FormButtonGroup>
200 |       <Submit onSubmit={console.log}>提交</Submit>
201 |     </FormButtonGroup>
202 |   </FormProvider>
203 | )
204 | ```
205 | 
206 | ## 纯 JSX 案例
207 | 
208 | ```tsx
209 | import React from 'react'
210 | import {
211 |   Input,
212 |   DatePicker,
213 |   Editable,
214 |   FormItem,
215 |   FormButtonGroup,
216 |   Submit,
217 | } from '@formily/next'
218 | import { createForm } from '@formily/core'
219 | import { FormProvider, Field, VoidField, ObjectField } from '@formily/react'
220 | 
221 | const form = createForm()
222 | 
223 | export default () => (
224 |   <FormProvider form={form}>
225 |     <Field
226 |       name="date"
227 |       title="日期"
228 |       decorator={[Editable]}
229 |       component={[DatePicker]}
230 |     />
231 |     <Field
232 |       name="input"
233 |       title="输入框"
234 |       decorator={[Editable]}
235 |       component={[Input]}
236 |     />
237 |     <VoidField
238 |       name="void"
239 |       title="虚拟节点容器"
240 |       reactions={(field) => {
241 |         field.title = field.query('.void.date2').get('value') || field.title
242 |       }}
243 |       component={[Editable.Popover]}
244 |     >
245 |       <Field
246 |         name="date2"
247 |         title="日期"
248 |         decorator={[FormItem]}
249 |         component={[
250 |           DatePicker,
251 |           {
252 |             followTrigger: true,
253 |           },
254 |         ]}
255 |       />
256 |       <Field
257 |         name="input2"
258 |         title="输入框"
259 |         decorator={[FormItem]}
260 |         component={[Input]}
261 |       />
262 |     </VoidField>
263 |     <ObjectField
264 |       name="iobject"
265 |       title="对象节点容器"
266 |       component={[
267 |         Editable.Popover,
268 |         {
269 |           renderPreview: (field) => {
270 |             return field.value?.date
271 |           },
272 |         },
273 |       ]}
274 |     >
275 |       <Field
276 |         name="date"
277 |         title="日期"
278 |         decorator={[FormItem]}
279 |         component={[
280 |           DatePicker,
281 |           {
282 |             followTrigger: true,
283 |           },
284 |         ]}
285 |       />
286 |       <Field
287 |         name="input"
288 |         title="输入框"
289 |         decorator={[FormItem]}
290 |         component={[Input]}
291 |       />
292 |     </ObjectField>
293 | 
294 |     <FormButtonGroup>
295 |       <Submit onSubmit={console.log}>提交</Submit>
296 |     </FormButtonGroup>
297 |   </FormProvider>
298 | )
299 | ```
300 | 
301 | ## API
302 | 
303 | ### Editable
304 | 
305 | > 内联编辑
306 | 
307 | 参考 https://fusion.design/pc/component/basic/form 中的 FormItem 属性
308 | 
309 | ### Editable.Popover
310 | 
311 | > 浮层编辑
312 | 
313 | | 属性名        | 类型                              | 描述       | 默认值 |
314 | | ------------- | --------------------------------- | ---------- | ------ |
315 | | renderPreview | `(field:GeneralField)=>ReactNode` | 预览渲染器 |        |
316 | 
317 | 注意:如果在 Popover 内部有 Select/DatePicker 之类的浮层组件,需要在浮层组件上配置 followTrigger=true
318 | 
319 | 其余参考 https://fusion.design/pc/component/basic/balloon
320 | 
```

--------------------------------------------------------------------------------
/packages/shared/src/merge.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { isFn, isPlainObj } from './checkers'
  2 | import { isEmpty, isValid } from './isEmpty'
  3 | 
  4 | function defaultIsMergeableObject(value: any) {
  5 |   return isNonNullObject(value) && !isSpecial(value)
  6 | }
  7 | 
  8 | function isNonNullObject(value: any) {
  9 |   // TODO: value !== null && typeof value === 'object'
 10 |   return Boolean(value) && typeof value === 'object'
 11 | }
 12 | 
 13 | function isSpecial(value: any) {
 14 |   // TODO: use isComplexObject()
 15 |   if ('$$typeof' in value && '_owner' in value) {
 16 |     return true
 17 |   }
 18 |   if (value._isAMomentObject) {
 19 |     return true
 20 |   }
 21 |   if (value._isJSONSchemaObject) {
 22 |     return true
 23 |   }
 24 |   if (isFn(value.toJS)) {
 25 |     return true
 26 |   }
 27 |   if (isFn(value.toJSON)) {
 28 |     return true
 29 |   }
 30 |   return !isPlainObj(value)
 31 | }
 32 | 
 33 | function emptyTarget(val: any) {
 34 |   return Array.isArray(val) ? [] : {}
 35 | }
 36 | // @ts-ignore
 37 | function cloneUnlessOtherwiseSpecified(value: any, options: Options) {
 38 |   if (options.clone !== false && options.isMergeableObject?.(value)) {
 39 |     return deepmerge(emptyTarget(value), value, options)
 40 |   }
 41 |   return value
 42 | }
 43 | 
 44 | function defaultArrayMerge(target: any, source: any, options: Options) {
 45 |   return target.concat(source).map(function (element: any) {
 46 |     return cloneUnlessOtherwiseSpecified(element, options)
 47 |   })
 48 | }
 49 | 
 50 | function getMergeFunction(key: string, options: Options) {
 51 |   if (!options.customMerge) {
 52 |     return deepmerge
 53 |   }
 54 |   const customMerge = options.customMerge(key)
 55 |   return typeof customMerge === 'function' ? customMerge : deepmerge
 56 | }
 57 | 
 58 | function getEnumerableOwnPropertySymbols(target: any): any {
 59 |   return Object.getOwnPropertySymbols
 60 |     ? Object.getOwnPropertySymbols(target).filter(function (symbol) {
 61 |         return target.propertyIsEnumerable(symbol)
 62 |       })
 63 |     : []
 64 | }
 65 | 
 66 | function getKeys(target: any) {
 67 |   if (!isValid(target)) return []
 68 |   return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
 69 | }
 70 | 
 71 | function propertyIsOnObject(object: any, property: any) {
 72 |   /* istanbul ignore next */
 73 |   try {
 74 |     return property in object
 75 |   } catch (_) {
 76 |     return false
 77 |   }
 78 | }
 79 | 
 80 | // Protects from prototype poisoning and unexpected merging up the prototype chain.
 81 | function propertyIsUnsafe(target: any, key: PropertyKey) {
 82 |   return (
 83 |     propertyIsOnObject(target, key) && // Properties are safe to merge if they don't exist in the target yet,
 84 |     !(
 85 |       Object.hasOwnProperty.call(target, key) && // unsafe if they exist up the prototype chain,
 86 |       Object.propertyIsEnumerable.call(target, key)
 87 |     )
 88 |   ) // and also unsafe if they're nonenumerable.
 89 | }
 90 | 
 91 | function mergeObject(target: any, source: any, options: Options) {
 92 |   const destination = options.assign ? target || {} : {}
 93 |   if (!options.isMergeableObject(target)) return target
 94 |   if (!options.assign) {
 95 |     getKeys(target).forEach(function (key) {
 96 |       destination[key] = cloneUnlessOtherwiseSpecified(target[key], options)
 97 |     })
 98 |   }
 99 |   getKeys(source).forEach(function (key) {
100 |     /* istanbul ignore next */
101 |     if (propertyIsUnsafe(target, key)) {
102 |       return
103 |     }
104 |     if (isEmpty(target[key])) {
105 |       destination[key] = source[key]
106 |     } else if (
107 |       propertyIsOnObject(target, key) &&
108 |       // @ts-ignore
109 |       options.isMergeableObject(source[key])
110 |     ) {
111 |       destination[key] = getMergeFunction(key, options)(
112 |         target[key],
113 |         source[key],
114 |         options
115 |       )
116 |     } else {
117 |       destination[key] = cloneUnlessOtherwiseSpecified(source[key], options)
118 |     }
119 |   })
120 |   return destination
121 | }
122 | 
123 | interface Options {
124 |   arrayMerge?(target: any[], source: any[], options?: Options): any[]
125 |   clone?: boolean
126 |   assign?: boolean
127 |   customMerge?: (
128 |     key: string,
129 |     options?: Options
130 |   ) => ((x: any, y: any) => any) | undefined
131 |   isMergeableObject?(value: object): boolean
132 |   cloneUnlessOtherwiseSpecified?: (value: any, options: Options) => any
133 | }
134 | 
135 | // @ts-ignore
136 | function deepmerge(target: any, source: any, options?: Options) {
137 |   options = options || {}
138 |   options.arrayMerge = options.arrayMerge || defaultArrayMerge
139 |   options.isMergeableObject =
140 |     options.isMergeableObject || defaultIsMergeableObject
141 |   // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
142 |   // implementations can use it. The caller may not replace it.
143 |   options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified
144 | 
145 |   const sourceIsArray = Array.isArray(source)
146 |   const targetIsArray = Array.isArray(target)
147 |   const sourceAndTargetTypesMatch = sourceIsArray === targetIsArray
148 | 
149 |   if (!sourceAndTargetTypesMatch) {
150 |     return cloneUnlessOtherwiseSpecified(source, options)
151 |   } else if (sourceIsArray) {
152 |     return options.arrayMerge(target, source, options)
153 |   } else {
154 |     return mergeObject(target, source, options)
155 |   }
156 | }
157 | 
158 | export const lazyMerge = <T extends object | Function>(
159 |   target: T,
160 |   ...args: T[]
161 | ): any => {
162 |   const _lazyMerge = <T extends object | Function>(
163 |     target: T,
164 |     source: T
165 |   ): {} => {
166 |     if (!isValid(source)) return target
167 |     if (!isValid(target)) return source
168 |     const isTargetObject = typeof target === 'object'
169 |     const isSourceObject = typeof source === 'object'
170 |     const isTargetFn = typeof target === 'function'
171 |     const isSourceFn = typeof source === 'function'
172 |     if (!isTargetObject && !isTargetFn) return source
173 |     if (!isSourceObject && !isSourceFn) return target
174 |     const getTarget = () => (isTargetFn ? target() : target)
175 |     const getSource = () => (isSourceFn ? source() : source)
176 |     const set = (_: object, key: PropertyKey, value: any) => {
177 |       const source = getSource()
178 |       const target = getTarget()
179 |       if (key in source) {
180 |         // @ts-ignore
181 |         source[key] = value
182 |       } else if (key in target) {
183 |         // @ts-ignore
184 |         target[key] = value
185 |       } else {
186 |         source[key] = value
187 |       }
188 |       return true
189 |     }
190 |     const get = (_: object, key: PropertyKey) => {
191 |       const source = getSource()
192 |       // @ts-ignore
193 |       if (key in source) {
194 |         return source[key]
195 |       }
196 |       // @ts-ignore
197 |       return getTarget()[key]
198 |     }
199 |     const ownKeys = () => {
200 |       const source = getSource()
201 |       const target = getTarget()
202 |       const keys = Object.keys(target)
203 |       for (const key in source) {
204 |         if (!(key in target)) {
205 |           keys.push(key)
206 |         }
207 |       }
208 |       return keys
209 |     }
210 |     const getOwnPropertyDescriptor = (_: object, key: PropertyKey) => ({
211 |       value: get(_, key),
212 |       enumerable: true,
213 |       configurable: true,
214 |     })
215 |     const has = (_: object, key: PropertyKey) => {
216 |       if (key in getSource() || key in getTarget()) return true
217 |       return false
218 |     }
219 |     const getPrototypeOf = () => Object.getPrototypeOf({})
220 |     return new Proxy(Object.create(null), {
221 |       set,
222 |       get,
223 |       ownKeys,
224 |       getPrototypeOf,
225 |       getOwnPropertyDescriptor,
226 |       has,
227 |     }) as any
228 |   }
229 |   return args.reduce<{}>((buf, arg) => _lazyMerge(buf, arg), target)
230 | }
231 | 
232 | export const merge = deepmerge
233 | 
```

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

```markdown
  1 | # FormCollapse
  2 | 
  3 | > Folding panel, usually used in form scenes with high layout space requirements
  4 | >
  5 | > Note: Can only be used in Schema scenarios
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormCollapse,
 13 |   FormLayout,
 14 |   FormItem,
 15 |   Input,
 16 |   FormButtonGroup,
 17 |   Submit,
 18 | } from '@formily/antd'
 19 | import { createForm } from '@formily/core'
 20 | import { FormProvider, createSchemaField } from '@formily/react'
 21 | import { Button } from 'antd'
 22 | 
 23 | const SchemaField = createSchemaField({
 24 |   components: {
 25 |     FormItem,
 26 |     FormCollapse,
 27 |     Input,
 28 |   },
 29 | })
 30 | 
 31 | const form = createForm()
 32 | const formCollapse = FormCollapse.createFormCollapse()
 33 | export default () => {
 34 |   return (
 35 |     <FormProvider form={form}>
 36 |       <FormLayout labelCol={6} wrapperCol={10}>
 37 |         <SchemaField>
 38 |           <SchemaField.Void
 39 |             title="Folding Panel"
 40 |             x-decorator="FormItem"
 41 |             x-component="FormCollapse"
 42 |             x-component-props={{
 43 |               formCollapse,
 44 |             }}
 45 |           >
 46 |             <SchemaField.Void
 47 |               name="panel1"
 48 |               x-component="FormCollapse.CollapsePanel"
 49 |               x-component-props={{ header: 'A1' }}
 50 |             >
 51 |               <SchemaField.String
 52 |                 name="aaa"
 53 |                 title="AAA"
 54 |                 x-decorator="FormItem"
 55 |                 required
 56 |                 x-component="Input"
 57 |               />
 58 |             </SchemaField.Void>
 59 |             <SchemaField.Void
 60 |               name="panel2"
 61 |               x-component="FormCollapse.CollapsePanel"
 62 |               x-component-props={{ header: 'A2' }}
 63 |             >
 64 |               <SchemaField.String
 65 |                 name="bbb"
 66 |                 title="BBB"
 67 |                 x-decorator="FormItem"
 68 |                 required
 69 |                 x-component="Input"
 70 |               />
 71 |             </SchemaField.Void>
 72 |             <SchemaField.Void
 73 |               name="panel3"
 74 |               x-component="FormCollapse.CollapsePanel"
 75 |               x-component-props={{ header: 'A3' }}
 76 |             >
 77 |               <SchemaField.String
 78 |                 name="ccc"
 79 |                 title="CCC"
 80 |                 x-decorator="FormItem"
 81 |                 required
 82 |                 x-component="Input"
 83 |               />
 84 |             </SchemaField.Void>
 85 |           </SchemaField.Void>
 86 |         </SchemaField>
 87 |         <FormButtonGroup.FormItem>
 88 |           <Button
 89 |             onClick={() => {
 90 |               form.query('panel3').take((field) => {
 91 |                 field.visible = !field.visible
 92 |               })
 93 |             }}
 94 |           >
 95 |             Show/hide the last tab
 96 |           </Button>
 97 |           <Button
 98 |             onClick={() => {
 99 |               formCollapse.toggleActiveKey('panel2')
100 |             }}
101 |           >
102 |             Switch to the second Tab
103 |           </Button>
104 |           <Submit onSubmit={console.log}>Submit</Submit>
105 |         </FormButtonGroup.FormItem>
106 |       </FormLayout>
107 |     </FormProvider>
108 |   )
109 | }
110 | ```
111 | 
112 | ## JSON Schema case
113 | 
114 | ```tsx
115 | import React from 'react'
116 | import {
117 |   FormCollapse,
118 |   FormItem,
119 |   FormLayout,
120 |   Input,
121 |   FormButtonGroup,
122 |   Submit,
123 | } from '@formily/antd'
124 | import { createForm } from '@formily/core'
125 | import { FormProvider, createSchemaField } from '@formily/react'
126 | import { Button } from 'antd'
127 | 
128 | const SchemaField = createSchemaField({
129 |   components: {
130 |     FormItem,
131 |     FormCollapse,
132 |     Input,
133 |   },
134 | })
135 | 
136 | const form = createForm()
137 | const formCollapse = FormCollapse.createFormCollapse()
138 | const schema = {
139 |   type: 'object',
140 |   properties: {
141 |     collapse: {
142 |       type: 'void',
143 |       title: 'Folding Panel',
144 |       'x-decorator': 'FormItem',
145 |       'x-component': 'FormCollapse',
146 |       'x-component-props': {
147 |         formCollapse: '{{formCollapse}}',
148 |       },
149 |       properties: {
150 |         panel1: {
151 |           type: 'void',
152 |           'x-component': 'FormCollapse.CollapsePanel',
153 |           'x-component-props': {
154 |             header: 'A1',
155 |           },
156 |           properties: {
157 |             aaa: {
158 |               type: 'string',
159 |               title: 'AAA',
160 |               'x-decorator': 'FormItem',
161 |               required: true,
162 |               'x-component': 'Input',
163 |             },
164 |           },
165 |         },
166 |         panel2: {
167 |           type: 'void',
168 |           'x-component': 'FormCollapse.CollapsePanel',
169 |           'x-component-props': {
170 |             header: 'A2',
171 |           },
172 |           properties: {
173 |             bbb: {
174 |               type: 'string',
175 |               title: 'BBB',
176 |               'x-decorator': 'FormItem',
177 |               required: true,
178 |               'x-component': 'Input',
179 |             },
180 |           },
181 |         },
182 |         panel3: {
183 |           type: 'void',
184 |           'x-component': 'FormCollapse.CollapsePanel',
185 |           'x-component-props': {
186 |             header: 'A3',
187 |           },
188 |           properties: {
189 |             ccc: {
190 |               type: 'string',
191 |               title: 'CCC',
192 |               'x-decorator': 'FormItem',
193 |               required: true,
194 |               'x-component': 'Input',
195 |             },
196 |           },
197 |         },
198 |       },
199 |     },
200 |   },
201 | }
202 | 
203 | export default () => {
204 |   return (
205 |     <FormProvider form={form}>
206 |       <FormLayout labelCol={6} wrapperCol={10}>
207 |         <SchemaField schema={schema} scope={{ formCollapse }} />
208 |         <FormButtonGroup.FormItem>
209 |           <Button
210 |             onClick={() => {
211 |               form.query('panel3').take((field) => {
212 |                 field.visible = !field.visible
213 |               })
214 |             }}
215 |           >
216 |             Show/hide the last tab
217 |           </Button>
218 |           <Button
219 |             onClick={() => {
220 |               formCollapse.toggleActiveKey('panel2')
221 |             }}
222 |           >
223 |             Switch to the second Tab
224 |           </Button>
225 |           <Submit onSubmit={console.log}>Submit</Submit>
226 |         </FormButtonGroup.FormItem>
227 |       </FormLayout>
228 |     </FormProvider>
229 |   )
230 | }
231 | ```
232 | 
233 | ## API
234 | 
235 | ### FormCollapse
236 | 
237 | | Property name | Type          | Description                                                     | Default value |
238 | | ------------- | ------------- | --------------------------------------------------------------- | ------------- |
239 | | formCollapse  | IFormCollapse | Pass in the model created by createFormCollapse/useFormCollapse |               |
240 | 
241 | Other references https://ant.design/components/collapse-cn/
242 | 
243 | ### FormCollapse.CollapsePanel
244 | 
245 | Reference https://ant.design/components/collapse-cn/
246 | 
247 | ### FormCollapse.createFormCollapse
248 | 
249 | ```ts pure
250 | type ActiveKey = string | number
251 | type ActiveKeys = string | number | Array<string | number>
252 | 
253 | interface createFormCollapse {
254 |   (defaultActiveKeys?: ActiveKeys): IFormCollpase
255 | }
256 | 
257 | interface IFormCollapse {
258 |   //Activate the primary key list
259 |   activeKeys: ActiveKeys
260 |   //Does the activation key exist?
261 |   hasActiveKey(key: ActiveKey): boolean
262 |   //Set the list of active primary keys
263 |   setActiveKeys(keys: ActiveKeys): void
264 |   //Add activation key
265 |   addActiveKey(key: ActiveKey): void
266 |   //Delete the active primary key
267 |   removeActiveKey(key: ActiveKey): void
268 |   //Switch to activate the main key
269 |   toggleActiveKey(key: ActiveKey): void
270 | }
271 | ```
272 | 
```

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

```markdown
  1 | # FormCollapse
  2 | 
  3 | > Folding panel, usually used in form scenes with high layout space requirements
  4 | >
  5 | > Note: Can only be used in Schema scenarios
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormCollapse,
 13 |   FormItem,
 14 |   Input,
 15 |   FormButtonGroup,
 16 |   Submit,
 17 |   FormLayout,
 18 | } from '@formily/next'
 19 | import { createForm } from '@formily/core'
 20 | import { FormProvider, createSchemaField } from '@formily/react'
 21 | import { Button } from '@alifd/next'
 22 | 
 23 | const SchemaField = createSchemaField({
 24 |   components: {
 25 |     FormItem,
 26 |     FormCollapse,
 27 |     Input,
 28 |   },
 29 | })
 30 | 
 31 | const form = createForm()
 32 | const formCollapse = FormCollapse.createFormCollapse()
 33 | 
 34 | export default () => {
 35 |   return (
 36 |     <FormProvider form={form}>
 37 |       <FormLayout labelCol={6} wrapperCol={10}>
 38 |         <SchemaField>
 39 |           <SchemaField.Void
 40 |             title="Folding Panel"
 41 |             x-decorator="FormItem"
 42 |             x-component="FormCollapse"
 43 |             x-component-props={{
 44 |               formCollapse,
 45 |             }}
 46 |           >
 47 |             <SchemaField.Void
 48 |               name="panel1"
 49 |               x-component="FormCollapse.CollapsePanel"
 50 |               x-component-props={{ title: 'A1' }}
 51 |             >
 52 |               <SchemaField.String
 53 |                 name="aaa"
 54 |                 title="AAA"
 55 |                 x-decorator="FormItem"
 56 |                 required
 57 |                 x-component="Input"
 58 |               />
 59 |             </SchemaField.Void>
 60 |             <SchemaField.Void
 61 |               name="panel2"
 62 |               x-component="FormCollapse.CollapsePanel"
 63 |               x-component-props={{ title: 'A2' }}
 64 |             >
 65 |               <SchemaField.String
 66 |                 name="bbb"
 67 |                 title="BBB"
 68 |                 x-decorator="FormItem"
 69 |                 required
 70 |                 x-component="Input"
 71 |               />
 72 |             </SchemaField.Void>
 73 |             <SchemaField.Void
 74 |               name="panel3"
 75 |               x-component="FormCollapse.CollapsePanel"
 76 |               x-component-props={{ title: 'A3' }}
 77 |             >
 78 |               <SchemaField.String
 79 |                 name="ccc"
 80 |                 title="CCC"
 81 |                 x-decorator="FormItem"
 82 |                 required
 83 |                 x-component="Input"
 84 |               />
 85 |             </SchemaField.Void>
 86 |           </SchemaField.Void>
 87 |         </SchemaField>
 88 |         <FormButtonGroup.FormItem>
 89 |           <Button
 90 |             onClick={() => {
 91 |               form.query('panel3').take((field) => {
 92 |                 field.visible = !field.visible
 93 |               })
 94 |             }}
 95 |           >
 96 |             Show/hide the last tab
 97 |           </Button>
 98 |           <Button
 99 |             onClick={() => {
100 |               formCollapse.toggleActiveKey('panel2')
101 |             }}
102 |           >
103 |             Switch to the second Tab
104 |           </Button>
105 |           <Submit onSubmit={console.log}>Submit</Submit>
106 |         </FormButtonGroup.FormItem>
107 |       </FormLayout>
108 |     </FormProvider>
109 |   )
110 | }
111 | ```
112 | 
113 | ## JSON Schema case
114 | 
115 | ```tsx
116 | import React from 'react'
117 | import {
118 |   FormCollapse,
119 |   FormItem,
120 |   Input,
121 |   FormButtonGroup,
122 |   Submit,
123 |   FormLayout,
124 | } from '@formily/next'
125 | import { createForm } from '@formily/core'
126 | import { FormProvider, createSchemaField } from '@formily/react'
127 | import { Button } from '@alifd/next'
128 | 
129 | const SchemaField = createSchemaField({
130 |   components: {
131 |     FormItem,
132 |     FormCollapse,
133 |     Input,
134 |   },
135 | })
136 | 
137 | const form = createForm()
138 | const formCollapse = FormCollapse.createFormCollapse()
139 | 
140 | const schema = {
141 |   type: 'object',
142 |   properties: {
143 |     collapse: {
144 |       type: 'void',
145 |       title: 'Folding Panel',
146 |       'x-decorator': 'FormItem',
147 |       'x-component': 'FormCollapse',
148 |       'x-component-props': {
149 |         formCollapse: '{{formCollapse}}',
150 |       },
151 |       properties: {
152 |         panel1: {
153 |           type: 'void',
154 |           'x-component': 'FormCollapse.CollapsePanel',
155 |           'x-component-props': {
156 |             title: 'A1',
157 |           },
158 |           properties: {
159 |             aaa: {
160 |               type: 'string',
161 |               title: 'AAA',
162 |               'x-decorator': 'FormItem',
163 |               required: true,
164 |               'x-component': 'Input',
165 |             },
166 |           },
167 |         },
168 |         panel2: {
169 |           type: 'void',
170 |           'x-component': 'FormCollapse.CollapsePanel',
171 |           'x-component-props': {
172 |             title: 'A2',
173 |           },
174 |           properties: {
175 |             bbb: {
176 |               type: 'string',
177 |               title: 'BBB',
178 |               'x-decorator': 'FormItem',
179 |               required: true,
180 |               'x-component': 'Input',
181 |             },
182 |           },
183 |         },
184 |         panel3: {
185 |           type: 'void',
186 |           'x-component': 'FormCollapse.CollapsePanel',
187 |           'x-component-props': {
188 |             title: 'A3',
189 |           },
190 |           properties: {
191 |             ccc: {
192 |               type: 'string',
193 |               title: 'CCC',
194 |               'x-decorator': 'FormItem',
195 |               required: true,
196 |               'x-component': 'Input',
197 |             },
198 |           },
199 |         },
200 |       },
201 |     },
202 |   },
203 | }
204 | 
205 | export default () => {
206 |   return (
207 |     <FormProvider form={form}>
208 |       <FormLayout labelCol={6} wrapperCol={10}>
209 |         <SchemaField schema={schema} scope={{ formCollapse }} />
210 |         <FormButtonGroup.FormItem>
211 |           <Button
212 |             onClick={() => {
213 |               form.query('panel3').take((field) => {
214 |                 field.visible = !field.visible
215 |               })
216 |             }}
217 |           >
218 |             Show/hide the last tab
219 |           </Button>
220 |           <Button
221 |             onClick={() => {
222 |               formCollapse.toggleActiveKey('panel2')
223 |             }}
224 |           >
225 |             Switch to the second Tab
226 |           </Button>
227 |           <Submit onSubmit={console.log}>Submit</Submit>
228 |         </FormButtonGroup.FormItem>
229 |       </FormLayout>
230 |     </FormProvider>
231 |   )
232 | }
233 | ```
234 | 
235 | ## API
236 | 
237 | ### FormCollapse
238 | 
239 | | Property name | Type          | Description                                                     | Default value |
240 | | ------------- | ------------- | --------------------------------------------------------------- | ------------- |
241 | | formCollapse  | IFormCollapse | Pass in the model created by createFormCollapse/useFormCollapse |               |
242 | 
243 | Other references https://fusion.design/pc/component/basic/collapse
244 | 
245 | ### FormCollapse.CollapsePanel
246 | 
247 | Reference https://fusion.design/pc/component/basic/collapse
248 | 
249 | ### FormCollapse.createFormCollapse
250 | 
251 | ```ts pure
252 | type ActiveKey = string | number
253 | type ActiveKeys = string | number | Array<string | number>
254 | 
255 | interface createFormCollapse {
256 |   (defaultActiveKeys?: ActiveKeys): IFormCollpase
257 | }
258 | 
259 | interface IFormCollapse {
260 |   //Activate the primary key list
261 |   activeKeys: ActiveKeys
262 |   //Does the activation key exist?
263 |   hasActiveKey(key: ActiveKey): boolean
264 |   //Set the list of active primary keys
265 |   setActiveKeys(keys: ActiveKeys): void
266 |   //Add activation key
267 |   addActiveKey(key: ActiveKey): void
268 |   //Delete the active primary key
269 |   removeActiveKey(key: ActiveKey): void
270 |   //Switch to activate the main key
271 |   toggleActiveKey(key: ActiveKey): void
272 | }
273 | ```
274 | 
```

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

```markdown
  1 | # FormLayout
  2 | 
  3 | > 区块级布局批量控制组件,借助该组件,我们可以轻松的控制被 FormLayout 圈住的所有 FormItem 组件的布局模式
  4 | 
  5 | ## Markup Schema 案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { Input, Select, 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 |     Input,
 16 |     Select,
 17 |     FormItem,
 18 |     FormLayout,
 19 |   },
 20 | })
 21 | 
 22 | const form = createForm()
 23 | 
 24 | export default () => (
 25 |   <FormProvider form={form}>
 26 |     <SchemaField>
 27 |       <SchemaField.Void
 28 |         x-component="FormLayout"
 29 |         x-component-props={{
 30 |           labelCol: 6,
 31 |           wrapperCol: 10,
 32 |         }}
 33 |       >
 34 |         <SchemaField.String
 35 |           name="input"
 36 |           title="输入框"
 37 |           x-decorator="FormItem"
 38 |           x-decorator-props={{
 39 |             tooltip: <div>123</div>,
 40 |           }}
 41 |           x-component="Input"
 42 |           required
 43 |         />
 44 |         <SchemaField.String
 45 |           name="select"
 46 |           title="选择框"
 47 |           x-decorator="FormItem"
 48 |           x-component="Select"
 49 |           required
 50 |         />
 51 |       </SchemaField.Void>
 52 |     </SchemaField>
 53 |   </FormProvider>
 54 | )
 55 | ```
 56 | 
 57 | ## JSON Schema 案例
 58 | 
 59 | ```tsx
 60 | import React from 'react'
 61 | import { Input, Select, FormItem, FormLayout } from '@formily/next'
 62 | import { createForm } from '@formily/core'
 63 | import { FormProvider, createSchemaField } from '@formily/react'
 64 | 
 65 | const SchemaField = createSchemaField({
 66 |   components: {
 67 |     Input,
 68 |     Select,
 69 |     FormItem,
 70 |     FormLayout,
 71 |   },
 72 | })
 73 | 
 74 | const schema = {
 75 |   type: 'object',
 76 |   properties: {
 77 |     layout: {
 78 |       type: 'void',
 79 |       'x-component': 'FormLayout',
 80 |       'x-component-props': {
 81 |         labelCol: 6,
 82 |         wrapperCol: 10,
 83 |         layout: 'vertical',
 84 |       },
 85 |       properties: {
 86 |         input: {
 87 |           type: 'string',
 88 |           title: '输入框',
 89 |           required: true,
 90 |           'x-decorator': 'FormItem',
 91 |           'x-decorator-props': {
 92 |             tooltip: <div>123</div>,
 93 |           },
 94 |           'x-component': 'Input',
 95 |         },
 96 |         select: {
 97 |           type: 'string',
 98 |           title: '选择框',
 99 |           required: true,
100 |           'x-decorator': 'FormItem',
101 |           'x-component': 'Select',
102 |         },
103 |       },
104 |     },
105 |   },
106 | }
107 | 
108 | const form = createForm()
109 | 
110 | export default () => (
111 |   <FormProvider form={form}>
112 |     <SchemaField schema={schema} />
113 |   </FormProvider>
114 | )
115 | ```
116 | 
117 | ## 纯 JSX 案例
118 | 
119 | ```tsx
120 | import React from 'react'
121 | import {
122 |   Input,
123 |   Select,
124 |   FormItem,
125 |   FormButtonGroup,
126 |   Submit,
127 |   FormLayout,
128 | } from '@formily/next'
129 | import { createForm } from '@formily/core'
130 | import { FormProvider, Field } from '@formily/react'
131 | 
132 | const form = createForm()
133 | 
134 | export default () => (
135 |   <FormProvider form={form}>
136 |     <FormLayout
137 |       breakpoints={[680]}
138 |       layout={['vertical', 'horizontal']}
139 |       labelAlign={['left', 'right']}
140 |       labelCol={[24, 6]}
141 |       wrapperCol={[24, 10]}
142 |     >
143 |       <Field
144 |         name="input"
145 |         required
146 |         title="输入框"
147 |         decorator={[FormItem]}
148 |         component={[Input]}
149 |       />
150 |       <Field
151 |         name="select"
152 |         required
153 |         title="选择框"
154 |         decorator={[FormItem]}
155 |         component={[Select]}
156 |       />
157 |       <FormButtonGroup.FormItem>
158 |         <Submit onSubmit={console.log}>提交</Submit>
159 |       </FormButtonGroup.FormItem>
160 |     </FormLayout>
161 |   </FormProvider>
162 | )
163 | ```
164 | 
165 | ## API
166 | 
167 | | 属性名         | 类型                                                                                  | 描述                    | 默认值     |
168 | | -------------- | ------------------------------------------------------------------------------------- | ----------------------- | ---------- |
169 | | style          | CSSProperties                                                                         | 样式                    | -          |
170 | | className      | string                                                                                | 类名                    | -          |
171 | | colon          | boolean                                                                               | 是否有冒号              | true       |
172 | | labelAlign     | `'right' \| 'left' \| ('right' \| 'left')[]`                                          | 标签内容对齐            | -          |
173 | | wrapperAlign   | `'right' \| 'left' \| ('right' \| 'left')[]`                                          | 组件容器内容对齐        | -          |
174 | | labelWrap      | boolean                                                                               | 标签内容换行            | false      |
175 | | labelWidth     | number                                                                                | 标签宽度(px)            | -          |
176 | | wrapperWidth   | number                                                                                | 组件容器宽度(px)        | -          |
177 | | wrapperWrap    | boolean                                                                               | 组件容器换行            | false      |
178 | | labelCol       | `number \| number[]`                                                                  | 标签宽度(24 column)     | -          |
179 | | wrapperCol     | `number \| number[]`                                                                  | 组件容器宽度(24 column) | -          |
180 | | fullness       | boolean                                                                               | 组件容器宽度 100%       | false      |
181 | | size           | `'small' \| 'default' \| 'large'`                                                     | 组件尺寸                | default    |
182 | | layout         | `'vertical' \| 'horizontal' \| 'inline' \|('vertical' \| 'horizontal' \| 'inline')[]` | 布局模式                | horizontal |
183 | | direction      | `'rtl' \| 'ltr'`                                                                      | 方向(暂不支持)          | ltr        |
184 | | inset          | boolean                                                                               | 内联布局                | false      |
185 | | shallow        | boolean                                                                               | 上下文浅层传递          | true       |
186 | | feedbackLayout | `'loose' \| 'terse' \| 'popover' \| 'none'`                                           | 反馈布局                | true       |
187 | | tooltipLayout  | `"icon" \| "text"`                                                                    | 问号提示布局            | `"icon"`   |
188 | | tooltipIcon    | ReactNode                                                                             | 问号提示图标            | -          |
189 | | bordered       | boolean                                                                               | 是否有边框              | true       |
190 | | breakpoints    | number[]                                                                              | 容器尺寸断点            | -          |
191 | | gridColumnGap  | number                                                                                | 网格布局列间距          | 8          |
192 | | gridRowGap     | number                                                                                | 网格布局行间距          | 4          |
193 | | spaceGap       | number                                                                                | 弹性间距                | 8          |
194 | 
```

--------------------------------------------------------------------------------
/packages/element/src/array-cards/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 type { Card as CardProps } from 'element-ui'
  6 | import { Card, Empty, Row } from 'element-ui'
  7 | import { defineComponent } from 'vue-demi'
  8 | import { ArrayBase } from '../array-base'
  9 | import { stylePrefix } from '../__builtins__/configs'
 10 | import { composeExport } from '../__builtins__/shared'
 11 | 
 12 | const isAdditionComponent = (schema: ISchema) => {
 13 |   return schema['x-component']?.indexOf?.('Addition') > -1
 14 | }
 15 | 
 16 | const isIndexComponent = (schema: ISchema) => {
 17 |   return schema['x-component']?.indexOf?.('Index') > -1
 18 | }
 19 | 
 20 | const isRemoveComponent = (schema: ISchema) => {
 21 |   return schema['x-component']?.indexOf?.('Remove') > -1
 22 | }
 23 | 
 24 | const isMoveUpComponent = (schema: ISchema) => {
 25 |   return schema['x-component']?.indexOf?.('MoveUp') > -1
 26 | }
 27 | 
 28 | const isMoveDownComponent = (schema: ISchema) => {
 29 |   return schema['x-component']?.indexOf?.('MoveDown') > -1
 30 | }
 31 | 
 32 | const isOperationComponent = (schema: ISchema) => {
 33 |   return (
 34 |     isAdditionComponent(schema) ||
 35 |     isRemoveComponent(schema) ||
 36 |     isMoveDownComponent(schema) ||
 37 |     isMoveUpComponent(schema)
 38 |   )
 39 | }
 40 | const ArrayCardsInner = observer(
 41 |   defineComponent<CardProps>({
 42 |     name: 'FArrayCards',
 43 |     props: [],
 44 |     setup(props, { attrs }) {
 45 |       const fieldRef = useField<ArrayField>()
 46 |       const schemaRef = useFieldSchema()
 47 |       const prefixCls = `${stylePrefix}-array-cards`
 48 |       const { getKey, keyMap } = ArrayBase.useKey(schemaRef.value)
 49 | 
 50 |       return () => {
 51 |         const field = fieldRef.value
 52 |         const schema = schemaRef.value
 53 |         const dataSource = Array.isArray(field.value) ? field.value : []
 54 |         if (!schema) throw new Error('can not found schema object')
 55 | 
 56 |         const renderItems = () => {
 57 |           return dataSource?.map((item, index) => {
 58 |             const items = Array.isArray(schema.items)
 59 |               ? schema.items[index] || schema.items[0]
 60 |               : schema.items
 61 | 
 62 |             const title = h(
 63 |               'span',
 64 |               {},
 65 |               {
 66 |                 default: () => [
 67 |                   h(
 68 |                     RecursionField,
 69 |                     {
 70 |                       props: {
 71 |                         schema: items,
 72 |                         name: index,
 73 |                         filterProperties: (schema) => {
 74 |                           if (!isIndexComponent(schema)) return false
 75 |                           return true
 76 |                         },
 77 |                         onlyRenderProperties: true,
 78 |                       },
 79 |                     },
 80 |                     {}
 81 |                   ),
 82 |                   attrs.title || field.title,
 83 |                 ],
 84 |               }
 85 |             )
 86 |             const extra = h(
 87 |               'span',
 88 |               {},
 89 |               {
 90 |                 default: () => [
 91 |                   h(
 92 |                     RecursionField,
 93 |                     {
 94 |                       props: {
 95 |                         schema: items,
 96 |                         name: index,
 97 |                         filterProperties: (schema) => {
 98 |                           if (!isOperationComponent(schema)) return false
 99 |                           return true
100 |                         },
101 |                         onlyRenderProperties: true,
102 |                       },
103 |                     },
104 |                     {}
105 |                   ),
106 |                   attrs.extra,
107 |                 ],
108 |               }
109 |             )
110 |             const content = h(
111 |               RecursionField,
112 |               {
113 |                 props: {
114 |                   schema: items,
115 |                   name: index,
116 |                   filterProperties: (schema) => {
117 |                     if (isIndexComponent(schema)) return false
118 |                     if (isOperationComponent(schema)) return false
119 |                     return true
120 |                   },
121 |                 },
122 |               },
123 |               {}
124 |             )
125 | 
126 |             return h(
127 |               ArrayBase.Item,
128 |               {
129 |                 key: getKey(item, index),
130 |                 props: {
131 |                   index,
132 |                   record: item,
133 |                 },
134 |               },
135 |               {
136 |                 default: () =>
137 |                   h(
138 |                     Card,
139 |                     {
140 |                       class: [`${prefixCls}-item`],
141 |                       attrs: {
142 |                         shadow: 'never',
143 |                         ...attrs,
144 |                       },
145 |                     },
146 |                     {
147 |                       default: () => [content],
148 |                       header: () =>
149 |                         h(
150 |                           Row,
151 |                           {
152 |                             props: {
153 |                               type: 'flex',
154 |                               justify: 'space-between',
155 |                             },
156 |                           },
157 |                           {
158 |                             default: () => [title, extra],
159 |                           }
160 |                         ),
161 |                     }
162 |                   ),
163 |               }
164 |             )
165 |           })
166 |         }
167 |         const renderAddition = () => {
168 |           return schema.reduceProperties((addition, schema) => {
169 |             if (isAdditionComponent(schema)) {
170 |               return h(
171 |                 RecursionField,
172 |                 {
173 |                   props: {
174 |                     schema,
175 |                     name: 'addition',
176 |                   },
177 |                 },
178 |                 {}
179 |               )
180 |             }
181 |             return addition
182 |           }, null)
183 |         }
184 |         const renderEmpty = () => {
185 |           if (dataSource?.length) return
186 |           return h(
187 |             Card,
188 |             {
189 |               class: [`${prefixCls}-item`],
190 |               attrs: {
191 |                 shadow: 'never',
192 |                 ...attrs,
193 |                 header: attrs.title || field.title,
194 |               },
195 |             },
196 |             {
197 |               default: () =>
198 |                 h(
199 |                   Empty,
200 |                   { props: { description: 'No Data', imageSize: 100 } },
201 |                   {}
202 |                 ),
203 |             }
204 |           )
205 |         }
206 | 
207 |         return h(
208 |           'div',
209 |           {
210 |             class: [prefixCls],
211 |           },
212 |           {
213 |             default: () =>
214 |               h(
215 |                 ArrayBase,
216 |                 {
217 |                   props: {
218 |                     keyMap,
219 |                   },
220 |                 },
221 |                 {
222 |                   default: () => [
223 |                     renderEmpty(),
224 |                     renderItems(),
225 |                     renderAddition(),
226 |                   ],
227 |                 }
228 |               ),
229 |           }
230 |         )
231 |       }
232 |     },
233 |   })
234 | )
235 | 
236 | export const ArrayCards = composeExport(ArrayCardsInner, {
237 |   Index: ArrayBase.Index,
238 |   SortHandle: ArrayBase.SortHandle,
239 |   Addition: ArrayBase.Addition,
240 |   Remove: ArrayBase.Remove,
241 |   MoveDown: ArrayBase.MoveDown,
242 |   MoveUp: ArrayBase.MoveUp,
243 |   useArray: ArrayBase.useArray,
244 |   useIndex: ArrayBase.useIndex,
245 |   useRecord: ArrayBase.useRecord,
246 | })
247 | 
248 | export default ArrayCards
249 | 
```

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

```markdown
  1 | # FormButtonGroup
  2 | 
  3 | > 表单按钮组布局组件
  4 | 
  5 | ## 普通案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   FormButtonGroup,
 11 |   Submit,
 12 |   Reset,
 13 |   FormItem,
 14 |   Input,
 15 |   FormLayout,
 16 | } from '@formily/antd'
 17 | import { createForm } from '@formily/core'
 18 | import { FormProvider, createSchemaField } from '@formily/react'
 19 | const SchemaField = createSchemaField({
 20 |   components: {
 21 |     FormItem,
 22 |     Input,
 23 |   },
 24 | })
 25 | 
 26 | const form = createForm()
 27 | 
 28 | export default () => {
 29 |   return (
 30 |     <FormProvider form={form}>
 31 |       <FormLayout labelCol={6} wrapperCol={10}>
 32 |         <SchemaField>
 33 |           <SchemaField.String
 34 |             title="输入框"
 35 |             x-decorator="FormItem"
 36 |             required
 37 |             x-component="Input"
 38 |           />
 39 |           <SchemaField.String
 40 |             title="输入框"
 41 |             x-decorator="FormItem"
 42 |             required
 43 |             x-component="Input"
 44 |           />
 45 |           <SchemaField.String
 46 |             title="输入框"
 47 |             x-decorator="FormItem"
 48 |             required
 49 |             x-component="Input"
 50 |           />
 51 |           <SchemaField.String
 52 |             title="输入框"
 53 |             x-decorator="FormItem"
 54 |             required
 55 |             x-component="Input"
 56 |           />
 57 |           <SchemaField.String
 58 |             title="输入框"
 59 |             x-decorator="FormItem"
 60 |             required
 61 |             x-component="Input"
 62 |           />
 63 |           <SchemaField.String
 64 |             title="输入框"
 65 |             x-decorator="FormItem"
 66 |             required
 67 |             x-component="Input"
 68 |           />
 69 |           <SchemaField.String
 70 |             title="输入框"
 71 |             x-decorator="FormItem"
 72 |             required
 73 |             x-component="Input"
 74 |           />
 75 |           <SchemaField.String
 76 |             title="输入框"
 77 |             x-decorator="FormItem"
 78 |             required
 79 |             x-component="Input"
 80 |           />
 81 |           <SchemaField.String
 82 |             title="输入框"
 83 |             x-decorator="FormItem"
 84 |             required
 85 |             x-component="Input"
 86 |           />
 87 |         </SchemaField>
 88 |         <FormButtonGroup.FormItem>
 89 |           <Submit onSubmit={console.log}>提交</Submit>
 90 |           <Reset>重置</Reset>
 91 |         </FormButtonGroup.FormItem>
 92 |       </FormLayout>
 93 |     </FormProvider>
 94 |   )
 95 | }
 96 | ```
 97 | 
 98 | ## 吸底案例
 99 | 
100 | ```tsx
101 | import React from 'react'
102 | import {
103 |   FormButtonGroup,
104 |   Submit,
105 |   Reset,
106 |   FormItem,
107 |   FormLayout,
108 |   Input,
109 | } from '@formily/antd'
110 | import { createForm } from '@formily/core'
111 | import { FormProvider, createSchemaField } from '@formily/react'
112 | 
113 | const SchemaField = createSchemaField({
114 |   components: {
115 |     FormItem,
116 |     Input,
117 |   },
118 | })
119 | 
120 | const form = createForm()
121 | 
122 | export default () => {
123 |   return (
124 |     <FormProvider form={form}>
125 |       <FormLayout labelCol={6} wrapperCol={10}>
126 |         <SchemaField>
127 |           <SchemaField.String
128 |             title="输入框"
129 |             x-decorator="FormItem"
130 |             required
131 |             x-component="Input"
132 |           />
133 |           <SchemaField.String
134 |             title="输入框"
135 |             x-decorator="FormItem"
136 |             required
137 |             x-component="Input"
138 |           />
139 |           <SchemaField.String
140 |             title="输入框"
141 |             x-decorator="FormItem"
142 |             required
143 |             x-component="Input"
144 |           />
145 |           <SchemaField.String
146 |             title="输入框"
147 |             x-decorator="FormItem"
148 |             required
149 |             x-component="Input"
150 |           />
151 |           <SchemaField.String
152 |             title="输入框"
153 |             x-decorator="FormItem"
154 |             required
155 |             x-component="Input"
156 |           />
157 |           <SchemaField.String
158 |             title="输入框"
159 |             x-decorator="FormItem"
160 |             required
161 |             x-component="Input"
162 |           />
163 |           <SchemaField.String
164 |             title="输入框"
165 |             x-decorator="FormItem"
166 |             required
167 |             x-component="Input"
168 |           />
169 |           <SchemaField.String
170 |             title="输入框"
171 |             x-decorator="FormItem"
172 |             required
173 |             x-component="Input"
174 |           />
175 |           <SchemaField.String
176 |             title="输入框"
177 |             x-decorator="FormItem"
178 |             required
179 |             x-component="Input"
180 |           />
181 |         </SchemaField>
182 |         <FormButtonGroup.Sticky>
183 |           <FormButtonGroup.FormItem>
184 |             <Submit onSubmit={console.log}>提交</Submit>
185 |             <Reset>重置</Reset>
186 |           </FormButtonGroup.FormItem>
187 |         </FormButtonGroup.Sticky>
188 |       </FormLayout>
189 |     </FormProvider>
190 |   )
191 | }
192 | ```
193 | 
194 | ## 吸底居中案例
195 | 
196 | ```tsx
197 | import React from 'react'
198 | import {
199 |   FormButtonGroup,
200 |   Submit,
201 |   Reset,
202 |   FormItem,
203 |   FormLayout,
204 |   Input,
205 | } from '@formily/antd'
206 | import { createForm } from '@formily/core'
207 | import { FormProvider, createSchemaField } from '@formily/react'
208 | 
209 | const SchemaField = createSchemaField({
210 |   components: {
211 |     FormItem,
212 |     Input,
213 |   },
214 | })
215 | 
216 | const form = createForm()
217 | 
218 | export default () => {
219 |   return (
220 |     <FormProvider form={form}>
221 |       <FormLayout labelCol={6} wrapperCol={10}>
222 |         <SchemaField>
223 |           <SchemaField.String
224 |             title="输入框"
225 |             x-decorator="FormItem"
226 |             required
227 |             x-component="Input"
228 |           />
229 |           <SchemaField.String
230 |             title="输入框"
231 |             x-decorator="FormItem"
232 |             required
233 |             x-component="Input"
234 |           />
235 |           <SchemaField.String
236 |             title="输入框"
237 |             x-decorator="FormItem"
238 |             required
239 |             x-component="Input"
240 |           />
241 |           <SchemaField.String
242 |             title="输入框"
243 |             x-decorator="FormItem"
244 |             required
245 |             x-component="Input"
246 |           />
247 |           <SchemaField.String
248 |             title="输入框"
249 |             x-decorator="FormItem"
250 |             required
251 |             x-component="Input"
252 |           />
253 |           <SchemaField.String
254 |             title="输入框"
255 |             x-decorator="FormItem"
256 |             required
257 |             x-component="Input"
258 |           />
259 |           <SchemaField.String
260 |             title="输入框"
261 |             x-decorator="FormItem"
262 |             required
263 |             x-component="Input"
264 |           />
265 |           <SchemaField.String
266 |             title="输入框"
267 |             x-decorator="FormItem"
268 |             required
269 |             x-component="Input"
270 |           />
271 |           <SchemaField.String
272 |             title="输入框"
273 |             x-decorator="FormItem"
274 |             required
275 |             x-component="Input"
276 |           />
277 |         </SchemaField>
278 |         <FormButtonGroup.Sticky align="center">
279 |           <FormButtonGroup>
280 |             <Submit onSubmit={console.log}>提交</Submit>
281 |             <Reset>重置</Reset>
282 |           </FormButtonGroup>
283 |         </FormButtonGroup.Sticky>
284 |       </FormLayout>
285 |     </FormProvider>
286 |   )
287 | }
288 | ```
289 | 
290 | ## API
291 | 
292 | ### FormButtonGroup
293 | 
294 | > 该组件主要用来处理按钮组间隙
295 | 
296 | | 属性名 | 类型                        | 描述     | 默认值   |
297 | | ------ | --------------------------- | -------- | -------- |
298 | | gutter | number                      | 间隙大小 | 8px      |
299 | | align  | `'left'\|'center'\|'right'` | 对齐方式 | `'left'` |
300 | 
301 | ### FormButtonGroup.FormItem
302 | 
303 | > 该组件主要用来处理按钮组与主表单 FormItem 对齐问题
304 | 
305 | 参考 [FormItem](/components/form-item) 属性
306 | 
307 | ### FormButtonGroup.Sticky
308 | 
309 | > 该组件主要用来处理按钮组浮动定位问题
310 | 
311 | | 属性名 | 类型                        | 描述     | 默认值   |
312 | | ------ | --------------------------- | -------- | -------- |
313 | | align  | `'left'\|'center'\|'right'` | 对齐方式 | `'left'` |
314 | 
```

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

```markdown
  1 | # FormButtonGroup
  2 | 
  3 | > 表单按钮组布局组件
  4 | 
  5 | ## 普通案例
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import {
 10 |   FormButtonGroup,
 11 |   Submit,
 12 |   Reset,
 13 |   FormItem,
 14 |   Input,
 15 |   FormLayout,
 16 | } from '@formily/next'
 17 | import { createForm } from '@formily/core'
 18 | import { FormProvider, createSchemaField } from '@formily/react'
 19 | 
 20 | const SchemaField = createSchemaField({
 21 |   components: {
 22 |     FormItem,
 23 |     Input,
 24 |   },
 25 | })
 26 | 
 27 | const form = createForm()
 28 | 
 29 | export default () => {
 30 |   return (
 31 |     <FormProvider form={form}>
 32 |       <FormLayout labelCol={6} wrapperCol={10}>
 33 |         <SchemaField>
 34 |           <SchemaField.String
 35 |             title="输入框"
 36 |             x-decorator="FormItem"
 37 |             required
 38 |             x-component="Input"
 39 |           />
 40 |           <SchemaField.String
 41 |             title="输入框"
 42 |             x-decorator="FormItem"
 43 |             required
 44 |             x-component="Input"
 45 |           />
 46 |           <SchemaField.String
 47 |             title="输入框"
 48 |             x-decorator="FormItem"
 49 |             required
 50 |             x-component="Input"
 51 |           />
 52 |           <SchemaField.String
 53 |             title="输入框"
 54 |             x-decorator="FormItem"
 55 |             required
 56 |             x-component="Input"
 57 |           />
 58 |           <SchemaField.String
 59 |             title="输入框"
 60 |             x-decorator="FormItem"
 61 |             required
 62 |             x-component="Input"
 63 |           />
 64 |           <SchemaField.String
 65 |             title="输入框"
 66 |             x-decorator="FormItem"
 67 |             required
 68 |             x-component="Input"
 69 |           />
 70 |           <SchemaField.String
 71 |             title="输入框"
 72 |             x-decorator="FormItem"
 73 |             required
 74 |             x-component="Input"
 75 |           />
 76 |           <SchemaField.String
 77 |             title="输入框"
 78 |             x-decorator="FormItem"
 79 |             required
 80 |             x-component="Input"
 81 |           />
 82 |           <SchemaField.String
 83 |             title="输入框"
 84 |             x-decorator="FormItem"
 85 |             required
 86 |             x-component="Input"
 87 |           />
 88 |         </SchemaField>
 89 |         <FormButtonGroup.FormItem>
 90 |           <Submit onSubmit={console.log}>提交</Submit>
 91 |           <Reset>重置</Reset>
 92 |         </FormButtonGroup.FormItem>
 93 |       </FormLayout>
 94 |     </FormProvider>
 95 |   )
 96 | }
 97 | ```
 98 | 
 99 | ## 吸底案例
100 | 
101 | ```tsx
102 | import React from 'react'
103 | import {
104 |   FormButtonGroup,
105 |   Submit,
106 |   Reset,
107 |   FormItem,
108 |   FormLayout,
109 |   Input,
110 | } from '@formily/next'
111 | import { createForm } from '@formily/core'
112 | import { FormProvider, createSchemaField } from '@formily/react'
113 | 
114 | const SchemaField = createSchemaField({
115 |   components: {
116 |     FormItem,
117 |     Input,
118 |   },
119 | })
120 | 
121 | const form = createForm()
122 | 
123 | export default () => {
124 |   return (
125 |     <FormProvider form={form}>
126 |       <FormLayout labelCol={6} wrapperCol={10}>
127 |         <SchemaField>
128 |           <SchemaField.String
129 |             title="输入框"
130 |             x-decorator="FormItem"
131 |             required
132 |             x-component="Input"
133 |           />
134 |           <SchemaField.String
135 |             title="输入框"
136 |             x-decorator="FormItem"
137 |             required
138 |             x-component="Input"
139 |           />
140 |           <SchemaField.String
141 |             title="输入框"
142 |             x-decorator="FormItem"
143 |             required
144 |             x-component="Input"
145 |           />
146 |           <SchemaField.String
147 |             title="输入框"
148 |             x-decorator="FormItem"
149 |             required
150 |             x-component="Input"
151 |           />
152 |           <SchemaField.String
153 |             title="输入框"
154 |             x-decorator="FormItem"
155 |             required
156 |             x-component="Input"
157 |           />
158 |           <SchemaField.String
159 |             title="输入框"
160 |             x-decorator="FormItem"
161 |             required
162 |             x-component="Input"
163 |           />
164 |           <SchemaField.String
165 |             title="输入框"
166 |             x-decorator="FormItem"
167 |             required
168 |             x-component="Input"
169 |           />
170 |           <SchemaField.String
171 |             title="输入框"
172 |             x-decorator="FormItem"
173 |             required
174 |             x-component="Input"
175 |           />
176 |           <SchemaField.String
177 |             title="输入框"
178 |             x-decorator="FormItem"
179 |             required
180 |             x-component="Input"
181 |           />
182 |         </SchemaField>
183 |         <FormButtonGroup.Sticky>
184 |           <FormButtonGroup.FormItem>
185 |             <Submit onSubmit={console.log}>提交</Submit>
186 |             <Reset>重置</Reset>
187 |           </FormButtonGroup.FormItem>
188 |         </FormButtonGroup.Sticky>
189 |       </FormLayout>
190 |     </FormProvider>
191 |   )
192 | }
193 | ```
194 | 
195 | ## 吸底居中案例
196 | 
197 | ```tsx
198 | import React from 'react'
199 | import {
200 |   FormButtonGroup,
201 |   Submit,
202 |   Reset,
203 |   FormItem,
204 |   FormLayout,
205 |   Input,
206 | } from '@formily/next'
207 | import { createForm } from '@formily/core'
208 | import { FormProvider, createSchemaField } from '@formily/react'
209 | 
210 | const SchemaField = createSchemaField({
211 |   components: {
212 |     FormItem,
213 |     Input,
214 |   },
215 | })
216 | 
217 | const form = createForm()
218 | 
219 | export default () => {
220 |   return (
221 |     <FormProvider form={form}>
222 |       <FormLayout labelCol={6} wrapperCol={10}>
223 |         <SchemaField>
224 |           <SchemaField.String
225 |             title="输入框"
226 |             x-decorator="FormItem"
227 |             required
228 |             x-component="Input"
229 |           />
230 |           <SchemaField.String
231 |             title="输入框"
232 |             x-decorator="FormItem"
233 |             required
234 |             x-component="Input"
235 |           />
236 |           <SchemaField.String
237 |             title="输入框"
238 |             x-decorator="FormItem"
239 |             required
240 |             x-component="Input"
241 |           />
242 |           <SchemaField.String
243 |             title="输入框"
244 |             x-decorator="FormItem"
245 |             required
246 |             x-component="Input"
247 |           />
248 |           <SchemaField.String
249 |             title="输入框"
250 |             x-decorator="FormItem"
251 |             required
252 |             x-component="Input"
253 |           />
254 |           <SchemaField.String
255 |             title="输入框"
256 |             x-decorator="FormItem"
257 |             required
258 |             x-component="Input"
259 |           />
260 |           <SchemaField.String
261 |             title="输入框"
262 |             x-decorator="FormItem"
263 |             required
264 |             x-component="Input"
265 |           />
266 |           <SchemaField.String
267 |             title="输入框"
268 |             x-decorator="FormItem"
269 |             required
270 |             x-component="Input"
271 |           />
272 |           <SchemaField.String
273 |             title="输入框"
274 |             x-decorator="FormItem"
275 |             required
276 |             x-component="Input"
277 |           />
278 |         </SchemaField>
279 |         <FormButtonGroup.Sticky align="center">
280 |           <FormButtonGroup>
281 |             <Submit onSubmit={console.log}>提交</Submit>
282 |             <Reset>重置</Reset>
283 |           </FormButtonGroup>
284 |         </FormButtonGroup.Sticky>
285 |       </FormLayout>
286 |     </FormProvider>
287 |   )
288 | }
289 | ```
290 | 
291 | ## API
292 | 
293 | ### FormButtonGroup
294 | 
295 | > 该组件主要用来处理按钮组间隙
296 | 
297 | | 属性名 | 类型                        | 描述     | 默认值   |
298 | | ------ | --------------------------- | -------- | -------- |
299 | | gutter | number                      | 间隙大小 | 8px      |
300 | | align  | `'left'\|'center'\|'right'` | 对齐方式 | `'left'` |
301 | 
302 | ### FormButtonGroup.FormItem
303 | 
304 | > 该组件主要用来处理按钮组与主表单 FormItem 对齐问题
305 | 
306 | 参考 [FormItem](/components/form-item) 属性
307 | 
308 | ### FormButtonGroup.Sticky
309 | 
310 | > 该组件主要用来处理按钮组浮动定位问题
311 | 
312 | | 属性名 | 类型                        | 描述     | 默认值   |
313 | | ------ | --------------------------- | -------- | -------- |
314 | | align  | `'left'\|'center'\|'right'` | 对齐方式 | `'left'` |
315 | 
```

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

```typescript
  1 | import React from 'react'
  2 | import { Card } from '@alifd/next'
  3 | import { CardProps } from '@alifd/next/lib/card'
  4 | import { ArrayField } from '@formily/core'
  5 | import {
  6 |   useField,
  7 |   observer,
  8 |   useFieldSchema,
  9 |   RecursionField,
 10 | } from '@formily/react'
 11 | import { ISchema } from '@formily/json-schema'
 12 | import { usePrefixCls } from '../__builtins__'
 13 | import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from '../array-base'
 14 | import cls from 'classnames'
 15 | 
 16 | type ComposedArrayCards = React.FC<
 17 |   React.PropsWithChildren<CardProps & IArrayBaseProps>
 18 | > &
 19 |   ArrayBaseMixins
 20 | 
 21 | const isAdditionComponent = (schema: ISchema) => {
 22 |   return schema['x-component']?.indexOf?.('Addition') > -1
 23 | }
 24 | 
 25 | const isIndexComponent = (schema: ISchema) => {
 26 |   return schema['x-component']?.indexOf?.('Index') > -1
 27 | }
 28 | 
 29 | const isRemoveComponent = (schema: ISchema) => {
 30 |   return schema['x-component']?.indexOf?.('Remove') > -1
 31 | }
 32 | 
 33 | const isCopyComponent = (schema: ISchema) => {
 34 |   return schema['x-component']?.indexOf?.('Copy') > -1
 35 | }
 36 | 
 37 | const isMoveUpComponent = (schema: ISchema) => {
 38 |   return schema['x-component']?.indexOf?.('MoveUp') > -1
 39 | }
 40 | 
 41 | const isMoveDownComponent = (schema: ISchema) => {
 42 |   return schema['x-component']?.indexOf?.('MoveDown') > -1
 43 | }
 44 | 
 45 | const isOperationComponent = (schema: ISchema) => {
 46 |   return (
 47 |     isAdditionComponent(schema) ||
 48 |     isRemoveComponent(schema) ||
 49 |     isCopyComponent(schema) ||
 50 |     isMoveDownComponent(schema) ||
 51 |     isMoveUpComponent(schema)
 52 |   )
 53 | }
 54 | 
 55 | const Empty = () => {
 56 |   return (
 57 |     <div className="next-empty">
 58 |       <div className="next-empty-image">
 59 |         <svg
 60 |           className="ant-empty-img-default"
 61 |           width="184"
 62 |           height="152"
 63 |           viewBox="0 0 184 152"
 64 |           xmlns="http://www.w3.org/2000/svg"
 65 |         >
 66 |           <g fill="none" fillRule="evenodd">
 67 |             <g transform="translate(24 31.67)">
 68 |               <ellipse
 69 |                 className="ant-empty-img-default-ellipse"
 70 |                 cx="67.797"
 71 |                 cy="106.89"
 72 |                 rx="67.797"
 73 |                 ry="12.668"
 74 |               ></ellipse>
 75 |               <path
 76 |                 className="ant-empty-img-default-path-1"
 77 |                 d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
 78 |               ></path>
 79 |               <path
 80 |                 className="ant-empty-img-default-path-2"
 81 |                 d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
 82 |                 transform="translate(13.56)"
 83 |               ></path>
 84 |               <path
 85 |                 className="ant-empty-img-default-path-3"
 86 |                 d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
 87 |               ></path>
 88 |               <path
 89 |                 className="ant-empty-img-default-path-4"
 90 |                 d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
 91 |               ></path>
 92 |             </g>
 93 |             <path
 94 |               className="ant-empty-img-default-path-5"
 95 |               d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
 96 |             ></path>
 97 |             <g
 98 |               className="ant-empty-img-default-g"
 99 |               transform="translate(149.65 15.383)"
100 |             >
101 |               <ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse>
102 |               <path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path>
103 |             </g>
104 |           </g>
105 |         </svg>
106 |       </div>
107 |     </div>
108 |   )
109 | }
110 | 
111 | export const ArrayCards: ComposedArrayCards = observer((props) => {
112 |   const field = useField<ArrayField>()
113 |   const schema = useFieldSchema()
114 |   const dataSource = Array.isArray(field.value) ? field.value : []
115 |   const prefixCls = usePrefixCls('formily-array-cards', props)
116 |   const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp } = props
117 |   const renderItems = () => {
118 |     return dataSource?.map((item, index) => {
119 |       const items = Array.isArray(schema.items)
120 |         ? schema.items[index] || schema.items[0]
121 |         : schema.items
122 |       const title = (
123 |         <span>
124 |           <RecursionField
125 |             schema={items}
126 |             name={index}
127 |             filterProperties={(schema) => {
128 |               if (!isIndexComponent(schema)) return false
129 |               return true
130 |             }}
131 |             onlyRenderProperties
132 |           />
133 |           {props.title || field.title}
134 |         </span>
135 |       )
136 |       const extra = (
137 |         <span>
138 |           <RecursionField
139 |             schema={items}
140 |             name={index}
141 |             filterProperties={(schema) => {
142 |               if (!isOperationComponent(schema)) return false
143 |               return true
144 |             }}
145 |             onlyRenderProperties
146 |           />
147 |           {props.extra}
148 |         </span>
149 |       )
150 |       const content = (
151 |         <RecursionField
152 |           schema={items}
153 |           name={index}
154 |           filterProperties={(schema) => {
155 |             if (isIndexComponent(schema)) return false
156 |             if (isOperationComponent(schema)) return false
157 |             return true
158 |           }}
159 |         />
160 |       )
161 |       return (
162 |         <ArrayBase.Item
163 |           key={index}
164 |           index={index}
165 |           record={() => field.value?.[index]}
166 |         >
167 |           <Card
168 |             contentHeight="auto"
169 |             {...props}
170 |             onChange={() => {}}
171 |             className={cls(`${prefixCls}-item`, props.className)}
172 |             title={title}
173 |             extra={extra}
174 |           >
175 |             {content}
176 |           </Card>
177 |         </ArrayBase.Item>
178 |       )
179 |     })
180 |   }
181 | 
182 |   const renderAddition = () => {
183 |     return schema.reduceProperties((addition, schema, key) => {
184 |       if (isAdditionComponent(schema)) {
185 |         return <RecursionField schema={schema} name={key} />
186 |       }
187 |       return addition
188 |     }, null)
189 |   }
190 | 
191 |   const renderEmpty = () => {
192 |     if (dataSource?.length) return
193 |     return (
194 |       <Card
195 |         contentHeight="auto"
196 |         {...props}
197 |         className={cls(`${prefixCls}-item`, props.className)}
198 |         title={props.title || field.title}
199 |         onChange={() => {}}
200 |       >
201 |         <Empty />
202 |       </Card>
203 |     )
204 |   }
205 | 
206 |   return (
207 |     <ArrayBase
208 |       onAdd={onAdd}
209 |       onCopy={onCopy}
210 |       onRemove={onRemove}
211 |       onMoveUp={onMoveUp}
212 |       onMoveDown={onMoveDown}
213 |     >
214 |       {renderEmpty()}
215 |       {renderItems()}
216 |       {renderAddition()}
217 |     </ArrayBase>
218 |   )
219 | })
220 | 
221 | ArrayCards.displayName = 'ArrayCards'
222 | 
223 | ArrayBase.mixin(ArrayCards)
224 | 
225 | export default ArrayCards
226 | 
```

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

```markdown
  1 | # Editable
  2 | 
  3 | > Partial editor, you can use this component for some form areas with high space requirements
  4 | >
  5 | > Editable component is equivalent to a variant of FormItem component, so it is usually placed in decorator
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   Input,
 13 |   DatePicker,
 14 |   Editable,
 15 |   FormItem,
 16 |   FormButtonGroup,
 17 |   Submit,
 18 | } from '@formily/next'
 19 | import { createForm } from '@formily/core'
 20 | import { FormProvider, createSchemaField } from '@formily/react'
 21 | 
 22 | const SchemaField = createSchemaField({
 23 |   components: {
 24 |     DatePicker,
 25 |     Editable,
 26 |     Input,
 27 |     FormItem,
 28 |   },
 29 | })
 30 | 
 31 | const form = createForm()
 32 | 
 33 | export default () => (
 34 |   <FormProvider form={form}>
 35 |     <SchemaField>
 36 |       <SchemaField.String
 37 |         name="date"
 38 |         title="date"
 39 |         x-decorator="Editable"
 40 |         x-component="DatePicker"
 41 |       />
 42 |       <SchemaField.String
 43 |         name="input"
 44 |         title="input box"
 45 |         x-decorator="Editable"
 46 |         x-component="Input"
 47 |       />
 48 |       <SchemaField.Void
 49 |         name="void"
 50 |         title="Virtual Node Container"
 51 |         x-component="Editable.Popover"
 52 |         x-reactions={(field) => {
 53 |           field.title = field.query('.void.date2').get('value') || field.title
 54 |         }}
 55 |       >
 56 |         <SchemaField.String
 57 |           name="date2"
 58 |           title="date"
 59 |           x-decorator="FormItem"
 60 |           x-component="DatePicker"
 61 |           x-component-props={{
 62 |             followTrigger: true,
 63 |           }}
 64 |         />
 65 |         <SchemaField.String
 66 |           name="input2"
 67 |           title="input box"
 68 |           x-decorator="FormItem"
 69 |           x-component="Input"
 70 |         />
 71 |       </SchemaField.Void>
 72 |       <SchemaField.Object
 73 |         name="iobject"
 74 |         title="Object node container"
 75 |         x-component="Editable.Popover"
 76 |         x-reactions={(field) => {
 77 |           field.title = field.value?.date || field.title
 78 |         }}
 79 |       >
 80 |         <SchemaField.String
 81 |           name="date"
 82 |           title="date"
 83 |           x-decorator="FormItem"
 84 |           x-component="DatePicker"
 85 |           x-component-props={{
 86 |             followTrigger: true,
 87 |           }}
 88 |         />
 89 |         <SchemaField.String
 90 |           name="input"
 91 |           title="input box"
 92 |           x-decorator="FormItem"
 93 |           x-component="Input"
 94 |         />
 95 |       </SchemaField.Object>
 96 |     </SchemaField>
 97 |     <FormButtonGroup>
 98 |       <Submit onSubmit={console.log}>Submit</Submit>
 99 |     </FormButtonGroup>
100 |   </FormProvider>
101 | )
102 | ```
103 | 
104 | ## JSON Schema case
105 | 
106 | ```tsx
107 | import React from 'react'
108 | import {
109 |   Input,
110 |   DatePicker,
111 |   Editable,
112 |   FormItem,
113 |   FormButtonGroup,
114 |   Submit,
115 | } from '@formily/next'
116 | import { createForm } from '@formily/core'
117 | import { FormProvider, createSchemaField } from '@formily/react'
118 | 
119 | const SchemaField = createSchemaField({
120 |   components: {
121 |     DatePicker,
122 |     Editable,
123 |     Input,
124 |     FormItem,
125 |   },
126 | })
127 | 
128 | const form = createForm()
129 | 
130 | const schema = {
131 |   type: 'object',
132 |   properties: {
133 |     date: {
134 |       type: 'string',
135 |       title: 'Date',
136 |       'x-decorator': 'Editable',
137 |       'x-component': 'DatePicker',
138 |     },
139 |     input: {
140 |       type: 'string',
141 |       title: 'input box',
142 |       'x-decorator': 'Editable',
143 |       'x-component': 'Input',
144 |     },
145 |     void: {
146 |       type: 'void',
147 |       title: 'Virtual Node Container',
148 |       'x-component': 'Editable.Popover',
149 |       'x-reactions':
150 |         "{{(field) => field.title = field.query('.void.date2').get('value') || field.title}}",
151 |       properties: {
152 |         date2: {
153 |           type: 'string',
154 |           title: 'Date',
155 |           'x-decorator': 'FormItem',
156 |           'x-component': 'DatePicker',
157 |           'x-component-props': {
158 |             followTrigger: true,
159 |           },
160 |         },
161 |         input2: {
162 |           type: 'string',
163 |           title: 'input box',
164 |           'x-decorator': 'FormItem',
165 |           'x-component': 'Input',
166 |         },
167 |       },
168 |     },
169 |     iobject: {
170 |       type: 'object',
171 |       title: 'Object node container',
172 |       'x-component': 'Editable.Popover',
173 |       'x-reactions':
174 |         '{{(field) => field.title = field.value && field.value.date || field.title}}',
175 |       properties: {
176 |         date: {
177 |           type: 'string',
178 |           title: 'Date',
179 |           'x-decorator': 'FormItem',
180 |           'x-component': 'DatePicker',
181 |           'x-component-props': {
182 |             followTrigger: true,
183 |           },
184 |         },
185 |         input: {
186 |           type: 'string',
187 |           title: 'input box',
188 |           'x-decorator': 'FormItem',
189 |           'x-component': 'Input',
190 |         },
191 |       },
192 |     },
193 |   },
194 | }
195 | 
196 | export default () => (
197 |   <FormProvider form={form}>
198 |     <SchemaField schema={schema} />
199 |     <FormButtonGroup>
200 |       <Submit onSubmit={console.log}>Submit</Submit>
201 |     </FormButtonGroup>
202 |   </FormProvider>
203 | )
204 | ```
205 | 
206 | ## Pure JSX case
207 | 
208 | ```tsx
209 | import React from 'react'
210 | import {
211 |   Input,
212 |   DatePicker,
213 |   Editable,
214 |   FormItem,
215 |   FormButtonGroup,
216 |   Submit,
217 | } from '@formily/next'
218 | import { createForm } from '@formily/core'
219 | import { FormProvider, Field, VoidField, ObjectField } from '@formily/react'
220 | 
221 | const form = createForm()
222 | 
223 | export default () => (
224 |   <FormProvider form={form}>
225 |     <Field
226 |       name="date"
227 |       title="date"
228 |       decorator={[Editable]}
229 |       component={[DatePicker]}
230 |     />
231 |     <Field
232 |       name="input"
233 |       title="input box"
234 |       decorator={[Editable]}
235 |       component={[Input]}
236 |     />
237 |     <VoidField
238 |       name="void"
239 |       title="Virtual Node Container"
240 |       reactions={(field) => {
241 |         field.title = field.query('.void.date2').get('value') || field.title
242 |       }}
243 |       component={[Editable.Popover]}
244 |     >
245 |       <Field
246 |         name="date2"
247 |         title="date"
248 |         decorator={[FormItem]}
249 |         component={[
250 |           DatePicker,
251 |           {
252 |             followTrigger: true,
253 |           },
254 |         ]}
255 |       />
256 |       <Field
257 |         name="input2"
258 |         title="input box"
259 |         decorator={[FormItem]}
260 |         component={[Input]}
261 |       />
262 |     </VoidField>
263 |     <ObjectField
264 |       name="iobject"
265 |       title="Object node container"
266 |       component={[
267 |         Editable.Popover,
268 |         {
269 |           renderPreview: (field) => {
270 |             return field.value?.date
271 |           },
272 |         },
273 |       ]}
274 |     >
275 |       <Field
276 |         name="date"
277 |         title="date"
278 |         decorator={[FormItem]}
279 |         component={[
280 |           DatePicker,
281 |           {
282 |             followTrigger: true,
283 |           },
284 |         ]}
285 |       />
286 |       <Field
287 |         name="input"
288 |         title="input box"
289 |         decorator={[FormItem]}
290 |         component={[Input]}
291 |       />
292 |     </ObjectField>
293 | 
294 |     <FormButtonGroup>
295 |       <Submit onSubmit={console.log}>Submit</Submit>
296 |     </FormButtonGroup>
297 |   </FormProvider>
298 | )
299 | ```
300 | 
301 | ## API
302 | 
303 | ### Editable
304 | 
305 | > Inline editing
306 | 
307 | Refer to the FormItem property in https://fusion.design/pc/component/basic/form
308 | 
309 | ### Editable.Popover
310 | 
311 | > Floating layer editing
312 | 
313 | | Property name | Type                              | Description      | Default value |
314 | | ------------- | --------------------------------- | ---------------- | ------------- |
315 | | renderPreview | `(field:GeneralField)=>ReactNode` | Preview renderer |               |
316 | 
317 | Note: If there is a floating layer component such as Select/DatePicker inside the Popover, followTrigger=true needs to be configured on the floating layer component
318 | 
319 | Other references https://fusion.design/pc/component/basic/balloon
320 | 
```
Page 20/52FirstPrevNextLast