#
tokens: 48630/50000 38/1152 files (page 8/35)
lines: off (toggle) GitHub
raw markdown copy
This is page 8 of 35. Use http://codebase.md/alibaba/formily?lines=false&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/packages/next/src/__builtins__/empty.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react'

export const Empty = () => {
  return (
    <div className="next-empty">
      <div className="next-empty-image">
        <svg
          className="ant-empty-img-default"
          width="184"
          height="120"
          viewBox="0 0 184 152"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g fill="none" fillRule="evenodd">
            <g transform="translate(24 31.67)">
              <ellipse
                className="ant-empty-img-default-ellipse"
                cx="67.797"
                cy="106.89"
                rx="67.797"
                ry="12.668"
              ></ellipse>
              <path
                className="ant-empty-img-default-path-1"
                d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
              ></path>
              <path
                className="ant-empty-img-default-path-2"
                d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
                transform="translate(13.56)"
              ></path>
              <path
                className="ant-empty-img-default-path-3"
                d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
              ></path>
              <path
                className="ant-empty-img-default-path-4"
                d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
              ></path>
            </g>
            <path
              className="ant-empty-img-default-path-5"
              d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
            ></path>
            <g
              className="ant-empty-img-default-g"
              transform="translate(149.65 15.383)"
            >
              <ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse>
              <path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path>
            </g>
          </g>
        </svg>
      </div>
    </div>
  )
}

```

--------------------------------------------------------------------------------
/packages/next/src/date-picker/index.tsx:
--------------------------------------------------------------------------------

```typescript
import moment from 'moment'
import { connect, mapProps, mapReadPretty } from '@formily/react'
import { DatePicker as NextDatePicker } from '@alifd/next'
import {
  DatePickerProps as NextDatePickerProps,
  MonthPickerProps,
  YearPickerProps,
  RangePickerProps,
} from '@alifd/next/lib/date-picker'
import { PreviewText } from '../preview-text'
import {
  formatMomentValue,
  momentable,
  mapSize,
  mapStatus,
} from '../__builtins__'

type DatePickerProps<PickerProps> = Exclude<
  PickerProps,
  'value' | 'onChange'
> & {
  value: string
  onChange: (value: string | string[]) => void
}

type ComposedDatePicker = React.FC<
  React.PropsWithChildren<NextDatePickerProps>
> & {
  RangePicker?: React.FC<React.PropsWithChildren<RangePickerProps>>
  MonthPicker?: React.FC<React.PropsWithChildren<MonthPickerProps>>
  YearPicker?: React.FC<React.PropsWithChildren<YearPickerProps>>
  WeekPicker?: React.FC<React.PropsWithChildren<NextDatePickerProps>>
}

const mapDateFormat = function (type?: 'month' | 'year' | 'week') {
  const getDefaultFormat = (props: DatePickerProps<NextDatePickerProps>) => {
    const _type = props['type'] || type
    if (_type === 'month') {
      return 'YYYY-MM'
    } else if (_type === 'year') {
      return 'YYYY'
    } else if (_type === 'week') {
      return 'YYYY-wo'
    }
    return 'YYYY-MM-DD'
  }

  return (props: any) => {
    const dateFormat = props['format'] || getDefaultFormat(props)

    let valueFormat = dateFormat
    if (props.showTime) {
      const timeFormat = props.showTime.format || 'HH:mm:ss'
      valueFormat = `${valueFormat} ${timeFormat}`
    }

    const onChange = props.onChange
    return {
      ...props,
      format: dateFormat,
      value: momentable(
        props.value,
        valueFormat === 'YYYY-wo' ? 'YYYY-w' : valueFormat
      ),
      onChange: (value: moment.Moment | moment.Moment[]) => {
        if (onChange) {
          onChange(formatMomentValue(value, valueFormat))
        }
      },
    }
  }
}

