#
tokens: 49063/50000 22/1152 files (page 13/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 13 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/next/src/form-tab/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { Fragment, useMemo } from 'react'
  2 | import { Tab as Tabs, Badge } from '@alifd/next'
  3 | import { model, markRaw } from '@formily/reactive'
  4 | import { isValid } from '@formily/shared'
  5 | import {
  6 |   ItemProps as TabPaneProps,
  7 |   TabProps as TabsProps,
  8 | } from '@alifd/next/lib/tab'
  9 | import {
 10 |   useField,
 11 |   observer,
 12 |   ReactFC,
 13 |   useFieldSchema,
 14 |   RecursionField,
 15 | } from '@formily/react'
 16 | import { Schema, SchemaKey } from '@formily/json-schema'
 17 | import cls from 'classnames'
 18 | import { usePrefixCls } from '../__builtins__'
 19 | export interface IFormTab {
 20 |   activeKey: SchemaKey
 21 |   setActiveKey(key: SchemaKey): void
 22 | }
 23 | 
 24 | export interface IFormTabProps extends TabsProps {
 25 |   formTab?: IFormTab
 26 | }
 27 | 
 28 | export interface IFormTabPaneProps extends TabPaneProps {
 29 |   key: SchemaKey
 30 | }
 31 | 
 32 | interface IFeedbackBadgeProps {
 33 |   name: SchemaKey
 34 |   tab: React.ReactNode
 35 | }
 36 | 
 37 | type ComposedFormTab = React.FC<React.PropsWithChildren<IFormTabProps>> & {
 38 |   TabPane: React.FC<React.PropsWithChildren<IFormTabPaneProps>>
 39 |   createFormTab: (defaultActiveKey?: React.ReactText) => IFormTab
 40 | }
 41 | 
 42 | const useTabs = () => {
 43 |   const tabsField = useField()
 44 |   const schema = useFieldSchema()
 45 |   const tabs: { name: SchemaKey; props: any; schema: Schema }[] = []
 46 |   schema.mapProperties((schema, name) => {
 47 |     const field = tabsField.query(tabsField.address.concat(name)).take()
 48 |     if (field?.display === 'none' || field?.display === 'hidden') return
 49 |     if (schema['x-component']?.indexOf('TabPane') > -1) {
 50 |       tabs.push({
 51 |         name,
 52 |         props: {
 53 |           key: schema?.['x-component-props']?.key || name,
 54 |           ...schema?.['x-component-props'],
 55 |         },
 56 |         schema,
 57 |       })
 58 |     }
 59 |   })
 60 |   return tabs
 61 | }
 62 | 
 63 | const createFormTab = (defaultActiveKey?: string) => {
 64 |   const formTab = model({
 65 |     activeKey: defaultActiveKey,
 66 |     setActiveKey(key: string) {
 67 |       formTab.activeKey = key
 68 |     },
 69 |   })
 70 |   return markRaw(formTab)
 71 | }
 72 | 
 73 | const FeedbackBadge: ReactFC<IFeedbackBadgeProps> = observer((props) => {
 74 |   const field = useField()
 75 |   const errors = field.form.queryFeedbacks({
 76 |     type: 'error',
 77 |     address: `${field.address.concat(props.name)}.*`,
 78 |   })
 79 |   if (errors.length) {
 80 |     return (
 81 |       <Badge className="errors-badge" count={errors.length}>
 82 |         {props.tab}
 83 |       </Badge>
 84 |     )
 85 |   }
 86 |   return <Fragment>{props.tab}</Fragment>
 87 | })
 88 | 
 89 | export const FormTab: ComposedFormTab = observer(
 90 |   ({ formTab, ...props }: IFormTabProps) => {
 91 |     const tabs = useTabs()
 92 |     const _formTab = useMemo(() => {
 93 |       return formTab ? formTab : createFormTab()
 94 |     }, [])
 95 |     const prefixCls = usePrefixCls('formily-tab', props)
 96 |     const activeKey = props.activeKey || _formTab?.activeKey
 97 | 
 98 |     return (
 99 |       <Tabs
100 |         {...props}
101 |         {...(isValid(activeKey) && { activeKey })}
102 |         className={cls(prefixCls, props.className)}
103 |         onChange={(key) => {
104 |           props.onChange?.(key)
105 |           _formTab?.setActiveKey?.(key)
106 |         }}
107 |         lazyLoad={false}
108 |       >
109 |         {tabs.map(({ props, schema, name }, key) => (
110 |           <Tabs.Item
111 |             key={key}
112 |             {...props}
113 |             tab={<FeedbackBadge name={name} tab={props.tab} />}
114 |           >
115 |             <RecursionField schema={schema} name={name} />
116 |           </Tabs.Item>
117 |         ))}
118 |       </Tabs>
119 |     )
120 |   }
121 | ) as unknown as ComposedFormTab
122 | 
123 | const TabPane: React.FC<React.PropsWithChildren<IFormTabPaneProps>> = ({
124 |   children,
125 | }) => {
126 |   return <Fragment>{children}</Fragment>
127 | }
128 | 
129 | FormTab.TabPane = TabPane
130 | FormTab.createFormTab = createFormTab
131 | 
132 | export default FormTab
133 | 
```

--------------------------------------------------------------------------------
/packages/core/docs/api/entry/FormHooksAPI.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | order: 3
  3 | ---
  4 | 
  5 | # Form Hooks API
  6 | 
  7 | ## createEffectHook
  8 | 
  9 | #### Description
 10 | 
 11 | Create a custom hook listener
 12 | 
 13 | #### Signature
 14 | 
 15 | ```ts
 16 | interface createEffectHook {
 17 |   (
 18 |     type: string,
 19 |     callback?: (
 20 |       payload: any,
 21 |       form: Form,
 22 |       ...ctx: any[] //user-injected context
 23 |     ) => (...args: any[]) => void //High-level callbacks are used to process the encapsulation of the listener and help users achieve parameter customization capabilities
 24 |   )
 25 | }
 26 | ```
 27 | 
 28 | #### Example
 29 | 
 30 | ```tsx
 31 | import React, { useMemo, useState } from 'react'
 32 | import { createForm, createEffectHook } from '@formily/core'
 33 | import { ActionResponse } from './ActionResponse'
 34 | 
 35 | const onCustomEvent = createEffectHook(
 36 |   'custom-event',
 37 |   (payload, form) => (listener) => {
 38 |     listener(payload, form)
 39 |   }
 40 | )
 41 | 
 42 | export default () => {
 43 |   const [response, setResponse] = useState('')
 44 |   const form = useMemo(
 45 |     () =>
 46 |       createForm({
 47 |         effects() {
 48 |           onCustomEvent((payload, form) => {
 49 |             setResponse(payload + 'Form:' + form.id)
 50 |           })
 51 |         },
 52 |       }),
 53 |     []
 54 |   )
 55 |   return (
 56 |     <ActionResponse response={response}>
 57 |       <button
 58 |         onClick={() => {
 59 |           form.notify('custom-event', 'This is Custom Event')
 60 |         }}
 61 |       >
 62 |         Notify
 63 |       </button>
 64 |     </ActionResponse>
 65 |   )
 66 | }
 67 | ```
 68 | 
 69 | ## createEffectContext
 70 | 
 71 | #### Description
 72 | 
 73 | In the effects function, if we abstract a lot of fine-grained hooks, we need to pass it layer by layer if we want to read the top-level context data in hooks, which is obviously very inefficient, so formily provides createEffectContext to help users quickly obtain context data
 74 | 
 75 | #### Signature
 76 | 
 77 | ```ts
 78 | interface createEffectContext<T> {
 79 |   (defaultValue: T): {
 80 |     provide(value: T): void
 81 |     consume(): T
 82 |   }
 83 | }
 84 | ```
 85 | 
 86 | #### Example
 87 | 
 88 | ```tsx
 89 | import React, { useMemo, useState } from 'react'
 90 | import { createForm, onFormSubmit, createEffectContext } from '@formily/core'
 91 | import { ActionResponse } from './ActionResponse'
 92 | 
 93 | const { provide, consume } = createEffectContext()
 94 | 
 95 | const useMyHook = () => {
 96 |   const setResponse = consume()
 97 |   onFormSubmit(() => {
 98 |     setResponse('Context communication succeeded')
 99 |   })
100 | }
101 | 
102 | export default () => {
103 |   const [response, setResponse] = useState('')
104 |   const form = useMemo(
105 |     () =>
106 |       createForm({
107 |         effects() {
108 |           provide(setResponse)
109 |           useMyHook()
110 |         },
111 |       }),
112 |     []
113 |   )
114 |   return (
115 |     <ActionResponse response={response}>
116 |       <button
117 |         onClick={() => {
118 |           form.submit()
119 |         }}
120 |       >
121 |         submit
122 |       </button>
123 |     </ActionResponse>
124 |   )
125 | }
126 | ```
127 | 
128 | ## useEffectForm
129 | 
130 | #### Description
131 | 
132 | useEffectForm is actually a convenient usage of EffectContext, because most scene users will read Form instances, so there is no need to manually define an EffectFormContext
133 | 
134 | #### Signature
135 | 
136 | ```ts
137 | interface useEffectForm {
138 |   (): Form
139 | }
140 | ```
141 | 
142 | #### Example
143 | 
144 | ```tsx
145 | import React, { useMemo, useState } from 'react'
146 | import { createForm, useEffectForm, createEffectContext } from '@formily/core'
147 | import { ActionResponse } from './ActionResponse'
148 | 
149 | const { provide, consume } = createEffectContext()
150 | 
151 | const useMyHook = () => {
152 |   const form = useEffectForm()
153 |   const setResponse = consume()
154 |   setResponse('Communication successful:' + form.id)
155 | }
156 | 
157 | export default () => {
158 |   const [response, setResponse] = useState('')
159 |   useMemo(
160 |     () =>
161 |       createForm({
162 |         effects() {
163 |           provide(setResponse)
164 |           useMyHook()
165 |         },
166 |       }),
167 |     []
168 |   )
169 |   return <ActionResponse response={response} />
170 | }
171 | ```
172 | 
```

--------------------------------------------------------------------------------
/packages/antd/src/form-item/grid.less:
--------------------------------------------------------------------------------

```
  1 | .@{form-item-cls} {
  2 |   .@{form-item-cls}-item-col-24 {
  3 |     -webkit-box-flex: 0;
  4 |     -ms-flex: 0 0 100%;
  5 |     flex: 0 0 100%;
  6 |     max-width: 100%;
  7 |   }
  8 | 
  9 |   .@{form-item-cls}-item-col-23 {
 10 |     -webkit-box-flex: 0;
 11 |     -ms-flex: 0 0 95.83333333%;
 12 |     flex: 0 0 95.83333333%;
 13 |     max-width: 95.83333333%;
 14 |   }
 15 | 
 16 |   .@{form-item-cls}-item-col-22 {
 17 |     -webkit-box-flex: 0;
 18 |     -ms-flex: 0 0 91.66666667%;
 19 |     flex: 0 0 91.66666667%;
 20 |     max-width: 91.66666667%;
 21 |   }
 22 | 
 23 |   .@{form-item-cls}-item-col-21 {
 24 |     -webkit-box-flex: 0;
 25 |     -ms-flex: 0 0 87.5%;
 26 |     flex: 0 0 87.5%;
 27 |     max-width: 87.5%;
 28 |   }
 29 | 
 30 |   .@{form-item-cls}-item-col-20 {
 31 |     -webkit-box-flex: 0;
 32 |     -ms-flex: 0 0 83.33333333%;
 33 |     flex: 0 0 83.33333333%;
 34 |     max-width: 83.33333333%;
 35 |   }
 36 | 
 37 |   .@{form-item-cls}-item-col-19 {
 38 |     -webkit-box-flex: 0;
 39 |     -ms-flex: 0 0 79.16666667%;
 40 |     flex: 0 0 79.16666667%;
 41 |     max-width: 79.16666667%;
 42 |   }
 43 | 
 44 |   .@{form-item-cls}-item-col-18 {
 45 |     -webkit-box-flex: 0;
 46 |     -ms-flex: 0 0 75%;
 47 |     flex: 0 0 75%;
 48 |     max-width: 75%;
 49 |   }
 50 | 
 51 |   .@{form-item-cls}-item-col-17 {
 52 |     -webkit-box-flex: 0;
 53 |     -ms-flex: 0 0 70.83333333%;
 54 |     flex: 0 0 70.83333333%;
 55 |     max-width: 70.83333333%;
 56 |   }
 57 | 
 58 |   .@{form-item-cls}-item-col-16 {
 59 |     -webkit-box-flex: 0;
 60 |     -ms-flex: 0 0 66.66666667%;
 61 |     flex: 0 0 66.66666667%;
 62 |     max-width: 66.66666667%;
 63 |   }
 64 | 
 65 |   .@{form-item-cls}-item-col-15 {
 66 |     -webkit-box-flex: 0;
 67 |     -ms-flex: 0 0 62.5%;
 68 |     flex: 0 0 62.5%;
 69 |     max-width: 62.5%;
 70 |   }
 71 | 
 72 |   .@{form-item-cls}-item-col-14 {
 73 |     -webkit-box-flex: 0;
 74 |     -ms-flex: 0 0 58.33333333%;
 75 |     flex: 0 0 58.33333333%;
 76 |     max-width: 58.33333333%;
 77 |   }
 78 | 
 79 |   .@{form-item-cls}-item-col-13 {
 80 |     -webkit-box-flex: 0;
 81 |     -ms-flex: 0 0 54.16666667%;
 82 |     flex: 0 0 54.16666667%;
 83 |     max-width: 54.16666667%;
 84 |   }
 85 | 
 86 |   .@{form-item-cls}-item-col-12 {
 87 |     -webkit-box-flex: 0;
 88 |     -ms-flex: 0 0 50%;
 89 |     flex: 0 0 50%;
 90 |     max-width: 50%;
 91 |   }
 92 | 
 93 |   .@{form-item-cls}-item-col-11 {
 94 |     -webkit-box-flex: 0;
 95 |     -ms-flex: 0 0 45.83333333%;
 96 |     flex: 0 0 45.83333333%;
 97 |     max-width: 45.83333333%;
 98 |   }
 99 | 
100 |   .@{form-item-cls}-item-col-10 {
101 |     -webkit-box-flex: 0;
102 |     -ms-flex: 0 0 41.66666667%;
103 |     flex: 0 0 41.66666667%;
104 |     max-width: 41.66666667%;
105 |   }
106 | 
107 |   .@{form-item-cls}-item-col-9 {
108 |     -webkit-box-flex: 0;
109 |     -ms-flex: 0 0 37.5%;
110 |     flex: 0 0 37.5%;
111 |     max-width: 37.5%;
112 |   }
113 | 
114 |   .@{form-item-cls}-item-col-8 {
115 |     -webkit-box-flex: 0;
116 |     -ms-flex: 0 0 33.33333333%;
117 |     flex: 0 0 33.33333333%;
118 |     max-width: 33.33333333%;
119 |   }
120 | 
121 |   .@{form-item-cls}-item-col-7 {
122 |     -webkit-box-flex: 0;
123 |     -ms-flex: 0 0 29.16666667%;
124 |     flex: 0 0 29.16666667%;
125 |     max-width: 29.16666667%;
126 |   }
127 | 
128 |   .@{form-item-cls}-item-col-6 {
129 |     -webkit-box-flex: 0;
130 |     -ms-flex: 0 0 25%;
131 |     flex: 0 0 25%;
132 |     max-width: 25%;
133 |   }
134 | 
135 |   .@{form-item-cls}-item-col-5 {
136 |     -webkit-box-flex: 0;
137 |     -ms-flex: 0 0 20.83333333%;
138 |     flex: 0 0 20.83333333%;
139 |     max-width: 20.83333333%;
140 |   }
141 | 
142 |   .@{form-item-cls}-item-col-4 {
143 |     -webkit-box-flex: 0;
144 |     -ms-flex: 0 0 16.66666667%;
145 |     flex: 0 0 16.66666667%;
146 |     max-width: 16.66666667%;
147 |   }
148 | 
149 |   .@{form-item-cls}-item-col-3 {
150 |     -webkit-box-flex: 0;
151 |     -ms-flex: 0 0 12.5%;
152 |     flex: 0 0 12.5%;
153 |     max-width: 12.5%;
154 |   }
155 | 
156 |   .@{form-item-cls}-item-col-2 {
157 |     -webkit-box-flex: 0;
158 |     -ms-flex: 0 0 8.33333333%;
159 |     flex: 0 0 8.33333333%;
160 |     max-width: 8.33333333%;
161 |   }
162 | 
163 |   .@{form-item-cls}-item-col-1 {
164 |     -webkit-box-flex: 0;
165 |     -ms-flex: 0 0 4.16666667%;
166 |     flex: 0 0 4.16666667%;
167 |     max-width: 4.16666667%;
168 |   }
169 | 
170 |   .@{form-item-cls}-item-col-0 {
171 |     display: none;
172 |   }
173 | }
174 | 
```

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

```markdown
  1 | # ArrayTabs
  2 | 
  3 | > Self-increasing tab, you can consider using this component for scenarios with high vertical space requirements
  4 | >
  5 | > Note: This component is only applicable to Schema scenarios, please avoid cross-tab linkage in interaction
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormItem,
 13 |   Input,
 14 |   ArrayTabs,
 15 |   FormButtonGroup,
 16 |   Submit,
 17 | } from '@formily/antd'
 18 | import { createForm } from '@formily/core'
 19 | import { FormProvider, createSchemaField } from '@formily/react'
 20 | 
 21 | const SchemaField = createSchemaField({
 22 |   components: {
 23 |     FormItem,
 24 |     Input,
 25 |     ArrayTabs,
 26 |   },
 27 | })
 28 | 
 29 | const form = createForm()
 30 | 
 31 | export default () => {
 32 |   return (
 33 |     <FormProvider form={form}>
 34 |       <SchemaField>
 35 |         <SchemaField.Array
 36 |           name="string_array"
 37 |           x-decorator="FormItem"
 38 |           title="string array"
 39 |           maxItems={3}
 40 |           x-component="ArrayTabs"
 41 |         >
 42 |           <SchemaField.String
 43 |             x-decorator="FormItem"
 44 |             required
 45 |             x-component="Input"
 46 |           />
 47 |         </SchemaField.Array>
 48 |         <SchemaField.Array
 49 |           name="array"
 50 |           x-decorator="FormItem"
 51 |           title="Object array"
 52 |           maxItems={3}
 53 |           x-component="ArrayTabs"
 54 |         >
 55 |           <SchemaField.Object>
 56 |             <SchemaField.String
 57 |               x-decorator="FormItem"
 58 |               title="AAA"
 59 |               name="aaa"
 60 |               required
 61 |               x-component="Input"
 62 |             />
 63 |             <SchemaField.String
 64 |               x-decorator="FormItem"
 65 |               title="BBB"
 66 |               name="bbb"
 67 |               required
 68 |               x-component="Input"
 69 |             />
 70 |           </SchemaField.Object>
 71 |         </SchemaField.Array>
 72 |       </SchemaField>
 73 |       <FormButtonGroup>
 74 |         <Submit onSubmit={console.log}>Submit</Submit>
 75 |       </FormButtonGroup>
 76 |     </FormProvider>
 77 |   )
 78 | }
 79 | ```
 80 | 
 81 | ## JSON Schema case
 82 | 
 83 | ```tsx
 84 | import React from 'react'
 85 | import {
 86 |   FormItem,
 87 |   Input,
 88 |   ArrayTabs,
 89 |   FormButtonGroup,
 90 |   Submit,
 91 | } from '@formily/antd'
 92 | import { createForm } from '@formily/core'
 93 | import { FormProvider, createSchemaField } from '@formily/react'
 94 | 
 95 | const SchemaField = createSchemaField({
 96 |   components: {
 97 |     FormItem,
 98 |     Input,
 99 |     ArrayTabs,
100 |   },
101 | })
102 | 
103 | const form = createForm()
104 | 
105 | const schema = {
106 |   type: 'object',
107 |   properties: {
108 |     string_array: {
109 |       type: 'array',
110 |       title: 'String array',
111 |       'x-decorator': 'FormItem',
112 |       maxItems: 3,
113 |       'x-component': 'ArrayTabs',
114 |       items: {
115 |         type: 'string',
116 |         'x-decorator': 'FormItem',
117 |         required: true,
118 |         'x-component': 'Input',
119 |       },
120 |     },
121 |     array: {
122 |       type: 'array',
123 |       title: 'Object array',
124 |       'x-decorator': 'FormItem',
125 |       maxItems: 3,
126 |       'x-component': 'ArrayTabs',
127 |       items: {
128 |         type: 'object',
129 |         properties: {
130 |           aaa: {
131 |             type: 'string',
132 |             'x-decorator': 'FormItem',
133 |             title: 'AAA',
134 |             required: true,
135 |             'x-component': 'Input',
136 |           },
137 |           bbb: {
138 |             type: 'string',
139 |             'x-decorator': 'FormItem',
140 |             title: 'BBB',
141 |             required: true,
142 |             'x-component': 'Input',
143 |           },
144 |         },
145 |       },
146 |     },
147 |   },
148 | }
149 | 
150 | export default () => {
151 |   return (
152 |     <FormProvider form={form}>
153 |       <SchemaField schema={schema} />
154 |       <FormButtonGroup>
155 |         <Submit onSubmit={console.log}>Submit</Submit>
156 |       </FormButtonGroup>
157 |     </FormProvider>
158 |   )
159 | }
160 | ```
161 | 
162 | ## API
163 | 
164 | ### ArrayTabs
165 | 
166 | Reference https://ant.design/components/tabs-cn/
167 | 
```

--------------------------------------------------------------------------------
/packages/reactive-vue/src/observer/observerInVue2.ts:
--------------------------------------------------------------------------------

```typescript
  1 | // https://github.com/mobxjs/mobx-vue/blob/master/src/observer.ts
  2 | 
  3 | /**
  4 |  * @author Kuitos
  5 |  * @homepage https://github.com/kuitos/
  6 |  * @since 2018-05-22 16:39
  7 |  */
  8 | import { Tracker, batch } from '@formily/reactive'
  9 | import collectDataForVue from './collectData'
 10 | import { Vue2 as Vue } from 'vue-demi'
 11 | import { IObserverOptions } from '../types'
 12 | 
 13 | const noop = () => {}
 14 | const disposerSymbol = Symbol('disposerSymbol')
 15 | 
 16 | function observer(Component: any, observerOptions?: IObserverOptions): any {
 17 |   const name =
 18 |     observerOptions?.name ||
 19 |     (Component as any).name ||
 20 |     (Component as any)._componentTag ||
 21 |     (Component.constructor && Component.constructor.name) ||
 22 |     '<component>'
 23 | 
 24 |   const originalOptions =
 25 |     typeof Component === 'object' ? Component : (Component as any).options
 26 |   // To not mutate the original component options, we need to construct a new one
 27 |   const dataDefinition = originalOptions.data
 28 |   const options = {
 29 |     name,
 30 |     ...originalOptions,
 31 |     data(vm: any) {
 32 |       return collectDataForVue(vm || this, dataDefinition)
 33 |     },
 34 |     // overrider the cached constructor to avoid extending skip
 35 |     // @see https://github.com/vuejs/vue/blob/6cc070063bd211229dff5108c99f7d11b6778550/src/core/global-api/extend.js#L24
 36 |     _Ctor: {},
 37 |   }
 38 | 
 39 |   // we couldn't use the Component as super class when Component was a VueClass, that will invoke the lifecycle twice after we called Component.extend
 40 |   const superProto =
 41 |     typeof Component === 'function' &&
 42 |     Object.getPrototypeOf(Component.prototype)
 43 |   const Super =
 44 |     superProto instanceof (Vue as any) ? superProto.constructor : Vue
 45 |   const ExtendedComponent = Super.extend(options)
 46 | 
 47 |   const { $mount, $destroy } = ExtendedComponent.prototype
 48 | 
 49 |   ExtendedComponent.prototype.$mount = function (this: any, ...args: any[]) {
 50 |     let mounted = false
 51 |     this[disposerSymbol] = noop
 52 | 
 53 |     let nativeRenderOfVue: any
 54 | 
 55 |     const reactiveRender = () => {
 56 |       batch(() => {
 57 |         tracker.track(() => {
 58 |           if (!mounted) {
 59 |             $mount.apply(this, args)
 60 |             mounted = true
 61 |             nativeRenderOfVue = this._watcher.getter
 62 |             // rewrite the native render method of vue with our reactive tracker render
 63 |             // thus if component updated by vue watcher, we could re track and collect dependencies by @formily/reactive
 64 |             this._watcher.getter = reactiveRender
 65 |           } else {
 66 |             nativeRenderOfVue.call(this, this)
 67 |           }
 68 |         })
 69 |       })
 70 | 
 71 |       return this
 72 |     }
 73 | 
 74 |     reactiveRender.$vm = this
 75 | 
 76 |     const tracker = new Tracker(() => {
 77 |       if (
 78 |         reactiveRender.$vm._isBeingDestroyed ||
 79 |         reactiveRender.$vm._isDestroyed
 80 |       ) {
 81 |         return tracker.dispose()
 82 |       }
 83 | 
 84 |       if (
 85 |         observerOptions?.scheduler &&
 86 |         typeof observerOptions.scheduler === 'function'
 87 |       ) {
 88 |         observerOptions.scheduler(reactiveRender)
 89 |       } else {
 90 |         reactiveRender()
 91 |       }
 92 |     })
 93 | 
 94 |     this[disposerSymbol] = tracker.dispose
 95 | 
 96 |     return reactiveRender()
 97 |   }
 98 | 
 99 |   ExtendedComponent.prototype.$destroy = function (this: any) {
100 |     ;(this as any)[disposerSymbol]()
101 |     $destroy.apply(this)
102 |   }
103 | 
104 |   const extendedComponentNamePropertyDescriptor =
105 |     Object.getOwnPropertyDescriptor(ExtendedComponent, 'name') || {}
106 |   if (extendedComponentNamePropertyDescriptor.configurable === true) {
107 |     Object.defineProperty(ExtendedComponent, 'name', {
108 |       writable: false,
109 |       value: name,
110 |       enumerable: false,
111 |       configurable: false,
112 |     })
113 |   }
114 | 
115 |   return ExtendedComponent
116 | }
117 | 
118 | export { observer, observer as Observer }
119 | 
```

--------------------------------------------------------------------------------
/packages/next/src/form-item/grid.scss:
--------------------------------------------------------------------------------

```scss
  1 | .#{$form-item-cls} {
  2 |   .#{$form-item-cls}-item-col-24 {
  3 |     -webkit-box-flex: 0;
  4 |     -ms-flex: 0 0 100%;
  5 |     flex: 0 0 100%;
  6 |     max-width: 100%;
  7 |   }
  8 | 
  9 |   .#{$form-item-cls}-item-col-23 {
 10 |     -webkit-box-flex: 0;
 11 |     -ms-flex: 0 0 95.83333333%;
 12 |     flex: 0 0 95.83333333%;
 13 |     max-width: 95.83333333%;
 14 |   }
 15 | 
 16 |   .#{$form-item-cls}-item-col-22 {
 17 |     -webkit-box-flex: 0;
 18 |     -ms-flex: 0 0 91.66666667%;
 19 |     flex: 0 0 91.66666667%;
 20 |     max-width: 91.66666667%;
 21 |   }
 22 | 
 23 |   .#{$form-item-cls}-item-col-21 {
 24 |     -webkit-box-flex: 0;
 25 |     -ms-flex: 0 0 87.5%;
 26 |     flex: 0 0 87.5%;
 27 |     max-width: 87.5%;
 28 |   }
 29 | 
 30 |   .#{$form-item-cls}-item-col-20 {
 31 |     -webkit-box-flex: 0;
 32 |     -ms-flex: 0 0 83.33333333%;
 33 |     flex: 0 0 83.33333333%;
 34 |     max-width: 83.33333333%;
 35 |   }
 36 | 
 37 |   .#{$form-item-cls}-item-col-19 {
 38 |     -webkit-box-flex: 0;
 39 |     -ms-flex: 0 0 79.16666667%;
 40 |     flex: 0 0 79.16666667%;
 41 |     max-width: 79.16666667%;
 42 |   }
 43 | 
 44 |   .#{$form-item-cls}-item-col-18 {
 45 |     -webkit-box-flex: 0;
 46 |     -ms-flex: 0 0 75%;
 47 |     flex: 0 0 75%;
 48 |     max-width: 75%;
 49 |   }
 50 | 
 51 |   .#{$form-item-cls}-item-col-17 {
 52 |     -webkit-box-flex: 0;
 53 |     -ms-flex: 0 0 70.83333333%;
 54 |     flex: 0 0 70.83333333%;
 55 |     max-width: 70.83333333%;
 56 |   }
 57 | 
 58 |   .#{$form-item-cls}-item-col-16 {
 59 |     -webkit-box-flex: 0;
 60 |     -ms-flex: 0 0 66.66666667%;
 61 |     flex: 0 0 66.66666667%;
 62 |     max-width: 66.66666667%;
 63 |   }
 64 | 
 65 |   .#{$form-item-cls}-item-col-15 {
 66 |     -webkit-box-flex: 0;
 67 |     -ms-flex: 0 0 62.5%;
 68 |     flex: 0 0 62.5%;
 69 |     max-width: 62.5%;
 70 |   }
 71 | 
 72 |   .#{$form-item-cls}-item-col-14 {
 73 |     -webkit-box-flex: 0;
 74 |     -ms-flex: 0 0 58.33333333%;
 75 |     flex: 0 0 58.33333333%;
 76 |     max-width: 58.33333333%;
 77 |   }
 78 | 
 79 |   .#{$form-item-cls}-item-col-13 {
 80 |     -webkit-box-flex: 0;
 81 |     -ms-flex: 0 0 54.16666667%;
 82 |     flex: 0 0 54.16666667%;
 83 |     max-width: 54.16666667%;
 84 |   }
 85 | 
 86 |   .#{$form-item-cls}-item-col-12 {
 87 |     -webkit-box-flex: 0;
 88 |     -ms-flex: 0 0 50%;
 89 |     flex: 0 0 50%;
 90 |     max-width: 50%;
 91 |   }
 92 | 
 93 |   .#{$form-item-cls}-item-col-11 {
 94 |     -webkit-box-flex: 0;
 95 |     -ms-flex: 0 0 45.83333333%;
 96 |     flex: 0 0 45.83333333%;
 97 |     max-width: 45.83333333%;
 98 |   }
 99 | 
