#
tokens: 48857/50000 23/1152 files (page 12/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 12 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/vue/docs/.vuepress/config.js:
--------------------------------------------------------------------------------

```javascript
  1 | const path = require('path')
  2 | 
  3 | module.exports = {
  4 |   title: 'Formily Vue',
  5 |   dest: './doc-site',
  6 |   theme: '@vuepress-dumi/dumi',
  7 |   head: [
  8 |     [
  9 |       'link',
 10 |       {
 11 |         rel: 'icon',
 12 |         href: '//img.alicdn.com/imgextra/i3/O1CN01XtT3Tv1Wd1b5hNVKy_!!6000000002810-55-tps-360-360.svg',
 13 |       },
 14 |     ],
 15 |   ],
 16 |   themeConfig: {
 17 |     logo: '//img.alicdn.com/imgextra/i2/O1CN01Kq3OHU1fph6LGqjIz_!!6000000004056-55-tps-1141-150.svg',
 18 |     nav: [
 19 |       {
 20 |         text: '指南',
 21 |         link: '/guide/',
 22 |       },
 23 |       {
 24 |         text: 'API',
 25 |         link: '/api/components/field',
 26 |       },
 27 |       {
 28 |         text: 'Q&A',
 29 |         link: '/questions/',
 30 |       },
 31 |       {
 32 |         text: '主站',
 33 |         link: 'https://formilyjs.org',
 34 |       },
 35 |       {
 36 |         text: 'GITHUB',
 37 |         link: 'https://github.com/alibaba/formily',
 38 |       },
 39 |     ],
 40 |     sidebar: {
 41 |       '/guide/': ['', 'architecture', 'concept'],
 42 |       '/api/': [
 43 |         {
 44 |           title: 'Components',
 45 |           children: [
 46 |             '/api/components/field',
 47 |             '/api/components/array-field',
 48 |             '/api/components/object-field',
 49 |             '/api/components/void-field',
 50 |             '/api/components/schema-field',
 51 |             '/api/components/schema-field-with-schema',
 52 |             '/api/components/recursion-field',
 53 |             '/api/components/recursion-field-with-component',
 54 |             '/api/components/form-provider',
 55 |             '/api/components/form-consumer',
 56 |             '/api/components/expression-scope',
 57 |           ],
 58 |         },
 59 |         {
 60 |           title: 'Hooks',
 61 |           children: [
 62 |             '/api/hooks/use-field',
 63 |             '/api/hooks/use-field-schema',
 64 |             '/api/hooks/use-form',
 65 |             '/api/hooks/use-form-effects',
 66 |             '/api/hooks/use-parent-form',
 67 |           ],
 68 |         },
 69 |         {
 70 |           title: 'Shared',
 71 |           children: [
 72 |             '/api/shared/connect',
 73 |             '/api/shared/injections',
 74 |             '/api/shared/map-props',
 75 |             '/api/shared/map-read-pretty',
 76 |             '/api/shared/observer',
 77 |             '/api/shared/schema',
 78 |           ],
 79 |         },
 80 |       ],
 81 |     },
 82 |     lastUpdated: 'Last Updated',
 83 |     smoothScroll: true,
 84 |   },
 85 |   plugins: [
 86 |     'vuepress-plugin-typescript',
 87 |     '@vuepress/back-to-top',
 88 |     '@vuepress/last-updated',
 89 |     '@vuepress-dumi/dumi-previewer',
 90 |     [
 91 |       '@vuepress/medium-zoom',
 92 |       {
 93 |         selector: '.content__default :not(a) > img',
 94 |       },
 95 |     ],
 96 |   ],
 97 |   configureWebpack: (config, isServer) => {
 98 |     return {
 99 |       resolve: {
100 |         alias: {
101 |           '@formily/vue': path.resolve(__dirname, '../../src'),
102 |           '@formily/json-schema': path.resolve(
103 |             __dirname,
104 |             '../../../json-schema/src'
105 |           ),
106 |           '@formily/path': path.resolve(__dirname, '../../../path/src'),
107 |           '@formily/reactive-vue': path.resolve(
108 |             __dirname,
109 |             '../../../reactive-vue/src'
110 |           ),
111 |           '@formily/element': path.resolve(__dirname, '../../../element/src'),
112 |           vue: path.resolve(
113 |             __dirname,
114 |             '../../../../node_modules/vue/dist/vue.runtime.esm.js'
115 |           ),
116 |         },
117 |       },
118 |     }
119 |   },
120 | }
121 | 
```

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

```typescript
  1 | import {
  2 |   isArr,
  3 |   isFn,
  4 |   isPlainObj,
  5 |   isStr,
  6 |   reduce,
  7 |   FormPath,
  8 | } from '@formily/shared'
  9 | import { IGeneralFieldState } from '@formily/core'
 10 | import { untracked, hasCollected } from '@formily/reactive'
 11 | import {
 12 |   traverse,
 13 |   traverseSchema,
 14 |   isNoNeedCompileObject,
 15 |   hasOwnProperty,
 16 |   patchStateFormSchema,
 17 | } from './shared'
 18 | import { ISchema } from './types'
 19 | 
 20 | const ExpRE = /^\s*\{\{([\s\S]*)\}\}\s*$/
 21 | const Registry = {
 22 |   silent: false,
 23 |   compile(expression: string, scope = {}) {
 24 |     if (Registry.silent) {
 25 |       try {
 26 |         return new Function('$root', `with($root) { return (${expression}); }`)(
 27 |           scope
 28 |         )
 29 |       } catch {}
 30 |     } else {
 31 |       return new Function('$root', `with($root) { return (${expression}); }`)(
 32 |         scope
 33 |       )
 34 |     }
 35 |   },
 36 | }
 37 | 
 38 | export const silent = (value = true) => {
 39 |   Registry.silent = !!value
 40 | }
 41 | 
 42 | export const registerCompiler = (
 43 |   compiler: (expression: string, scope: any) => any
 44 | ) => {
 45 |   if (isFn(compiler)) {
 46 |     Registry.compile = compiler
 47 |   }
 48 | }
 49 | 
 50 | export const shallowCompile = <Source = any, Scope = any>(
 51 |   source: Source,
 52 |   scope?: Scope
 53 | ) => {
 54 |   if (isStr(source)) {
 55 |     const matched = source.match(ExpRE)
 56 |     if (!matched) return source
 57 |     return Registry.compile(matched[1], scope)
 58 |   }
 59 |   return source
 60 | }
 61 | 
 62 | export const compile = <Source = any, Scope = any>(
 63 |   source: Source,
 64 |   scope?: Scope
 65 | ): any => {
 66 |   const seenObjects = []
 67 |   const compile = (source: any) => {
 68 |     if (isStr(source)) {
 69 |       return shallowCompile(source, scope)
 70 |     } else if (isArr(source)) {
 71 |       return source.map((value: any) => compile(value))
 72 |     } else if (isPlainObj(source)) {
 73 |       if (isNoNeedCompileObject(source)) return source
 74 |       const seenIndex = seenObjects.indexOf(source)
 75 |       if (seenIndex > -1) {
 76 |         return source
 77 |       }
 78 |       const addIndex = seenObjects.length
 79 |       seenObjects.push(source)
 80 |       const results = reduce(
 81 |         source,
 82 |         (buf, value, key) => {
 83 |           buf[key] = compile(value)
 84 |           return buf
 85 |         },
 86 |         {}
 87 |       )
 88 |       seenObjects.splice(addIndex, 1)
 89 |       return results
 90 |     }
 91 |     return source
 92 |   }
 93 |   return compile(source)
 94 | }
 95 | 
 96 | export const patchCompile = (
 97 |   targetState: IGeneralFieldState,
 98 |   sourceState: any,
 99 |   scope: any
100 | ) => {
101 |   traverse(sourceState, (value, pattern) => {
102 |     const compiled = compile(value, scope)
103 |     if (compiled === undefined) return
104 |     const path = FormPath.parse(pattern)
105 |     const key = path.segments[0]
106 |     if (hasOwnProperty.call(targetState, key)) {
107 |       untracked(() => FormPath.setIn(targetState, path, compiled))
108 |     }
109 |   })
110 | }
111 | 
112 | export const patchSchemaCompile = (
113 |   targetState: IGeneralFieldState,
114 |   sourceSchema: ISchema,
115 |   scope: any,
116 |   demand = false
117 | ) => {
118 |   traverseSchema(sourceSchema, (value, path, omitCompile) => {
119 |     let compiled = value
120 |     let collected = hasCollected(() => {
121 |       if (!omitCompile) {
122 |         compiled = compile(value, scope)
123 |       }
124 |     })
125 |     if (compiled === undefined) return
126 |     if (demand) {
127 |       if (collected || !targetState.initialized) {
128 |         patchStateFormSchema(targetState, path, compiled)
129 |       }
130 |     } else {
131 |       patchStateFormSchema(targetState, path, compiled)
132 |     }
133 |   })
134 | }
135 | 
```

--------------------------------------------------------------------------------
/packages/reactive/src/__tests__/externals.spec.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import {
 2 |   isObservable,
 3 |   isSupportObservable,
 4 |   markObservable,
 5 |   markRaw,
 6 |   observable,
 7 |   toJS,
 8 | } from '..'
 9 | 
10 | test('is support observable', () => {
11 |   const obs = observable<any>({ aa: 111 })
12 |   class Class {}
13 | 
14 |   expect(isSupportObservable(obs)).toBe(true)
15 |   expect(isSupportObservable(new Class())).toBe(true)
16 |   expect(isSupportObservable(null)).toBe(false)
17 |   expect(isSupportObservable([])).toBe(true)
18 |   expect(isSupportObservable({})).toBe(true)
19 |   expect(isSupportObservable({ $$typeof: {}, _owner: {} })).toBe(false)
20 |   expect(isSupportObservable({ _isAMomentObject: {} })).toBe(false)
21 |   expect(isSupportObservable({ _isJSONSchemaObject: {} })).toBe(false)
22 |   expect(isSupportObservable({ toJS: () => {} })).toBe(false)
23 |   expect(isSupportObservable({ toJSON: () => {} })).toBe(false)
24 |   expect(isSupportObservable(new Map())).toBe(true)
25 |   expect(isSupportObservable(new WeakMap())).toBe(true)
26 |   expect(isSupportObservable(new Set())).toBe(true)
27 |   expect(isSupportObservable(new WeakSet())).toBe(true)
28 | })
29 | 
30 | describe('mark operation', () => {
31 |   test('plain object should be observable', () => {
32 |     const obs = observable<any>({ aa: 111 })
33 |     expect(isObservable(obs)).toBe(true)
34 |   })
35 | 
36 |   test('class instance should be observable', () => {
37 |     class Class {}
38 |     const obs = observable<any>(new Class())
39 |     const obs2 = observable<any>(new Class())
40 |     expect(isObservable(obs)).toBe(true)
41 |     expect(isObservable(obs2)).toBe(true)
42 |   })
43 | 
44 |   test('object with toJS function should NOT be observable', () => {
45 |     const obs = observable<any>({ aa: 111, toJS: () => {} })
46 |     expect(isObservable(obs)).toBe(false)
47 |   })
48 | 
49 |   test('plain object marked as raw should NOT be observable', () => {
50 |     const obs = observable<any>(markRaw({ aa: 111 }))
51 |     expect(isObservable(obs)).toBe(false)
52 |   })
53 | 
54 |   test('class marked as raw instance should NOT be observable', () => {
55 |     class Class {}
56 |     markRaw(Class)
57 |     const obs = observable<any>(new Class())
58 |     const obs2 = observable<any>(new Class())
59 |     expect(isObservable(obs)).toBe(false)
60 |     expect(isObservable(obs2)).toBe(false)
61 |   })
62 | 
63 |   test('object with toJS function marked as observable should be observable', () => {
64 |     const obs = observable<any>(markObservable({ aa: 111, toJS: () => {} }))
65 |     expect(isObservable(obs)).toBe(true)
66 |   })
67 | 
68 |   test('plain object marked as raw and observable should NOT be observable', () => {
69 |     const obs = observable<any>(markRaw(markObservable({ aa: 111 })))
70 |     expect(isObservable(obs)).toBe(false)
71 |   })
72 | 
73 |   test('plain object marked as observable and raw should NOT be observable', () => {
74 |     const obs = observable<any>(markObservable(markRaw({ aa: 111 })))
75 |     expect(isObservable(obs)).toBe(false)
76 |   })
77 | 
78 |   test('function marked as observable should NOT be observable', () => {
79 |     const obs = observable<any>(markObservable(() => {}))
80 |     expect(isObservable(obs)).toBe(false)
81 |   })
82 | })
83 | 
84 | test('recursive references tojs', () => {
85 |   const obj: any = { aa: 111 }
86 |   obj.obj = obj
87 |   const obs = observable<any>(obj)
88 |   obs.obs = obs
89 |   expect(toJS(obs)).toBeTruthy()
90 | 
91 |   const arrObs = observable([{ aa: 1 }, { bb: 2 }, { cc: 3 }])
92 |   expect(toJS(arrObs)).toEqual([{ aa: 1 }, { bb: 2 }, { cc: 3 }])
93 | })
94 | 
```

--------------------------------------------------------------------------------
/packages/element/src/upload/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Field } from '@formily/core'
  2 | import { connect, Fragment, h, mapProps, useField } from '@formily/vue'
  3 | import { defineComponent } from 'vue-demi'
  4 | 
  5 | import type {
  6 |   ElUpload as ElUploadProps,
  7 |   ElUploadInternalFileDetail,
  8 | } from 'element-ui/types/upload'
  9 | 
 10 | import { Button as ElButton, Upload as ElUpload } from 'element-ui'
 11 | 
 12 | export type UploadProps = ElUploadProps & {
 13 |   textContent?: String
 14 |   errorAdaptor?: (error?: ErrorEvent) => String
 15 | }
 16 | 
 17 | const UploadWrapper = defineComponent<UploadProps>({
 18 |   name: 'FUpload',
 19 |   props: {
 20 |     textContent: {
 21 |       type: String,
 22 |       default: '',
 23 |     },
 24 |     errorAdaptor: {
 25 |       type: Function,
 26 |       default(error?: ErrorEvent) {
 27 |         return error?.message || ''
 28 |       },
 29 |     },
 30 |   },
 31 |   setup(curProps: UploadProps, { slots, attrs, listeners, emit }) {
 32 |     return () => {
 33 |       const fieldRef = useField<Field>()
 34 |       const setFeedBack = (error?: ErrorEvent) => {
 35 |         const message = curProps.errorAdaptor(error)
 36 | 
 37 |         fieldRef.value.setFeedback({
 38 |           type: 'error',
 39 |           code: 'UploadError',
 40 |           messages: message ? [message] : [],
 41 |         })
 42 |       }
 43 | 
 44 |       const props = {
 45 |         ...attrs,
 46 |         onChange(
 47 |           file: ElUploadInternalFileDetail,
 48 |           fileList: ElUploadInternalFileDetail[]
 49 |         ) {
 50 |           ;(attrs.onChange as Function)?.(file, fileList)
 51 |           setFeedBack()
 52 |           emit('change', fileList)
 53 |         },
 54 | 
 55 |         onRemove(
 56 |           file: ElUploadInternalFileDetail,
 57 |           fileList: ElUploadInternalFileDetail[]
 58 |         ) {
 59 |           ;(attrs.onRemove as Function)?.(file, fileList)
 60 |           setFeedBack()
 61 |           emit('change', fileList)
 62 |         },
 63 | 
 64 |         onError(
 65 |           error: ErrorEvent,
 66 |           file: ElUploadInternalFileDetail,
 67 |           fileList: ElUploadInternalFileDetail[]
 68 |         ) {
 69 |           ;(attrs.onError as Function)?.(error, file, fileList)
 70 | 
 71 |           setTimeout(() => {
 72 |             setFeedBack(error)
 73 |           }, 0)
 74 |         },
 75 |       }
 76 |       const children = {
 77 |         ...slots,
 78 |       }
 79 |       if (!slots.default) {
 80 |         children.default = () => {
 81 |           const listType = attrs.listType
 82 |           const drag = attrs.drag
 83 | 
 84 |           if (drag) {
 85 |             return h(
 86 |               Fragment,
 87 |               {},
 88 |               {
 89 |                 default: () => [
 90 |                   h('i', { staticClass: 'el-icon-upload' }, {}),
 91 |                   h(
 92 |                     'div',
 93 |                     { staticClass: 'el-upload__text' },
 94 |                     { default: () => [curProps.textContent] }
 95 |                   ),
 96 |                 ],
 97 |               }
 98 |             )
 99 |           }
100 | 
101 |           if (listType === 'picture-card') {
102 |             return h(
103 |               'i',
104 |               {
105 |                 staticClass: 'el-icon-plus',
106 |               },
107 |               {}
108 |             )
109 |           }
110 | 
111 |           return h(
112 |             ElButton,
113 |             { props: { icon: 'el-icon-upload2' } },
114 |             { default: () => [curProps.textContent] }
115 |           )
116 |         }
117 |       }
118 |       return h(ElUpload, { attrs: props, on: listeners }, children)
119 |     }
120 |   },
121 | })
122 | 
123 | export const Upload = connect(
124 |   UploadWrapper,
125 |   mapProps({ readOnly: 'readonly', value: 'fileList' })
126 | )
127 | 
128 | export default Upload
129 | 
```

--------------------------------------------------------------------------------
/packages/reactive/src/__tests__/observe.spec.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { observable, observe } from '../'
  2 | 
  3 | test('deep observe', () => {
  4 |   const obs = observable<any>({
  5 |     aa: {
  6 |       bb: {
  7 |         cc: [11, 22, 33],
  8 |       },
  9 |     },
 10 |     ee: observable([]),
 11 |   })
 12 |   const handler = jest.fn()
 13 |   observe(obs, handler)
 14 |   obs.dd = 123
 15 |   obs.aa.bb.cc.push(44)
 16 |   expect(obs.aa.bb.cc).toEqual([11, 22, 33, 44])
 17 |   expect(handler).toHaveBeenCalledTimes(2)
 18 |   delete obs.aa
 19 |   expect(handler).toHaveBeenCalledTimes(3)
 20 | 
 21 |   // Are these expected behaviors?
 22 |   obs.ee.push(11)
 23 |   expect(handler).toHaveBeenCalledTimes(3)
 24 |   obs.ee = []
 25 |   expect(handler).toHaveBeenCalledTimes(4)
 26 |   obs.ee.push(11)
 27 |   expect(handler).toHaveBeenCalledTimes(5)
 28 | })
 29 | 
 30 | test('shallow observe', () => {
 31 |   const obs = observable<any>({
 32 |     aa: {
 33 |       bb: {
 34 |         cc: [11, 22, 33],
 35 |       },
 36 |     },
 37 |   })
 38 |   const handler = jest.fn()
 39 |   observe(obs, handler, false)
 40 |   obs.dd = 123
 41 |   obs.aa.bb.cc.push(44)
 42 |   expect(obs.aa.bb.cc).toEqual([11, 22, 33, 44])
 43 |   expect(handler).toHaveBeenCalledTimes(1)
 44 |   delete obs.aa
 45 |   expect(handler).toHaveBeenCalledTimes(2)
 46 | })
 47 | 
 48 | test('root replace observe', () => {
 49 |   const obs = observable<any>({
 50 |     aa: {
 51 |       bb: {
 52 |         cc: [11, 22, 33],
 53 |       },
 54 |     },
 55 |   })
 56 |   const handler1 = jest.fn()
 57 |   const handler = jest.fn()
 58 |   observe(obs, handler1)
 59 |   observe(obs.aa, handler)
 60 |   obs.aa = {
 61 |     mm: 123,
 62 |   }
 63 |   expect(handler1).toBeCalledTimes(1)
 64 |   expect(handler).toBeCalledTimes(1)
 65 |   obs.aa = {
 66 |     bb: {
 67 |       cc: [11, 22, 33],
 68 |     },
 69 |   }
 70 |   obs.aa.bb.cc.push(44)
 71 |   expect(handler1).toBeCalledTimes(3)
 72 |   expect(handler).toBeCalledTimes(3)
 73 | })
 74 | 
 75 | test('dispose observe', () => {
 76 |   const obs = observable<any>({
 77 |     aa: {
 78 |       bb: {
 79 |         cc: [11, 22, 33],
 80 |       },
 81 |     },
 82 |   })
 83 |   const handler = jest.fn()
 84 |   const dispose = observe(obs, handler)
 85 |   obs.kk = 123
 86 |   expect(handler).toBeCalledTimes(1)
 87 |   dispose()
 88 |   obs.aa = 123
 89 |   expect(handler).toBeCalledTimes(1)
 90 | })
 91 | 
 92 | test('dispose observe', () => {
 93 |   const obs = observable<any>({
 94 |     aa: {
 95 |       bb: {
 96 |         cc: [11, 22, 33],
 97 |       },
 98 |     },
 99 |   })
100 |   const handler = jest.fn()
101 |   const dispose = observe(obs.aa, handler)
102 |   obs.kk = 111
103 |   expect(handler).toBeCalledTimes(0)
104 |   obs.aa = { mm: 222 }
105 |   expect(handler).toBeCalledTimes(1)
106 |   obs.aa = { mm: 222 }
107 |   expect(handler).toBeCalledTimes(2)
108 |   obs.aa = { mm: '111' }
109 |   expect(handler).toBeCalledTimes(3)
110 |   obs.aa = { mm: 333 }
111 |   expect(handler).toBeCalledTimes(4)
112 |   dispose()
113 |   obs.aa = { mm: 444 }
114 |   expect(handler).toBeCalledTimes(4)
115 | })
116 | 
117 | test('array delete', () => {
118 |   const array = observable([{ value: 1 }, { value: 2 }])
119 | 
120 |   const fn = jest.fn()
121 | 
122 |   const dispose = observe(array, (change) => {
123 |     if (change.type === 'set' && change.key === 'value') {
124 |       fn(change.path?.join('.'))
125 |     }
126 |   })
127 | 
128 |   array[0].value = 3
129 |   expect(fn.mock.calls[0][0]).toBe('0.value')
130 | 
131 |   array.splice(0, 1)
132 | 
133 |   array[0].value = 3
134 |   expect(fn.mock.calls[1][0]).toBe('0.value')
135 | 
136 |   dispose()
137 | })
138 | 
139 | test('observe dynamic tree', () => {
140 |   const handler = jest.fn()
141 |   const tree = observable<any>({})
142 |   const childTree = observable({})
143 |   tree.children = childTree
144 |   observe(tree, handler)
145 |   tree.children.aa = 123
146 |   expect(handler).toBeCalledTimes(1)
147 | })
148 | 
149 | test('invalid target', () => {
150 |   expect(() => observe(function () {})).toThrowError()
151 | })
152 | 
```

--------------------------------------------------------------------------------
/packages/validator/src/formats.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export default {
 2 |   url: new RegExp(
 3 |     // protocol identifier
 4 |     '^(?:(?:(?:https?|ftp|rtmp):)?//)' +
 5 |       // user:pass authentication
 6 |       '(?:\\S+(?::\\S*)?@)?' +
 7 |       '(?:' +
 8 |       // IP address exclusion - private & local networks
 9 |       // Reference: https://www.arin.net/knowledge/address_filters.html
10 | 
11 |       // filter 10.*.*.* and 127.*.*.* addresses
12 |       '(?!(?:10|127)(?:\\.\\d{1,3}){3})' +
13 |       // filter 169.254.*.* and 192.168.*.*
14 |       '(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})' +
15 |       // filter 172.16.0.0 - 172.31.255.255
16 |       // TODO: add test to validate that it invalidates address in 16-31 range
17 |       '(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})' +
18 |       // IP address dotted notation octets
19 |       // excludes loopback network 0.0.0.0
20 |       // excludes reserved space >= 224.0.0.0
21 |       // excludes network & broadcast addresses
22 |       // (first & last IP address of each class)
23 | 
24 |       // filter 1. part for 1-223
25 |       '(?:22[0-3]|2[01]\\d|[1-9]\\d?|1\\d\\d)' +
26 |       // filter 2. and 3. part for 0-255
27 |       '(?:\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})){2}' +
28 |       // filter 4. part for 1-254
29 |       '(?:\\.(?:25[0-4]|2[0-4]\\d|1\\d\\d|[1-9]\\d?))' +
30 |       '|' +
31 |       // host name
32 |       '(?:(?:[a-z\\u00a1-\\uffff0-9_]-*)*[a-z\\u00a1-\\uffff0-9_]+)' +
33 |       // domain name
34 |       '(?:\\.(?:[a-z\\u00a1-\\uffff0-9_]-*)*[a-z\\u00a1-\\uffff0-9_]+)*' +
35 |       // TLD identifier
36 |       '(?:\\.(?:[a-z\\u00a1-\\uffff_]{2,}))' +
37 |       ')' +
38 |       // port number
39 |       '(?::\\d{2,5})?' +
40 |       // resource path
41 |       '(?:/?\\S*)?$'
42 |   ),
43 |   email: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
44 | 
45 |   ipv6: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
46 | 
47 |   ipv4: /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/,
48 | 
49 |   number: /^[+-]?\d+(\.\d+)?$/,
50 | 
51 |   integer: /^[+-]?\d+$/,
52 | 
53 |   qq: /^(\+?[1-9]\d*|0)$/,
54 | 
55 |   phone: /^\d{3}-\d{8}$|^\d{4}-\d{7}$|^\d{11}$/,
56 | 
57 |   idcard: /^\d{15}$|^\d{17}(\d|x|X)$/,
58 | 
59 |   money:
60 |     /^([\u0024\u00A2\u00A3\u00A4\u20AC\u00A5\u20B1\u20B9\uFFE5]\s*)(\d+,?)+(\.\d+)?\s*$/,
61 | 
62 |   zh: /^[\u4e00-\u9fa5]+$/,
63 | 
64 |   date: /^[0-9]+[./-][0-9]+[./-][0-9]+\s*(?:[0-9]+\s*:\s*[0-9]+\s*:\s*[0-9]+)?$/,
65 | 
66 |   zip: /^[0-9]{6}$/,
67 | }
68 | 
```

--------------------------------------------------------------------------------
/packages/core/src/models/VoidField.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { toArr, FormPathPattern } from '@formily/shared'
  2 | import { define, observable, batch, action } from '@formily/reactive'
  3 | import {
  4 |   createReactions,
  5 |   createStateSetter,
  6 |   createStateGetter,
  7 |   initializeStart,
  8 |   initializeEnd,
  9 | } from '../shared/internals'
 10 | import {
 11 |   IModelSetter,
 12 |   IModelGetter,
 13 |   IVoidFieldProps,
 14 |   IVoidFieldState,
 15 | } from '../types'
 16 | import { Form } from './Form'
 17 | import { BaseField } from './BaseField'
 18 | 
 19 | export class VoidField<
 20 |   Decorator = any,
 21 |   Component = any,
 22 |   TextType = any
 23 | > extends BaseField<Decorator, Component, TextType> {
 24 |   displayName: 'VoidField' = 'VoidField'
 25 |   props: IVoidFieldProps<Decorator, Component>
 26 | 
 27 |   constructor(
 28 |     address: FormPathPattern,
 29 |     props: IVoidFieldProps<Decorator, Component>,
 30 |     form: Form,
 31 |     designable: boolean
 32 |   ) {
 33 |     super()
 34 |     this.form = form
 35 |     this.props = props
 36 |     this.designable = designable
 37 |     initializeStart()
 38 |     this.locate(address)
 39 |     this.initialize()
 40 |     this.makeObservable()
 41 |     this.makeReactive()
 42 |     this.onInit()
 43 |     initializeEnd()
 44 |   }
 45 | 
 46 |   protected initialize() {
 47 |     this.mounted = false
 48 |     this.unmounted = false
 49 |     this.initialized = false
 50 |     this.title = this.props.title
 51 |     this.description = this.props.description
 52 |     this.pattern = this.props.pattern
 53 |     this.display = this.props.display
 54 |     this.hidden = this.props.hidden
 55 |     this.editable = this.props.editable
 56 |     this.disabled = this.props.disabled
 57 |     this.readOnly = this.props.readOnly
 58 |     this.readPretty = this.props.readPretty
 59 |     this.visible = this.props.visible
 60 |     this.content = this.props.content
 61 |     this.data = this.props.data
 62 |     this.decorator = toArr(this.props.decorator)
 63 |     this.component = toArr(this.props.component)
 64 |   }
 65 | 
 66 |   protected makeObservable() {
 67 |     if (this.designable) return
 68 |     define(this, {
 69 |       path: observable.ref,
 70 |       title: observable.ref,
 71 |       description: observable.ref,
 72 |       selfDisplay: observable.ref,
 73 |       selfPattern: observable.ref,
 74 |       initialized: observable.ref,
 75 |       mounted: observable.ref,
 76 |       unmounted: observable.ref,
 77 |       decoratorType: observable.ref,
 78 |       componentType: observable.ref,
 79 |       content: observable.ref,
 80 |       data: observable.shallow,
 81 |       decoratorProps: observable,
 82 |       componentProps: observable,
 83 |       display: observable.computed,
 84 |       pattern: observable.computed,
 85 |       hidden: observable.computed,
 86 |       visible: observable.computed,
 87 |       disabled: observable.computed,
 88 |       readOnly: observable.computed,
 89 |       readPretty: observable.computed,
 90 |       editable: observable.computed,
 91 |       component: observable.computed,
 92 |       decorator: observable.computed,
 93 |       indexes: observable.computed,
 94 |       setTitle: action,
 95 |       setDescription: action,
 96 |       setDisplay: action,
 97 |       setPattern: action,
 98 |       setComponent: action,
 99 |       setComponentProps: action,
100 |       setDecorator: action,
101 |       setDecoratorProps: action,
102 |       setData: action,
103 |       setContent: action,
104 |       onInit: batch,
105 |       onMount: batch,
106 |       onUnmount: batch,
107 |     })
108 |   }
109 | 
110 |   protected makeReactive() {
111 |     if (this.designable) return
112 |     createReactions(this)
113 |   }
114 | 
115 |   setState: IModelSetter<IVoidFieldState> = createStateSetter(this)
116 | 
117 |   getState: IModelGetter<IVoidFieldState> = createStateGetter(this)
118 | }
119 | 
```

--------------------------------------------------------------------------------
/packages/react/src/components/ReactiveField.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { Fragment, useContext } from 'react'
  2 | import { toJS } from '@formily/reactive'
  3 | import { observer } from '@formily/reactive-react'
  4 | import { FormPath, isFn } from '@formily/shared'
  5 | import { isVoidField, GeneralField, Form } from '@formily/core'
  6 | import { SchemaComponentsContext } from '../shared'
  7 | import { RenderPropsChildren } from '../types'
  8 | interface IReactiveFieldProps {
  9 |   field: GeneralField
 10 |   children?: RenderPropsChildren<GeneralField>
 11 | }
 12 | 
 13 | const mergeChildren = (
 14 |   children: RenderPropsChildren<GeneralField>,
 15 |   content: React.ReactNode
 16 | ) => {
 17 |   if (!children && !content) return
 18 |   if (isFn(children)) return
 19 |   return (
 20 |     <Fragment>
 21 |       {children}
 22 |       {content}
 23 |     </Fragment>
 24 |   )
 25 | }
 26 | 
 27 | const isValidComponent = (target: any) =>
 28 |   target && (typeof target === 'object' || typeof target === 'function')
 29 | 
 30 | const renderChildren = (
 31 |   children: RenderPropsChildren<GeneralField>,
 32 |   field?: GeneralField,
 33 |   form?: Form
 34 | ) => (isFn(children) ? children(field, form) : children)
 35 | 
 36 | const ReactiveInternal: React.FC<IReactiveFieldProps> = (props) => {
 37 |   const components = useContext(SchemaComponentsContext)
 38 |   if (!props.field) {
 39 |     return <Fragment>{renderChildren(props.children)}</Fragment>
 40 |   }
 41 |   const field = props.field
 42 |   const content = mergeChildren(
 43 |     renderChildren(props.children, field, field.form),
 44 |     field.content ?? field.componentProps.children
 45 |   )
 46 |   if (field.display !== 'visible') return null
 47 | 
 48 |   const getComponent = (target: any) => {
 49 |     return isValidComponent(target)
 50 |       ? target
 51 |       : FormPath.getIn(components, target) ?? target
 52 |   }
 53 | 
 54 |   const renderDecorator = (children: React.ReactNode) => {
 55 |     if (!field.decoratorType) {
 56 |       return <Fragment>{children}</Fragment>
 57 |     }
 58 | 
 59 |     return React.createElement(
 60 |       getComponent(field.decoratorType),
 61 |       toJS(field.decoratorProps),
 62 |       children
 63 |     )
 64 |   }
 65 | 
 66 |   const renderComponent = () => {
 67 |     if (!field.componentType) return content
 68 |     const value = !isVoidField(field) ? field.value : undefined
 69 |     const onChange = !isVoidField(field)
 70 |       ? (...args: any[]) => {
 71 |           field.onInput(...args)
 72 |           field.componentProps?.onChange?.(...args)
 73 |         }
 74 |       : field.componentProps?.onChange
 75 |     const onFocus = !isVoidField(field)
 76 |       ? (...args: any[]) => {
 77 |           field.onFocus(...args)
 78 |           field.componentProps?.onFocus?.(...args)
 79 |         }
 80 |       : field.componentProps?.onFocus
 81 |     const onBlur = !isVoidField(field)
 82 |       ? (...args: any[]) => {
 83 |           field.onBlur(...args)
 84 |           field.componentProps?.onBlur?.(...args)
 85 |         }
 86 |       : field.componentProps?.onBlur
 87 |     const disabled = !isVoidField(field)
 88 |       ? field.pattern === 'disabled' || field.pattern === 'readPretty'
 89 |       : undefined
 90 |     const readOnly = !isVoidField(field)
 91 |       ? field.pattern === 'readOnly'
 92 |       : undefined
 93 |     return React.createElement(
 94 |       getComponent(field.componentType),
 95 |       {
 96 |         disabled,
 97 |         readOnly,
 98 |         ...toJS(field.componentProps),
 99 |         value,
100 |         onChange,
101 |         onFocus,
102 |         onBlur,
103 |       },
104 |       content
105 |     )
106 |   }
107 | 
108 |   return renderDecorator(renderComponent())
109 | }
110 | 
111 | ReactiveInternal.displayName = 'ReactiveField'
112 | 
113 | export const ReactiveField = observer(ReactiveInternal, {
114 |   forwardRef: true,
115 | })
116 | 
```

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

```typescript
  1 | import { Path } from './index'
  2 | interface INode {
  3 |   type?: string
  4 |   after?: Node
  5 |   depth?: number
  6 | }
  7 | 
  8 | export type Node =
  9 |   | IdentifierNode
 10 |   | WildcardOperatorNode
 11 |   | GroupExpressionNode
 12 |   | RangeExpressionNode
 13 |   | DestructorExpressionNode
 14 |   | ObjectPatternNode
 15 |   | ArrayPatternNode
 16 |   | DotOperatorNode
 17 |   | ExpandOperatorNode
 18 |   | INode
 19 | 
 20 | export type IdentifierNode = {
 21 |   type: 'Identifier'
 22 |   value: string
 23 |   arrayIndex?: boolean
 24 | } & INode
 25 | 
 26 | export type IgnoreExpressionNode = {
 27 |   type: 'IgnoreExpression'
 28 |   value: string
 29 | } & INode
 30 | 
 31 | export type DotOperatorNode = {
 32 |   type: 'DotOperator'
 33 | } & INode
 34 | 
 35 | export type WildcardOperatorNode = {
 36 |   type: 'WildcardOperator'
 37 |   filter?: GroupExpressionNode | RangeExpressionNode
 38 |   optional?: boolean
 39 | } & INode
 40 | 
 41 | export type ExpandOperatorNode = {
 42 |   type: 'ExpandOperator'
 43 | } & INode
 44 | 
 45 | export type GroupExpressionNode = {
 46 |   type: 'GroupExpression'
 47 |   value: Node[]
 48 |   isExclude?: boolean
 49 | } & INode
 50 | 
 51 | export type RangeExpressionNode = {
 52 |   type: 'RangeExpression'
 53 |   start?: IdentifierNode
 54 |   end?: IdentifierNode
 55 | } & INode
 56 | 
 57 | export type DestructorExpressionNode = {
 58 |   type: 'DestructorExpression'
 59 |   value?: ObjectPatternNode | ArrayPatternNode
 60 |   source?: string
 61 | } & INode
 62 | 
 63 | export type ObjectPatternNode = {
 64 |   type: 'ObjectPattern'
 65 |   properties: ObjectPatternPropertyNode[]
 66 | } & INode
 67 | 
 68 | export type ObjectPatternPropertyNode = {
 69 |   type: 'ObjectPatternProperty'
 70 |   key: IdentifierNode
 71 |   value?: ObjectPatternNode[] | ArrayPatternNode[] | IdentifierNode
 72 | } & INode
 73 | 
 74 | export type ArrayPatternNode = {
 75 |   type: 'ArrayPattern'
 76 |   elements: ObjectPatternNode[] | ArrayPatternNode[] | IdentifierNode[]
 77 | } & INode
 78 | 
 79 | export type DestructorRule = {
 80 |   key?: string | number
 81 |   path?: Array<number | string>
 82 | }
 83 | 
 84 | export type MatcherFunction = ((path: Segments) => boolean) & {
 85 |   path: Path
 86 | }
 87 | 
 88 | export type Pattern =
 89 |   | string
 90 |   | number
 91 |   | Path
 92 |   | Segments
 93 |   | MatcherFunction
 94 |   | RegExp
 95 | 
 96 | export type DestructorRules = DestructorRule[]
 97 | 
 98 | export type Segments = Array<string | number>
 99 | 
100 | export const isType =
101 |   <T>(type: string) =>
102 |   (obj: any): obj is T => {
103 |     return obj && obj.type === type
104 |   }
105 | 
106 | export const isIdentifier = isType<IdentifierNode>('Identifier')
107 | 
108 | export const isIgnoreExpression =
109 |   isType<IgnoreExpressionNode>('IgnoreExpression')
110 | 
111 | export const isDotOperator = isType<DotOperatorNode>('DotOperator')
112 | 
113 | export const isWildcardOperator =
114 |   isType<WildcardOperatorNode>('WildcardOperator')
115 | 
116 | export const isExpandOperator = isType<ExpandOperatorNode>('ExpandOperator')
117 | 
118 | export const isGroupExpression = isType<GroupExpressionNode>('GroupExpression')
119 | 
120 | export const isRangeExpression = isType<RangeExpressionNode>('RangeExpression')
121 | 
122 | export const isDestructorExpression = isType<DestructorExpressionNode>(
123 |   'DestructorExpression'
124 | )
125 | 
126 | export const isObjectPattern = isType<ObjectPatternNode>('ObjectPattern')
127 | 
128 | export const isObjectPatternProperty = isType<ObjectPatternPropertyNode>(
129 |   'ObjectPatternProperty'
130 | )
131 | 
132 | export const isArrayPattern = isType<ArrayPatternNode>('ArrayPattern')
133 | 
134 | export type KeyType = string | number | symbol
135 | 
136 | export type IAccessors = {
137 |   get?: (source: any, key: KeyType) => any
138 |   set?: (source: any, key: KeyType, value: any) => any
139 |   has?: (source: any, key: KeyType) => boolean
140 |   delete?: (source: any, key: KeyType) => any
141 | }
142 | 
143 | export type IRegistry = {
144 |   accessors?: IAccessors
145 | }
146 | 
```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/form-item/size.vue:
--------------------------------------------------------------------------------

```vue
  1 | <template>
  2 |   <Form :form="form">
  3 |     <SchemaField>
  4 |       <SchemaStringField
  5 |         name="size"
  6 |         title="Radio.Group"
  7 |         x-decorator="FormItem"
  8 |         x-component="Radio.Group"
  9 |         :enum="[
 10 |           { value: 'small', label: 'Small' },
 11 |           { value: 'default', label: 'Default' },
 12 |           { value: 'large', label: 'Large' },
 13 |         ]"
 14 |       />
 15 |       <SchemaVoidField name="sizeWrap" x-component="Div">
 16 |         <SchemaStringField
 17 |           name="input"
 18 |           title="Input"
 19 |           x-decorator="FormItem"
 20 |           x-component="Input"
 21 |           required
 22 |         />
 23 |         <SchemaStringField
 24 |           name="select1"
 25 |           title="Multiple Select"
 26 |           x-decorator="FormItem"
 27 |           x-component="Select"
 28 |           :enum="[
 29 |             {
 30 |               label: '选项1',
 31 |               value: 1,
 32 |             },
 33 |             {
 34 |               label: '选项2',
 35 |               value: 2,
 36 |             },
 37 |           ]"
 38 |           :x-component-props="{
 39 |             multiple: true,
 40 |             placeholder: '请选择',
 41 |           }"
 42 |           required
 43 |         />
 44 |         <SchemaStringField
 45 |           name="select2"
 46 |           title="Select"
 47 |           x-decorator="FormItem"
 48 |           x-component="Select"
 49 |           :enum="[
 50 |             {
 51 |               label: '选项1',
 52 |               value: 1,
 53 |             },
 54 |             {
 55 |               label: '选项2',
 56 |               value: 2,
 57 |             },
 58 |           ]"
 59 |           :x-component-props="{
 60 |             placeholder: '请选择',
 61 |           }"
 62 |           required
 63 |         />
 64 |         <SchemaStringField
 65 |           name="Cascader"
 66 |           title="Cascader"
 67 |           x-decorator="FormItem"
 68 |           x-component="Cascader"
 69 |           required
 70 |         />
 71 |         <SchemaStringField
 72 |           name="DatePicker"
 73 |           title="DatePicker"
 74 |           x-decorator="FormItem"
 75 |           x-component="DatePicker"
 76 |           required
 77 |         />
 78 |         <SchemaStringField
 79 |           name="InputNumber"
 80 |           title="InputNumber"
 81 |           x-decorator="FormItem"
 82 |           x-component="InputNumber"
 83 |           required
 84 |         />
 85 |         <SchemaBooleanField
 86 |           name="Switch"
 87 |           title="Switch"
 88 |           x-decorator="FormItem"
 89 |           x-component="Switch"
 90 |           required
 91 |         />
 92 |       </SchemaVoidField>
 93 |     </SchemaField>
 94 |   </Form>
 95 | </template>
 96 | 
 97 | <script>
 98 | import { createForm, onFieldChange } from '@formily/core'
 99 | import { createSchemaField } from '@formily/vue'
100 | import {
101 |   Form,
102 |   FormItem,
103 |   Input,
104 |   Select,
105 |   Cascader,
106 |   DatePicker,
107 |   Switch,
108 |   InputNumber,
109 |   Radio,
110 | } from '@formily/element'
111 | 
112 | const Div = {
113 |   functional: true,
114 |   render(h, context) {
115 |     return h('div', context.data, context.children)
116 |   },
117 | }
118 | 
119 | const form = createForm({
120 |   values: {
121 |     size: 'default',
122 |   },
123 |   effects: () => {
124 |     onFieldChange('size', ['value'], (field, form) => {
125 |       form.setFieldState('sizeWrap.*', (state) => {
126 |         if (state.decorator[1]) {
127 |           state.decorator[1].size = field.value
128 |         }
129 |       })
130 |     })
131 |   },
132 | })
133 | const fields = createSchemaField({
134 |   components: {
135 |     FormItem,
136 |     Input,
137 |     Select,
138 |     Cascader,
139 |     DatePicker,
140 |     Switch,
141 |     InputNumber,
142 |     Radio,
143 |     Div,
144 |   },
145 | })
146 | 
147 | export default {
148 |   components: { Form, ...fields },
149 |   data() {
150 |     return {
151 |       form,
152 |     }
153 |   },
154 |   methods: {
155 |     onSubmit(value) {
156 |       console.log(value)
157 |     },
158 |   },
159 | }
160 | </script>
161 | 
```

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

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

--------------------------------------------------------------------------------
/packages/core/src/models/ArrayField.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { isArr, move } from '@formily/shared'
  2 | import { action, reaction } from '@formily/reactive'
  3 | import {
  4 |   spliceArrayState,
  5 |   exchangeArrayState,
  6 |   cleanupArrayChildren,
  7 | } from '../shared/internals'
  8 | import { Field } from './Field'
  9 | import { Form } from './Form'
 10 | import { JSXComponent, IFieldProps, FormPathPattern } from '../types'
 11 | 
 12 | export class ArrayField<
 13 |   Decorator extends JSXComponent = any,
 14 |   Component extends JSXComponent = any
 15 | > extends Field<Decorator, Component, any, any[]> {
 16 |   displayName = 'ArrayField'
 17 | 
 18 |   constructor(
 19 |     address: FormPathPattern,
 20 |     props: IFieldProps<Decorator, Component>,
 21 |     form: Form,
 22 |     designable: boolean
 23 |   ) {
 24 |     super(address, props, form, designable)
 25 |     this.makeAutoCleanable()
 26 |   }
 27 | 
 28 |   protected makeAutoCleanable() {
 29 |     this.disposers.push(
 30 |       reaction(
 31 |         () => this.value?.length,
 32 |         (newLength, oldLength) => {
 33 |           if (oldLength && !newLength) {
 34 |             cleanupArrayChildren(this, 0)
 35 |           } else if (newLength < oldLength) {
 36 |             cleanupArrayChildren(this, newLength)
 37 |           }
 38 |         }
 39 |       )
 40 |     )
 41 |   }
 42 | 
 43 |   push = (...items: any[]) => {
 44 |     return action(() => {
 45 |       if (!isArr(this.value)) {
 46 |         this.value = []
 47 |       }
 48 |       this.value.push(...items)
 49 |       return this.onInput(this.value)
 50 |     })
 51 |   }
 52 | 
 53 |   pop = () => {
 54 |     if (!isArr(this.value)) return
 55 |     return action(() => {
 56 |       const index = this.value.length - 1
 57 |       spliceArrayState(this, {
 58 |         startIndex: index,
 59 |         deleteCount: 1,
 60 |       })
 61 |       this.value.pop()
 62 |       return this.onInput(this.value)
 63 |     })
 64 |   }
 65 | 
 66 |   insert = (index: number, ...items: any[]) => {
 67 |     return action(() => {
 68 |       if (!isArr(this.value)) {
 69 |         this.value = []
 70 |       }
 71 |       if (items.length === 0) {
 72 |         return
 73 |       }
 74 |       spliceArrayState(this, {
 75 |         startIndex: index,
 76 |         insertCount: items.length,
 77 |       })
 78 |       this.value.splice(index, 0, ...items)
 79 |       return this.onInput(this.value)
 80 |     })
 81 |   }
 82 | 
 83 |   remove = (index: number) => {
 84 |     if (!isArr(this.value)) return
 85 |     return action(() => {
 86 |       spliceArrayState(this, {
 87 |         startIndex: index,
 88 |         deleteCount: 1,
 89 |       })
 90 |       this.value.splice(index, 1)
 91 |       return this.onInput(this.value)
 92 |     })
 93 |   }
 94 | 
 95 |   shift = () => {
 96 |     if (!isArr(this.value)) return
 97 |     return action(() => {
 98 |       this.value.shift()
 99 |       return this.onInput(this.value)
100 |     })
101 |   }
102 | 
103 |   unshift = (...items: any[]) => {
104 |     return action(() => {
105 |       if (!isArr(this.value)) {
106 |         this.value = []
107 |       }
108 |       spliceArrayState(this, {
109 |         startIndex: 0,
110 |         insertCount: items.length,
111 |       })
112 |       this.value.unshift(...items)
113 |       return this.onInput(this.value)
114 |     })
115 |   }
116 | 
117 |   move = (fromIndex: number, toIndex: number) => {
118 |     if (!isArr(this.value)) return
119 |     if (fromIndex === toIndex) return
120 |     return action(() => {
121 |       move(this.value, fromIndex, toIndex)
122 |       exchangeArrayState(this, {
123 |         fromIndex,
124 |         toIndex,
125 |       })
126 |       return this.onInput(this.value)
127 |     })
128 |   }
129 | 
130 |   moveUp = (index: number) => {
131 |     if (!isArr(this.value)) return
132 |     return this.move(index, index - 1 < 0 ? this.value.length - 1 : index - 1)
133 |   }
134 | 
135 |   moveDown = (index: number) => {
136 |     if (!isArr(this.value)) return
137 |     return this.move(index, index + 1 >= this.value.length ? 0 : index + 1)
138 |   }
139 | }
140 | 
```

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

```typescript
  1 | import {
  2 |   isValid,
  3 |   isFn,
  4 |   isMap,
  5 |   isWeakMap,
  6 |   isSet,
  7 |   isWeakSet,
  8 |   isPlainObj,
  9 |   isArr,
 10 | } from './checkers'
 11 | import {
 12 |   ProxyRaw,
 13 |   MakeObModelSymbol,
 14 |   DependencyCollected,
 15 |   ObModelSymbol,
 16 | } from './environment'
 17 | import { getDataNode } from './tree'
 18 | import { Annotation } from './types'
 19 | 
 20 | const RAW_TYPE = Symbol('RAW_TYPE')
 21 | const OBSERVABLE_TYPE = Symbol('OBSERVABLE_TYPE')
 22 | const hasOwnProperty = Object.prototype.hasOwnProperty
 23 | 
 24 | export const isObservable = (target: any) => {
 25 |   return ProxyRaw.has(target) || !!target?.[ObModelSymbol]
 26 | }
 27 | 
 28 | export const isAnnotation = (target: any): target is Annotation => {
 29 |   return target && !!target[MakeObModelSymbol]
 30 | }
 31 | 
 32 | export const isSupportObservable = (target: any) => {
 33 |   if (!isValid(target)) return false
 34 |   if (isArr(target)) return true
 35 |   if (isPlainObj(target)) {
 36 |     if (target[RAW_TYPE]) {
 37 |       return false
 38 |     }
 39 |     if (target[OBSERVABLE_TYPE]) {
 40 |       return true
 41 |     }
 42 |     if ('$$typeof' in target && '_owner' in target) {
 43 |       return false
 44 |     }
 45 |     if (target['_isAMomentObject']) {
 46 |       return false
 47 |     }
 48 |     if (target['_isJSONSchemaObject']) {
 49 |       return false
 50 |     }
 51 |     if (isFn(target['toJS'])) {
 52 |       return false
 53 |     }
 54 |     if (isFn(target['toJSON'])) {
 55 |       return false
 56 |     }
 57 |     return true
 58 |   }
 59 |   if (isMap(target) || isWeakMap(target) || isSet(target) || isWeakSet(target))
 60 |     return true
 61 |   return false
 62 | }
 63 | 
 64 | export const markRaw = <T>(target: T): T => {
 65 |   if (!target) return
 66 |   if (isFn(target)) {
 67 |     target.prototype[RAW_TYPE] = true
 68 |   } else {
 69 |     target[RAW_TYPE] = true
 70 |   }
 71 |   return target
 72 | }
 73 | 
 74 | export const markObservable = <T>(target: T): T => {
 75 |   if (!target) return
 76 |   if (isFn(target)) {
 77 |     target.prototype[OBSERVABLE_TYPE] = true
 78 |   } else {
 79 |     target[OBSERVABLE_TYPE] = true
 80 |   }
 81 |   return target
 82 | }
 83 | 
 84 | export const raw = <T>(target: T): T => {
 85 |   if (target?.[ObModelSymbol]) return target[ObModelSymbol]
 86 |   return ProxyRaw.get(target as any) || target
 87 | }
 88 | 
 89 | export const toJS = <T>(values: T): T => {
 90 |   const visited = new WeakSet<any>()
 91 |   const _toJS: typeof toJS = (values: any) => {
 92 |     if (visited.has(values)) {
 93 |       return values
 94 |     }
 95 |     if (values && values[RAW_TYPE]) return values
 96 |     if (isArr(values)) {
 97 |       if (isObservable(values)) {
 98 |         visited.add(values)
 99 |         const res: any = []
100 |         values.forEach((item: any) => {
101 |           res.push(_toJS(item))
102 |         })
103 |         visited.delete(values)
104 |         return res
105 |       }
106 |     } else if (isPlainObj(values)) {
107 |       if (isObservable(values)) {
108 |         visited.add(values)
109 |         const res: any = {}
110 |         for (const key in values) {
111 |           if (hasOwnProperty.call(values, key)) {
112 |             res[key] = _toJS(values[key])
113 |           }
114 |         }
115 |         visited.delete(values)
116 |         return res
117 |       }
118 |     }
119 |     return values
120 |   }
121 | 
122 |   return _toJS(values)
123 | }
124 | 
125 | export const contains = (target: any, property: any) => {
126 |   const targetRaw = raw(target)
127 |   const propertyRaw = raw(property)
128 |   if (targetRaw === propertyRaw) return true
129 |   const targetNode = getDataNode(targetRaw)
130 |   const propertyNode = getDataNode(propertyRaw)
131 |   if (!targetNode) return false
132 |   if (!propertyNode) return false
133 |   return targetNode.contains(propertyNode)
134 | }
135 | 
136 | export const hasCollected = (callback?: () => void) => {
137 |   DependencyCollected.value = false
138 |   callback?.()
139 |   return DependencyCollected.value
140 | }
141 | 
```

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

```markdown
  1 | # ArrayTabs
  2 | 
  3 | > 自增选项卡,对于纵向空间要求较高的场景可以考虑使用该组件
  4 | >
  5 | > 注意:该组件只适用于 Schema 场景,交互上请避免跨 Tab 联动
  6 | 
  7 | ## Markup Schema 案例
  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="字符串数组"
 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="对象数组"
 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>
 75 |       </FormButtonGroup>
 76 |     </FormProvider>
 77 |   )
 78 | }
 79 | ```
 80 | 
 81 | ## JSON Schema 案例
 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: '字符串数组',
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: '对象数组',
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>
156 |       </FormButtonGroup>
157 |     </FormProvider>
158 |   )
159 | }
160 | ```
161 | 
162 | ## API
163 | 
164 | ### ArrayTabs
165 | 
166 | 参考 https://ant.design/components/tabs-cn/
167 | 
```

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

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

--------------------------------------------------------------------------------
/packages/json-schema/src/__tests__/patches.spec.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Schema } from '../schema'
  2 | import {
  3 |   registerTypeDefaultComponents,
  4 |   registerVoidComponents,
  5 | } from '../polyfills'
  6 | 
  7 | registerVoidComponents(['MyCard'])
  8 | registerTypeDefaultComponents({
  9 |   string: 'Input',
 10 | })
 11 | 
 12 | Schema.enablePolyfills(['1.0'])
 13 | 
 14 | test('v1 polyfill', () => {
 15 |   const schema = new Schema({
 16 |     type: 'string',
 17 |     editable: true,
 18 |   } as any)
 19 |   expect(schema['x-editable']).toEqual(true)
 20 |   const schema1 = new Schema({
 21 |     type: 'string',
 22 |     visible: true,
 23 |   } as any)
 24 |   expect(schema1['x-visible']).toEqual(true)
 25 |   const schema2 = new Schema({
 26 |     type: 'string',
 27 |     display: false,
 28 |   } as any)
 29 |   expect(schema2['x-display']).toEqual('hidden')
 30 |   expect(schema2['x-display']).toEqual('hidden')
 31 |   const schema3 = new Schema({
 32 |     type: 'string',
 33 |     'x-linkages': [
 34 |       {
 35 |         type: 'value:visible',
 36 |         condition: '{{$value == 123}}',
 37 |       },
 38 |     ],
 39 |   } as any)
 40 |   expect(schema3['x-reactions']).toEqual([
 41 |     {
 42 |       when: '{{$self.value == 123}}',
 43 |       fulfill: {
 44 |         state: {
 45 |           visible: true,
 46 |         },
 47 |       },
 48 |       otherwise: {
 49 |         state: {
 50 |           visible: false,
 51 |         },
 52 |       },
 53 |     },
 54 |   ])
 55 |   const schema4 = new Schema({
 56 |     type: 'string',
 57 |     'x-linkages': [
 58 |       {
 59 |         type: 'value:schema',
 60 |         target: 'xxx',
 61 |         condition: '{{$value == 123}}',
 62 |         schema: {
 63 |           title: 'xxx',
 64 |         },
 65 |         otherwise: {
 66 |           title: '123',
 67 |         },
 68 |       },
 69 |     ],
 70 |   } as any)
 71 |   expect(schema4['x-reactions']).toEqual([
 72 |     {
 73 |       when: '{{$self.value == 123}}',
 74 |       target: 'xxx',
 75 |       fulfill: {
 76 |         schema: {
 77 |           version: '1.0',
 78 |           title: 'xxx',
 79 |           'x-decorator': 'FormItem',
 80 |         },
 81 |       },
 82 |       otherwise: {
 83 |         schema: {
 84 |           version: '1.0',
 85 |           title: '123',
 86 |           'x-decorator': 'FormItem',
 87 |         },
 88 |       },
 89 |     },
 90 |   ])
 91 |   const schema5 = new Schema({
 92 |     type: 'string',
 93 |     'x-linkages': [
 94 |       {
 95 |         type: 'value:state',
 96 |         target: 'xxx',
 97 |         condition: '{{$value == 123}}',
 98 |         state: {
 99 |           title: 'xxx',
100 |         },
101 |         otherwise: {
102 |           title: '123',
103 |         },
104 |       },
105 |     ],
106 |   } as any)
107 |   expect(schema5['x-reactions']).toEqual([
108 |     {
109 |       when: '{{$self.value == 123}}',
110 |       target: 'xxx',
111 |       fulfill: {
112 |         state: {
113 |           title: 'xxx',
114 |         },
115 |       },
116 |       otherwise: {
117 |         state: {
118 |           title: '123',
119 |         },
120 |       },
121 |     },
122 |   ])
123 |   const schema6 = new Schema({
124 |     type: 'string',
125 |     'x-props': {
126 |       labelCol: 3,
127 |       wrapperCol: 4,
128 |     },
129 |     'x-linkages': [
130 |       {
131 |         type: 'value:visible',
132 |         condition: null,
133 |       },
134 |     ],
135 |   } as any)
136 |   expect(schema6['x-component']).toEqual('Input')
137 |   expect(schema6['x-decorator']).toEqual('FormItem')
138 |   expect(schema6['x-decorator-props']).toEqual({
139 |     labelCol: 3,
140 |     wrapperCol: 4,
141 |   })
142 |   const schema7 = new Schema({
143 |     type: 'object',
144 |     'x-component': 'MyCard',
145 |     'x-linkages': {},
146 |   } as any)
147 |   expect(schema7.type === 'void').toBeTruthy()
148 |   new Schema({
149 |     type: 'object',
150 |     'x-component': 'MyCard',
151 |     'x-linkages': [null],
152 |   } as any)
153 |   new Schema({
154 |     type: 'object',
155 |     'x-component': 'MyCard',
156 |     'x-linkages': [{}],
157 |   } as any)
158 |   const schema8 = new Schema({
159 |     type: 'string',
160 |     'x-rules': ['phone'],
161 |   } as any)
162 |   expect(schema8['x-validator']).toEqual(['phone'])
163 | })
164 | 
```

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

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

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