export const DatePicker: ComposedDatePicker = connect(
  NextDatePicker,
  mapProps(mapDateFormat(), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker.RangePicker = connect(
  NextDatePicker.RangePicker,
  mapProps(mapDateFormat(), mapSize, mapStatus),
  mapReadPretty(PreviewText.DateRangePicker)
)

DatePicker.YearPicker = connect(
  NextDatePicker.YearPicker,
  mapProps(mapDateFormat('year'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker.MonthPicker = connect(
  NextDatePicker.MonthPicker,
  mapProps(mapDateFormat('month'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker.WeekPicker = connect(
  NextDatePicker.WeekPicker,
  mapProps(mapDateFormat('week'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

export default DatePicker

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaArrayField
        name="array"
        :maxItems="3"
        x-component="ArrayCollapse"
        x-decorator="FormItem"
        :x-component-props="{
          title: '对象数组',
        }"
      >
        <SchemaObjectField
          x-component="ArrayCollapse.Item"
          x-decorator="FormItem"
          :x-component-props="{
            title: '对象数组',
          }"
        >
          <SchemaVoidField x-component="ArrayCollapse.Index" />
          <SchemaStringField
            name="aa"
            x-decorator="FormItem"
            title="AA"
            required
            description="AA输入123时隐藏BB"
            x-component="Input"
          />
          <SchemaStringField
            name="bb"
            x-decorator="FormItem"
            title="BB"
            required
            x-component="Input"
          />
          <SchemaStringField
            name="cc"
            x-decorator="FormItem"
            title="CC"
            required
            description="CC输入123时隐藏DD"
            x-component="Input"
          />
          <SchemaStringField
            name="dd"
            x-decorator="FormItem"
            title="DD"
            required
            x-component="Input"
          />
          <SchemaVoidField x-component="ArrayCollapse.Remove" />
          <SchemaVoidField x-component="ArrayCollapse.MoveUp" />
          <SchemaVoidField x-component="ArrayCollapse.MoveDown" />
        </SchemaObjectField>
        <SchemaVoidField
          x-component="ArrayCollapse.Addition"
          title="添加条目"
        />
      </SchemaArrayField>
    </SchemaField>
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>

<script>
import { createForm, onFieldChange, onFieldReact } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormButtonGroup,
  Submit,
  Input,
  ArrayCollapse,
} from '@formily/element'
import { Button } from 'element-ui'

const SchemaField = createSchemaField({
  components: {
    FormItem,
    Input,
    ArrayCollapse,
  },
})

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    Button,
    Submit,
    ...SchemaField,
  },

  data() {
    const form = createForm({
      effects: () => {
        //主动联动模式
        onFieldChange('array.*.aa', ['value'], (field, form) => {
          form.setFieldState(field.query('.bb'), (state) => {
            state.visible = field.value != '123'
          })
        })
        //被动联动模式
        onFieldReact('array.*.dd', (field) => {
          field.visible = field.query('.cc').get('value') != '123'
        })
      },
    })

    return {
      form,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField :schema="schema" />
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormButtonGroup,
  Submit,
  Input,
  ArrayCards,
} from '@formily/element'
import { Button } from 'element-ui'

const SchemaField = createSchemaField({
  components: {
    FormItem,
    Input,
    ArrayCards,
  },
})

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    Button,
    Submit,
    ...SchemaField,
  },

  data() {
    const form = createForm()
    const schema = {
      type: 'object',
      properties: {
        array: {
          type: 'array',
          'x-component': 'ArrayCards',
          maxItems: 3,
          title: '对象数组',
          items: {
            type: 'object',
            properties: {
              index: {
                type: 'void',
                'x-component': 'ArrayCards.Index',
              },
              aa: {
                type: 'string',
                'x-decorator': 'FormItem',
                title: 'AA',
                required: true,
                'x-component': 'Input',
                description: '输入123',
              },
              bb: {
                type: 'string',
                title: 'BB',
                required: true,
                'x-decorator': 'FormItem',
                'x-component': 'Input',
                'x-reactions': [
                  {
                    dependencies: ['.aa'],
                    when: "{{$deps[0] != '123'}}",
                    fulfill: {
                      schema: {
                        title: 'BB',
                        'x-disabled': true,
                      },
                    },
                    otherwise: {
                      schema: {
                        title: 'Changed',
                        'x-disabled': false,
                      },
                    },
                  },
                ],
              },
              remove: {
                type: 'void',
                'x-component': 'ArrayCards.Remove',
              },
              moveUp: {
                type: 'void',
                'x-component': 'ArrayCards.MoveUp',
              },
              moveDown: {
                type: 'void',
                'x-component': 'ArrayCards.MoveDown',
              },
            },
          },
          properties: {
            addition: {
              type: 'void',
              title: '添加条目',
              'x-component': 'ArrayCards.Addition',
            },
          },
        },
      },
    }

    return {
      form,
      schema,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```typescript
import {
  FormPath,
  each,
  lowerCase,
  globalThisPolyfill,
  merge as deepmerge,
  isFn,
  isStr,
} from '@formily/shared'
import {
  ValidatorFunctionResponse,
  ValidatorFunction,
  IRegistryFormats,
  IRegistryLocaleMessages,
  IRegistryLocales,
  IRegistryRules,
} from './types'

const getIn = FormPath.getIn

const self: any = globalThisPolyfill

const defaultLanguage = 'en'

const getBrowserlanguage = () => {
  /* istanbul ignore next */
  if (!self.navigator) {
    return defaultLanguage
  }
  return (
    self.navigator.browserlanguage || self.navigator.language || defaultLanguage
  )
}

const registry = {
  locales: {
    messages: {},
    language: getBrowserlanguage(),
  },
  formats: {},
  rules: {},
  template: null,
}

const getISOCode = (language: string) => {
  let isoCode = registry.locales.language
  if (registry.locales.messages[language]) {
    return language
  }
  const lang = lowerCase(language)
  each(
    registry.locales.messages,
    (messages: IRegistryLocaleMessages, key: string) => {
      const target = lowerCase(key)
      if (target.indexOf(lang) > -1 || lang.indexOf(target) > -1) {
        isoCode = key
        return false
      }
    }
  )
  return isoCode
}

export const getValidateLocaleIOSCode = getISOCode

export const setValidateLanguage = (lang: string) => {
  registry.locales.language = lang || defaultLanguage
}

export const getValidateLanguage = () => registry.locales.language

export const getLocaleByPath = (
  path: string,
  lang: string = registry.locales.language
) => getIn(registry.locales.messages, `${getISOCode(lang)}.${path}`)

export const getValidateLocale = (path: string) => {
  const message = getLocaleByPath(path)
  return (
    message ||
    getLocaleByPath('pattern') ||
    getLocaleByPath('pattern', defaultLanguage)
  )
}

export const getValidateMessageTemplateEngine = () => registry.template

export const getValidateFormats = (key?: string) =>
  key ? registry.formats[key] : registry.formats

export const getValidateRules = <T>(
  key?: T
): T extends string
  ? ValidatorFunction
  : { [key: string]: ValidatorFunction } =>
  key ? registry.rules[key as any] : registry.rules

export const registerValidateLocale = (locale: IRegistryLocales) => {
  registry.locales.messages = deepmerge(registry.locales.messages, locale)
}

export const registerValidateRules = (rules: IRegistryRules) => {
  each(rules, (rule, key) => {
    if (isFn(rule)) {
      registry.rules[key] = rule
    }
  })
}

export const registerValidateFormats = (formats: IRegistryFormats) => {
  each(formats, (pattern, key) => {
    if (isStr(pattern) || pattern instanceof RegExp) {
      registry.formats[key] = new RegExp(pattern)
    }
  })
}

export const registerValidateMessageTemplateEngine = (
  template: (message: ValidatorFunctionResponse, context: any) => any
) => {
  registry.template = template
}

```

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

```markdown
---
order: 6
---

# Form Validator Registry

## setValidateLanguage

#### Description

Set the built-in verification rule language

#### Signature

```ts
interface setValidateLanguage {
  (language: string): void
}
```

#### Example

```ts
import { setValidateLanguage } from '@formily/core'

setValidateLanguage('en-US')

setValidateLanguage('zh-CN')
```

## registerValidateFormats

#### Description

Register general regular rules, the current built-in regular library reference: [formats.ts](https://github.com/alibaba/formily/blob/master/packages/validator/src/formats.ts)

#### Signature

```ts
interface registerValidateFormats {
  (rules: { [key: string]: RegExp }): void
}
```

#### Example

```ts
import { registerValidateFormats } from '@formily/core'

registerValidateFormats({
  integer: /^[+-]?\d+$/,
})
```

## registerValidateLocale

#### Description

Global registration verification language package, the current built-in language package reference: [locale.ts](https://github.com/alibaba/formily/blob/master/packages/validator/src/locale.ts)

#### Signature

```ts
interface registerValidateLocale {
  (locales: {
    [key: string]: {
      key: string
    }
  }): void
}
```

#### Example

```ts
import { registerValidateLocale } from '@formily/core'

registerValidateLocale({
  ja: {
    required: 'このProjectは mustです',
  },
})
```

## registerValidateMessageTemplateEngine

#### Description

Globally register the verification message template engine. When we return the verification message in the validator, we can perform conversion based on the template engine syntax

#### Signature

```ts
interface registerValidateMessageTemplateEngine {
  (template: (message: ValidatorFunctionResponse, context: any) => any): void
}
```

#### Example

```ts
import { registerValidateMessageTemplateEngine } from '@formily/core'

registerValidateMessageTemplateEngine((message, context) => {
  return message.replace(/\<\%\s*([\w.]+)\s*\%\>/g, (_, $0) => {
    return FormPath.getIn(context, $0)
  })
})
```

## registerValidateRules

#### Description

Register general verification rules, the current built-in rule library reference: [rules.ts](https://github.com/alibaba/formily/blob/master/packages/validator/src/rules.ts)

#### Signature

```ts
interface registerValidateRules {
  (rules: {
    [key: string]: (
      value: any,
      rule: ValidatorRules,
      ctx: Context
    ) => ValidateResult | Promise<ValidateResult>
  }): void
}
```

#### Example

```ts
import { registerValidateRules } from '@formily/core'

registerValidateRules({
  custom(value) {
    return value > 100 ? 'error' : ''
  },
})
```

## getValidateLocaleIOSCode

#### Description

Get the built-in ISO Code

#### Signature

```ts
interface getValidateLocaleIOSCode {
  (language: string): string | undefined
}
```

#### Example

```ts
import { getValidateLocaleIOSCode } from '@formily/core'

getValidateLocaleIOSCode('en')

// ==> en_US
```

```

--------------------------------------------------------------------------------
/packages/next/src/date-picker2/index.tsx:
--------------------------------------------------------------------------------

```typescript
import moment from 'moment'
import { connect, mapProps, mapReadPretty } from '@formily/react'
import { DatePicker2 as NextDatePicker } from '@alifd/next'
import {
  DatePickerProps as NextDatePickerProps,
  RangePickerProps,
} from '@alifd/next/lib/date-picker2'
import { PreviewText } from '../preview-text'
import {
  formatMomentValue,
  momentable,
  mapSize,
  mapStatus,
} from '../__builtins__'

type DatePickerProps<PickerProps> = Exclude<
  PickerProps,
  'value' | 'onChange'
> & {
  value: string
  onChange: (value: string | string[]) => void
}

type ComposedDatePicker = React.FC<
  React.PropsWithChildren<NextDatePickerProps>
> & {
  RangePicker?: React.FC<React.PropsWithChildren<RangePickerProps>>
  MonthPicker?: React.FC<React.PropsWithChildren<NextDatePickerProps>>
  YearPicker?: React.FC<React.PropsWithChildren<NextDatePickerProps>>
  WeekPicker?: React.FC<React.PropsWithChildren<NextDatePickerProps>>
  QuarterPicker?: React.FC<React.PropsWithChildren<NextDatePickerProps>>
}

const mapDateFormat = function (type?: 'month' | 'year' | 'week' | 'quarter') {
  const getDefaultFormat = (props: DatePickerProps<NextDatePickerProps>) => {
    const _type = props['type'] || type
    if (_type === 'month') {
      return 'YYYY-MM'
    } else if (_type === 'quarter') {
      return 'YYYY-\\QQ'
    } else if (_type === 'year') {
      return 'YYYY'
    } else if (_type === 'week') {
      return 'YYYY-wo'
    }
    return props['showTime'] ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'
  }

  return (props: any) => {
    const format = props['format'] || getDefaultFormat(props)
    const onChange = props.onChange
    return {
      ...props,
      format,
      value: momentable(props.value, format === 'YYYY-wo' ? 'YYYY-w' : format),
      onChange: (value: moment.Moment | moment.Moment[]) => {
        if (onChange) {
          onChange(formatMomentValue(value, format))
        }
      },
    }
  }
}

export const DatePicker2: ComposedDatePicker = connect(
  NextDatePicker,
  mapProps(mapDateFormat(), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker2.RangePicker = connect(
  NextDatePicker.RangePicker,
  mapProps(mapDateFormat(), mapSize, mapStatus),
  mapReadPretty(PreviewText.DateRangePicker)
)

DatePicker2.YearPicker = connect(
  NextDatePicker.YearPicker,
  mapProps(mapDateFormat('year'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker2.MonthPicker = connect(
  NextDatePicker.MonthPicker,
  mapProps(mapDateFormat('month'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker2.WeekPicker = connect(
  NextDatePicker.WeekPicker,
  mapProps(mapDateFormat('week'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

DatePicker2.QuarterPicker = connect(
  NextDatePicker.QuarterPicker,
  mapProps(mapDateFormat('quarter'), mapSize, mapStatus),
  mapReadPretty(PreviewText.DatePicker)
)

export default DatePicker2

```

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

```typescript
import { FormPath, isFn, each, FormPathPattern } from '@formily/shared'
import { buildDataPath } from '../shared/internals'
import { GeneralField, IGeneralFieldState, IQueryProps } from '../types'
import { Form } from './Form'

const output = (
  field: GeneralField,
  taker: (field: GeneralField, address: FormPath) => any
) => {
  if (!field) return
  if (isFn(taker)) {
    return taker(field, field.address)
  }
  return field
}

const takeMatchPattern = (form: Form, pattern: FormPath) => {
  const identifier = pattern.toString()
  const indexIdentifier = form.indexes[identifier]
  const absoluteField = form.fields[identifier]
  const indexField = form.fields[indexIdentifier]
  if (absoluteField) {
    return identifier
  } else if (indexField) {
    return indexIdentifier
  }
}

export class Query {
  private pattern: FormPath
  private addresses: string[] = []
  private form: Form
  constructor(props: IQueryProps) {
    this.pattern = FormPath.parse(props.pattern, props.base)
    this.form = props.form
    if (!this.pattern.isMatchPattern) {
      const matched = takeMatchPattern(
        this.form,
        this.pattern.haveRelativePattern
          ? buildDataPath(props.form.fields, this.pattern)
          : this.pattern
      )
      if (matched) {
        this.addresses = [matched]
      }
    } else {
      each(this.form.fields, (field, address) => {
        if (!field) {
          delete this.form.fields[address]
          return
        }
        if (field.match(this.pattern)) {
          this.addresses.push(address)
        }
      })
    }
  }

  take(): GeneralField | undefined
  take<Result>(
    getter: (field: GeneralField, address: FormPath) => Result
  ): Result
  take(taker?: any): any {
    return output(this.form.fields[this.addresses[0]], taker)
  }

  map(): GeneralField[]
  map<Result>(
    iterator?: (field: GeneralField, address: FormPath) => Result
  ): Result[]
  map(iterator?: any): any {
    return this.addresses.map((address) =>
      output(this.form.fields[address], iterator)
    )
  }

  forEach<Result>(
    iterator: (field: GeneralField, address: FormPath) => Result
  ) {
    return this.addresses.forEach((address) =>
      output(this.form.fields[address], iterator)
    )
  }

  reduce<Result>(
    reducer: (value: Result, field: GeneralField, address: FormPath) => Result,
    initial?: Result
  ): Result {
    return this.addresses.reduce(
      (value, address) =>
        output(this.form.fields[address], (field, address) =>
          reducer(value, field, address)
        ),
      initial
    )
  }

  get<K extends keyof IGeneralFieldState>(key: K): IGeneralFieldState[K] {
    const results: any = this.take()
    if (results) {
      return results[key]
    }
  }

  getIn(pattern?: FormPathPattern) {
    return FormPath.getIn(this.take(), pattern)
  }

  value() {
    return this.get('value')
  }

  initialValue() {
    return this.get('initialValue')
  }
}

```

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

```markdown
# Checkbox

> 复选框

## Markup Schema 案例

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Boolean
        name="single"
        title="是否确认"
        x-decorator="FormItem"
        x-component="Checkbox"
      />
      <SchemaField.String
        name="multiple"
        title="复选"
        enum={[
          {
            label: '选项1',
            value: 1,
          },
          {
            label: '选项2',
            value: 2,
          },
        ]}
        x-decorator="FormItem"
        x-component="Checkbox.Group"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 案例

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    single: {
      type: 'boolean',
      title: '是否确认',
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox',
    },
    multiple: {
      type: 'array',
      title: '复选',
      enum: [
        {
          label: '选项1',
          value: 1,
        },
        {
          label: '选项2',
          value: 2,
        },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox.Group',
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 案例

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="single"
      title="是否确认"
      decorator={[FormItem]}
      component={[Checkbox]}
    />
    <Field
      name="multiple"
      title="复选"
      dataSource={[
        {
          label: '选项1',
          value: 1,
        },
        {
          label: '选项2',
          value: 2,
        },
      ]}
      decorator={[FormItem]}
      component={[Checkbox.Group]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://ant.design/components/checkbox-cn/

```

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

```markdown
# Checkbox

> 复选框

## Markup Schema 案例

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Boolean
        name="single"
        title="是否确认"
        x-decorator="FormItem"
        x-component="Checkbox"
      />
      <SchemaField.String
        name="multiple"
        title="复选"
        enum={[
          {
            label: '选项1',
            value: 1,
          },
          {
            label: '选项2',
            value: 2,
          },
        ]}
        x-decorator="FormItem"
        x-component="Checkbox.Group"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 案例

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    single: {
      type: 'boolean',
      title: '是否确认',
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox',
    },
    multiple: {
      type: 'array',
      title: '复选',
      enum: [
        {
          label: '选项1',
          value: 1,
        },
        {
          label: '选项2',
          value: 2,
        },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox.Group',
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 案例

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="single"
      title="是否确认"
      decorator={[FormItem]}
      component={[Checkbox]}
    />
    <Field
      name="multiple"
      title="复选"
      dataSource={[
        {
          label: '选项1',
          value: 1,
        },
        {
          label: '选项2',
          value: 2,
        },
      ]}
      decorator={[FormItem]}
      component={[Checkbox.Group]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://fusion.design/pc/component/basic/checkbox

```

--------------------------------------------------------------------------------
/packages/element/docs/.vuepress/components/createCodeSandBox.js:
--------------------------------------------------------------------------------

```javascript
import { getParameters } from 'codesandbox/lib/api/define'

const CodeSandBoxHTML = '<div id="app"></div>'
const CodeSandBoxJS = `
import Vue from 'vue'
import App from './App.vue'
import Element  from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false
Vue.use(Element, { size: 'small' });

new Vue({
  render: h => h(App),
}).$mount('#app')`

const createForm = ({ method, action, data }) => {
  const form = document.createElement('form') // 构造 form
  form.style.display = 'none' // 设置为不显示
  form.target = '_blank' // 指向 iframe

  // 构造 formdata
  Object.keys(data).forEach((key) => {
    const input = document.createElement('input') // 创建 input

    input.name = key // 设置 name
    input.value = data[key] // 设置 value

    form.appendChild(input)
  })

  form.method = method // 设置方法
  form.action = action // 设置地址

  document.body.appendChild(form)

  // 对该 form 执行提交
  form.submit()

  document.body.removeChild(form)
}

export function createCodeSandBox(codeStr) {
  const parameters = getParameters({
    files: {
      'sandbox.config.json': {
        content: {
          template: 'node',
          infiniteLoopProtection: true,
          hardReloadOnChange: false,
          view: 'browser',
          container: {
            port: 8080,
            node: '14',
          },
        },
      },
      'package.json': {
        content: {
          scripts: {
            serve: 'vue-cli-service serve',
            build: 'vue-cli-service build',
            lint: 'vue-cli-service lint',
          },
          dependencies: {
            '@formily/core': 'latest',
            '@formily/vue': 'latest',
            '@formily/element': 'latest',
            axios: '^0.21.1',
            'core-js': '^3.6.5',
            'element-ui': 'latest',
            'vue-demi': 'latest',
            vue: '^2.6.11',
          },
          devDependencies: {
            '@vue/cli-plugin-babel': '~4.5.0',
            '@vue/cli-service': '~4.5.0',
            '@vue/composition-api': 'latest',
            'vue-template-compiler': '^2.6.11',
            sass: '^1.34.1',
            'sass-loader': '^8.0.2',
          },
          babel: {
            presets: [
              [
                '@vue/babel-preset-jsx',
                {
                  vModel: false,
                  compositionAPI: true,
                },
              ],
            ],
          },
          vue: {
            devServer: {
              host: '0.0.0.0',
              disableHostCheck: true, // 必须
            },
          },
        },
      },
      'src/App.vue': {
        content: codeStr,
      },
      'src/main.js': {
        content: CodeSandBoxJS,
      },
      'public/index.html': {
        content: CodeSandBoxHTML,
      },
    },
  })

  createForm({
    method: 'post',
    action: 'https://codesandbox.io/api/v1/sandboxes/define',
    data: {
      parameters,
      query: 'file=/src/App.vue',
    },
  })
}

```

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

```typescript
import React, { useLayoutEffect, useRef, useMemo, useContext } from 'react'
import { markRaw } from '@formily/reactive'
import { observer } from '@formily/react'
import { Grid, IGridOptions } from '@formily/grid'
import { usePrefixCls, pickDataProps } from '../__builtins__'
import { useFormLayout } from '../form-layout'
import cls from 'classnames'

const FormGridContext = React.createContext<Grid<HTMLElement>>(null)

export interface IFormGridProps extends IGridOptions {
  grid?: Grid<HTMLElement>
  prefix?: string
  className?: string
  style?: React.CSSProperties
}

export interface IGridColumnProps {
  gridSpan?: number
  style?: React.CSSProperties
  className?: string
}

type ComposedFormGrid = React.FC<React.PropsWithChildren<IFormGridProps>> & {
  GridColumn: React.FC<React.PropsWithChildren<IGridColumnProps>>
  useFormGrid: () => Grid<HTMLElement>
  createFormGrid: (props: IFormGridProps) => Grid<HTMLElement>
  /**
   * @deprecated
   */
  useGridSpan: (gridSpan: number) => number
  /**
   * @deprecated
   */
  useGridColumn: (gridSpan: number) => number
}

export const createFormGrid = (props: IFormGridProps) => {
  return markRaw(new Grid(props))
}

export const useFormGrid = () => useContext(FormGridContext)

/**
 * @deprecated
 */
export const useGridSpan = (gridSpan = 1) => {
  return gridSpan
}
/**
 * @deprecated
 */
export const useGridColumn = (gridSpan = 1) => {
  return gridSpan
}

export const FormGrid: ComposedFormGrid = observer(
  ({
    children,
    className,
    style,
    ...props
  }: React.PropsWithChildren<IFormGridProps>) => {
    const layout = useFormLayout()
    const options = {
      columnGap: layout?.gridColumnGap ?? 8,
      rowGap: layout?.gridRowGap ?? 4,
      ...props,
    }
    const grid = useMemo(
      () => markRaw(options?.grid ? options.grid : new Grid(options)),
      [Grid.id(options)]
    )
    const ref = useRef<HTMLDivElement>()
    const prefixCls = usePrefixCls('formily-grid', props)
    const dataProps = pickDataProps(props)
    useLayoutEffect(() => {
      return grid.connect(ref.current)
    }, [grid])
    return (
      <FormGridContext.Provider value={grid}>
        <div
          {...dataProps}
          className={cls(`${prefixCls}-layout`, className)}
          style={{
            ...style,
            gridTemplateColumns: grid.templateColumns,
            gap: grid.gap,
          }}
          ref={ref}
        >
          {children}
        </div>
      </FormGridContext.Provider>
    )
  },
  {
    forwardRef: true,
  }
) as any

export const GridColumn: React.FC<React.PropsWithChildren<IGridColumnProps>> =
  observer(({ gridSpan = 1, children, ...props }) => {
    return (
      <div {...props} data-grid-span={gridSpan}>
        {children}
      </div>
    )
  })

FormGrid.createFormGrid = createFormGrid
FormGrid.useFormGrid = useFormGrid
FormGrid.useGridSpan = useGridSpan
FormGrid.useGridColumn = useGridColumn
FormGrid.GridColumn = GridColumn

export default FormGrid

```

--------------------------------------------------------------------------------
/devtools/chrome-extension/src/extension/backend.ts:
--------------------------------------------------------------------------------

```typescript
//inject content script

const serializeObject = (obj: any) => {
  const seens = new WeakMap()
  const serialize = (obj: any) => {
    if (Array.isArray(obj)) {
      return obj.map(serialize)
    } else if (typeof obj === 'function') {
      return `f ${obj.displayName || obj.name}(){ }`
    } else if (typeof obj === 'object') {
      if (seens.get(obj)) return '#CircularReference'
      if (!obj) return obj
      if ('$$typeof' in obj && '_owner' in obj) {
        seens.set(obj, true)
        return '#ReactNode'
      } else if (obj.toJS) {
        seens.set(obj, true)
        return obj.toJS()
      } else if (obj.toJSON) {
        seens.set(obj, true)
        return obj.toJSON()
      } else {
        seens.set(obj, true)
        const result = {}
        for (let key in obj) {
          result[key] = serialize(obj[key])
        }
        seens.set(obj, false)
        return result
      }
    }
    return obj
  }
  return serialize(obj)
}

const send = ({
  type,
  id,
  form,
}: {
  type: string
  id?: string | number
  form?: any
}) => {
  const graph = serializeObject(form?.getFormGraph())
  window.postMessage(
    {
      source: '@formily-devtools-inject-script',
      type,
      id,
      graph:
        form &&
        JSON.stringify(graph, (key, value) => {
          if (typeof value === 'symbol') {
            return value.toString()
          }
          return value
        }),
    },
    '*'
  )
}

send({
  type: 'init',
})

interface IIdleDeadline {
  didTimeout: boolean
  timeRemaining: () => DOMHighResTimeStamp
}

const HOOK = {
  hasFormilyInstance: false,
  hasOpenDevtools: false,
  store: {},
  openDevtools() {
    this.hasOpenDevtools = true
  },
  closeDevtools() {
    this.hasOpenDevtools = false
  },
  setVm(fieldId: string, formId: string) {
    if (fieldId) {
      globalThis.$vm = this.store[formId].fields[fieldId]
    } else {
      globalThis.$vm = this.store[formId]
    }
  },
  inject(id: number, form: any) {
    this.hasFormilyInstance = true
    this.store[id] = form
    send({
      type: 'install',
      id,
      form,
    })
    let timer = null
    const task = () => {
      globalThis.requestIdleCallback((deadline: IIdleDeadline) => {
        if (this.store[id]) {
          if (deadline.timeRemaining() < 16) {
            task()
          } else {
            send({
              type: 'update',
              id,
              form,
            })
          }
        }
      })
    }
    form.subscribe(() => {
      if (!this.hasOpenDevtools) return
      clearTimeout(timer)
      timer = setTimeout(task, 300)
    })
  },
  update() {
    const keys = Object.keys(this.store || {})
    keys.forEach((id) => {
      send({
        type: 'update',
        id,
        form: this.store[id],
      })
    })
  },
  unmount(id: number) {
    delete this.store[id]
    send({
      type: 'uninstall',
      id,
    })
  },
}

globalThis.__FORMILY_DEV_TOOLS_HOOK__ = HOOK
globalThis.__UFORM_DEV_TOOLS_HOOK__ = HOOK

```

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

```typescript
import { connect, h, mapProps, mapReadPretty } from '@formily/vue'
import type {
  Radio as ElRadioProps,
  RadioGroup as ElRadioGroupProps,
} from 'element-ui'
import {
  Radio as ElRadio,
  RadioButton,
  RadioGroup as ElRadioGroup,
} from 'element-ui'
import { defineComponent, PropType } from 'vue-demi'
import { PreviewText } from '../preview-text'
import {
  composeExport,
  resolveComponent,
  SlotTypes,
  transformComponent,
} from '../__builtins__/shared'

export type RadioGroupProps = ElRadioGroupProps & {
  value: any
  options?: (
    | (Omit<ElRadioProps, 'value'> & {
        value: ElRadioProps['label']
        label: SlotTypes
      })
    | string
  )[]
  optionType: 'default' | 'button'
}

export type RadioProps = ElRadioProps

const TransformElRadioGroup = transformComponent(ElRadioGroup, {
  change: 'input',
  uselessChange:'change'
})

const RadioGroupOption = defineComponent<RadioGroupProps>({
  name: 'FRadioGroup',
  props: {
    options: {
      type: Array as PropType<RadioGroupProps['options']>,
      default: () => [],
    },
    optionType: {
      type: String as PropType<RadioGroupProps['optionType']>,
      default: 'default',
    },
  },
  setup(customProps, { attrs, slots, listeners }) {
    return () => {
      const options = customProps.options || []
      const OptionType =
        customProps.optionType === 'button' ? RadioButton : ElRadio
      const children =
        options.length !== 0
          ? {
              default: () =>
                options.map((option) => {
                  if (typeof option === 'string') {
                    return h(
                      OptionType,
                      { props: { label: option } },
                      {
                        default: () => [
                          resolveComponent(slots?.option ?? option, { option }),
                        ],
                      }
                    )
                  } else {
                    return h(
                      OptionType,
                      {
                        props: {
                          ...option,
                          value: undefined,
                          label: option.value,
                        },
                      },
                      {
                        default: () => [
                          resolveComponent(slots?.option ?? option.label, {
                            option,
                          }),
                        ],
                      }
                    )
                  }
                }),
            }
          : slots
      return h(
        TransformElRadioGroup,
        {
          attrs: {
            ...attrs,
          },
          on: listeners,
        },
        children
      )
    }
  },
})

const RadioGroup = connect(
  RadioGroupOption,
  mapProps({ dataSource: 'options' }),
  mapReadPretty(PreviewText.Select)
)
export const Radio = composeExport(ElRadio, {
  Group: RadioGroup,
})

export default Radio

```

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

```typescript
import React, { useLayoutEffect, useRef, useMemo, useContext } from 'react'
import { markRaw } from '@formily/reactive'
import { observer } from '@formily/react'
import { Grid, IGridOptions } from '@formily/grid'
import { usePrefixCls, pickDataProps } from '../__builtins__'
import { useFormLayout } from '../form-layout'
import cls from 'classnames'

const FormGridContext = React.createContext<Grid<HTMLElement>>(null)

export interface IFormGridProps extends IGridOptions {
  grid?: Grid<HTMLElement>
  prefixCls?: string
  className?: string
  style?: React.CSSProperties
}

export interface IGridColumnProps {
  gridSpan?: number
  style?: React.CSSProperties
  className?: string
}

type ComposedFormGrid = React.FC<React.PropsWithChildren<IFormGridProps>> & {
  GridColumn: React.FC<React.PropsWithChildren<IGridColumnProps>>
  useFormGrid: () => Grid<HTMLElement>
  createFormGrid: (props: IFormGridProps) => Grid<HTMLElement>
  /**
   * @deprecated
   */
  useGridSpan: (gridSpan: number) => number
  /**
   * @deprecated
   */
  useGridColumn: (gridSpan: number) => number
}

export const createFormGrid = (props: IFormGridProps) => {
  return markRaw(new Grid(props))
}

export const useFormGrid = () => useContext(FormGridContext)

/**
 * @deprecated
 */
export const useGridSpan = (gridSpan = 1) => {
  return gridSpan
}

/**
 * @deprecated
 */
export const useGridColumn = (gridSpan = 1) => {
  return gridSpan
}

export const FormGrid: ComposedFormGrid = observer(
  ({
    children,
    className,
    style,
    ...props
  }: React.PropsWithChildren<IFormGridProps>) => {
    const layout = useFormLayout()
    const options = {
      columnGap: layout?.gridColumnGap ?? 8,
      rowGap: layout?.gridRowGap ?? 4,
      ...props,
    }
    const grid = useMemo(
      () => markRaw(options?.grid ? options.grid : new Grid(options)),
      [Grid.id(options)]
    )
    const ref = useRef<HTMLDivElement>()
    const prefixCls = usePrefixCls('formily-grid', props)
    const dataProps = pickDataProps(props)
    useLayoutEffect(() => {
      return grid.connect(ref.current)
    }, [grid])
    return (
      <FormGridContext.Provider value={grid}>
        <div
          {...dataProps}
          className={cls(`${prefixCls}-layout`, className)}
          style={{
            ...style,
            gridTemplateColumns: grid.templateColumns,
            gap: grid.gap,
          }}
          ref={ref}
        >
          {children}
        </div>
      </FormGridContext.Provider>
    )
  },
  {
    forwardRef: true,
  }
) as any

export const GridColumn: React.FC<React.PropsWithChildren<IGridColumnProps>> =
  observer(({ gridSpan = 1, children, ...props }) => {
    return (
      <div {...props} style={props.style} data-grid-span={gridSpan}>
        {children}
      </div>
    )
  })

FormGrid.createFormGrid = createFormGrid
FormGrid.useGridSpan = useGridSpan
FormGrid.useGridColumn = useGridColumn
FormGrid.useFormGrid = useFormGrid
FormGrid.GridColumn = GridColumn

export default FormGrid

```

--------------------------------------------------------------------------------
/packages/element/docs/demos/guide/form-step/json-schema.vue:
--------------------------------------------------------------------------------

```vue
<template>
  <FormProvider :form="form">
    <SchemaField :schema="schema" :scope="{ formStep }" />
    <FormConsumer>
      <template #default>
        <FormButtonGroup>
          <Button
            :disabled="!formStep.allowBack"
            @click="
              () => {
                formStep.back()
              }
            "
          >
            上一步
          </Button>
          <Button
            :disabled="!formStep.allowNext"
            @click="
              () => {
                formStep.next()
              }
            "
          >
            下一步
          </Button>
          <Submit :disabled="formStep.allowNext" @submit="log">提交</Submit>
        </FormButtonGroup>
      </template>
    </FormConsumer>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField, FormConsumer } from '@formily/vue'
import {
  FormItem,
  FormStep,
  FormButtonGroup,
  Submit,
  Input,
} from '@formily/element'
import { Button } from 'element-ui'

const { SchemaField } = createSchemaField({
  components: {
    FormItem,
    FormStep,
    Input,
  },
})

const schema = {
  type: 'object',
  properties: {
    collapse: {
      type: 'void',
      'x-component': 'FormStep',
      'x-component-props': {
        formStep: '{{formStep}}',
      },
      properties: {
        step1: {
          type: 'void',
          'x-component': 'FormStep.StepPane',
          'x-component-props': {
            title: '第一步',
          },
          properties: {
            aaa: {
              type: 'string',
              title: 'AAA',
              required: true,
              'x-decorator': 'FormItem',
              'x-component': 'Input',
            },
          },
        },
        step2: {
          type: 'void',
          'x-component': 'FormStep.StepPane',
          'x-component-props': {
            title: '第二步',
          },
          properties: {
            bbb: {
              type: 'string',
              title: 'AAA',
              required: true,
              'x-decorator': 'FormItem',
              'x-component': 'Input',
            },
          },
        },
        step3: {
          type: 'void',
          'x-component': 'FormStep.StepPane',
          'x-component-props': {
            title: '第三步',
          },
          properties: {
            ccc: {
              type: 'string',
              title: 'AAA',
              required: true,
              'x-decorator': 'FormItem',
              'x-component': 'Input',
            },
          },
        },
      },
    },
  },
}

export default {
  components: {
    FormProvider,
    FormConsumer,
    FormButtonGroup,
    Button,
    Submit,
    SchemaField,
  },

  data() {
    const form = createForm()
    const formStep = FormStep.createFormStep()
    return {
      schema,
      form,
      formStep,
    }
  },
  methods: {
    log() {
      this.formStep.submit(console.log)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```vue
<template>
  <FormProvider :form="form">
    <FormLayout :labelCol="6" :wrapperCol="16">
      <SchemaField :schema="schema" />
      <FormButtonGroup alignFormItem>
        <Submit onSubmit="log">提交</Submit>
      </FormButtonGroup>
    </FormLayout>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { createSchemaField, FormProvider } from '@formily/vue'
import {
  FormButtonGroup,
  FormLayout,
  FormItem,
  Input,
  Submit,
  Space,
} from '@formily/element'

const { SchemaField } = createSchemaField({
  components: {
    FormLayout,
    FormItem,
    Input,
    Space,
  },
})

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    FormLayout,
    SchemaField,
    Submit,
  },
  data() {
    const schema = {
      type: 'object',
      properties: {
        name: {
          type: 'void',
          title: '姓名',
          'x-decorator': 'FormItem',
          'x-decorator-props': {
            asterisk: true,
            feedbackLayout: 'none',
          },
          'x-component': 'Space',
          properties: {
            firstName: {
              type: 'string',
              'x-decorator': 'FormItem',
              'x-component': 'Input',
              required: true,
            },
            lastName: {
              type: 'string',
              'x-decorator': 'FormItem',
              'x-component': 'Input',
              required: true,
            },
          },
        },
        texts: {
          type: 'void',
          title: '文本串联',
          'x-decorator': 'FormItem',
          'x-decorator-props': {
            asterisk: true,
            feedbackLayout: 'none',
          },
          'x-component': 'Space',
          properties: {
            aa: {
              type: 'string',
              'x-decorator': 'FormItem',
              'x-decorator-props': {
                addonAfter: '单位',
              },
              'x-component': 'Input',
              required: true,
            },
            bb: {
              type: 'string',
              'x-decorator': 'FormItem',
              'x-decorator-props': {
                addonAfter: '单位',
              },
              'x-component': 'Input',
              required: true,
            },
            cc: {
              type: 'string',
              'x-decorator': 'FormItem',
              'x-decorator-props': {
                addonAfter: '单位',
              },
              'x-component': 'Input',
              required: true,
            },
          },
        },

        textarea: {
          type: 'string',
          title: '文本框',
          'x-decorator': 'FormItem',
          'x-component': 'Input.TextArea',
          'x-component-props': {
            style: {
              width: 400,
            },
          },
          required: true,
        },
      },
    }

    const form = createForm()

    return {
      form,
      schema,
    }
  },
  methods: {
    logs(value) {
      console.log(value)
    },
  },
}
</script>

```

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

```vue
<template>
  <FormProvider :form="form">
    <SchemaField :schema="schema" />
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormButtonGroup,
  Submit,
  Input,
  ArrayCollapse,
} from '@formily/element'
import { Button } from 'element-ui'

const SchemaField = createSchemaField({
  components: {
    FormItem,
    Input,
    ArrayCollapse,
  },
})

export default {
  components: {
    FormProvider,
    FormButtonGroup,
    Button,
    Submit,
    ...SchemaField,
  },

  data() {
    const form = createForm()
    const schema = {
      type: 'object',
      properties: {
        array: {
          type: 'array',
          'x-component': 'ArrayCollapse',
          maxItems: 3,
          title: '对象数组',
          items: {
            type: 'object',
            'x-component': 'ArrayCollapse.Item',
            'x-component-props': {
              header: '对象数组',
            },
            properties: {
              index: {
                type: 'void',
                'x-component': 'ArrayCollapse.Index',
              },
              aa: {
                type: 'string',
                'x-decorator': 'FormItem',
                title: 'AA',
                required: true,
                'x-component': 'Input',
                description: '输入123',
              },
              bb: {
                type: 'string',
                title: 'BB',
                required: true,
                'x-decorator': 'FormItem',
                'x-component': 'Input',
                'x-reactions': [
                  {
                    dependencies: ['.aa'],
                    when: "{{$deps[0] != '123'}}",
                    fulfill: {
                      schema: {
                        title: 'BB',
                        'x-disabled': true,
                      },
                    },
                    otherwise: {
                      schema: {
                        title: 'Changed',
                        'x-disabled': false,
                      },
                    },
                  },
                ],
              },
              remove: {
                type: 'void',
                'x-component': 'ArrayCollapse.Remove',
              },
              moveUp: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveUp',
              },
              moveDown: {
                type: 'void',
                'x-component': 'ArrayCollapse.MoveDown',
              },
            },
          },
          properties: {
            addition: {
              type: 'void',
              title: '添加条目',
              'x-component': 'ArrayCollapse.Addition',
            },
          },
        },
      },
    }

    return {
      form,
      schema,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```typescript
import { createForm } from '..'
import {
  isArrayField,
  isArrayFieldState,
  isDataField,
  isDataFieldState,
  isField,
  isFieldState,
  isForm,
  isFormState,
  isGeneralField,
  isGeneralFieldState,
  isObjectField,
  isObjectFieldState,
  isQuery,
  isVoidField,
  isVoidFieldState,
  createEffectHook,
} from '../shared/externals'
import { attach } from './shared'

test('type checkers', () => {
  const form = attach(createForm())
  const normal = attach(
    form.createField({
      name: 'normal',
    })
  )
  const array = attach(
    form.createArrayField({
      name: 'array',
    })
  )
  const object = attach(
    form.createObjectField({
      name: 'object',
    })
  )
  const void_ = attach(
    form.createVoidField({
      name: 'void',
    })
  )
  expect(isField(normal)).toBeTruthy()
  expect(isFieldState(normal.getState())).toBeTruthy()
  expect(isFieldState(null)).toBeFalsy()
  expect(isFieldState({})).toBeFalsy()
  expect(isFieldState(normal)).toBeFalsy()

  expect(isArrayField(array)).toBeTruthy()
  expect(isArrayFieldState(array.getState())).toBeTruthy()
  expect(isArrayFieldState(null)).toBeFalsy()
  expect(isArrayFieldState({})).toBeFalsy()
  expect(isArrayFieldState(array)).toBeFalsy()

  expect(isObjectField(object)).toBeTruthy()
  expect(isObjectFieldState(object.getState())).toBeTruthy()
  expect(isObjectFieldState(null)).toBeFalsy()
  expect(isObjectFieldState({})).toBeFalsy()
  expect(isObjectFieldState(object)).toBeFalsy()

  expect(isVoidField(void_)).toBeTruthy()
  expect(isVoidFieldState(void_.getState())).toBeTruthy()
  expect(isVoidFieldState(null)).toBeFalsy()
  expect(isVoidFieldState({})).toBeFalsy()
  expect(isVoidFieldState(void_)).toBeFalsy()

  expect(isDataField(void_)).toBeFalsy()
  expect(isDataFieldState(void_.getState())).toBeFalsy()

  expect(isDataField(normal)).toBeTruthy()
  expect(isDataFieldState(normal.getState())).toBeTruthy()
  expect(isGeneralField(normal)).toBeTruthy()
  expect(isGeneralField(array)).toBeTruthy()
  expect(isGeneralField(object)).toBeTruthy()
  expect(isGeneralField(void_)).toBeTruthy()

  expect(isGeneralFieldState(normal.getState())).toBeTruthy()
  expect(isGeneralFieldState(array.getState())).toBeTruthy()
  expect(isGeneralFieldState(object.getState())).toBeTruthy()
  expect(isGeneralFieldState(void_.getState())).toBeTruthy()
  expect(isGeneralFieldState(null)).toBeFalsy()
  expect(isGeneralFieldState({})).toBeFalsy()
  expect(isGeneralFieldState(void_)).toBeFalsy()

  expect(isForm(form)).toBeTruthy()
  expect(isFormState(form.getState())).toBeTruthy()
  expect(isFormState({})).toBeFalsy()
  expect(isFormState(form)).toBeFalsy()
  expect(isFormState(null)).toBeFalsy()
  expect(isQuery(form.query('*'))).toBeTruthy()
})

test('createEffectHook', () => {
  try {
    createEffectHook('xxx')()
  } catch {}
  const form = attach(
    createForm({
      effects() {
        createEffectHook('xxx')()
        createEffectHook('yyy', () => () => {})()
      },
    })
  )
  form.notify('xxx')
  form.notify('yyy')
})

```

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

```markdown
# Checkbox

> Checkbox

## Markup Schema example

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Boolean
        name="single"
        title="Are you sure"
        x-decorator="FormItem"
        x-component="Checkbox"
      />
      <SchemaField.String
        name="multiple"
        title="Check"
        enum={[
          {
            label: 'Option 1',
            value: 1,
          },
          {
            label: 'Option 2',
            value: 2,
          },
        ]}
        x-decorator="FormItem"
        x-component="Checkbox.Group"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema case

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    single: {
      type: 'boolean',
      title: 'Are you sure?',
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox',
    },
    multiple: {
      type: 'array',
      title: 'Check',
      enum: [
        {
          label: 'Option 1',
          value: 1,
        },
        {
          label: 'Option 2',
          value: 2,
        },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox.Group',
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Pure JSX case

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="single"
      title="Are you sure"
      decorator={[FormItem]}
      component={[Checkbox]}
    />
    <Field
      name="multiple"
      title="Check"
      dataSource={[
        {
          label: 'Option 1',
          value: 1,
        },
        {
          label: 'Option 2',
          value: 2,
        },
      ]}
      decorator={[FormItem]}
      component={[Checkbox.Group]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

Reference https://ant.design/components/checkbox-cn/

```

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

```markdown
# Input

> 文本输入框

## Markup Schema 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        x-decorator="FormItem"
        x-component="Input"
        required
        x-component-props={{
          style: {
            width: 240,
          },
        }}
      />
      <SchemaField.String
        name="textarea"
        title="文本框"
        x-decorator="FormItem"
        required
        x-component="Input.TextArea"
        x-component-props={{
          style: {
            width: 400,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    input: {
      type: 'string',
      title: '输入框',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
    textarea: {
      type: 'string',
      title: '输入框',
      'x-decorator': 'FormItem',
      'x-component': 'Input.TextArea',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="input"
      title="输入框"
      required
      decorator={[FormItem]}
      component={[
        Input,
        {
          style: {
            width: 240,
          },
        },
      ]}
    />
    <Field
      name="textarea"
      title="文本框"
      required
      decorator={[FormItem]}
      component={[
        Input.TextArea,
        {
          style: {
            width: 400,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://ant.design/components/input-cn/

```

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

```markdown
# Checkbox

> Checkbox

## Markup Schema example

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.Boolean
        name="single"
        title="Are you sure"
        x-decorator="FormItem"
        x-component="Checkbox"
      />
      <SchemaField.String
        name="multiple"
        title="Check"
        enum={[
          {
            label: 'Option 1',
            value: 1,
          },
          {
            label: 'Option 2',
            value: 2,
          },
        ]}
        x-decorator="FormItem"
        x-component="Checkbox.Group"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema case

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Checkbox,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    single: {
      type: 'boolean',
      title: 'Are you sure?',
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox',
    },
    multiple: {
      type: 'array',
      title: 'Check',
      enum: [
        {
          label: 'Option 1',
          value: 1,
        },
        {
          label: 'Option 2',
          value: 2,
        },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Checkbox.Group',
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Pure JSX case

```tsx
import React from 'react'
import { Checkbox, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="single"
      title="Are you sure"
      decorator={[FormItem]}
      component={[Checkbox]}
    />
    <Field
      name="multiple"
      title="Check"
      dataSource={[
        {
          label: 'Option 1',
          value: 1,
        },
        {
          label: 'Option 2',
          value: 2,
        },
      ]}
      decorator={[FormItem]}
      component={[Checkbox.Group]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

Reference https://fusion.design/pc/component/basic/checkbox

```

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

```markdown
---
order: 9
---

# RecordScope

## Description

Standard scoped injection component for injecting the following built-in variables:

- `$record` current record data
- `$record.$lookup` The parent record of the current record, you can always look up
- `$record.$index` the index of the current record
- `$index` The current record index, equivalent to `$record.$index`, considering that if the record data is not an object, it needs to be read independently
- `$lookup` The parent record of the current record, equivalent to `$record.$lookup`, considering that if the record data is not an object, it needs to be read independently

## Signature

```ts
interface IRecordScopeProps {
  getRecord(): any
  getIndex?(): number
}

type RecordScope = React.FC<React.PropsWithChildren<IRecordScopeProps>>
```

## Usage

Any auto-increment list extension component should use RecordScope internally to pass record scope variables. Components that have implemented this convention include:
All components of the ArrayX family in @formily/antd and @formily/next

## Custom component extension use case

```tsx
import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField, RecordScope } from '@formily/react'
import { Input } from 'antd'

const form = createForm()

const MyCustomComponent = (props) => {
  return (
    <RecordScope getRecord={() => props.record} getIndex={() => props.index}>
      {props.children}
    </RecordScope>
  )
}

const SchemaField = createSchemaField({
  components: {
    Input,
    MyCustomComponent,
  },
})

export default () => (
  <FormProvider form={form}>
    <SchemaField
      schema={{
        type: 'object',
        properties: {
          lookup: {
            type: 'void',
            'x-component': 'MyCustomComponent',
            'x-component-props': {
              record: {
                name: 'Lookup Name',
                code: 'Lookup Code',
              },
              index: 1,
            },
            properties: {
              record: {
                type: 'void',
                'x-component': 'MyCustomComponent',
                'x-component-props': {
                  record: {
                    name: 'Name',
                    code: 'Code',
                  },
                  index: 0,
                },
                properties: {
                  input: {
                    type: 'string',
                    'x-component': 'Input',
                    'x-value':
                      '{{`' +
                      '${$record.name} ' +
                      '${$record.code} ' +
                      '${$record.$index} ' +
                      '${$record.$lookup.name} ' +
                      '${$record.$lookup.code} ' +
                      '${$index} ' +
                      '${$lookup.name} ' +
                      '${$lookup.code} ' +
                      '`}}',
                  },
                },
              },
            },
          },
        },
      }}
    ></SchemaField>
  </FormProvider>
)
```

```

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

```markdown
# Input

> 文本输入框

## Markup Schema 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        x-decorator="FormItem"
        x-component="Input"
        required
        x-component-props={{
          style: {
            width: 240,
          },
        }}
      />
      <SchemaField.String
        name="textarea"
        title="文本框"
        x-decorator="FormItem"
        required
        x-component="Input.TextArea"
        x-component-props={{
          style: {
            width: 400,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    input: {
      type: 'string',
      title: '输入框',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
    textarea: {
      type: 'string',
      title: '输入框',
      'x-decorator': 'FormItem',
      'x-component': 'Input.TextArea',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 纯 JSX 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="input"
      title="输入框"
      required
      decorator={[FormItem]}
      component={[
        Input,
        {
          style: {
            width: 240,
          },
        },
      ]}
    />
    <Field
      name="textarea"
      title="文本框"
      required
      decorator={[FormItem]}
      component={[
        Input.TextArea,
        {
          style: {
            width: 400,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

参考 https://fusion.design/pc/component/basic/input

```

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

```markdown
# Pack on Demand

## Based on Umi Development

#### Install `babel-plugin-import`

```shell
npm install babel-plugin-import --save-dev
```

or

```shell
yarn add babel-plugin-import --dev
```

#### Plugin Configuration

Modify `.umirc.js` or `.umirc.ts`

```js
export default {
  extraBabelPlugins: [
    [
      'babel-plugin-import',
      { libraryName: 'antd', libraryDirectory: 'es', style: true },
      'antd',
    ],
    [
      'babel-plugin-import',
      { libraryName: '@formily/antd', libraryDirectory: 'esm', style: true },
      '@formily/antd',
    ],
  ],
}
```

## Based on Create-react-app Development

First, we need to customize the default configuration of `create-react-app`, here we use [react-app-rewired](https://github.com/timarney/react-app-rewired) (A community solution for custom configuration of `create-react-app`)
Introduce `react-app-rewired` and modify the startup configuration in `package.json`. Due to the new [[email protected]](https://github.com/timarney/react-app-rewired#alternatives) version, you also need to install [customize-cra](https://github.com/arackaf/customize-cra).

```shell
$ npm install react-app-rewired customize-cra  --save-dev
```

or

```shell
$ yarn add react-app-rewired customize-cra --dev
```

modify `package.json`

```diff
"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
}
```

Then create a `config-overrides.js` in the project root directory to modify the default configuration.

```js
module.exports = function override(config, env) {
  // do stuff with the webpack config...
  return config
}
```

#### Install babel-plugin-import

```shell
npm install babel-plugin-import --save-dev
```

or

```shell
yarn add babel-plugin-import --dev
```

modify `config-overrides.js`

```diff
+ const { override, fixBabelImports } = require('customize-cra');