100 |   .#{$form-item-cls}-item-col-10 {
101 |     -webkit-box-flex: 0;
102 |     -ms-flex: 0 0 41.66666667%;
103 |     flex: 0 0 41.66666667%;
104 |     max-width: 41.66666667%;
105 |   }
106 | 
107 |   .#{$form-item-cls}-item-col-9 {
108 |     -webkit-box-flex: 0;
109 |     -ms-flex: 0 0 37.5%;
110 |     flex: 0 0 37.5%;
111 |     max-width: 37.5%;
112 |   }
113 | 
114 |   .#{$form-item-cls}-item-col-8 {
115 |     -webkit-box-flex: 0;
116 |     -ms-flex: 0 0 33.33333333%;
117 |     flex: 0 0 33.33333333%;
118 |     max-width: 33.33333333%;
119 |   }
120 | 
121 |   .#{$form-item-cls}-item-col-7 {
122 |     -webkit-box-flex: 0;
123 |     -ms-flex: 0 0 29.16666667%;
124 |     flex: 0 0 29.16666667%;
125 |     max-width: 29.16666667%;
126 |   }
127 | 
128 |   .#{$form-item-cls}-item-col-6 {
129 |     -webkit-box-flex: 0;
130 |     -ms-flex: 0 0 25%;
131 |     flex: 0 0 25%;
132 |     max-width: 25%;
133 |   }
134 | 
135 |   .#{$form-item-cls}-item-col-5 {
136 |     -webkit-box-flex: 0;
137 |     -ms-flex: 0 0 20.83333333%;
138 |     flex: 0 0 20.83333333%;
139 |     max-width: 20.83333333%;
140 |   }
141 | 
142 |   .#{$form-item-cls}-item-col-4 {
143 |     -webkit-box-flex: 0;
144 |     -ms-flex: 0 0 16.66666667%;
145 |     flex: 0 0 16.66666667%;
146 |     max-width: 16.66666667%;
147 |   }
148 | 
149 |   .#{$form-item-cls}-item-col-3 {
150 |     -webkit-box-flex: 0;
151 |     -ms-flex: 0 0 12.5%;
152 |     flex: 0 0 12.5%;
153 |     max-width: 12.5%;
154 |   }
155 | 
156 |   .#{$form-item-cls}-item-col-2 {
157 |     -webkit-box-flex: 0;
158 |     -ms-flex: 0 0 8.33333333%;
159 |     flex: 0 0 8.33333333%;
160 |     max-width: 8.33333333%;
161 |   }
162 | 
163 |   .#{$form-item-cls}-item-col-1 {
164 |     -webkit-box-flex: 0;
165 |     -ms-flex: 0 0 4.16666667%;
166 |     flex: 0 0 4.16666667%;
167 |     max-width: 4.16666667%;
168 |   }
169 | 
170 |   .#{$form-item-cls}-item-col-0 {
171 |     display: none;
172 |   }
173 | }
174 | 
```

--------------------------------------------------------------------------------
/packages/json-schema/src/polyfills/SPECIFICATION_1_0.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { registerPolyfills } from '../patches'
  2 | import { toArr, isArr, isStr, lowerCase, isValid } from '@formily/shared'
  3 | import { ISchema } from '../types'
  4 | 
  5 | const VOID_COMPONENTS = [
  6 |   'card',
  7 |   'block',
  8 |   'grid-col',
  9 |   'grid-row',
 10 |   'grid',
 11 |   'layout',
 12 |   'step',
 13 |   'tab',
 14 |   'text-box',
 15 | ]
 16 | 
 17 | const TYPE_DEFAULT_COMPONENTS = {}
 18 | 
 19 | const transformCondition = (condition: string) => {
 20 |   if (isStr(condition)) {
 21 |     return condition.replace(/\$value/, '$self.value')
 22 |   }
 23 | }
 24 | 
 25 | const transformXLinkage = (linkages: any[]) => {
 26 |   if (isArr(linkages)) {
 27 |     return linkages.reduce((buf, item) => {
 28 |       if (!item) return buf
 29 |       if (item.type === 'value:visible') {
 30 |         return buf.concat({
 31 |           target: item.target,
 32 |           when: transformCondition(item.condition),
 33 |           fulfill: {
 34 |             state: {
 35 |               visible: true,
 36 |             },
 37 |           },
 38 |           otherwise: {
 39 |             state: {
 40 |               visible: false,
 41 |             },
 42 |           },
 43 |         })
 44 |       } else if (item.type === 'value:schema') {
 45 |         return buf.concat({
 46 |           target: item.target,
 47 |           when: transformCondition(item.condition),
 48 |           fulfill: {
 49 |             schema: SpecificationV1Polyfill({ version: '1.0', ...item.schema }),
 50 |           },
 51 |           otherwise: {
 52 |             schema: SpecificationV1Polyfill({
 53 |               version: '1.0',
 54 |               ...item.otherwise,
 55 |             }),
 56 |           },
 57 |         })
 58 |       } else if (item.type === 'value:state') {
 59 |         return buf.concat({
 60 |           target: item.target,
 61 |           when: transformCondition(item.condition),
 62 |           fulfill: {
 63 |             state: item.state,
 64 |           },
 65 |           otherwise: {
 66 |             state: item.otherwise,
 67 |           },
 68 |         })
 69 |       }
 70 |     }, [])
 71 |   }
 72 |   return []
 73 | }
 74 | 
 75 | const SpecificationV1Polyfill = (schema: ISchema) => {
 76 |   if (isValid(schema['editable'])) {
 77 |     schema['x-editable'] = schema['x-editable'] || schema['editable']
 78 |     delete schema['editable']
 79 |   }
 80 |   if (isValid(schema['visible'])) {
 81 |     schema['x-visible'] = schema['x-visible'] || schema['visible']
 82 |     delete schema['visible']
 83 |   }
 84 |   if (isValid(schema['display'])) {
 85 |     schema['x-display'] =
 86 |       schema['x-display'] || (schema['display'] ? 'visible' : 'hidden')
 87 |     delete schema['display']
 88 |   }
 89 |   if (isValid(schema['x-props'])) {
 90 |     schema['x-decorator-props'] =
 91 |       schema['x-decorator-props'] || schema['x-props']
 92 |     delete schema['display']
 93 |   }
 94 |   if (schema['x-linkages']) {
 95 |     schema['x-reactions'] = toArr(schema['x-reactions']).concat(
 96 |       transformXLinkage(schema['x-linkages'])
 97 |     )
 98 |     delete schema['x-linkages']
 99 |   }
100 |   if (schema['x-component']) {
101 |     if (
102 |       VOID_COMPONENTS.some(
103 |         (component) => lowerCase(component) === lowerCase(schema['x-component'])
104 |       )
105 |     ) {
106 |       schema['type'] = 'void'
107 |     }
108 |   } else {
109 |     if (TYPE_DEFAULT_COMPONENTS[schema['type']]) {
110 |       schema['x-component'] = TYPE_DEFAULT_COMPONENTS[schema['type']]
111 |     }
112 |   }
113 |   if (
114 |     !schema['x-decorator'] &&
115 |     schema['type'] !== 'void' &&
116 |     schema['type'] !== 'object'
117 |   ) {
118 |     schema['x-decorator'] = schema['x-decorator'] || 'FormItem'
119 |   }
120 |   if (schema['x-rules']) {
121 |     schema['x-validator'] = []
122 |       .concat(schema['x-validator'] || [])
123 |       .concat(schema['x-rules'])
124 |   }
125 |   return schema
126 | }
127 | 
128 | registerPolyfills('1.0', SpecificationV1Polyfill)
129 | 
130 | export const registerVoidComponents = (components: string[]) => {
131 |   VOID_COMPONENTS.push(...components)
132 | }
133 | 
134 | export const registerTypeDefaultComponents = (maps: Record<string, string>) => {
135 |   Object.assign(TYPE_DEFAULT_COMPONENTS, maps)
136 | }
137 | 
```