```vue
  1 | <template>
  2 |   <FormProvider :form="form">
  3 |     <SchemaField>
  4 |       <SchemaArrayField
  5 |         name="array"
  6 |         x-decorator="FormItem"
  7 |         x-component="ArrayTable"
  8 |         :x-component-props="{
  9 |           pagination: { pageSize: 10 },
 10 |         }"
 11 |       >
 12 |         <SchemaObjectField>
 13 |           <SchemaVoidField
 14 |             x-component="ArrayTable.Column"
 15 |             :x-component-props="{ width: 80, title: 'Index' }"
 16 |             ><SchemaVoidField
 17 |               x-decorator="FormItem"
 18 |               x-component="ArrayTable.Index"
 19 |             />
 20 |           </SchemaVoidField>
 21 |           <SchemaVoidField
 22 |             x-component="ArrayTable.Column"
 23 |             :x-component-props="{ prop: 'a1', title: 'A1', width: 200 }"
 24 |           >
 25 |             <SchemaStringField
 26 |               x-decorator="Editable"
 27 |               name="a1"
 28 |               :required="true"
 29 |               x-component="Input"
 30 |             />
 31 |           </SchemaVoidField>
 32 |           <SchemaVoidField
 33 |             x-component="ArrayTable.Column"
 34 |             :x-component-props="{ title: 'A2', width: 200 }"
 35 |           >
 36 |             <SchemaStringField
 37 |               x-decorator="FormItem"
 38 |               name="a2"
 39 |               :required="true"
 40 |               x-component="Input"
 41 |             />
 42 |           </SchemaVoidField>
 43 |           <SchemaVoidField
 44 |             x-component="ArrayTable.Column"
 45 |             :x-component-props="{ title: 'A3' }"
 46 |           >
 47 |             <SchemaStringField
 48 |               name="a3"
 49 |               :required="true"
 50 |               x-decorator="FormItem"
 51 |               x-component="Input"
 52 |             />
 53 |           </SchemaVoidField>
 54 |           <SchemaVoidField
 55 |             x-component="ArrayTable.Column"
 56 |             :x-component-props="{
 57 |               title: 'Operations',
 58 |               prop: 'operations',
 59 |               width: 200,
 60 |               fixed: 'right',
 61 |             }"
 62 |           >
 63 |             <SchemaVoidField x-component="FormItem">
 64 |               <SchemaVoidField x-component="ArrayTable.Remove" />
 65 |               <SchemaVoidField x-component="ArrayTable.MoveUp" />
 66 |               <SchemaVoidField x-component="ArrayTable.MoveDown" />
 67 |             </SchemaVoidField>
 68 |           </SchemaVoidField>
 69 |         </SchemaObjectField>
 70 |         <SchemaVoidField x-component="ArrayTable.Addition" title="添加条目" />
 71 |       </SchemaArrayField>
 72 |     </SchemaField>
 73 |     <Submit @submit="log">提交</Submit>
 74 |     <Button
 75 |       @click="
 76 |         () => {
 77 |           form.setInitialValues({
 78 |             array: range(100000),
 79 |           })
 80 |         }
 81 |       "
 82 |     >
 83 |       加载10W条超大数据
 84 |     </Button>
 85 |     <Alert
 86 |       :style="{ marginTop: '10px' }"
 87 |       title="注意:开启formily插件的页面,因为后台有数据通信,会占用浏览器算力,最好在无痕模式(无formily插件)下测试"
 88 |       type="warning"
 89 |     />
 90 |   </FormProvider>
 91 | </template>
 92 | 
 93 | <script>
 94 | import { createForm } from '@formily/core'
 95 | import { FormProvider, createSchemaField } from '@formily/vue'
 96 | import { Submit, FormItem, ArrayTable, Input, Editable } from '@formily/element'
 97 | import { Button, Alert } from 'element-ui'
 98 | 
 99 | const fields = createSchemaField({
100 |   components: {
101 |     FormItem,
102 |     ArrayTable,
103 |     Input,
104 |     Editable,
105 |   },
106 | })
107 | 
108 | export default {
109 |   components: { FormProvider, Submit, Button, Alert, ...fields },
110 |   data() {
111 |     const form = createForm()
112 |     return {
113 |       form,
114 |     }
115 |   },
116 |   methods: {
117 |     log(...v) {
118 |       console.log(...v)
119 |     },
120 |     range(count) {
121 |       return Array.from(new Array(count)).map((_, key) => ({
122 |         aaa: key,
123 |       }))
124 |     },
125 |   },
126 | }
127 | </script>
128 | 
```

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