- module.exports = function override(config, env) {
-   // do stuff with the webpack config...
-   return config;
- };
+ module.exports = override(
+   fixBabelImports('antd', {
+     libraryName: 'antd',
+     libraryDirectory: 'es',
+     style: true
+   }),
+   fixBabelImports('@formily/antd', {
+     libraryName: '@formily/antd',
+     libraryDirectory: 'esm',
+     style: true
+   }),
+ );
```

## Use in Webpack

#### Install babel-plugin-import

```shell
npm install babel-plugin-import --save-dev
```

or

```shell
yarn add babel-plugin-import --dev
```

Modify `.babelrc` or babel-loader

```json
{
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd",
        "libraryDirectory": "es",
        "style": true
      },
      "antd"
    ],
    [
      "import",
      {
        "libraryName": "@formily/antd",
        "libraryDirectory": "esm",
        "style": true
      },
      "@formily/antd"
    ]
  ]
}
```

For more configuration, please refer to [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)

```

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

```vue
<template>
  <FormProvider :form="form">
    <FormLayout :label-col="6" :wrapper-col="10">
      <SchemaField :schema="schema" :scope="{ formCollapse }" />
      <FormButtonGroup alignFormItem>
        <Button
          @click="
            () => {
              form.query('tab3').take((field) => {
                field.visible = !field.visible
              })
            }
          "
        >
          显示/隐藏最后一个Tab
        </Button>
        <Button
          @click="
            () => {
              formCollapse.toggleActiveKey('tab2')
            }
          "
        >
          切换第二个Tab
        </Button>
        <Submit @submit="log">提交</Submit>
      </FormButtonGroup>
    </FormLayout>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import {
  FormItem,
  FormCollapse,
  FormButtonGroup,
  Form,
  FormLayout,
  Submit,
  Input,
} from '@formily/element'
import { Button } from 'element-ui'

const { SchemaField } = createSchemaField({
  components: {
    FormItem,
    FormCollapse,
    Input,
  },
})

const schema = {
  type: 'object',
  properties: {
    collapse: {
      type: 'void',
      title: '折叠面板',
      'x-decorator': 'FormItem',
      'x-component': 'FormCollapse',
      'x-component-props': {
        formCollapse: '{{formCollapse}}',
      },
      properties: {
        tab1: {
          type: 'void',
          'x-component': 'FormCollapse.Item',
          'x-component-props': {
            title: 'A1',
          },
          properties: {
            aaa: {
              type: 'string',
              title: 'AAA',
              'x-decorator': 'FormItem',
              required: true,
              'x-component': 'Input',
            },
          },
        },
        tab2: {
          type: 'void',
          'x-component': 'FormCollapse.Item',
          'x-component-props': {
            title: 'A2',
          },
          properties: {
            bbb: {
              type: 'string',
              title: 'BBB',
              'x-decorator': 'FormItem',
              required: true,
              'x-component': 'Input',
            },
          },
        },
        tab3: {
          type: 'void',
          'x-component': 'FormCollapse.Item',
          'x-component-props': {
            title: 'A3',
          },
          properties: {
            ccc: {
              type: 'string',
              title: 'CCC',
              'x-decorator': 'FormItem',
              required: true,
              'x-component': 'Input',
            },
          },
        },
      },
    },
  },
}

export default {
  components: {
    Form,
    FormButtonGroup,
    Button,
    Submit,
    SchemaField,
    FormProvider,
    FormLayout,
  },

  data() {
    const form = createForm()
    const formCollapse = FormCollapse.createFormCollapse()

    return {
      schema,
      form,
      formCollapse,
    }
  },
  methods: {
    log(values) {
      console.log(values)
    },
  },
}
</script>

<style lang="scss" scoped></style>

```

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