--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | title: Formily - Alibaba unified front-end form solution
  3 | order: 10
  4 | hero:
  5 |   title: Alibaba Formily
  6 |   desc: Alibaba Unified Front-end Form Solution
  7 |   actions:
  8 |     - text: Introduction
  9 |       link: /guide
 10 |     - text: Quick start
 11 |       link: /guide/quick-start
 12 | features:
 13 |   - icon: https://img.alicdn.com/imgextra/i2/O1CN016i72sH1c5wh1kyy9U_!!6000000003550-55-tps-800-800.svg
 14 |     title: Easier to Use
 15 |     desc: Out of the box, rich cases
 16 |   - icon: https://img.alicdn.com/imgextra/i1/O1CN01bHdrZJ1rEOESvXEi5_!!6000000005599-55-tps-800-800.svg
 17 |     title: More Efficient
 18 |     desc: Fool writing, ultra-high performance
 19 |   - icon: https://img.alicdn.com/imgextra/i3/O1CN01xlETZk1G0WSQT6Xii_!!6000000000560-55-tps-800-800.svg
 20 |     title: More Professional
 21 |     desc: Complete, flexible and elegant
 22 | footer: Open-source MIT Licensed | Copyright © 2019-present<br />Powered by self
 23 | ---
 24 | 
 25 | ```tsx
 26 | /**
 27 |  * inline: true
 28 |  */
 29 | import React from 'react'
 30 | import { Section } from './site/Section'
 31 | import './site/styles.less'
 32 | 
 33 | export default () => (
 34 |   <Section
 35 |     title="Fool Writing, Ultra-high Performance"
 36 |     style={{ marginTop: 40 }}
 37 |     titleStyle={{ paddingBottom: 100, fontWeight: 'bold' }}
 38 |   >
 39 |     <iframe
 40 |       className="codesandbox"
 41 |       src="https://codesandbox.io/embed/formilyyaliceshi-vbu4w?fontsize=12&module=%2FApp.tsx&theme=dark"
 42 |       allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
 43 |       sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
 44 |     ></iframe>
 45 |   </Section>
 46 | )
 47 | ```
 48 | 
 49 | ```tsx
 50 | /**
 51 |  * inline: true
 52 |  */
 53 | import React from 'react'
 54 | import { Section } from './site/Section'
 55 | import './site/styles.less'
 56 | 
 57 | export default () => (
 58 |   <Section
 59 |     title="Form Builder,Efficient Development"
 60 |     style={{ marginTop: 140, fontWeight: 'bold' }}
 61 |     titleStyle={{ paddingBottom: 140 }}
 62 |     scale={1.2}
 63 |   >
 64 |     <a href="//designable-antd.formilyjs.org" target="_blank" rel="noreferrer">
 65 |       <img src="//img.alicdn.com/imgextra/i2/O1CN01eI9FLz22tZek2jv7E_!!6000000007178-2-tps-3683-2272.png" />
 66 |     </a>
 67 |   </Section>
 68 | )
 69 | ```
 70 | 
 71 | ```tsx
 72 | /**
 73 |  * inline: true
 74 |  */
 75 | import React from 'react'
 76 | import { Section } from './site/Section'
 77 | import './site/styles.less'
 78 | 
 79 | export default () => (
 80 |   <Section
 81 |     title="Pure Core, More Extensibility"
 82 |     style={{ marginTop: 140 }}
 83 |     titleStyle={{ paddingBottom: 100, fontWeight: 'bold' }}
 84 |   >
 85 |     <a href="//core.formilyjs.org" target="_blank" rel="noreferrer">
 86 |       <img src="//img.alicdn.com/imgextra/i4/O1CN019qbf1b1ChnTfT9x3X_!!6000000000113-55-tps-1939-1199.svg" />
 87 |     </a>
 88 |   </Section>
 89 | )
 90 | ```
 91 | 
 92 | ```tsx
 93 | /**
 94 |  * inline: true
 95 |  */
 96 | import React from 'react'
 97 | import { Section } from './site/Section'
 98 | import { Contributors } from './site/Contributors'
 99 | import './site/styles.less'
100 | 
101 | export default () => (
102 |   <Section
103 |     title="Active Community & Genius People"
104 |     style={{ marginTop: 100 }}
105 |     titleStyle={{ paddingBottom: 140, fontWeight: 'bold' }}
106 |   >
107 |     <Contributors />
108 |   </Section>
109 | )
110 | ```
111 | 
112 | ```tsx
113 | /**
114 |  * inline: true
115 |  */
116 | import React from 'react'
117 | import { Section } from './site/Section'
118 | import { QrCode, QrCodeGroup } from './site/QrCode'
119 | import './site/styles.less'
120 | 
121 | export default () => (
122 |   <Section
123 |     title="High-Quality Community Group"
124 |     style={{ marginTop: 140 }}
125 |     titleStyle={{ paddingBottom: 20, fontWeight: 'bold' }}
126 |   >
127 |     <QrCodeGroup>
128 |       <QrCode link="//img.alicdn.com/imgextra/i1/O1CN011zlc5b1uu1BDUpNg1_!!6000000006096-2-tps-978-1380.png" />
129 |     </QrCodeGroup>
130 |   </Section>
131 | )
132 | ```
133 | 
```

--------------------------------------------------------------------------------
/packages/vue/src/shared/connect.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { isVue2, markRaw, defineComponent, getCurrentInstance } from 'vue-demi'
  2 | import { isFn, isStr, FormPath, each, isValid } from '@formily/shared'
  3 | import { isVoidField, GeneralField } from '@formily/core'
  4 | import { observer } from '@formily/reactive-vue'
  5 | 
  6 | import { useField } from '../hooks/useField'
  7 | import h from './h'
  8 | 
  9 | import type {
 10 |   VueComponent,
 11 |   IComponentMapper,
 12 |   IStateMapper,
 13 |   VueComponentProps,
 14 | } from '../types'
 15 | 
 16 | export function mapProps<T extends VueComponent = VueComponent>(
 17 |   ...args: IStateMapper<VueComponentProps<T>>[]
 18 | ) {
 19 |   const transform = (input: VueComponentProps<T>, field: GeneralField) =>
 20 |     args.reduce((props, mapper) => {
 21 |       if (isFn(mapper)) {
 22 |         props = Object.assign(props, mapper(props, field))
 23 |       } else {
 24 |         each(mapper, (to, extract) => {
 25 |           const extractValue = FormPath.getIn(field, extract)
 26 |           const targetValue = isStr(to) ? to : extract
 27 |           const originalValue = FormPath.getIn(props, targetValue)
 28 |           if (extract === 'value') {
 29 |             if (to !== extract) {
 30 |               delete props['value']
 31 |             }
 32 |           }
 33 |           if (isValid(originalValue) && !isValid(extractValue)) return
 34 |           FormPath.setIn(props, targetValue, extractValue)
 35 |         })
 36 |       }
 37 |       return props
 38 |     }, input)
 39 | 
 40 |   return (target: T) => {
 41 |     return observer(
 42 |       defineComponent({
 43 |         name: target.name ? `Connected${target.name}` : `ConnectedComponent`,
 44 |         setup(props, { attrs, slots, listeners }: any) {
 45 |           const fieldRef = useField()
 46 |           return () => {
 47 |             const newAttrs = fieldRef.value
 48 |               ? transform({ ...attrs } as VueComponentProps<T>, fieldRef.value)
 49 |               : { ...attrs }
 50 |             return h(
 51 |               target,
 52 |               {
 53 |                 attrs: newAttrs,
 54 |                 on: listeners,
 55 |               },
 56 |               slots
 57 |             )
 58 |           }
 59 |         },
 60 |       })
 61 |     )
 62 |   }
 63 | }
 64 | 
 65 | export function mapReadPretty<T extends VueComponent, C extends VueComponent>(
 66 |   component: C,
 67 |   readPrettyProps?: Record<string, any>
 68 | ) {
 69 |   return (target: T) => {
 70 |     return observer(
 71 |       defineComponent({
 72 |         name: target.name ? `Read${target.name}` : `ReadComponent`,
 73 |         setup(props, { attrs, slots, listeners }: Record<string, any>) {
 74 |           const fieldRef = useField()
 75 |           return () => {
 76 |             const field = fieldRef.value
 77 |             return h(
 78 |               field && !isVoidField(field) && field.pattern === 'readPretty'
 79 |                 ? component
 80 |                 : target,
 81 |               {
 82 |                 attrs: {
 83 |                   ...readPrettyProps,
 84 |                   ...attrs,
 85 |                 },
 86 |                 on: listeners,
 87 |               },
 88 |               slots
 89 |             )
 90 |           }
 91 |         },
 92 |       })
 93 |     )
 94 |   }
 95 | }
 96 | 
 97 | export function connect<T extends VueComponent>(
 98 |   target: T,
 99 |   ...args: IComponentMapper[]
100 | ): T {
101 |   const Component = args.reduce((target: VueComponent, mapper) => {
102 |     return mapper(target)
103 |   }, target)
104 |   /* istanbul ignore else */
105 |   if (isVue2) {
106 |     const functionalComponent = defineComponent({
107 |       functional: true,
108 |       name: target.name,
109 |       render(h, context) {
110 |         return h(Component, context.data, context.children)
111 |       },
112 |     })
113 |     return markRaw(functionalComponent) as T
114 |   } else {
115 |     const functionalComponent = defineComponent({
116 |       name: target.name,
117 |       setup(props, { attrs, slots }) {
118 |         return () => {
119 |           return h(Component, { props, attrs }, slots)
120 |         }
121 |       },
122 |     })
123 |     return markRaw(functionalComponent) as T
124 |   }
125 | }
126 | 
```