```typescript
  1 | import React, { createContext, useContext } from 'react'
  2 | import { useResponsiveFormLayout } from './useResponsiveFormLayout'
  3 | import { usePrefixCls } from '../__builtins__'
  4 | import cls from 'classnames'
  5 | 
  6 | export interface IFormLayoutProps {
  7 |   prefix?: string
  8 |   className?: string
  9 |   style?: React.CSSProperties
 10 |   colon?: boolean
 11 |   labelAlign?: 'right' | 'left' | ('right' | 'left')[]
 12 |   wrapperAlign?: 'right' | 'left' | ('right' | 'left')[]
 13 |   labelWrap?: boolean
 14 |   labelWidth?: number
 15 |   wrapperWidth?: number
 16 |   wrapperWrap?: boolean
 17 |   labelCol?: number | number[]
 18 |   wrapperCol?: number | number[]
 19 |   fullness?: boolean
 20 |   size?: 'small' | 'default' | 'large'
 21 |   layout?:
 22 |     | 'vertical'
 23 |     | 'horizontal'
 24 |     | 'inline'
 25 |     | ('vertical' | 'horizontal' | 'inline')[]
 26 |   direction?: 'rtl' | 'ltr'
 27 |   inset?: boolean
 28 |   shallow?: boolean
 29 |   tooltipLayout?: 'icon' | 'text'
 30 |   tooltipIcon?: React.ReactNode
 31 |   feedbackLayout?: 'loose' | 'terse' | 'popover' | 'none'
 32 |   bordered?: boolean
 33 |   breakpoints?: number[]
 34 |   gridColumnGap?: number
 35 |   gridRowGap?: number
 36 |   spaceGap?: number
 37 | }
 38 | 
 39 | export interface IFormLayoutContext
 40 |   extends Omit<
 41 |     IFormLayoutProps,
 42 |     'labelAlign' | 'wrapperAlign' | 'layout' | 'labelCol' | 'wrapperCol'
 43 |   > {
 44 |   labelAlign?: 'right' | 'left'
 45 |   wrapperAlign?: 'right' | 'left'
 46 |   layout?: 'vertical' | 'horizontal' | 'inline'
 47 |   labelCol?: number
 48 |   wrapperCol?: number
 49 | }
 50 | 
 51 | export const FormLayoutDeepContext = createContext<IFormLayoutContext>(null)
 52 | 
 53 | export const FormLayoutShallowContext = createContext<IFormLayoutContext>(null)
 54 | 
 55 | export const useFormDeepLayout = () => useContext(FormLayoutDeepContext)
 56 | 
 57 | export const useFormShallowLayout = () => useContext(FormLayoutShallowContext)
 58 | 
 59 | export const useFormLayout = () => ({
 60 |   ...useFormDeepLayout(),
 61 |   ...useFormShallowLayout(),
 62 | })
 63 | 
 64 | export const FormLayout: React.FC<React.PropsWithChildren<IFormLayoutProps>> & {
 65 |   useFormLayout: () => IFormLayoutContext
 66 |   useFormDeepLayout: () => IFormLayoutContext
 67 |   useFormShallowLayout: () => IFormLayoutContext
 68 | } = ({ shallow = true, children, prefix, className, style, ...otherProps }) => {
 69 |   const { ref, props } = useResponsiveFormLayout(otherProps)
 70 |   const deepLayout = useFormDeepLayout()
 71 |   const formPrefixCls = usePrefixCls('form', { prefix })
 72 |   const layoutPrefixCls = usePrefixCls('formily-layout', { prefix })
 73 |   const layoutClassName = cls(
 74 |     layoutPrefixCls,
 75 |     {
 76 |       [`${formPrefixCls}-${props.layout}`]: true,
 77 |       [`${formPrefixCls}-rtl`]: props.direction === 'rtl',
 78 |       [`${formPrefixCls}-${props.size}`]: props.size,
 79 |     },
 80 |     className
 81 |   )
 82 |   const renderChildren = () => {
 83 |     const newDeepLayout = {
 84 |       ...deepLayout,
 85 |     }
 86 |     if (!shallow) {
 87 |       Object.assign(newDeepLayout, props)
 88 |     } else {
 89 |       if (props.size) {
 90 |         newDeepLayout.size = props.size
 91 |       }
 92 |       if (props.colon) {
 93 |         newDeepLayout.colon = props.colon
 94 |       }
 95 |     }
 96 |     return (
 97 |       <FormLayoutDeepContext.Provider value={newDeepLayout}>
 98 |         <FormLayoutShallowContext.Provider value={shallow ? props : undefined}>
 99 |           {children}
100 |         </FormLayoutShallowContext.Provider>
101 |       </FormLayoutDeepContext.Provider>
102 |     )
103 |   }
104 |   return (
105 |     <div ref={ref} className={layoutClassName} style={style}>
106 |       {renderChildren()}
107 |     </div>
108 |   )
109 | }
110 | 
111 | FormLayout.useFormDeepLayout = useFormDeepLayout
112 | FormLayout.useFormShallowLayout = useFormShallowLayout
113 | FormLayout.useFormLayout = useFormLayout
114 | 
115 | export default FormLayout
116 | 
```

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