```vue
<template>
  <FormProvider :form="form">
    <FormLayout :labelCol="6" :wrapperCol="16">
      <SchemaField>
        <SchemaVoidField
          x-component="FormLayout"
          :x-component-props="{
            labelCol: 6,
            wrapperCol: 10,
          }"
        >
          <SchemaVoidField
            title="姓名"
            x-decorator="FormItem"
            :x-decorator-props="{
              asterisk: true,
              feedbackLayout: 'none',
            }"
            x-component="Space"
          >
            <SchemaStringField
              name="firstName"
              x-decorator="FormItem"
              x-component="Input"
              :required="true"
            />
            <SchemaStringField
              name="lastName"
              x-decorator="FormItem"
              x-component="Input"
              :required="true"
            />
          </SchemaVoidField>
          <SchemaVoidField
            title="文本串联"
            x-decorator="FormItem"
            :x-decorator-props="{
              asterisk: true,
              feedbackLayout: 'none',
            }"
            x-component="Space"
          >
            <SchemaStringField
              name="aa"
              x-decorator="FormItem"
              x-component="Input"
              :x-decorator-props="{
                addonAfter: '单位',
              }"
              :required="true"
            />
            <SchemaStringField
              name="bb"
              x-decorator="FormItem"
              x-component="Input"
              :x-decorator-props="{
                addonAfter: '单位',
              }"
              :required="true"
            />
            <SchemaStringField
              name="cc"
              x-decorator="FormItem"
              x-component="Input"
              :x-decorator-props="{
                addonAfter: '单位',
              }"
              :required="true"
            />
          </SchemaVoidField>
          <SchemaStringField
            name="textarea"
            title="文本框"
            x-decorator="FormItem"
            :required="true"
            x-component="Input"
            :x-component-props="{
              style: {
                width: 400,
              },
              type: 'textarea',
            }"
          />
        </SchemaVoidField>
      </SchemaField>
      <FormButtonGroup alignFormItem>
        <Submit onSubmit="log">提交</Submit>
      </FormButtonGroup>
    </FormLayout>
  </FormProvider>
</template>

<script>
import { createForm } from '@formily/core'
import { createSchemaField, FormProvider } from '@formily/vue'
import {
  FormLayout,
  FormItem,
  Input,
  Space,
  FormButtonGroup,
  Submit,
} from '@formily/element'

const fields = createSchemaField({
  components: { FormItem, FormLayout, Input, Space },
})

export default {
  components: { FormProvider, FormLayout, FormButtonGroup, Submit, ...fields },
  data() {
    const form = createForm()
    return {
      form,
    }
  },

  methods: {
    log(value) {
      console.log(value)
    },
  },
}
</script>

```