--------------------------------------------------------------------------------
/packages/path/src/destructor.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import {
  2 |   Segments,
  3 |   Node,
  4 |   DestructorRules,
  5 |   isArrayPattern,
  6 |   isObjectPattern,
  7 |   isIdentifier,
  8 |   isDestructorExpression,
  9 | } from './types'
 10 | import { isNum } from './shared'
 11 | 
 12 | type Mutators = {
 13 |   getIn: (segments: Segments, source: any) => any
 14 |   setIn: (segments: Segments, source: any, value: any) => void
 15 |   deleteIn?: (segments: Segments, source: any) => any
 16 |   existIn?: (segments: Segments, source: any, start: number) => boolean
 17 | }
 18 | 
 19 | const DestructorCache = new Map()
 20 | 
 21 | const isValid = (val: any) => val !== undefined && val !== null
 22 | 
 23 | export const getDestructor = (source: string) => {
 24 |   return DestructorCache.get(source)
 25 | }
 26 | 
 27 | export const setDestructor = (source: string, rules: DestructorRules) => {
 28 |   DestructorCache.set(source, rules)
 29 | }
 30 | 
 31 | export const parseDestructorRules = (node: Node): DestructorRules => {
 32 |   const rules = []
 33 |   if (isObjectPattern(node)) {
 34 |     let index = 0
 35 |     node.properties.forEach((child) => {
 36 |       rules[index] = {
 37 |         path: [],
 38 |       }
 39 |       rules[index].key = child.key.value
 40 |       rules[index].path.push(child.key.value)
 41 |       if (isIdentifier(child.value)) {
 42 |         rules[index].key = child.value.value
 43 |       }
 44 |       const basePath = rules[index].path
 45 |       const childRules = parseDestructorRules(child.value as Node)
 46 |       let k = index
 47 |       childRules.forEach((rule) => {
 48 |         if (rules[k]) {
 49 |           rules[k].key = rule.key
 50 |           rules[k].path = basePath.concat(rule.path)
 51 |         } else {
 52 |           rules[k] = {
 53 |             key: rule.key,
 54 |             path: basePath.concat(rule.path),
 55 |           }
 56 |         }
 57 |         k++
 58 |       })
 59 |       if (k > index) {
 60 |         index = k
 61 |       } else {
 62 |         index++
 63 |       }
 64 |     })
 65 |     return rules
 66 |   } else if (isArrayPattern(node)) {
 67 |     let index = 0
 68 |     node.elements.forEach((child, key) => {
 69 |       rules[index] = {
 70 |         path: [],
 71 |       }
 72 |       rules[index].key = key
 73 |       rules[index].path.push(key)
 74 |       if (isIdentifier(child)) {
 75 |         rules[index].key = child.value
 76 |       }
 77 |       const basePath = rules[index].path
 78 |       const childRules = parseDestructorRules(child as Node)
 79 |       let k = index
 80 |       childRules.forEach((rule) => {
 81 |         if (rules[k]) {
 82 |           rules[k].key = rule.key
 83 |           rules[k].path = basePath.concat(rule.path)
 84 |         } else {
 85 |           rules[k] = {
 86 |             key: rule.key,
 87 |             path: basePath.concat(rule.path),
 88 |           }
 89 |         }
 90 |         k++
 91 |       })
 92 |       if (k > index) {
 93 |         index = k
 94 |       } else {
 95 |         index++
 96 |       }
 97 |     })
 98 |     return rules
 99 |   }
100 |   if (isDestructorExpression(node)) {
101 |     return parseDestructorRules(node.value)
102 |   }
103 |   return rules
104 | }
105 | 
106 | export const setInByDestructor = (
107 |   source: any,
108 |   rules: DestructorRules,
109 |   value: any,
110 |   mutators: Mutators
111 | ) => {
112 |   rules.forEach(({ key, path }) => {
113 |     mutators.setIn([key], source, mutators.getIn(path, value))
114 |   })
115 | }
116 | 
117 | export const getInByDestructor = (
118 |   source: any,
119 |   rules: DestructorRules,
120 |   mutators: Mutators
121 | ) => {
122 |   let response = {}
123 |   if (rules.length) {
124 |     if (isNum(rules[0].path[0])) {
125 |       response = []
126 |     }
127 |   }
128 |   source = isValid(source) ? source : {}
129 |   rules.forEach(({ key, path }) => {
130 |     mutators.setIn(path, response, source[key])
131 |   })
132 |   return response
133 | }
134 | 
135 | export const deleteInByDestructor = (
136 |   source: any,
137 |   rules: DestructorRules,
138 |   mutators: Mutators
139 | ) => {
140 |   rules.forEach(({ key }) => {
141 |     mutators.deleteIn([key], source)
142 |   })
143 | }
144 | 
145 | export const existInByDestructor = (
146 |   source: any,
147 |   rules: DestructorRules,
148 |   start: number,
149 |   mutators: Mutators
150 | ) => {
151 |   return rules.every(({ key }) => {
152 |     return mutators.existIn([key], source, start)
153 |   })
154 | }
155 | 
```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/array-table/effects-markup-schema.vue:
--------------------------------------------------------------------------------

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField>
  4 |       <SchemaBooleanField
  5 |         name="hideFirstColumn"
  6 |         x-decorator="FormItem"
  7 |         x-component="Switch"
  8 |         title="隐藏A2"
  9 |       />
 10 |       <SchemaArrayField
 11 |         name="array"
 12 |         x-decorator="FormItem"
 13 |         x-component="ArrayTable"
 14 |       >
 15 |         <SchemaObjectField>
 16 |           <SchemaVoidField
 17 |             name="column1"
 18 |             x-component="ArrayTable.Column"
 19 |             :x-component-props="{ width: 80, title: 'Index' }"
 20 |             ><SchemaVoidField x-component="ArrayTable.Index" />
 21 |           </SchemaVoidField>
 22 |           <SchemaVoidField
 23 |             name="column2"
 24 |             x-component="ArrayTable.Column"
 25 |             :x-component-props="{
 26 |               title: '显隐->A2',
 27 |               width: 100,
 28 |             }"
 29 |           >
 30 |             <SchemaBooleanField
 31 |               name="a1"
 32 |               x-decorator="FormItem"
 33 |               x-component="Switch"
 34 |             />
 35 |           </SchemaVoidField>
 36 |           <SchemaVoidField
 37 |             x-component="ArrayTable.Column"
 38 |             name="column3"
 39 |             :x-component-props="{ title: 'A2', width: 200 }"
 40 |           >
 41 |             <SchemaStringField
 42 |               x-decorator="FormItem"
 43 |               name="a2"
 44 |               x-component="Input"
 45 |             />
 46 |           </SchemaVoidField>
 47 |           <SchemaVoidField
 48 |             name="column4"
 49 |             x-component="ArrayTable.Column"
 50 |             :x-component-props="{ title: 'A3' }"
 51 |           >
 52 |             <SchemaStringField
 53 |               name="a3"
 54 |               x-decorator="FormItem"
 55 |               x-component="Input"
 56 |             />
 57 |           </SchemaVoidField>
 58 |           <SchemaVoidField
 59 |             name="column5"
 60 |             x-component="ArrayTable.Column"
 61 |             :x-component-props="{
 62 |               title: 'Operations',
 63 |               prop: 'operations',
 64 |               width: 200,
 65 |               fixed: 'right',
 66 |             }"
 67 |           >
 68 |             <SchemaVoidField x-component="FormItem">
 69 |               <SchemaVoidField x-component="ArrayTable.Remove" />
 70 |               <SchemaVoidField x-component="ArrayTable.MoveUp" />
 71 |               <SchemaVoidField x-component="ArrayTable.MoveDown" />
 72 |             </SchemaVoidField>
 73 |           </SchemaVoidField>
 74 |         </SchemaObjectField>
 75 |         <SchemaVoidField x-component="ArrayTable.Addition" title="添加条目" />
 76 |       </SchemaArrayField>
 77 |     </SchemaField>
 78 |     <Submit @submit="log">提交</Submit>
 79 |   </FormProvider>
 80 | </template>
 81 | 
 82 | <script>
 83 | import { createForm, onFieldChange, onFieldReact } from '@formily/core'
 84 | import { FormProvider, createSchemaField } from '@formily/vue'
 85 | import {
 86 |   Submit,
 87 |   FormItem,
 88 |   ArrayTable,
 89 |   Input,
 90 |   Editable,
 91 |   Switch,
 92 | } from '@formily/element'
 93 | 
 94 | const fields = createSchemaField({
 95 |   components: {
 96 |     FormItem,
 97 |     ArrayTable,
 98 |     Input,
 99 |     Editable,
100 |     Switch,
101 |   },
102 | })
103 | 
104 | export default {
105 |   components: { FormProvider, Submit, ...fields },
106 |   data() {
107 |     const form = createForm({
108 |       effects: () => {
109 |         //主动联动模式
110 |         onFieldChange('hideFirstColumn', ['value'], (field) => {
111 |           field.query('array.column3').take((target) => {
112 |             console.log('target', target)
113 |             target.visible = !field.value
114 |           })
115 |           field.query('array.*.a2').take((target) => {
116 |             target.visible = !field.value
117 |           })
118 |         })
119 |         //被动联动模式
120 |         onFieldReact('array.*.a2', (field) => {
121 |           field.visible = !field.query('.a1').get('value')
122 |         })
123 |       },
124 |     })
125 | 
126 |     return {
127 |       form,
128 |     }
129 |   },
130 |   methods: {
131 |     log(...v) {
132 |       console.log(...v)
133 |     },
134 |   },
135 | }
136 | </script>
137 | 
```