```markdown
  1 | # Submit
  2 | 
  3 | > Submit button
  4 | 
  5 | ## Ordinary submission
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
 10 | import { createForm } from '@formily/core'
 11 | import { FormProvider, createSchemaField } from '@formily/react'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     Input,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.String
 26 |         name="input"
 27 |         title="input box"
 28 |         required
 29 |         x-decorator="FormItem"
 30 |         x-component="Input"
 31 |       />
 32 |       <SchemaField.String
 33 |         name="input2"
 34 |         title="input box"
 35 |         default="123"
 36 |         required
 37 |         x-decorator="FormItem"
 38 |         x-component="Input"
 39 |       />
 40 |     </SchemaField>
 41 |     <FormButtonGroup>
 42 |       <Submit onSubmit={console.log}>Submit</Submit>
 43 |     </FormButtonGroup>
 44 |   </FormProvider>
 45 | )
 46 | ```
 47 | 
 48 | ## Prevent Duplicate Submission (Loading)
 49 | 
 50 | ```tsx
 51 | import React from 'react'
 52 | import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
 53 | import { createForm } from '@formily/core'
 54 | import { FormProvider, createSchemaField } from '@formily/react'
 55 | 
 56 | const SchemaField = createSchemaField({
 57 |   components: {
 58 |     Input,
 59 |     FormItem,
 60 |   },
 61 | })
 62 | 
 63 | const form = createForm()
 64 | 
 65 | export default () => (
 66 |   <FormProvider form={form}>
 67 |     <SchemaField>
 68 |       <SchemaField.String
 69 |         name="input"
 70 |         title="input box"
 71 |         required
 72 |         x-decorator="FormItem"
 73 |         x-component="Input"
 74 |       />
 75 |       <SchemaField.String
 76 |         name="input2"
 77 |         title="input box"
 78 |         default="123"
 79 |         required
 80 |         x-decorator="FormItem"
 81 |         x-component="Input"
 82 |       />
 83 |     </SchemaField>
 84 |     <FormButtonGroup>
 85 |       <Submit
 86 |         onSubmit={(values) => {
 87 |           return new Promise((resolve) => {
 88 |             setTimeout(() => {
 89 |               console.log(values)
 90 |               resolve()
 91 |             }, 2000)
 92 |           })
 93 |         }}
 94 |         onSubmitFailed={console.log}
 95 |       >
 96 |         submit
 97 |       </Submit>
 98 |     </FormButtonGroup>
 99 |   </FormProvider>
100 | )
101 | ```
102 | 
103 | ## API
104 | 
105 | For button-related API properties, we can refer to https://ant.design/components/button-cn/, and the rest are the unique API properties of the Submit component
106 | 
107 | | Property name   | Type                                                                                             | Description                                               | Default value |
108 | | --------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ------------- |
109 | | onClick         | `(event: MouseEvent) => void \| boolean`                                                         | Click event, if it returns false, it can block submission | -             |
110 | | onSubmit        | `(values: any) => Promise<any> \| any`                                                           | Submit event callback                                     | -             |
111 | | onSubmitSuccess | (payload: any) => void                                                                           | Submit successful response event                          | -             |
112 | | onSubmitFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Submit verification failure event callback                | -             |
113 | 
```

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

```markdown
  1 | # Submit
  2 | 
  3 | > Submit button
  4 | 
  5 | ## Ordinary submission
  6 | 
  7 | ```tsx
  8 | import React from 'react'
  9 | import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
 10 | import { createForm } from '@formily/core'
 11 | import { FormProvider, createSchemaField } from '@formily/react'
 12 | 
 13 | const SchemaField = createSchemaField({
 14 |   components: {
 15 |     Input,
 16 |     FormItem,
 17 |   },
 18 | })
 19 | 
 20 | const form = createForm()
 21 | 
 22 | export default () => (
 23 |   <FormProvider form={form}>
 24 |     <SchemaField>
 25 |       <SchemaField.String
 26 |         name="input"
 27 |         title="input box"
 28 |         required
 29 |         x-decorator="FormItem"
 30 |         x-component="Input"
 31 |       />
 32 |       <SchemaField.String
 33 |         name="input2"
 34 |         title="input box"
 35 |         default="123"
 36 |         required
 37 |         x-decorator="FormItem"
 38 |         x-component="Input"
 39 |       />
 40 |     </SchemaField>
 41 |     <FormButtonGroup>
 42 |       <Submit onSubmit={console.log}>Submit</Submit>
 43 |     </FormButtonGroup>
 44 |   </FormProvider>
 45 | )
 46 | ```
 47 | 
 48 | ## Prevent Duplicate Submission (Loading)
 49 | 
 50 | ```tsx
 51 | import React from 'react'
 52 | import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
 53 | import { createForm } from '@formily/core'
 54 | import { FormProvider, createSchemaField } from '@formily/react'
 55 | 
 56 | const SchemaField = createSchemaField({
 57 |   components: {
 58 |     Input,
 59 |     FormItem,
 60 |   },
 61 | })
 62 | 
 63 | const form = createForm()
 64 | 
 65 | export default () => (
 66 |   <FormProvider form={form}>
 67 |     <SchemaField>
 68 |       <SchemaField.String
 69 |         name="input"
 70 |         title="input box"
 71 |         required
 72 |         x-decorator="FormItem"
 73 |         x-component="Input"
 74 |       />
 75 |       <SchemaField.String
 76 |         name="input2"
 77 |         title="input box"
 78 |         default="123"
 79 |         required
 80 |         x-decorator="FormItem"
 81 |         x-component="Input"
 82 |       />
 83 |     </SchemaField>
 84 |     <FormButtonGroup>
 85 |       <Submit
 86 |         onSubmit={(values) => {
 87 |           return new Promise((resolve) => {
 88 |             setTimeout(() => {
 89 |               console.log(values)
 90 |               resolve()
 91 |             }, 2000)
 92 |           })
 93 |         }}
 94 |         onSubmitFailed={console.log}
 95 |       >
 96 |         submit
 97 |       </Submit>
 98 |     </FormButtonGroup>
 99 |   </FormProvider>
100 | )
101 | ```
102 | 
103 | ## API
104 | 
105 | For button-related API properties, we can refer to https://fusion.design/pc/component/basic/button, and the rest are the unique API properties of the Submit component
106 | 
107 | | Property name   | Type                                                                                             | Description                                               | Default value |
108 | | --------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ------------- |
109 | | onClick         | `(event: MouseEvent) => void \| boolean`                                                         | Click event, if it returns false, it can block submission | -             |
110 | | onSubmit        | `(values: any) => Promise<any> \| any`                                                           | Submit event callback                                     | -             |
111 | | onSubmitSuccess | (payload: any) => void                                                                           | Submit successful response event                          | -             |
112 | | onSubmitFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/api/models/form#iformfeedback)[]) => void | Submit verification failure event callback                | -             |
113 | 
```

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

```markdown
  1 | ---
  2 | order: 1
  3 | ---
  4 | 
  5 | # ArrayField
  6 | 
  7 | ## 描述
  8 | 
  9 | 作为@formily/core 的 [createArrayField](https://core.formilyjs.org/zh-CN/api/models/form#createarrayfield) React 实现,它是专门用于将 ViewModel 与输入控件做绑定的桥接组件,ArrayField 组件属性参考[IFieldFactoryProps](https://core.formilyjs.org/zh-CN/api/models/form#ifieldfactoryprops)
 10 | 
 11 | <Alert>
 12 | 我们在使用 ArrayField 组件的时候,一定要记得传name属性。同时要使用render props形式来组织子组件
 13 | </Alert>
 14 | 
 15 | ## 签名
 16 | 
 17 | ```ts
 18 | type ArrayField = React.FC<React.PropsWithChildren<IFieldFactoryProps>>
 19 | ```
 20 | 
 21 | ## 自定义组件用例
 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 用例
 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/antd/src/form-layout/index.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { createContext, useContext } from 'react'
  2 | import { useResponsiveFormLayout } from './useResponsiveFormLayout'
  3 | import { usePrefixCls } from '../__builtins__'
  4 | import cls from 'classnames'
  5 | 
  6 | export interface IFormLayoutProps {
  7 |   prefixCls?: string
  8 |   className?: string
  9 |   style?: React.CSSProperties
 10 |   colon?: boolean
 11 |   requiredMark?: boolean | 'optional'
 12 |   labelAlign?: 'right' | 'left' | ('right' | 'left')[]
 13 |   wrapperAlign?: 'right' | 'left' | ('right' | 'left')[]
 14 |   labelWrap?: boolean
 15 |   labelWidth?: number
 16 |   wrapperWidth?: number
 17 |   wrapperWrap?: boolean
 18 |   labelCol?: number | number[]
 19 |   wrapperCol?: number | number[]
 20 |   fullness?: boolean
 21 |   size?: 'small' | 'default' | 'large'
 22 |   layout?:
 23 |     | 'vertical'
 24 |     | 'horizontal'
 25 |     | 'inline'
 26 |     | ('vertical' | 'horizontal' | 'inline')[]
 27 |   direction?: 'rtl' | 'ltr'
 28 |   inset?: boolean
 29 |   shallow?: boolean
 30 |   tooltipLayout?: 'icon' | 'text'
 31 |   tooltipIcon?: React.ReactNode
 32 |   feedbackLayout?: 'loose' | 'terse' | 'popover' | 'none'
 33 |   bordered?: boolean
 34 |   breakpoints?: number[]
 35 |   spaceGap?: number
 36 |   gridColumnGap?: number
 37 |   gridRowGap?: number
 38 | }
 39 | 
 40 | export interface IFormLayoutContext
 41 |   extends Omit<
 42 |     IFormLayoutProps,
 43 |     'labelAlign' | 'wrapperAlign' | 'layout' | 'labelCol' | 'wrapperCol'
 44 |   > {
 45 |   labelAlign?: 'right' | 'left'
 46 |   wrapperAlign?: 'right' | 'left'
 47 |   layout?: 'vertical' | 'horizontal' | 'inline'
 48 |   labelCol?: number
 49 |   wrapperCol?: number
 50 | }
 51 | 
 52 | export const FormLayoutDeepContext = createContext<IFormLayoutContext>(null)
 53 | 
 54 | export const FormLayoutShallowContext = createContext<IFormLayoutContext>(null)
 55 | 
 56 | export const useFormDeepLayout = () => useContext(FormLayoutDeepContext)
 57 | 
 58 | export const useFormShallowLayout = () => useContext(FormLayoutShallowContext)
 59 | 
 60 | export const useFormLayout = () => ({
 61 |   ...useFormDeepLayout(),
 62 |   ...useFormShallowLayout(),
 63 | })
 64 | 
 65 | export const FormLayout: React.FC<React.PropsWithChildren<IFormLayoutProps>> & {
 66 |   useFormLayout: () => IFormLayoutContext
 67 |   useFormDeepLayout: () => IFormLayoutContext
 68 |   useFormShallowLayout: () => IFormLayoutContext
 69 | } = ({
 70 |   shallow = true,
 71 |   children,
 72 |   prefixCls,
 73 |   className,
 74 |   style,
 75 |   ...otherProps
 76 | }) => {
 77 |   const { ref, props } = useResponsiveFormLayout(otherProps)
 78 |   const deepLayout = useFormDeepLayout()
 79 |   const formPrefixCls = usePrefixCls('form', { prefixCls })
 80 |   const layoutPrefixCls = usePrefixCls('formily-layout', { prefixCls })
 81 |   const layoutClassName = cls(
 82 |     layoutPrefixCls,
 83 |     {
 84 |       [`${formPrefixCls}-${props.layout}`]: true,
 85 |       [`${formPrefixCls}-rtl`]: props.direction === 'rtl',
 86 |       [`${formPrefixCls}-${props.size}`]: props.size,
 87 |     },
 88 |     className
 89 |   )
 90 |   const renderChildren = () => {
 91 |     const newDeepLayout = {
 92 |       ...deepLayout,
 93 |     }
 94 |     if (!shallow) {
 95 |       Object.assign(newDeepLayout, props)
 96 |     } else {
 97 |       if (props.size) {
 98 |         newDeepLayout.size = props.size
 99 |       }
100 |       if (props.colon) {
101 |         newDeepLayout.colon = props.colon
102 |       }
103 |     }
104 |     return (
105 |       <FormLayoutDeepContext.Provider value={newDeepLayout}>
106 |         <FormLayoutShallowContext.Provider value={shallow ? props : undefined}>
107 |           {children}
108 |         </FormLayoutShallowContext.Provider>
109 |       </FormLayoutDeepContext.Provider>
110 |     )
111 |   }
112 |   return (
113 |     <div ref={ref} className={layoutClassName} style={style}>
114 |       {renderChildren()}
115 |     </div>
116 |   )
117 | }
118 | 
119 | FormLayout.useFormDeepLayout = useFormDeepLayout
120 | FormLayout.useFormShallowLayout = useFormShallowLayout
121 | FormLayout.useFormLayout = useFormLayout
122 | 
123 | export default FormLayout
124 | 
```
Page 12/52FirstPrevNextLast