--------------------------------------------------------------------------------
/packages/react/docs/api/shared/observer.md:
--------------------------------------------------------------------------------

```markdown
# observer

## observer

### Description

The observer is a [HOC](https://reactjs.bootcss.com/docs/higher-order-components.html), which is used to add reactive features to react functional components.

### When to use

When a component uses an [observable](https://reactive.formilyjs.org/api/observable) object inside, and you want the component to respond to changes in the observable object.

### API definition

```ts
interface IObserverOptions {
  // Do you need observers to use forwardRef to pass ref attributes
  forwardRef?: boolean
  scheduler?: (updater: () => void) => void
  displayName?: string
}

function observer<P, Options extends IObserverOptions>(
  component: React.FunctionComponent<P>,
  options?: Options
): React.MemoExoticComponent<
  React.FunctionComponent<
    Options extends { forwardRef: true }
      ? React.PropsWithRef<P>
      : React.PropsWithoutRef<P>
  >
>
```

### Example

```tsx
/**
 * defaultShowCode: true
 */
import React from 'react'
import { observable } from '@formily/reactive'
import { observer } from '@formily/reactive-react'

const obs = observable({
  value: 'Hello world',
})

export default observer(() => {
  return (
    <div>
      <div>
        <input
          style={{
            height: 28,
            padding: '0 8px',
            border: '2px solid #888',
            borderRadius: 3,
          }}
          value={obs.value}
          onChange={(e) => {
            obs.value = e.target.value
          }}
        />
      </div>
      <div>{obs.value}</div>
    </div>
  )
})
```

### Note

`observer` can only receive callable function components, and does not support packaged components such as `React.forwardRef` | `React.memo`.

## Observer

### Description

Similar to Vue's responsive slot, it receives a Function RenderProps, as long as any responsive data consumed inside the Function, it will be automatically re-rendered as the data changes, and it is easier to achieve local accurate rendering

In fact, the function of this API is basically the same as that of FormConsumer, except that FormConsumer reveals the form instance of the current context in the RenderProps parameter.

### Signature

```ts
interface IObserverProps {
  children?: () => React.ReactElement
}