--------------------------------------------------------------------------------
/packages/reactive/src/internals.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { isFn, isCollectionType, isNormalType } from './checkers'
  2 | import {
  3 |   RawProxy,
  4 |   ProxyRaw,
  5 |   MakeObModelSymbol,
  6 |   RawShallowProxy,
  7 | } from './environment'
  8 | import { baseHandlers, collectionHandlers } from './handlers'
  9 | import { buildDataTree, getDataNode } from './tree'
 10 | import { isSupportObservable } from './externals'
 11 | import { PropertyKey, IVisitor, BoundaryFunction } from './types'
 12 | 
 13 | const createNormalProxy = (target: any, shallow?: boolean) => {
 14 |   const proxy = new Proxy(target, baseHandlers)
 15 |   ProxyRaw.set(proxy, target)
 16 |   if (shallow) {
 17 |     RawShallowProxy.set(target, proxy)
 18 |   } else {
 19 |     RawProxy.set(target, proxy)
 20 |   }
 21 |   return proxy
 22 | }
 23 | 
 24 | const createCollectionProxy = (target: any, shallow?: boolean) => {
 25 |   const proxy = new Proxy(target, collectionHandlers)
 26 |   ProxyRaw.set(proxy, target)
 27 |   if (shallow) {
 28 |     RawShallowProxy.set(target, proxy)
 29 |   } else {
 30 |     RawProxy.set(target, proxy)
 31 |   }
 32 |   return proxy
 33 | }
 34 | 
 35 | const createShallowProxy = (target: any) => {
 36 |   if (isNormalType(target)) return createNormalProxy(target, true)
 37 |   if (isCollectionType(target)) return createCollectionProxy(target, true)
 38 |   // never reach
 39 |   return target
 40 | }
 41 | 
 42 | export const createObservable = (
 43 |   target: any,
 44 |   key?: PropertyKey,
 45 |   value?: any,
 46 |   shallow?: boolean
 47 | ) => {
 48 |   if (typeof value !== 'object') return value
 49 |   const raw = ProxyRaw.get(value)
 50 |   if (!!raw) {
 51 |     const node = getDataNode(raw)
 52 |     if (!node.target) node.target = target
 53 |     node.key = key
 54 |     return value
 55 |   }
 56 | 
 57 |   if (!isSupportObservable(value)) return value
 58 | 
 59 |   if (target) {
 60 |     const parentRaw = ProxyRaw.get(target) || target
 61 |     const isShallowParent = RawShallowProxy.get(parentRaw)
 62 |     if (isShallowParent) return value
 63 |   }
 64 | 
 65 |   buildDataTree(target, key, value)
 66 |   if (shallow) return createShallowProxy(value)
 67 |   if (isNormalType(value)) return createNormalProxy(value)
 68 |   if (isCollectionType(value)) return createCollectionProxy(value)
 69 |   // never reach
 70 |   return value
 71 | }
 72 | 
 73 | export const createAnnotation = <T extends (visitor: IVisitor) => any>(
 74 |   maker: T
 75 | ) => {
 76 |   const annotation = (target: any): ReturnType<T> => {
 77 |     return maker({ value: target })
 78 |   }
 79 |   if (isFn(maker)) {
 80 |     annotation[MakeObModelSymbol] = maker
 81 |   }
 82 |   return annotation
 83 | }
 84 | 
 85 | export const getObservableMaker = (target: any) => {
 86 |   if (target[MakeObModelSymbol]) {
 87 |     if (!target[MakeObModelSymbol][MakeObModelSymbol]) {
 88 |       return target[MakeObModelSymbol]
 89 |     }
 90 |     return getObservableMaker(target[MakeObModelSymbol])
 91 |   }
 92 | }
 93 | 
 94 | export const createBoundaryFunction = (
 95 |   start: (...args: any) => void,
 96 |   end: (...args: any) => void
 97 | ) => {
 98 |   function boundary<F extends (...args: any) => any>(fn?: F): ReturnType<F> {
 99 |     let results: ReturnType<F>
100 |     try {
101 |       start()
102 |       if (isFn(fn)) {
103 |         results = fn()
104 |       }
105 |     } finally {
106 |       end()
107 |     }
108 |     return results
109 |   }
110 | 
111 |   boundary.bound = createBindFunction(boundary)
112 |   return boundary
113 | }
114 | 
115 | export const createBindFunction = <Boundary extends BoundaryFunction>(
116 |   boundary: Boundary
117 | ) => {
118 |   function bind<F extends (...args: any[]) => any>(
119 |     callback?: F,
120 |     context?: any
121 |   ): F {
122 |     return ((...args: any[]) =>
123 |       boundary(() => callback.apply(context, args))) as any
124 |   }
125 |   return bind
126 | }
127 | 
128 | export const createBoundaryAnnotation = (
129 |   start: (...args: any) => void,
130 |   end: (...args: any) => void
131 | ) => {
132 |   const boundary = createBoundaryFunction(start, end)
133 |   const annotation = createAnnotation(({ target, key }) => {
134 |     target[key] = boundary.bound(target[key], target)
135 |     return target
136 |   })
137 |   boundary[MakeObModelSymbol] = annotation
138 |   boundary.bound[MakeObModelSymbol] = annotation
139 |   return boundary
140 | }
141 | 
```

--------------------------------------------------------------------------------
/packages/antd/src/__builtins__/sort.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import { DndContext, DragEndEvent, DragStartEvent } from '@dnd-kit/core'
  2 | import {
  3 |   SortableContext,
  4 |   useSortable,
  5 |   verticalListSortingStrategy,
  6 | } from '@dnd-kit/sortable'
  7 | import { ReactFC } from '@formily/reactive-react'
  8 | import React, { createContext, useContext, useMemo } from 'react'
  9 | 
 10 | export interface ISortableContainerProps {
 11 |   list: any[]
 12 |   start?: number
 13 |   accessibility?: {
 14 |     container?: Element
 15 |   }
 16 |   onSortStart?: (event: DragStartEvent) => void
 17 |   onSortEnd?: (event: { oldIndex: number; newIndex: number }) => void
 18 | }
 19 | 
 20 | export function SortableContainer<T extends React.HTMLAttributes<HTMLElement>>(
 21 |   Component: ReactFC<T>
 22 | ): ReactFC<ISortableContainerProps & T> {
 23 |   return ({
 24 |     list,
 25 |     start = 0,
 26 |     accessibility,
 27 |     onSortStart,
 28 |     onSortEnd,
 29 |     ...props
 30 |   }) => {
 31 |     const _onSortEnd = (event: DragEndEvent) => {
 32 |       const { active, over } = event
 33 |       const oldIndex = (active.id as number) - 1
 34 |       const newIndex = (over?.id as number) - 1
 35 |       onSortEnd?.({
 36 |         oldIndex,
 37 |         newIndex,
 38 |       })
 39 |     }
 40 | 
 41 |     return (
 42 |       <DndContext
 43 |         accessibility={accessibility}
 44 |         onDragStart={onSortStart}
 45 |         onDragEnd={_onSortEnd}
 46 |       >
 47 |         <SortableContext
 48 |           items={list.map((_, index) => index + start + 1)}
 49 |           strategy={verticalListSortingStrategy}
 50 |         >
 51 |           <Component {...(props as unknown as T)}>{props.children}</Component>
 52 |         </SortableContext>
 53 |       </DndContext>
 54 |     )
 55 |   }
 56 | }
 57 | 
 58 | export const useSortableItem = () => {
 59 |   return useContext(SortableItemContext)
 60 | }
 61 | 
 62 | export const SortableItemContext = createContext<
 63 |   Partial<ReturnType<typeof useSortable>>
 64 | >({})
 65 | 
 66 | export interface ISortableElementProps {
 67 |   index?: number
 68 |   lockAxis?: 'x' | 'y'
 69 | }
 70 | 
 71 | export function SortableElement<T extends React.HTMLAttributes<HTMLElement>>(
 72 |   Component: ReactFC<T>
 73 | ): ReactFC<T & ISortableElementProps> {
 74 |   return ({ index = 0, lockAxis, ...props }) => {
 75 |     const sortable = useSortable({
 76 |       id: index + 1,
 77 |     })
 78 |     const { setNodeRef, transform, transition, isDragging } = sortable
 79 |     if (transform) {
 80 |       switch (lockAxis) {
 81 |         case 'x':
 82 |           transform.y = 0
 83 |           break
 84 |         case 'y':
 85 |           transform.x = 0
 86 |           break
 87 |         default:
 88 |           break
 89 |       }
 90 |     }
 91 | 
 92 |     const style = useMemo(() => {
 93 |       const itemStyle: React.CSSProperties = {
 94 |         position: 'relative',
 95 |         touchAction: 'none',
 96 |         zIndex: 1,
 97 |         transform: `translate3d(${transform?.x || 0}px, ${
 98 |           transform?.y || 0
 99 |         }px, 0)`,
100 |         transition: `${transform ? 'all 200ms ease' : ''}`,
101 |       }
102 |       const dragStyle: React.CSSProperties = {
103 |         transition,
104 |         opacity: '0.8',
105 |         transform: `translate3d(${transform?.x || 0}px, ${
106 |           transform?.y || 0
107 |         }px, 0)`,
108 |       }
109 | 
110 |       const computedStyle = isDragging
111 |         ? {
112 |             ...itemStyle,
113 |             ...dragStyle,
114 |             ...props.style,
115 |           }
116 |         : {
117 |             ...itemStyle,
118 |             ...props.style,
119 |           }
120 | 
121 |       return computedStyle
122 |     }, [isDragging, transform, transition, props.style])
123 | 
124 |     return (
125 |       <SortableItemContext.Provider value={sortable}>
126 |         {Component({
127 |           ...props,
128 |           style,
129 |           ref: setNodeRef,
130 |         } as unknown as T)}
131 |       </SortableItemContext.Provider>
132 |     )
133 |   }
134 | }
135 | 
136 | export function SortableHandle<T extends React.HTMLAttributes<HTMLElement>>(
137 |   Component: ReactFC<T>
138 | ): ReactFC<T> {
139 |   return (props: T) => {
140 |     const { attributes, listeners } = useSortableItem()
141 |     return <Component {...props} {...attributes} {...listeners} />
142 |   }
143 | }
144 | 
```