type Observer = React.FC<React.PropsWithChildren<IObserverProps>>
```

### Example

```tsx
/**
 * defaultShowCode: true
 */
import React from 'react'
import { observable } from '@formily/reactive'
import { Observer } from '@formily/react'

const obs = observable({
  value: 'Hello world',
})

export default () => {
  return (
    <div>
      <div>
        <Observer>
          {() => (
            <input
              style={{
                height: 28,
                padding: '0 8px',
                border: '2px solid #888',
                borderRadius: 3,
              }}
              value={obs.value}
              onChange={(e) => {
                obs.value = e.target.value
              }}
            />
          )}
        </Observer>
      </div>
      <Observer>{() => <div>{obs.value}</div>}</Observer>
    </div>
  )
}
```

```

--------------------------------------------------------------------------------
/packages/react/src/__tests__/expression.spec.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react'
import { render, waitFor } from '@testing-library/react'
import { createForm } from '@formily/core'
import {
  FormProvider,
  ExpressionScope,
  createSchemaField,
  useField,
  Field,
} from '..'

test('expression scope', async () => {
  const Container = (props) => {
    return (
      <ExpressionScope value={{ $innerScope: 'this is inner scope value' }}>
        {props.children}
      </ExpressionScope>
    )
  }
  const Input = (props) => <div data-testid="test-input">{props.value}</div>
  const SchemaField = createSchemaField({
    components: {
      Container,
      Input,
    },
  })
  const form = createForm()
  const { getByTestId } = render(
    <FormProvider form={form}>
      <SchemaField scope={{ $outerScope: 'this is outer scope value' }}>
        <SchemaField.Void x-component="Container">
          <SchemaField.String
            name="input"
            x-component="Input"
            x-value="{{$innerScope + ' ' + $outerScope}}"
          />
        </SchemaField.Void>
      </SchemaField>
    </FormProvider>
  )

  expect(getByTestId('test-input').textContent).toBe(
    'this is inner scope value this is outer scope value'
  )
})

test('x-compile-omitted', async () => {
  const form = createForm()
  const SchemaField = createSchemaField({
    components: {
      Input: (props) => (
        <div data-testid="input">
          {props.aa}
          {useField().title}
          {props.extra}
        </div>
      ),
    },
  })

  const { queryByTestId } = render(
    <FormProvider form={form}>
      <SchemaField>
        <SchemaField.String
          name="target"
          x-compile-omitted={['x-component-props']}
          title="{{123 + '321'}}"
          x-component-props={{
            aa: '{{fake}}',
            extra: 'extra',
          }}
          x-component="Input"
        />
        <SchemaField.String name="btn" x-component="Button" />
      </SchemaField>
    </FormProvider>
  )
  await waitFor(() => {
    expect(queryByTestId('input')?.textContent).toBe('{{fake}}123321extra')
  })
})

test('field hidden & visible', async () => {
  const form = createForm({ initialValues: { empty: null } })
  const { findByTestId } = render(
    <FormProvider form={form}>
      <div data-testid="testid">
        <Field name="empty" component={['input']} />
      </div>
    </FormProvider>
  )
  await findByTestId('testid')
  //
  expect(form.fields.empty.hidden).toBe(false)
  expect(form.fields.empty.value).toBe(null)
  form.fields.empty.hidden = true
  expect(form.fields.empty.hidden).toBe(true)
  expect(form.fields.empty.value).toBe(null)
  form.fields.empty.hidden = false
  expect(form.fields.empty.hidden).toBe(false)
  expect(form.fields.empty.value).toBe(null)
  //
  expect(form.fields.empty.visible).toBe(true)
  expect(form.fields.empty.value).toBe(null)
  form.fields.empty.visible = false
  expect(form.fields.empty.visible).toBe(false)
  expect(form.fields.empty.value).toBe(undefined)
  form.fields.empty.visible = true
  expect(form.fields.empty.visible).toBe(true)
  expect(form.fields.empty.value).toBe(null)
})

```

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

```markdown
# Submit

> 提交按钮

## 普通提交

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 防重复提交(Loading)

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit
        onSubmit={(values) => {
          return new Promise((resolve) => {
            setTimeout(() => {
              console.log(values)
              resolve()
            }, 2000)
          })
        }}
        onSubmitFailed={console.log}
      >
        提交
      </Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

按钮相关的 API 属性,我们参考 https://ant.design/components/button-cn/ 即可,剩下是 Submit 组件独有的 API 属性

| 属性名          | 类型                                                                                                   | 描述                                  | 默认值 |
| --------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ |
| onClick         | `(event: MouseEvent) => void \| boolean`                                                               | 点击事件,如果返回 false 可以阻塞提交 | -      |
| onSubmit        | `(values: any) => Promise<any> \| any`                                                                 | 提交事件回调                          | -      |
| onSubmitSuccess | (payload: any) => void                                                                                 | 提交成功响应事件                      | -      |
| onSubmitFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/zh-CN/api/models/form#iformfeedback)[]) => void | 提交校验失败事件回调                  | -      |

```

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

```markdown
# Submit

> 提交按钮

## 普通提交

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>提交</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## 防重复提交(Loading)

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="输入框"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
      <SchemaField.String
        name="input2"
        title="输入框"
        default="123"
        required
        x-decorator="FormItem"
        x-component="Input"
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit
        onSubmit={(values) => {
          return new Promise((resolve) => {
            setTimeout(() => {
              console.log(values)
              resolve()
            }, 2000)
          })
        }}
        onSubmitFailed={console.log}
      >
        提交
      </Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

按钮相关的 API 属性,我们参考 https://fusion.design/pc/component/basic/button 即可,剩下是 Submit 组件独有的 API 属性