--------------------------------------------------------------------------------
/packages/vue/src/types/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Component } from 'vue'
  2 | import * as VueDemi from 'vue-demi'
  3 | import {
  4 |   Form,
  5 |   IFieldFactoryProps,
  6 |   IVoidFieldFactoryProps,
  7 |   GeneralField,
  8 |   Field,
  9 |   ObjectField,
 10 |   FormPatternTypes,
 11 |   FieldDisplayTypes,
 12 |   FieldValidator,
 13 | } from '@formily/core'
 14 | import type { FormPathPattern } from '@formily/shared'
 15 | import type { ISchema, Schema, SchemaKey } from '@formily/json-schema'
 16 | 
 17 | class Helper<Props> {
 18 |   Return = VueDemi.defineComponent({} as { props: Record<keyof Props, any> })
 19 | }
 20 | 
 21 | export type DefineComponent<Props> = Helper<Props>['Return']
 22 | 
 23 | export type VueComponent = Component
 24 | 
 25 | export type VueComponentOptionsWithProps = {
 26 |   props: unknown
 27 | }
 28 | 
 29 | export type VueComponentProps<T extends VueComponent> =
 30 |   T extends VueComponentOptionsWithProps ? T['props'] : T
 31 | 
 32 | export interface IProviderProps {
 33 |   form: Form
 34 | }
 35 | 
 36 | export type IFieldProps<
 37 |   D extends VueComponent = VueComponent,
 38 |   C extends VueComponent = VueComponent
 39 | > = IFieldFactoryProps<D, C>
 40 | 
 41 | export type IVoidFieldProps<
 42 |   D extends VueComponent = VueComponent,
 43 |   C extends VueComponent = VueComponent
 44 | > = IVoidFieldFactoryProps<D, C>
 45 | 
 46 | export type IArrayFieldProps = IFieldProps
 47 | export type IObjectFieldProps = IFieldProps
 48 | 
 49 | export interface IReactiveFieldProps {
 50 |   fieldType: 'Field' | 'ArrayField' | 'ObjectField' | 'VoidField'
 51 |   fieldProps: IFieldProps | IVoidFieldProps
 52 | }
 53 | 
 54 | export interface IComponentMapper<T extends VueComponent = any> {
 55 |   (target: T): VueComponent
 56 | }
 57 | 
 58 | export type IStateMapper<Props> =
 59 |   | {
 60 |       [key in keyof Field]?: keyof Props | boolean
 61 |     }
 62 |   | ((props: Props, field: GeneralField) => Props)
 63 | 
 64 | export type SchemaVueComponents = Record<string, VueComponent>
 65 | 
 66 | export interface ISchemaFieldVueFactoryOptions<
 67 |   Components extends SchemaVueComponents = any
 68 | > {
 69 |   components?: Components
 70 |   scope?: any
 71 | }
 72 | 
 73 | export interface ISchemaFieldProps
 74 |   extends Omit<IRecursionFieldProps, 'name' | 'schema'> {
 75 |   schema?: ISchema
 76 |   components?: {
 77 |     [key: string]: VueComponent
 78 |   }
 79 |   scope?: any
 80 |   name?: SchemaKey
 81 | }
 82 | 
 83 | export interface ISchemaMapper {
 84 |   (schema: Schema, name: SchemaKey): Schema
 85 | }
 86 | 
 87 | export interface ISchemaFilter {
 88 |   (schema: Schema, name: SchemaKey): boolean
 89 | }
 90 | 
 91 | export interface IRecursionFieldProps {
 92 |   schema: Schema
 93 |   name?: SchemaKey
 94 |   basePath?: FormPathPattern
 95 |   onlyRenderProperties?: boolean
 96 |   onlyRenderSelf?: boolean
 97 |   mapProperties?: ISchemaMapper
 98 |   filterProperties?: ISchemaFilter
 99 | }
100 | 
101 | export type ObjectKey = string | number | boolean | symbol
102 | 
103 | export type KeyOfComponents<T> = keyof T
104 | 
105 | export type ComponentPath<
106 |   T,
107 |   Key extends KeyOfComponents<T> = KeyOfComponents<T>
108 | > = Key extends string ? Key : never
109 | 
110 | export type ComponentPropsByPathValue<
111 |   T extends SchemaVueComponents,
112 |   P extends ComponentPath<T>
113 | > = P extends keyof T ? VueComponentProps<T[P]> : never
114 | 
115 | export type ISchemaMarkupFieldProps<
116 |   Components extends SchemaVueComponents = SchemaVueComponents,
117 |   Decorator extends ComponentPath<Components> = ComponentPath<Components>,
118 |   Component extends ComponentPath<Components> = ComponentPath<Components>
119 | > = ISchema<
120 |   Decorator,
121 |   Component,
122 |   ComponentPropsByPathValue<Components, Decorator>,
123 |   ComponentPropsByPathValue<Components, Component>,
124 |   FormPatternTypes,
125 |   FieldDisplayTypes,
126 |   FieldValidator,
127 |   string,
128 |   GeneralField
129 | >
130 | 
131 | export type ISchemaTypeFieldProps<
132 |   Components extends SchemaVueComponents = SchemaVueComponents,
133 |   Decorator extends ComponentPath<Components> = ComponentPath<Components>,
134 |   Component extends ComponentPath<Components> = ComponentPath<Components>
135 | > = Omit<ISchemaMarkupFieldProps<Components, Decorator, Component>, 'type'>
136 | 
137 | export type IExpressionScopeProps = {
138 |   value: any
139 | }
140 | 
```

--------------------------------------------------------------------------------
/packages/core/docs/guide/mvvm.md:
--------------------------------------------------------------------------------

```markdown
 1 | # MVVM
 2 | 
 3 | ## OOP architecture
 4 | 
 5 | **MVVM** (**Model–view–viewmodel**) is an OOP software architecture model. Its core is to separate the logic and view of our application to improve code maintainability and application robustness. We can use a picture to describe:
 6 | 
 7 | ![](//img.alicdn.com/imgextra/i3/O1CN01jiB7h723ZFf0lBCTo_!!6000000007269-55-tps-1244-432.svg)
 8 | 
 9 | To explain, the View (view layer) is responsible for maintaining the UI structure and style, and is responsible for data binding with the ViewModel (view model). The data binding relationship here is two-way, that is, the ViewModel (view model) data occurs. Changes will trigger the update of the View (view layer), and at the same time changes in the data of the view layer will trigger the changes of the ViewModel (view model). Model is more biased towards the actual business data processing model. Both ViewModel and Model are congested models, and both are injected with business logic from different fields. For example, the business logic of ViewModel is more biased towards the domain logic of the view interaction layer, while the business logic of Model is more biased towards the processing logic of business data.
10 | 
11 | So, what should the Formily solution be positioned in MVVM?
12 | 
13 | Obviously, Formily provides two tiers of View and ViewModel capabilities. View is @formily/react @formily/vue, which is specifically used to bridge communication with @formily/core. Therefore, @formily/core is positioned at the ViewModel layer. ,
14 | 
15 | Where is the Model layer?
16 | 
17 | Of course it is our actual business code layer, this layer formily will not manage, so at this layer, whether users maintain a Model in OOP mode or maintain a series of business logic function sets in FP mode, formily Don't care.
18 | 
19 | Therefore, this also makes formily's intrusion into the business very low, because formily's goal is to reduce the cost of users designing ViewModels, allowing users to focus more on the realization of business logic.
20 | 
21 | ## FP architecture
22 | 
23 | Remember before the React team used the simplest expression **UI = fn(State)** to express the entire React system? Such a functional UI is very simple and clear. Will it conflict with the MVVM model?
24 | 
25 | There is no conflict, because in the MVVM mode, the relationship between View and ViewModel is actually approximately equal to **UI = fn(State)**, because ViewModel is a congestion model injected with logic, which is related to **fn(State) ** can achieve the same goal, but it is a more OOP expression, but **fn(State)** is a more functional expression, the state exists as an anemia model, through one function after another, Immutable updates to the anemia model are finally reflected in the UI.
26 | 
27 | Therefore, from the perspective of separation of logic and data, functional expression is clearer, but functional expression requires all data to be Immutable. Therefore, in scenarios with high performance requirements, the benefits of using a functional model will not be too great, of course, this is only the case in the js language. On the contrary, the MVVM model requires more data for Reactive data, that is, a responsive data model that can manipulate data by reference, so that data changes can be accurately monitored, and finally reflected on the UI.
28 | 
29 | Therefore, in the form scenario, the performance advantage of the MVVM mode will be better. The most important thing is that most of the GUI products that have survived for decades almost all use MVVM coincidentally. It seems that in the front-end field, the function The type system will be more academic. In terms of the actual benefits to the business, MVVM is still the first choice.
30 | 
```

--------------------------------------------------------------------------------
/packages/react/docs/api/components/ArrayField.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | order: 1
  3 | ---
  4 | 
  5 | # ArrayField
  6 | 
  7 | ## Description
  8 | 
  9 | As @formily/core's [createArrayField](https://core.formilyjs.org/api/models/form#createarrayfield) React implementation, it is a bridge component specifically used to bind ViewModel and input controls, ArrayField component Property reference [IFieldFactoryProps](https://core.formilyjs.org/api/models/form#ifieldfactoryprops)
 10 | 
 11 | <Alert>
 12 | When we use the ArrayField component, we must remember to pass the name attribute. At the same time, use render props to organize sub-components
 13 | </Alert>
 14 | 
 15 | ## Signature
 16 | 
 17 | ```ts
 18 | type ArrayField = React.FC<React.PropsWithChildren<IFieldFactoryProps>>
 19 | ```
 20 | 
 21 | ## Custom component use case
 22 | 
 23 | ```tsx
 24 | import React from 'react'
 25 | import { createForm, ArrayField as ArrayFieldType } from '@formily/core'
 26 | import {
 27 |   FormProvider,
 28 |   Field,
 29 |   ArrayField,
 30 |   useField,
 31 |   observer,
 32 | } from '@formily/react'
 33 | import { Input, Button, Space } from 'antd'
 34 | 
 35 | const form = createForm()
 36 | 
 37 | const ArrayComponent = observer(() => {
 38 |   const field = useField<ArrayFieldType>()
 39 |   return (
 40 |     <>
 41 |       <div>
 42 |         {field.value?.map((item, index) => (
 43 |           <div key={index} style={{ display: 'flex-block', marginBottom: 10 }}>
 44 |             <Space>
 45 |               <Field name={index} component={[Input]} />
 46 |               <Button
 47 |                 onClick={() => {
 48 |                   field.remove(index)
 49 |                 }}
 50 |               >
 51 |                 Remove
 52 |               </Button>
 53 |               <Button
 54 |                 onClick={() => {
 55 |                   field.moveUp(index)
 56 |                 }}
 57 |               >
 58 |                 Move Up
 59 |               </Button>
 60 |               <Button
 61 |                 onClick={() => {
 62 |                   field.moveDown(index)
 63 |                 }}
 64 |               >
 65 |                 Move Down
 66 |               </Button>
 67 |             </Space>
 68 |           </div>
 69 |         ))}
 70 |       </div>
 71 |       <Button
 72 |         onClick={() => {
 73 |           field.push('')
 74 |         }}
 75 |       >
 76 |         Add
 77 |       </Button>
 78 |     </>
 79 |   )
 80 | })
 81 | 
 82 | export default () => (
 83 |   <FormProvider form={form}>
 84 |     <ArrayField name="array" component={[ArrayComponent]} />
 85 |   </FormProvider>
 86 | )
 87 | ```
 88 | 
 89 | ## RenderProps use cases
 90 | 
 91 | ```tsx
 92 | import React from 'react'
 93 | import { createForm } from '@formily/core'
 94 | import { FormProvider, Field, ArrayField } from '@formily/react'
 95 | import { Input, Button, Space } from 'antd'
 96 | 
 97 | const form = createForm()
 98 | 
 99 | export default () => (
100 |   <FormProvider form={form}>
101 |     <ArrayField name="array">
102 |       {(field) => {
103 |         return (
104 |           <>
105 |             <div>
106 |               {field.value?.map((item, index) => (
107 |                 <div
108 |                   key={index}
109 |                   style={{ display: 'flex-block', marginBottom: 10 }}
110 |                 >
111 |                   <Space>
112 |                     <Field name={index} component={[Input]} />
113 |                     <Button
114 |                       onClick={() => {
115 |                         field.remove(index)
116 |                       }}
117 |                     >
118 |                       Remove
119 |                     </Button>
120 |                     <Button
121 |                       onClick={() => {
122 |                         field.moveUp(index)
123 |                       }}
124 |                     >
125 |                       Move Up
126 |                     </Button>
127 |                     <Button
128 |                       onClick={() => {
129 |                         field.moveDown(index)
130 |                       }}
131 |                     >
132 |                       Move Down
133 |                     </Button>
134 |                   </Space>
135 |                 </div>
136 |               ))}
137 |             </div>
138 |             <Button onClick={() => field.push('')}>Add</Button>
139 |           </>
140 |         )
141 |       }}
142 |     </ArrayField>
143 |   </FormProvider>
144 | )
145 | ```
146 | 
```

--------------------------------------------------------------------------------
/packages/next/src/form-button-group/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * 1. FormItem网格布局
  3 |  * 2. 居中,居右,居左布局
  4 |  * 3. 行内布局
  5 |  * 4. 吸底布局
  6 |  */
  7 | import React, { useRef, useLayoutEffect, useState } from 'react'
  8 | import StickyBox from 'react-sticky-box'
  9 | import { ReactFC } from '@formily/react'
 10 | import { Space, ISpaceProps } from '../space'
 11 | import { BaseItem, IFormItemProps } from '../form-item'
 12 | import { usePrefixCls } from '../__builtins__'
 13 | import cls from 'classnames'
 14 | interface IStickyProps extends React.ComponentProps<typeof StickyBox> {
 15 |   align?: React.CSSProperties['textAlign']
 16 | }
 17 | 
 18 | type IFormButtonGroupProps = Omit<ISpaceProps, 'align' | 'size'> & {
 19 |   align?: React.CSSProperties['textAlign']
 20 |   gutter?: number
 21 | }
 22 | 
 23 | type ComposedButtonGroup = ReactFC<IFormButtonGroupProps> & {
 24 |   Sticky: ReactFC<IStickyProps>
 25 |   FormItem: ReactFC<
 26 |     IFormItemProps & {
 27 |       gutter?: number
 28 |     }
 29 |   >
 30 | }
 31 | 
 32 | function getInheritedBackgroundColor(el: HTMLElement) {
 33 |   // get default style for current browser
 34 |   let defaultStyle = getDefaultBackground() // typically "rgba(0, 0, 0, 0)"
 35 | 
 36 |   // get computed color for el
 37 |   let backgroundColor = window.getComputedStyle(el).backgroundColor
 38 | 
 39 |   // if we got a real value, return it
 40 |   if (backgroundColor != defaultStyle) return backgroundColor
 41 | 
 42 |   // if we've reached the top parent el without getting an explicit color, return default
 43 |   if (!el.parentElement) return defaultStyle
 44 | 
 45 |   // otherwise, recurse and try again on parent element
 46 |   return getInheritedBackgroundColor(el.parentElement)
 47 | }
 48 | 
 49 | function getDefaultBackground() {
 50 |   // have to add to the document in order to use getComputedStyle
 51 |   let div = document.createElement('div')
 52 |   document.head.appendChild(div)
 53 |   let bg = window.getComputedStyle(div).backgroundColor
 54 |   document.head.removeChild(div)
 55 |   return bg
 56 | }
 57 | 
 58 | export const FormButtonGroup: ComposedButtonGroup = ({
 59 |   align = 'left',
 60 |   gutter,
 61 |   ...props
 62 | }) => {
 63 |   const prefixCls = usePrefixCls('formily-button-group')
 64 |   return (
 65 |     <Space
 66 |       {...props}
 67 |       size={gutter}
 68 |       className={cls(prefixCls, props.className)}
 69 |       style={{
 70 |         ...props.style,
 71 |         justifyContent:
 72 |           align === 'left'
 73 |             ? 'flex-start'
 74 |             : align === 'right'
 75 |             ? 'flex-end'
 76 |             : 'center',
 77 |         display: 'flex',
 78 |       }}
 79 |     >
 80 |       {props.children}
 81 |     </Space>
 82 |   )
 83 | }
 84 | 
 85 | FormButtonGroup.FormItem = ({ gutter, ...props }) => {
 86 |   return (
 87 |     <BaseItem
 88 |       {...props}
 89 |       label=" "
 90 |       style={{
 91 |         margin: 0,
 92 |         padding: 0,
 93 |         ...props.style,
 94 |         width: '100%',
 95 |       }}
 96 |       colon={false}
 97 |     >
 98 |       {props.children?.['length'] ? (
 99 |         <Space size={gutter}>{props.children}</Space>
100 |       ) : (
101 |         props.children
102 |       )}
103 |     </BaseItem>
104 |   )
105 | }
106 | 
107 | FormButtonGroup.Sticky = ({ align = 'left', ...props }) => {
108 |   const ref = useRef()
109 |   const [color, setColor] = useState('transparent')
110 |   const prefixCls = usePrefixCls('formily-button-group')
111 | 
112 |   useLayoutEffect(() => {
113 |     if (ref.current) {
114 |       const computed = getInheritedBackgroundColor(ref.current)
115 |       if (computed !== color) {
116 |         setColor(computed)
117 |       }
118 |     }
119 |   })
120 |   return (
121 |     <StickyBox
122 |       {...props}
123 |       className={cls(`${prefixCls}-sticky`, props.className)}
124 |       style={{
125 |         backgroundColor: color,
126 |         ...props.style,
127 |       }}
128 |       bottom
129 |     >
130 |       <div
131 |         ref={ref}
132 |         className={`${prefixCls}-sticky-inner`}
133 |         style={{
134 |           ...props.style,
135 |           justifyContent:
136 |             align === 'left'
137 |               ? 'flex-start'
138 |               : align === 'right'
139 |               ? 'flex-end'
140 |               : 'center',
141 |         }}
142 |       >
143 |         {props.children}
144 |       </div>
145 |     </StickyBox>
146 |   )
147 | }
148 | 
149 | export default FormButtonGroup
150 | 
```

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

```markdown
 1 | # Form
 2 | 
 3 | > The combination of FormProvider + FormLayout + form tags can help us quickly implement forms that are submitted with carriage return and can be laid out in batches
 4 | 
 5 | ## Use Cases
 6 | 
 7 | ```tsx
 8 | import React from 'react'
 9 | import {
10 |   Input,
11 |   Select,
12 |   Form,
13 |   FormItem,
14 |   FormGrid,
15 |   FormButtonGroup,
16 |   Submit,
17 | } from '@formily/antd'
18 | import { createForm } from '@formily/core'
19 | import { Field } from '@formily/react'
20 | 
21 | const form = createForm()
22 | 
23 | export default () => (
24 |   <Form
25 |     form={form}
26 |     layout="vertical"
27 |     feedbackLayout="terse"
28 |     onAutoSubmit={console.log}
29 |     onAutoSubmitFailed={console.log}
30 |   >
31 |     <FormGrid maxColumns={4}>
32 |       <Field
33 |         name="aa"
34 |         title="select box"
35 |         decorator={[FormItem]}
36 |         component={[Select]}
37 |         dataSource={[
38 |           {
39 |             label: 'Option 1',
40 |             value: 1,
41 |           },
42 |           {
43 |             label: 'Option 2',
44 |             value: 2,
45 |           },
46 |         ]}
47 |       />
48 |       <Field
49 |         name="bb"
50 |         title="input box"
51 |         required
52 |         decorator={[FormItem]}
53 |         component={[Input]}
54 |       />
55 |       <Field
56 |         name="cc"
57 |         title="input box"
58 |         decorator={[FormItem]}
59 |         component={[Input]}
60 |       />
61 |       <Field
62 |         name="dd"
63 |         title="input box"
64 |         decorator={[FormItem]}
65 |         component={[Input]}
66 |       />
67 |       <Field
68 |         name="ee"
69 |         title="input box"
70 |         decorator={[FormItem]}
71 |         component={[Input]}
72 |       />
73 |       <FormButtonGroup.FormItem>
74 |         <Submit>Query</Submit>
75 |       </FormButtonGroup.FormItem>
76 |     </FormGrid>
77 |   </Form>
78 | )
79 | ```
80 | 
81 | <Alert style="margin-top:20px">
82 | Note: To realize the carriage return submission, we cannot pass the onSubmit event to it when using the Submit component, otherwise the carriage return submission will become invalid. The purpose of this is to prevent users from writing onSubmit event listeners in multiple places at the same time, and processing logic If they are inconsistent, it is difficult to locate the problem when submitting.
83 | </Alert>
84 | 
85 | ## API
86 | 
87 | For layout-related API properties, we can refer to [FormLayout](./form-layout), and the rest are the unique API properties of the Form component
88 | 
89 | | Property name          | Type                                                                                             | Description                                                         | Default value |
90 | | ---------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | ------------- |
91 | | form                   | [Form](https://core.formilyjs.org/api/models/form)                                               | Form example                                                        | -             |
92 | | component              | string                                                                                           | Rendering component, can be specified as custom component rendering | `form`        |
93 | | previewTextPlaceholder | ReactNode                                                                                        | Preview State Placeholder                                           | `N/A`         |
94 | | onAutoSubmit           | `(values:any)=>any`                                                                              | Carriage return submit event callback                               | -             |
95 | | onAutoSubmitFailed     | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Carriage return submission verification failure event callback      | -             |
96 | 
```

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

```typescript
  1 | import { isArr } from './checkers'
  2 | import { instOf } from './instanceof'
  3 | const isArray = isArr
  4 | const keyList = Object.keys
  5 | const hasProp = Object.prototype.hasOwnProperty
  6 | 
  7 | /* eslint-disable */
  8 | function equal(a: any, b: any) {
  9 |   // fast-deep-equal index.js 2.0.1
 10 |   if (a === b) {
 11 |     return true
 12 |   }
 13 | 
 14 |   if (a && b && typeof a === 'object' && typeof b === 'object') {
 15 |     const arrA = isArray(a)
 16 |     const arrB = isArray(b)
 17 |     let i: number
 18 |     let length: number
 19 |     let key: string | number
 20 | 
 21 |     if (arrA && arrB) {
 22 |       length = a.length
 23 |       if (length !== b.length) {
 24 |         return false
 25 |       }
 26 |       for (i = length; i-- !== 0; ) {
 27 |         if (!equal(a[i], b[i])) {
 28 |           return false
 29 |         }
 30 |       }
 31 |       return true
 32 |     }
 33 | 
 34 |     if (arrA !== arrB) {
 35 |       return false
 36 |     }
 37 |     const momentA = a && a._isAMomentObject
 38 |     const momentB = b && b._isAMomentObject
 39 |     if (momentA !== momentB) return false
 40 |     if (momentA && momentB) return a.isSame(b)
 41 |     const immutableA = a && a.toJS
 42 |     const immutableB = b && b.toJS
 43 |     if (immutableA !== immutableB) return false
 44 |     if (immutableA) return a.is ? a.is(b) : a === b
 45 |     const dateA = instOf(a, 'Date')
 46 |     const dateB = instOf(b, 'Date')
 47 |     if (dateA !== dateB) {
 48 |       return false
 49 |     }
 50 |     if (dateA && dateB) {
 51 |       return a.getTime() === b.getTime()
 52 |     }
 53 |     const regexpA = instOf(a, 'RegExp')
 54 |     const regexpB = instOf(b, 'RegExp')
 55 |     if (regexpA !== regexpB) {
 56 |       return false
 57 |     }
 58 |     if (regexpA && regexpB) {
 59 |       return a.toString() === b.toString()
 60 |     }
 61 |     const urlA = instOf(a, 'URL')
 62 |     const urlB = instOf(b, 'URL')
 63 | 
 64 |     if (urlA !== urlB) {
 65 |       return false
 66 |     }
 67 | 
 68 |     if (urlA && urlB) {
 69 |       return a.href === b.href
 70 |     }
 71 | 
 72 |     const schemaA = a && a.toJSON
 73 |     const schemaB = b && b.toJSON
 74 |     if (schemaA !== schemaB) return false
 75 |     if (schemaA && schemaB) return equal(a.toJSON(), b.toJSON())
 76 | 
 77 |     const keys = keyList(a)
 78 |     length = keys.length
 79 | 
 80 |     if (length !== keyList(b).length) {
 81 |       return false
 82 |     }
 83 | 
 84 |     for (i = length; i-- !== 0; ) {
 85 |       if (!hasProp.call(b, keys[i])) {
 86 |         return false
 87 |       }
 88 |     }
 89 |     // end fast-deep-equal
 90 | 
 91 |     // Custom handling for React
 92 |     for (i = length; i-- !== 0; ) {
 93 |       key = keys[i]
 94 | 
 95 |       if (key === '_owner' && a.$$typeof) {
 96 |         // React-specific: avoid traversing React elements' _owner.
 97 |         //  _owner contains circular references
 98 |         // and is not needed when comparing the actual elements (and not their owners)
 99 |         // .$$typeof and ._store on just reasonable markers of a react element
100 |         continue
101 |       } else {
102 |         // all other properties should be traversed as usual
103 |         if (!equal(a[key], b[key])) {
104 |           return false
105 |         }
106 |       }
107 |     }
108 | 
109 |     // fast-deep-equal index.js 2.0.1
110 |     return true
111 |   }
112 | 
113 |   return a !== a && b !== b
114 | }
115 | // end fast-deep-equal
116 | 
117 | export const isEqual = function exportedEqual(a: any, b: any) {
118 |   try {
119 |     return equal(a, b)
120 |   } catch (error) {
121 |     /* istanbul ignore next */
122 |     if (
123 |       (error.message && error.message.match(/stack|recursion/i)) ||
124 |       error.number === -2146828260
125 |     ) {
126 |       // warn on circular references, don't crash
127 |       // browsers give this different errors name and messages:
128 |       // chrome/safari: "RangeError", "Maximum call stack size exceeded"
129 |       // firefox: "InternalError", too much recursion"
130 |       // edge: "Error", "Out of stack space"
131 |       console.warn(
132 |         'Warning: react-fast-compare does not handle circular references.',
133 |         error.name,
134 |         error.message
135 |       )
136 |       return false
137 |     }
138 |     // some other error. we should definitely know about these
139 |     /* istanbul ignore next */
140 |     throw error
141 |   }
142 | }
143 | 
```

--------------------------------------------------------------------------------
/packages/antd/src/form-button-group/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * 1. FormItem网格布局
  3 |  * 2. 居中,居右,居左布局
  4 |  * 3. 行内布局
  5 |  * 4. 吸底布局
  6 |  */
  7 | import React, { useRef, useLayoutEffect, useState } from 'react'
  8 | import { ReactFC } from '@formily/react'
  9 | import { Space } from 'antd'
 10 | import { SpaceProps } from 'antd/lib/space'
 11 | import { BaseItem, IFormItemProps } from '../form-item'
 12 | import { usePrefixCls } from '../__builtins__'
 13 | import StickyBox from 'react-sticky-box'
 14 | import cls from 'classnames'
 15 | interface IStickyProps extends React.ComponentProps<typeof StickyBox> {
 16 |   align?: React.CSSProperties['textAlign']
 17 | }
 18 | 
 19 | type IFormButtonGroupProps = Omit<SpaceProps, 'align' | 'size'> & {
 20 |   align?: React.CSSProperties['textAlign']
 21 |   gutter?: number
 22 | }
 23 | 
 24 | type ComposedButtonGroup = ReactFC<IFormButtonGroupProps> & {
 25 |   Sticky: ReactFC<React.PropsWithChildren<IStickyProps>>
 26 |   FormItem: ReactFC<
 27 |     IFormItemProps & {
 28 |       gutter?: number
 29 |     }
 30 |   >
 31 | }
 32 | 
 33 | function getInheritedBackgroundColor(el: HTMLElement) {
 34 |   // get default style for current browser
 35 |   const defaultStyle = getDefaultBackground() // typically "rgba(0, 0, 0, 0)"
 36 | 
 37 |   // get computed color for el
 38 |   const backgroundColor = window.getComputedStyle(el).backgroundColor
 39 | 
 40 |   // if we got a real value, return it
 41 |   if (backgroundColor != defaultStyle) return backgroundColor
 42 | 
 43 |   // if we've reached the top parent el without getting an explicit color, return default
 44 |   if (!el.parentElement) return defaultStyle
 45 | 
 46 |   // otherwise, recurse and try again on parent element
 47 |   return getInheritedBackgroundColor(el.parentElement)
 48 | }
 49 | 
 50 | function getDefaultBackground() {
 51 |   // have to add to the document in order to use getComputedStyle
 52 |   let div = document.createElement('div')
 53 |   document.head.appendChild(div)
 54 |   let bg = window.getComputedStyle(div).backgroundColor
 55 |   document.head.removeChild(div)
 56 |   return bg
 57 | }
 58 | 
 59 | export const FormButtonGroup: ComposedButtonGroup = ({
 60 |   align = 'left',
 61 |   gutter,
 62 |   ...props
 63 | }) => {
 64 |   const prefixCls = usePrefixCls('formily-button-group')
 65 |   return (
 66 |     <Space
 67 |       {...props}
 68 |       size={gutter}
 69 |       className={cls(prefixCls, props.className)}
 70 |       style={{
 71 |         ...props.style,
 72 |         justifyContent:
 73 |           align === 'left'
 74 |             ? 'flex-start'
 75 |             : align === 'right'
 76 |             ? 'flex-end'
 77 |             : 'center',
 78 |         display: 'flex',
 79 |       }}
 80 |     >
 81 |       {props.children}
 82 |     </Space>
 83 |   )
 84 | }
 85 | 
 86 | FormButtonGroup.FormItem = ({ gutter, ...props }) => {
 87 |   return (
 88 |     <BaseItem
 89 |       {...props}
 90 |       label=" "
 91 |       style={{
 92 |         margin: 0,
 93 |         padding: 0,
 94 |         ...props.style,
 95 |         width: '100%',
 96 |       }}
 97 |       colon={false}
 98 |     >
 99 |       {props.children?.['length'] ? (
100 |         <Space size={gutter}>{props.children}</Space>
101 |       ) : (
102 |         props.children
103 |       )}
104 |     </BaseItem>
105 |   )
106 | }
107 | 
108 | FormButtonGroup.Sticky = ({ align = 'left', ...props }) => {
109 |   const ref = useRef()
110 |   const [color, setColor] = useState('transparent')
111 |   const prefixCls = usePrefixCls('formily-button-group')
112 | 
113 |   useLayoutEffect(() => {
114 |     if (ref.current) {
115 |       const computed = getInheritedBackgroundColor(ref.current)
116 |       if (computed !== color) {
117 |         setColor(computed)
118 |       }
119 |     }
120 |   })
121 |   return (
122 |     <StickyBox
123 |       {...props}
124 |       className={cls(`${prefixCls}-sticky`, props.className)}
125 |       style={{
126 |         backgroundColor: color,
127 |         ...props.style,
128 |       }}
129 |       bottom
130 |     >
131 |       <div
132 |         ref={ref}
133 |         className={`${prefixCls}-sticky-inner`}
134 |         style={{
135 |           ...props.style,
136 |           justifyContent:
137 |             align === 'left'
138 |               ? 'flex-start'
139 |               : align === 'right'
140 |               ? 'flex-end'
141 |               : 'center',
142 |         }}
143 |       >
144 |         {props.children}
145 |       </div>
146 |     </StickyBox>
147 |   )
148 | }
149 | 
150 | export default FormButtonGroup
151 | 
```

--------------------------------------------------------------------------------
/packages/reactive/src/annotations/computed.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { ObModelSymbol, ReactionStack } from '../environment'
  2 | import { createAnnotation } from '../internals'
  3 | import { buildDataTree } from '../tree'
  4 | import { isFn } from '../checkers'
  5 | import {
  6 |   bindTargetKeyWithCurrentReaction,
  7 |   runReactionsFromTargetKey,
  8 |   bindComputedReactions,
  9 |   hasRunningReaction,
 10 |   isUntracking,
 11 |   batchStart,
 12 |   batchEnd,
 13 |   releaseBindingReactions,
 14 | } from '../reaction'
 15 | 
 16 | interface IValue<T = any> {
 17 |   value?: T
 18 | }
 19 | export interface IComputed {
 20 |   <T>(compute: () => T): IValue<T>
 21 |   <T>(compute: { get?: () => T; set?: (value: T) => void }): IValue<T>
 22 | }
 23 | 
 24 | const getDescriptor = Object.getOwnPropertyDescriptor
 25 | 
 26 | const getProto = Object.getPrototypeOf
 27 | 
 28 | const ClassDescriptorSymbol = Symbol('ClassDescriptorSymbol')
 29 | 
 30 | function getPropertyDescriptor(obj: any, key: PropertyKey) {
 31 |   if (!obj) return
 32 |   return getDescriptor(obj, key) || getPropertyDescriptor(getProto(obj), key)
 33 | }
 34 | 
 35 | function getPropertyDescriptorCache(obj: any, key: PropertyKey) {
 36 |   const constructor = obj.constructor
 37 |   if (constructor === Object || constructor === Array)
 38 |     return getPropertyDescriptor(obj, key)
 39 |   const cache = constructor[ClassDescriptorSymbol] || {}
 40 |   const descriptor = cache[key]
 41 |   if (descriptor) return descriptor
 42 |   const newDesc = getPropertyDescriptor(obj, key)
 43 |   constructor[ClassDescriptorSymbol] = cache
 44 |   cache[key] = newDesc
 45 |   return newDesc
 46 | }
 47 | 
 48 | function getPrototypeDescriptor(
 49 |   target: any,
 50 |   key: PropertyKey,
 51 |   value: any
 52 | ): PropertyDescriptor {
 53 |   if (!target) {
 54 |     if (value) {
 55 |       if (isFn(value)) {
 56 |         return { get: value }
 57 |       } else {
 58 |         return value
 59 |       }
 60 |     }
 61 |     return {}
 62 |   }
 63 |   const descriptor = getPropertyDescriptorCache(target, key)
 64 |   if (descriptor) {
 65 |     return descriptor
 66 |   }
 67 |   return {}
 68 | }
 69 | 
 70 | export const computed: IComputed = createAnnotation(
 71 |   ({ target, key, value }) => {
 72 |     const store: IValue = {}
 73 | 
 74 |     const proxy = {}
 75 | 
 76 |     const context = target ? target : store
 77 |     const property = target ? key : 'value'
 78 |     const descriptor = getPrototypeDescriptor(target, property, value)
 79 | 
 80 |     function compute() {
 81 |       store.value = descriptor.get?.call(context)
 82 |     }
 83 |     function reaction() {
 84 |       if (ReactionStack.indexOf(reaction) === -1) {
 85 |         releaseBindingReactions(reaction)
 86 |         try {
 87 |           ReactionStack.push(reaction)
 88 |           compute()
 89 |         } finally {
 90 |           ReactionStack.pop()
 91 |         }
 92 |       }
 93 |     }
 94 |     reaction._name = 'ComputedReaction'
 95 |     reaction._scheduler = () => {
 96 |       reaction._dirty = true
 97 |       runReactionsFromTargetKey({
 98 |         target: context,
 99 |         key: property,
100 |         value: store.value,
101 |         type: 'set',
102 |       })
103 |     }
104 |     reaction._isComputed = true
105 |     reaction._dirty = true
106 |     reaction._context = context
107 |     reaction._property = property
108 | 
109 |     function get() {
110 |       if (hasRunningReaction()) {
111 |         bindComputedReactions(reaction)
112 |       }
113 |       if (!isUntracking()) {
114 |         //如果允许untracked过程中收集依赖,那么永远不会存在绑定,因为_dirty已经设置为false
115 |         if (reaction._dirty) {
116 |           reaction()
117 |           reaction._dirty = false
118 |         }
119 |       } else {
120 |         compute()
121 |       }
122 |       bindTargetKeyWithCurrentReaction({
123 |         target: context,
124 |         key: property,
125 |         type: 'get',
126 |       })
127 |       return store.value
128 |     }
129 | 
130 |     function set(value: any) {
131 |       try {
132 |         batchStart()
133 |         descriptor.set?.call(context, value)
134 |       } finally {
135 |         batchEnd()
136 |       }
137 |     }
138 |     if (target) {
139 |       Object.defineProperty(target, key, {
140 |         get,
141 |         set,
142 |         enumerable: true,
143 |       })
144 |       return target
145 |     } else {
146 |       Object.defineProperty(proxy, 'value', {
147 |         set,
148 |         get,
149 |       })
150 |       buildDataTree(target, key, store)
151 |       proxy[ObModelSymbol] = store
152 |     }
153 |     return proxy
154 |   }
155 | )
156 | 
```

--------------------------------------------------------------------------------
/packages/react/docs/api/components/RecursionField.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | order: 5
  3 | ---
  4 | 
  5 | # RecursionField
  6 | 
  7 | ## Description
  8 | 
  9 | The recursive rendering component is mainly based on [JSON-Schema](/api/shared/schema) for recursive rendering. It is the core rendering component inside the [SchemaField](/api/components/schema-field) component. Of course, it can It is used separately from SchemaField. When we use it, it is mainly used in custom components to implement custom components with recursive rendering capabilities.
 10 | 
 11 | ## Signature
 12 | 
 13 | ```ts
 14 | interface IRecursionFieldProps {
 15 |   schema: ISchema //Field schema
 16 |   name?: string //Path name
 17 |   basePath?: FormPathPattern //base path
 18 |   propsRecursion?: boolean //Whether to recursiveliy pass mapProperties and filterProperties
 19 |   onlyRenderProperties?: boolean //Whether to only render properties
 20 |   onlyRenderSelf?: boolean //Whether to only render itself without rendering properties
 21 |   mapProperties?: (schema: Schema, name: string) => Schema //schema properties mapper, mainly used to rewrite the schema
 22 |   filterProperties?: (schema: Schema, name: string) => boolean //schema properties filter, the filtered schema nodes will not be rendered
 23 | }
 24 | 
 25 | type RecursionField = React.FC<React.PropsWithChildren<IRecursionFieldProps>>
 26 | ```
 27 | 
 28 | ## Example
 29 | 
 30 | ### Simple recursion
 31 | 
 32 | ```tsx
 33 | import React from 'react'
 34 | import { createForm } from '@formily/core'
 35 | import { FormProvider, createSchemaField, RecursionField } from '@formily/react'
 36 | import { Input } from 'antd'
 37 | 
 38 | const form = createForm()
 39 | 
 40 | const Custom = (props) => {
 41 |   return <RecursionField schema={props.schema} onlyRenderProperties />
 42 | }
 43 | 
 44 | const SchemaField = createSchemaField({
 45 |   components: {
 46 |     Custom,
 47 |     Input,
 48 |   },
 49 | })
 50 | 
 51 | export default () => (
 52 |   <FormProvider form={form}>
 53 |     <SchemaField>
 54 |       <SchemaField.Object
 55 |         name="custom"
 56 |         x-component="Custom"
 57 |         x-component-props={{
 58 |           schema: {
 59 |             type: 'object',
 60 |             properties: {
 61 |               input: {
 62 |                 type: 'string',
 63 |                 'x-component': 'Input',
 64 |               },
 65 |             },
 66 |           },
 67 |         }}
 68 |       />
 69 |     </SchemaField>
 70 |   </FormProvider>
 71 | )
 72 | ```
 73 | 
 74 | We can read independent schema objects from component properties and pass them to RecursionField for rendering
 75 | 
 76 | ### Incremental list recursion
 77 | 
 78 | ```tsx
 79 | import React from 'react'
 80 | import { createForm } from '@formily/core'
 81 | import {
 82 |   FormProvider,
 83 |   createSchemaField,
 84 |   RecursionField,
 85 |   useField,
 86 |   useFieldSchema,
 87 |   observer,
 88 | } from '@formily/react'
 89 | import { Input, Space, Button } from 'antd'
 90 | 
 91 | const form = createForm()
 92 | 
 93 | const ArrayItems = observer((props) => {
 94 |   const field = useField()
 95 |   const schema = useFieldSchema()
 96 |   return (
 97 |     <div>
 98 |       {props.value?.map((item, index) => {
 99 |         return (
100 |           <div key={index} style={{ marginBottom: 10 }}>
101 |             <Space>
102 |               <RecursionField schema={schema.items} name={index} />
103 |               <Button
104 |                 onClick={() => {
105 |                   field.remove(index)
106 |                 }}
107 |               >
108 |                 Remove
109 |               </Button>
110 |             </Space>
111 |           </div>
112 |         )
113 |       })}
114 |       <Button
115 |         onClick={() => {
116 |           field.push({})
117 |         }}
118 |       >
119 |         Add
120 |       </Button>
121 |     </div>
122 |   )
123 | })
124 | 
125 | const SchemaField = createSchemaField({
126 |   components: {
127 |     ArrayItems,
128 |     Input,
129 |   },
130 | })
131 | 
132 | export default () => (
133 |   <FormProvider form={form}>
134 |     <SchemaField>
135 |       <SchemaField.Array name="custom" x-component="ArrayItems">
136 |         <SchemaField.Object>
137 |           <SchemaField.String name="input" x-component="Input" />
138 |         </SchemaField.Object>
139 |       </SchemaField.Array>
140 |     </SchemaField>
141 |   </FormProvider>
142 | )
143 | ```
144 | 
145 | Use [useField](/api/hooks/useField) and [useFieldSchema](/api/shared/use-field-schema) to get the field instance and field schema in the current field context
146 | 
```
Page 13/52FirstPrevNextLast