| 属性名          | 类型                                                                                                   | 描述                                  | 默认值 |
| --------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ |
| onClick         | `(event: MouseEvent) => void \| boolean`                                                               | 点击事件,如果返回 false 可以阻塞提交 | -      |
| onSubmit        | `(values: any) => Promise<any> \| any`                                                                 | 提交事件回调                          | -      |
| onSubmitSuccess | (payload: any) => void                                                                                 | 提交成功响应事件                      | -      |
| onSubmitFailed  | (feedbacks: [IFormFeedback](https://core.formilyjs.org/zh-CN/api/models/form#iformfeedback)[]) => void | 提交校验失败事件回调                  | -      |

```

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

```markdown
# Input

> Text input box

## Markup Schema example

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        x-decorator="FormItem"
        x-component="Input"
        required
        x-component-props={{
          style: {
            width: 240,
          },
        }}
      />
      <SchemaField.String
        name="textarea"
        title="text box"
        x-decorator="FormItem"
        required
        x-component="Input.TextArea"
        x-component-props={{
          style: {
            width: 400,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema case

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    input: {
      type: 'string',
      title: 'input box',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
    textarea: {
      type: 'string',
      title: 'input box',
      'x-decorator': 'FormItem',
      'x-component': 'Input.TextArea',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Pure JSX case

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="input"
      title="input box"
      required
      decorator={[FormItem]}
      component={[
        Input,
        {
          style: {
            width: 240,
          },
        },
      ]}
    />
    <Field
      name="textarea"
      title="text box"
      required
      decorator={[FormItem]}
      component={[
        Input.TextArea,
        {
          style: {
            width: 400,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

Reference https://ant.design/components/input-cn/

```

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

```markdown
# Input

> Text input box

## Markup Schema example

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="input"
        title="input box"
        x-decorator="FormItem"
        x-component="Input"
        required
        x-component-props={{
          style: {
            width: 240,
          },
        }}
      />
      <SchemaField.String
        name="textarea"
        title="text box"
        x-decorator="FormItem"
        required
        x-component="Input.TextArea"
        x-component-props={{
          style: {
            width: 400,
          },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## JSON Schema case

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
  components: {
    Input,
    FormItem,
  },
})

const form = createForm()

const schema = {
  type: 'object',
  properties: {
    input: {
      type: 'string',
      title: 'input box',
      'x-decorator': 'FormItem',
      'x-component': 'Input',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
    textarea: {
      type: 'string',
      title: 'input box',
      'x-decorator': 'FormItem',
      'x-component': 'Input.TextArea',
      'x-component-props': {
        style: {
          width: 240,
        },
      },
    },
  },
}

export default () => (
  <FormProvider form={form}>
    <SchemaField schema={schema} />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## Pure JSX case

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/next'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
  <FormProvider form={form}>
    <Field
      name="input"
      title="input box"
      required
      decorator={[FormItem]}
      component={[
        Input,
        {
          style: {
            width: 240,
          },
        },
      ]}
    />
    <Field
      name="textarea"
      title="text box"
      required
      decorator={[FormItem]}
      component={[
        Input.TextArea,
        {
          style: {
            width: 400,
          },
        },
      ]}
    />
    <FormButtonGroup>
      <Submit onSubmit={console.log}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)
```

## API

Reference https://fusion.design/pc/component/basic/input

```

--------------------------------------------------------------------------------
/packages/vue/docs/.vuepress/config.js:
--------------------------------------------------------------------------------

```javascript
const path = require('path')

module.exports = {
  title: 'Formily Vue',
  dest: './doc-site',
  theme: '@vuepress-dumi/dumi',
  head: [
    [
      'link',
      {
        rel: 'icon',
        href: '//img.alicdn.com/imgextra/i3/O1CN01XtT3Tv1Wd1b5hNVKy_!!6000000002810-55-tps-360-360.svg',
      },
    ],
  ],
  themeConfig: {
    logo: '//img.alicdn.com/imgextra/i2/O1CN01Kq3OHU1fph6LGqjIz_!!6000000004056-55-tps-1141-150.svg',
    nav: [
      {
        text: '指南',
        link: '/guide/',
      },
      {
        text: 'API',
        link: '/api/components/field',
      },
      {
        text: 'Q&A',
        link: '/questions/',
      },
      {
        text: '主站',
        link: 'https://formilyjs.org',
      },
      {
        text: 'GITHUB',
        link: 'https://github.com/alibaba/formily',
      },
    ],
    sidebar: {
      '/guide/': ['', 'architecture', 'concept'],
      '/api/': [
        {
          title: 'Components',
          children: [
            '/api/components/field',
            '/api/components/array-field',
            '/api/components/object-field',
            '/api/components/void-field',
            '/api/components/schema-field',
            '/api/components/schema-field-with-schema',
            '/api/components/recursion-field',
            '/api/components/recursion-field-with-component',
            '/api/components/form-provider',
            '/api/components/form-consumer',
            '/api/components/expression-scope',
          ],
        },
        {
          title: 'Hooks',
          children: [
            '/api/hooks/use-field',
            '/api/hooks/use-field-schema',
            '/api/hooks/use-form',
            '/api/hooks/use-form-effects',
            '/api/hooks/use-parent-form',
          ],
        },
        {
          title: 'Shared',
          children: [
            '/api/shared/connect',
            '/api/shared/injections',
            '/api/shared/map-props',
            '/api/shared/map-read-pretty',
            '/api/shared/observer',
            '/api/shared/schema',
          ],
        },
      ],
    },
    lastUpdated: 'Last Updated',
    smoothScroll: true,
  },
  plugins: [
    'vuepress-plugin-typescript',
    '@vuepress/back-to-top',
    '@vuepress/last-updated',
    '@vuepress-dumi/dumi-previewer',
    [
      '@vuepress/medium-zoom',
      {
        selector: '.content__default :not(a) > img',
      },
    ],
  ],
  configureWebpack: (config, isServer) => {
    return {
      resolve: {
        alias: {
          '@formily/vue': path.resolve(__dirname, '../../src'),
          '@formily/json-schema': path.resolve(
            __dirname,
            '../../../json-schema/src'
          ),
          '@formily/path': path.resolve(__dirname, '../../../path/src'),
          '@formily/reactive-vue': path.resolve(
            __dirname,
            '../../../reactive-vue/src'
          ),
          '@formily/element': path.resolve(__dirname, '../../../element/src'),
          vue: path.resolve(
            __dirname,
            '../../../../node_modules/vue/dist/vue.runtime.esm.js'
          ),
        },
      },
    }
  },
}

```

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

```typescript
import {
  isArr,
  isFn,
  isPlainObj,
  isStr,
  reduce,
  FormPath,
} from '@formily/shared'
import { IGeneralFieldState } from '@formily/core'
import { untracked, hasCollected } from '@formily/reactive'
import {
  traverse,
  traverseSchema,
  isNoNeedCompileObject,
  hasOwnProperty,
  patchStateFormSchema,
} from './shared'
import { ISchema } from './types'

const ExpRE = /^\s*\{\{([\s\S]*)\}\}\s*$/
const Registry = {
  silent: false,
  compile(expression: string, scope = {}) {
    if (Registry.silent) {
      try {
        return new Function('$root', `with($root) { return (${expression}); }`)(
          scope
        )
      } catch {}
    } else {
      return new Function('$root', `with($root) { return (${expression}); }`)(
        scope
      )
    }
  },
}

export const silent = (value = true) => {
  Registry.silent = !!value
}

export const registerCompiler = (
  compiler: (expression: string, scope: any) => any
) => {
  if (isFn(compiler)) {
    Registry.compile = compiler
  }
}

export const shallowCompile = <Source = any, Scope = any>(
  source: Source,
  scope?: Scope
) => {
  if (isStr(source)) {
    const matched = source.match(ExpRE)
    if (!matched) return source
    return Registry.compile(matched[1], scope)
  }
  return source
}

export const compile = <Source = any, Scope = any>(
  source: Source,
  scope?: Scope
): any => {
  const seenObjects = []
  const compile = (source: any) => {
    if (isStr(source)) {
      return shallowCompile(source, scope)
    } else if (isArr(source)) {
      return source.map((value: any) => compile(value))
    } else if (isPlainObj(source)) {
      if (isNoNeedCompileObject(source)) return source
      const seenIndex = seenObjects.indexOf(source)
      if (seenIndex > -1) {
        return source
      }
      const addIndex = seenObjects.length
      seenObjects.push(source)
      const results = reduce(
        source,
        (buf, value, key) => {
          buf[key] = compile(value)
          return buf
        },
        {}
      )
      seenObjects.splice(addIndex, 1)
      return results
    }
    return source
  }
  return compile(source)
}

export const patchCompile = (
  targetState: IGeneralFieldState,
  sourceState: any,
  scope: any
) => {
  traverse(sourceState, (value, pattern) => {
    const compiled = compile(value, scope)
    if (compiled === undefined) return
    const path = FormPath.parse(pattern)
    const key = path.segments[0]
    if (hasOwnProperty.call(targetState, key)) {
      untracked(() => FormPath.setIn(targetState, path, compiled))
    }
  })
}

export const patchSchemaCompile = (
  targetState: IGeneralFieldState,
  sourceSchema: ISchema,
  scope: any,
  demand = false
) => {
  traverseSchema(sourceSchema, (value, path, omitCompile) => {
    let compiled = value
    let collected = hasCollected(() => {
      if (!omitCompile) {
        compiled = compile(value, scope)
      }
    })
    if (compiled === undefined) return
    if (demand) {
      if (collected || !targetState.initialized) {
        patchStateFormSchema(targetState, path, compiled)
      }
    } else {
      patchStateFormSchema(targetState, path, compiled)
    }
  })
}

```

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

```typescript
import {
  isObservable,
  isSupportObservable,
  markObservable,
  markRaw,
  observable,
  toJS,
} from '..'

test('is support observable', () => {
  const obs = observable<any>({ aa: 111 })
  class Class {}

  expect(isSupportObservable(obs)).toBe(true)
  expect(isSupportObservable(new Class())).toBe(true)
  expect(isSupportObservable(null)).toBe(false)
  expect(isSupportObservable([])).toBe(true)
  expect(isSupportObservable({})).toBe(true)
  expect(isSupportObservable({ $$typeof: {}, _owner: {} })).toBe(false)
  expect(isSupportObservable({ _isAMomentObject: {} })).toBe(false)
  expect(isSupportObservable({ _isJSONSchemaObject: {} })).toBe(false)
  expect(isSupportObservable({ toJS: () => {} })).toBe(false)
  expect(isSupportObservable({ toJSON: () => {} })).toBe(false)
  expect(isSupportObservable(new Map())).toBe(true)
  expect(isSupportObservable(new WeakMap())).toBe(true)
  expect(isSupportObservable(new Set())).toBe(true)
  expect(isSupportObservable(new WeakSet())).toBe(true)
})

describe('mark operation', () => {
  test('plain object should be observable', () => {
    const obs = observable<any>({ aa: 111 })
    expect(isObservable(obs)).toBe(true)
  })

  test('class instance should be observable', () => {
    class Class {}
    const obs = observable<any>(new Class())
    const obs2 = observable<any>(new Class())
    expect(isObservable(obs)).toBe(true)
    expect(isObservable(obs2)).toBe(true)
  })

  test('object with toJS function should NOT be observable', () => {
    const obs = observable<any>({ aa: 111, toJS: () => {} })
    expect(isObservable(obs)).toBe(false)
  })

  test('plain object marked as raw should NOT be observable', () => {
    const obs = observable<any>(markRaw({ aa: 111 }))
    expect(isObservable(obs)).toBe(false)
  })

  test('class marked as raw instance should NOT be observable', () => {
    class Class {}
    markRaw(Class)
    const obs = observable<any>(new Class())
    const obs2 = observable<any>(new Class())
    expect(isObservable(obs)).toBe(false)
    expect(isObservable(obs2)).toBe(false)
  })

  test('object with toJS function marked as observable should be observable', () => {
    const obs = observable<any>(markObservable({ aa: 111, toJS: () => {} }))
    expect(isObservable(obs)).toBe(true)
  })

  test('plain object marked as raw and observable should NOT be observable', () => {
    const obs = observable<any>(markRaw(markObservable({ aa: 111 })))
    expect(isObservable(obs)).toBe(false)
  })

  test('plain object marked as observable and raw should NOT be observable', () => {
    const obs = observable<any>(markObservable(markRaw({ aa: 111 })))
    expect(isObservable(obs)).toBe(false)
  })

  test('function marked as observable should NOT be observable', () => {
    const obs = observable<any>(markObservable(() => {}))
    expect(isObservable(obs)).toBe(false)
  })
})

test('recursive references tojs', () => {
  const obj: any = { aa: 111 }
  obj.obj = obj
  const obs = observable<any>(obj)
  obs.obs = obs
  expect(toJS(obs)).toBeTruthy()

  const arrObs = observable([{ aa: 1 }, { bb: 2 }, { cc: 3 }])
  expect(toJS(arrObs)).toEqual([{ aa: 1 }, { bb: 2 }, { cc: 3 }])
})

```

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

```typescript
import { Field } from '@formily/core'
import { connect, Fragment, h, mapProps, useField } from '@formily/vue'
import { defineComponent } from 'vue-demi'

import type {
  ElUpload as ElUploadProps,
  ElUploadInternalFileDetail,
} from 'element-ui/types/upload'

import { Button as ElButton, Upload as ElUpload } from 'element-ui'

export type UploadProps = ElUploadProps & {
  textContent?: String
  errorAdaptor?: (error?: ErrorEvent) => String
}

const UploadWrapper = defineComponent<UploadProps>({
  name: 'FUpload',
  props: {
    textContent: {
      type: String,
      default: '',
    },
    errorAdaptor: {
      type: Function,
      default(error?: ErrorEvent) {
        return error?.message || ''
      },
    },
  },
  setup(curProps: UploadProps, { slots, attrs, listeners, emit }) {
    return () => {
      const fieldRef = useField<Field>()
      const setFeedBack = (error?: ErrorEvent) => {
        const message = curProps.errorAdaptor(error)

        fieldRef.value.setFeedback({
          type: 'error',
          code: 'UploadError',
          messages: message ? [message] : [],
        })
      }

      const props = {
        ...attrs,
        onChange(
          file: ElUploadInternalFileDetail,
          fileList: ElUploadInternalFileDetail[]
        ) {
          ;(attrs.onChange as Function)?.(file, fileList)
          setFeedBack()
          emit('change', fileList)
        },

        onRemove(
          file: ElUploadInternalFileDetail,
          fileList: ElUploadInternalFileDetail[]
        ) {
          ;(attrs.onRemove as Function)?.(file, fileList)
          setFeedBack()
          emit('change', fileList)
        },

        onError(
          error: ErrorEvent,
          file: ElUploadInternalFileDetail,
          fileList: ElUploadInternalFileDetail[]
        ) {
          ;(attrs.onError as Function)?.(error, file, fileList)

          setTimeout(() => {
            setFeedBack(error)
          }, 0)
        },
      }
      const children = {
        ...slots,
      }
      if (!slots.default) {
        children.default = () => {
          const listType = attrs.listType
          const drag = attrs.drag

          if (drag) {
            return h(
              Fragment,
              {},
              {
                default: () => [
                  h('i', { staticClass: 'el-icon-upload' }, {}),
                  h(
                    'div',
                    { staticClass: 'el-upload__text' },
                    { default: () => [curProps.textContent] }
                  ),
                ],
              }
            )
          }

          if (listType === 'picture-card') {
            return h(
              'i',
              {
                staticClass: 'el-icon-plus',
              },
              {}
            )
          }

          return h(
            ElButton,
            { props: { icon: 'el-icon-upload2' } },
            { default: () => [curProps.textContent] }
          )
        }
      }
      return h(ElUpload, { attrs: props, on: listeners }, children)
    }
  },
})

export const Upload = connect(
  UploadWrapper,
  mapProps({ readOnly: 'readonly', value: 'fileList' })
)

export default Upload

```

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

```typescript
import { observable, observe } from '../'

test('deep observe', () => {
  const obs = observable<any>({
    aa: {
      bb: {
        cc: [11, 22, 33],
      },
    },
    ee: observable([]),
  })
  const handler = jest.fn()
  observe(obs, handler)
  obs.dd = 123
  obs.aa.bb.cc.push(44)
  expect(obs.aa.bb.cc).toEqual([11, 22, 33, 44])
  expect(handler).toHaveBeenCalledTimes(2)
  delete obs.aa
  expect(handler).toHaveBeenCalledTimes(3)

  // Are these expected behaviors?
  obs.ee.push(11)
  expect(handler).toHaveBeenCalledTimes(3)
  obs.ee = []
  expect(handler).toHaveBeenCalledTimes(4)
  obs.ee.push(11)
  expect(handler).toHaveBeenCalledTimes(5)
})

test('shallow observe', () => {
  const obs = observable<any>({
    aa: {
      bb: {
        cc: [11, 22, 33],
      },
    },
  })
  const handler = jest.fn()
  observe(obs, handler, false)
  obs.dd = 123
  obs.aa.bb.cc.push(44)
  expect(obs.aa.bb.cc).toEqual([11, 22, 33, 44])
  expect(handler).toHaveBeenCalledTimes(1)
  delete obs.aa
  expect(handler).toHaveBeenCalledTimes(2)
})

test('root replace observe', () => {
  const obs = observable<any>({
    aa: {
      bb: {
        cc: [11, 22, 33],
      },
    },
  })
  const handler1 = jest.fn()
  const handler = jest.fn()
  observe(obs, handler1)
  observe(obs.aa, handler)
  obs.aa = {
    mm: 123,
  }
  expect(handler1).toBeCalledTimes(1)
  expect(handler).toBeCalledTimes(1)
  obs.aa = {
    bb: {
      cc: [11, 22, 33],
    },
  }
  obs.aa.bb.cc.push(44)
  expect(handler1).toBeCalledTimes(3)
  expect(handler).toBeCalledTimes(3)
})

test('dispose observe', () => {
  const obs = observable<any>({
    aa: {
      bb: {
        cc: [11, 22, 33],
      },
    },
  })
  const handler = jest.fn()
  const dispose = observe(obs, handler)
  obs.kk = 123
  expect(handler).toBeCalledTimes(1)
  dispose()
  obs.aa = 123
  expect(handler).toBeCalledTimes(1)
})

test('dispose observe', () => {
  const obs = observable<any>({
    aa: {
      bb: {
        cc: [11, 22, 33],
      },
    },
  })
  const handler = jest.fn()
  const dispose = observe(obs.aa, handler)
  obs.kk = 111
  expect(handler).toBeCalledTimes(0)
  obs.aa = { mm: 222 }
  expect(handler).toBeCalledTimes(1)
  obs.aa = { mm: 222 }
  expect(handler).toBeCalledTimes(2)
  obs.aa = { mm: '111' }
  expect(handler).toBeCalledTimes(3)
  obs.aa = { mm: 333 }
  expect(handler).toBeCalledTimes(4)
  dispose()
  obs.aa = { mm: 444 }
  expect(handler).toBeCalledTimes(4)
})

test('array delete', () => {
  const array = observable([{ value: 1 }, { value: 2 }])

  const fn = jest.fn()

  const dispose = observe(array, (change) => {
    if (change.type === 'set' && change.key === 'value') {
      fn(change.path?.join('.'))
    }
  })

  array[0].value = 3
  expect(fn.mock.calls[0][0]).toBe('0.value')

  array.splice(0, 1)

  array[0].value = 3
  expect(fn.mock.calls[1][0]).toBe('0.value')

  dispose()
})

test('observe dynamic tree', () => {
  const handler = jest.fn()
  const tree = observable<any>({})
  const childTree = observable({})
  tree.children = childTree
  observe(tree, handler)
  tree.children.aa = 123
  expect(handler).toBeCalledTimes(1)
})

test('invalid target', () => {
  expect(() => observe(function () {})).toThrowError()
})

```
Page 8/35FirstPrevNextLast