Janry vor 6 Jahren
Ursprung
Commit
60c8bd57df
100 geänderte Dateien mit 1368 neuen und 7165 gelöschten Zeilen
  1. 1 1
      .eslintrc
  2. 44 24
      docs/Examples/antd/List.md
  3. 2 1
      docs/Examples/antd/Relations.md
  4. 1 2
      docs/Examples/antd/Sample.md
  5. 6 1
      docs/Examples/next/List.md
  6. 3 2
      docs/Examples/next/Relations.md
  7. 8 3
      package.json
  8. 18 6
      packages/.eslintrc
  9. 6 6
      packages/antd/build.ts
  10. 7 5
      packages/antd/package.json
  11. 22 0
      packages/antd/src/compat/Form.tsx
  12. 99 0
      packages/antd/src/compat/FormItem.tsx
  13. 35 0
      packages/antd/src/compat/context.tsx
  14. 10 0
      packages/antd/src/compat/index.ts
  15. 22 0
      packages/antd/src/components/FormBlock.tsx
  16. 18 0
      packages/antd/src/components/FormCard.tsx
  17. 87 0
      packages/antd/src/components/FormItemGrid.tsx
  18. 27 0
      packages/antd/src/components/FormLayout.tsx
  19. 98 0
      packages/antd/src/components/FormStep.tsx
  20. 104 0
      packages/antd/src/components/FormTextBox.tsx
  21. 39 0
      packages/antd/src/components/Select.tsx
  22. 65 16
      packages/antd/src/components/button.tsx
  23. 72 92
      packages/antd/src/components/formButtonGroup.tsx
  24. 0 175
      packages/antd/src/components/grid.tsx
  25. 8 0
      packages/antd/src/components/index.ts
  26. 0 326
      packages/antd/src/components/layout.tsx
  27. 0 177
      packages/antd/src/fields/array.tsx
  28. 2 2
      packages/antd/src/fields/boolean.tsx
  29. 137 130
      packages/antd/src/fields/cards.tsx
  30. 2 2
      packages/antd/src/fields/checkbox.tsx
  31. 22 32
      packages/antd/src/fields/date.tsx
  32. 15 0
      packages/antd/src/fields/index.ts
  33. 2 2
      packages/antd/src/fields/number.tsx
  34. 42 201
      packages/antd/src/fields/password.tsx
  35. 2 2
      packages/antd/src/fields/radio.tsx
  36. 2 2
      packages/antd/src/fields/range.tsx
  37. 2 2
      packages/antd/src/fields/rating.tsx
  38. 2 2
      packages/antd/src/fields/string.tsx
  39. 147 337
      packages/antd/src/fields/table.tsx
  40. 2 2
      packages/antd/src/fields/textarea.tsx
  41. 3 3
      packages/antd/src/fields/time.tsx
  42. 2 2
      packages/antd/src/fields/transfer.tsx
  43. 2 2
      packages/antd/src/fields/upload.tsx
  44. 0 481
      packages/antd/src/form.tsx
  45. 15 42
      packages/antd/src/index.tsx
  46. 0 7
      packages/antd/src/locale.ts
  47. 75 0
      packages/antd/src/shared.ts
  48. 0 186
      packages/antd/src/type.tsx
  49. 90 0
      packages/antd/src/types.ts
  50. 0 253
      packages/antd/src/utils.tsx
  51. 0 2
      packages/builder-next/README.md
  52. 0 138
      packages/builder-next/src/index.js
  53. 0 11
      packages/builder-next/tsconfig.json
  54. 0 8
      packages/builder/.npmignore
  55. 0 20
      packages/builder/LISENCE.md
  56. 0 2
      packages/builder/README.md
  57. 0 62
      packages/builder/package.json
  58. 0 366
      packages/builder/src/App.js
  59. 0 154
      packages/builder/src/actions/index.js
  60. 0 137
      packages/builder/src/components/editor/index.js
  61. 0 33
      packages/builder/src/components/editor/style.js
  62. 0 103
      packages/builder/src/components/fields/field.js
  63. 0 58
      packages/builder/src/components/fields/index.js
  64. 0 63
      packages/builder/src/components/fields/layout.js
  65. 0 85
      packages/builder/src/components/fields/layoutField.js
  66. 0 87
      packages/builder/src/components/fields/style.js
  67. 0 115
      packages/builder/src/components/globalBtnList/index.js
  68. 0 8
      packages/builder/src/components/index.js
  69. 0 191
      packages/builder/src/components/preview/card.js
  70. 0 45
      packages/builder/src/components/preview/fieldMiddleware.js
  71. 0 63
      packages/builder/src/components/preview/index.js
  72. 0 133
      packages/builder/src/components/preview/mainBox.js
  73. 0 161
      packages/builder/src/components/preview/style.js
  74. 0 53
      packages/builder/src/components/props/colsDetail.js
  75. 0 42
      packages/builder/src/components/props/dataSourceEditor/index.js
  76. 0 36
      packages/builder/src/components/props/defaultValueCascader/index.js
  77. 0 310
      packages/builder/src/components/props/editors/fieldAttrEditors/dataSourceEditor.js
  78. 0 126
      packages/builder/src/components/props/editors/fieldAttrEditors/dataSourceEnum.js
  79. 0 41
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/arrayDefaultEditor.js
  80. 0 29
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/boolDefaultEditor.js
  81. 0 79
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateDefaultEditor.js
  82. 0 47
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateRangeDefaultEditor.js
  83. 0 52
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateTimeDefaultEditor.js
  84. 0 35
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateTimeRangeDefaultEditor.js
  85. 0 110
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/defaultValueGenerator.js
  86. 0 118
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/index.js
  87. 0 80
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/monthDefaultEditor.js
  88. 0 39
      packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/stringDefaultEditor.js
  89. 0 196
      packages/builder/src/components/props/fileSetting.js
  90. 0 263
      packages/builder/src/components/props/propsSetting.js
  91. 0 60
      packages/builder/src/components/props/style.js
  92. 0 7
      packages/builder/src/configs/index.js
  93. 0 284
      packages/builder/src/configs/supportConfigList.js
  94. 0 246
      packages/builder/src/configs/supportFieldList.js
  95. 0 80
      packages/builder/src/configs/supportGlobalCfgList.js
  96. 0 44
      packages/builder/src/configs/supportLayoutList.js
  97. 0 57
      packages/builder/src/configs/theme.js
  98. 0 5
      packages/builder/src/constants/context.js
  99. 0 5
      packages/builder/src/constants/itemType.js
  100. 0 147
      packages/builder/src/demo/index-1-x.js

+ 1 - 1
.eslintrc

@@ -12,5 +12,5 @@
     "ecmaFeatures": {
       "jsx": true
     }
-  }
+  },
 }

+ 44 - 24
docs/Examples/antd/List.md

@@ -3,10 +3,11 @@
 > 数组场景,区块型数组,能解决大量字段的聚合输入,但是对于数据的对比化展示,区分
 > 度不够明显
 
-下面对于List场景我们主要封装了
-- Array类型组件
-- Table类型组件
-- Card类型组件
+下面对于 List 场景我们主要封装了
+
+- Array 类型组件
+- Table 类型组件
+- Card 类型组件
 
 这些组件你都可以对其做简单的定制来适应你当前的业务需求,比如
 
@@ -66,8 +67,8 @@ const App = () => {
           maxItems={3}
           type="array"
           x-props={{
-            renderAddition:'这是定制的添加文案',
-            renderRemove:'这是定制的删除文案'
+            renderAddition: '这是定制的添加文案',
+            renderRemove: '这是定制的删除文案'
           }}
         >
           <Field type="object">
@@ -82,11 +83,7 @@ const App = () => {
               </FormLayout>
             </FormBlock>
             <FormBlock title="嵌套数组">
-              <Field
-                name="array2"
-                maxItems={3}
-                type="array"
-              >
+              <Field name="array2" maxItems={3} type="array">
                 <Field type="object">
                   <FormLayout labelCol={9} wrapperCol={6}>
                     <Field name="aa" type="string" title="字段1" />
@@ -149,11 +146,23 @@ const App = () => (
         maxItems={3}
         type="array"
         x-component="table"
-         x-props={{
-          renderExtraOperations(){
-            return <div>Hello worldasdasdasdasd</div>
+        x-props={{
+          scroll: { x: '200%' },
+          renderExtraOperations() {
+            return (
+              <div
+                style={{
+                  whiteSpace: 'nowrap',
+                  textOverflow: 'ellipsis',
+                  overflow: 'hidden',
+                  lineHeight: '32px'
+                }}
+              >
+                Hello worldasdasdasdasd
+              </div>
+            )
           },
-          operationsWidth:400
+          operationsWidth: 400
         }}
       >
         <Field type="object">
@@ -169,7 +178,7 @@ const App = () => (
           <Field name="dd" type="string" title="字段5" />
           <Field name="ee" type="string" title="字段6" />
           <Field name="ff" type="string" title="字段7" />
-          <Field name="gg" type="daterange" title="字段8" width={400}  />
+          <Field name="gg" type="daterange" title="字段8" width={400} />
         </Field>
       </Field>
     </SchemaForm>
@@ -207,12 +216,17 @@ import 'antd/dist/antd.css'
 const App = () => (
   <Printer>
     <SchemaForm>
-      <Field name="array" maxItems={3} type="array" x-component="cards" 
-          x-props={{
-            title:'这是卡片标题',
-            renderAddition:'这是定制的添加文案',
-            renderRemove:'这是定制的删除文案'
-          }}>
+      <Field
+        name="array"
+        maxItems={3}
+        type="array"
+        x-component="cards"
+        x-props={{
+          title: '这是卡片标题',
+          renderAddition: '这是定制的添加文案',
+          renderRemove: '这是定制的删除文案'
+        }}
+      >
         <Field type="object">
           <FormLayout labelCol={6} wrapperCol={8}>
             <Field
@@ -227,9 +241,15 @@ const App = () => (
             <Field name="dd" type="string" title="字段5" />
             <Field name="ee" type="string" title="字段6" />
             <Field name="ff" type="string" title="字段7" />
-            <Field name="gg" type="daterange" title="字段8"/>
+            <Field name="gg" type="daterange" title="字段8" />
           </FormLayout>
-          <Field name="array" maxItems={3} type="array" x-component="cards" x-props={{title:'这是卡片标题'}}>
+          <Field
+            name="array"
+            maxItems={3}
+            type="array"
+            x-component="cards"
+            x-props={{ title: '这是卡片标题' }}
+          >
             <Field type="object">
               <FormLayout labelCol={6} wrapperCol={8}>
                 <Field

+ 2 - 1
docs/Examples/antd/Relations.md

@@ -65,6 +65,7 @@ const App = () => {
             })
           })
           $('onFieldChange', 'aa').subscribe(fieldState => {
+            console.log(fieldState.value)
             setFieldState('bb', state => {
               state.visible = !fieldState.value
             })
@@ -135,7 +136,7 @@ const App = () => {
             })
         }}
         labelCol={6}
-        wrapperCol={4}
+        wrapperCol={12}
         onSubmit={v => console.log(v)}
       >
         <FormBlock title="Block1">

+ 1 - 2
docs/Examples/antd/Sample.md

@@ -34,7 +34,6 @@ ReactDOM.render(
       actions={actions}
       labelCol={7}
       initialValues={{
-        date:'2019-08-01',
         upload3:[{
           downloadURL:
             "//img.alicdn.com/tfs/TB1n8jfr1uSBuNjy1XcXXcYjFXa-200-200.png",
@@ -82,7 +81,7 @@ ReactDOM.render(
       />
       <Field type="number" title="数字选择" name="number" />
       <Field type="boolean" title="开关选择" name="boolean" />
-      <Field type="date" title="日期选择" name="date" x-props={{disabled:true}} />
+      <Field type="date" title="日期选择" name="date" />
       <Field
         type="daterange"
         title="日期范围"

+ 6 - 1
docs/Examples/next/List.md

@@ -157,7 +157,12 @@ const App = () => (
             <Field name="ee" type="string" title="字段5" />
             <Field name="ff" type="string" title="字段6" />
             <Field name="gg" type="string" title="字段7" />
-            <Field name="hh" type="daterange" title="字段8" />
+            <Field
+              name="hh"
+              type="daterange"
+              x-props={{ width: 400 }}
+              title="字段8"
+            />
           </Field>
         </Field>
       </FormLayout>

+ 3 - 2
docs/Examples/next/Relations.md

@@ -51,6 +51,7 @@ const App = () => {
   return (
     <Printer>
       <SchemaForm
+        useDirty
         effects={($, { setFieldState, getFieldState }) => {
           $('onFormInit').subscribe(() => {
             setFieldState(FormPath.match('*(gg,hh)'), state => {
@@ -131,7 +132,7 @@ const App = () => {
         wrapperCol={4}
         onSubmit={v => console.log(v)}
       >
-        <FormBlock title="Block1">
+        <FormBlock name="block" title="Block1">
           <Field
             name="aa"
             type="boolean"
@@ -497,7 +498,7 @@ const App = () => {
               </FormLayout>
             </FormBlock>
             <FormBlock title="嵌套Array">
-              <Field type="array" name="dd" x-component="cards">
+              <Field type="array" name="dd">
                 <Field type="object">
                   <FormLayout inline style={{ marginLeft: 20 }}>
                     <Field

+ 8 - 3
package.json

@@ -12,8 +12,11 @@
     "build:docs": "node ./scripts/docs.js build -i docs -o docs",
     "start": "node ./scripts/docs.js start -i docs",
     "sort-api": "node ./scripts/sort-api-table.js",
-    "test": "jest",
+    "test": "npm run lint && jest",
+    "test:core": "jest --watch packages/core/src/__tests__/index.spec.ts",
     "test:prod": "cross-env TEST_ENV=production npm run build && jest",
+    "doc:core": "doc-scripts start -i packages/core",
+    "doc:react": "doc-scripts start -i packages/react",
     "test:watch": "jest --watch",
     "coverage": "npm run test -- --coverage",
     "coverage:upload": "rm -rf ./coverage && npm run coverage && node ./scripts/mapCoverage.js && codecov",
@@ -48,6 +51,7 @@
     "@babel/register": "^7.0.0",
     "@babel/runtime-corejs3": "^7.2.0",
     "@testing-library/react": "^8.0.0",
+    "@types/jest": "^24.0.18",
     "@types/node": "^12.6.8",
     "@typescript-eslint/eslint-plugin": "^1.11.0",
     "@typescript-eslint/parser": "^1.11.0",
@@ -94,6 +98,7 @@
     "pretty-format": "^24.0.0",
     "react": "^16.8.3",
     "react-dom": "^16.8.3",
+    "react-eva": "^1.1.7",
     "remark-parse": "^6.0.3",
     "remark-stringify": "^6.0.4",
     "scheduler": "^0.15.0",
@@ -118,11 +123,11 @@
     }
   },
   "lint-staged": {
-    "packages/**": [
+    "packages/*/src/**.@(ts|tsx|js)": [
       "npm run lint",
       "git add"
     ],
-    "scripts/**": [
+    "scripts/**.@(ts|tsx|js)": [
       "npm run lint",
       "git add"
     ]

+ 18 - 6
packages/.eslintrc

@@ -11,7 +11,12 @@
     "jest": true,
     "commonjs": true
   },
-  "plugins": ["@typescript-eslint", "react", "react-hooks", "prettier"],
+  "plugins": [
+    "@typescript-eslint",
+    "react",
+    "react-hooks",
+    "prettier"
+  ],
   "parserOptions": {
     "project": "./tsconfig.json",
     "sourceType": "module",
@@ -25,10 +30,8 @@
       "version": "detect",
     }
   },
-
   "rules": {
     "prettier/prettier": 2,
-
     // don't force es6 functions to include space before paren
     "space-before-function-paren": 0,
     "react/prop-types": 0,
@@ -40,13 +43,22 @@
     "react/no-did-update-set-state": 0,
     // maybe we should no-public
     "@typescript-eslint/explicit-member-accessibility": 0,
-
     "@typescript-eslint/interface-name-prefix": 0,
     "@typescript-eslint/no-explicit-any": 0,
     "@typescript-eslint/explicit-function-return-type": 0,
     "@typescript-eslint/no-parameter-properties": 0,
     "@typescript-eslint/array-type": 0,
     "@typescript-eslint/no-object-literal-type-assertion": 0,
-    "no-console": ["error", { "allow": ["warn", "error", "info"] }]
+    "@typescript-eslint/no-use-before-define": 0,
+    "no-console": [
+      "error",
+      {
+        "allow": [
+          "warn",
+          "error",
+          "info"
+        ]
+      }
+    ]
   }
-}
+}

+ 6 - 6
packages/antd/build.ts

@@ -1,19 +1,19 @@
 import { compile, getCompileConfig } from '../../scripts/build'
 import ts from 'typescript'
-import tsImportPluginFactory from 'ts-import-plugin'
+//import tsImportPluginFactory from 'ts-import-plugin'
 import glob from 'glob'
 
-const transformer = tsImportPluginFactory({
-  libraryName: 'antd',
-  //style: 'css',
-})
+// const transformer = tsImportPluginFactory({
+//   libraryName: 'antd',
+//   style: 'css',
+// })
 
 function buildESM() {
   const { fileNames, options } = getCompileConfig(require.resolve('./tsconfig.json'), {
     outDir: './esm',
     module: ts.ModuleKind.ESNext
   })
-  compile(fileNames, options, { before: [transformer] })
+  compile(fileNames, options)
   console.log('esm build successfully')
 }
 

+ 7 - 5
packages/antd/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@uform/antd",
-  "version": "0.4.3",
+  "version": "0.4.0",
   "license": "MIT",
   "main": "lib",
   "module": "esm",
@@ -26,12 +26,14 @@
     "@babel/runtime": "^7.4.4",
     "antd": "^3.14.1",
     "react": ">=16.8.0",
-    "react-dom": ">=16.8.0"
+    "react-dom": ">=16.8.0",
+    "@types/styled-components": "^4.1.19"
   },
   "dependencies": {
-    "@uform/react": "^0.4.3",
-    "@uform/types": "^0.4.3",
-    "@uform/utils": "^0.4.3",
+    "@uform/react-schema-renderer": "^0.4.0",
+    "@uform/react-shared-components":"^0.4.0",
+    "@uform/types": "^0.4.0",
+    "@uform/shared": "^0.4.0",
     "classnames": "^2.2.6",
     "moveto": "^1.7.4",
     "react-stikky": "^0.1.15",

+ 22 - 0
packages/antd/src/compat/Form.tsx

@@ -0,0 +1,22 @@
+import React from 'react'
+import { Form } from 'antd'
+import { FormProps } from 'antd/lib/form'
+import { IFormItemTopProps } from '../types'
+import { FormItemProvider } from './context'
+import { normalizeCol } from '../shared'
+
+export const CompatNextForm: React.FC<
+  FormProps & IFormItemTopProps
+> = props => {
+  return (
+    <FormItemProvider {...props}>
+      <Form
+        {...props}
+        labelCol={normalizeCol(props.labelCol)}
+        wrapperCol={normalizeCol(props.wrapperCol)}
+        layout={props.inline ? 'inline' : props.layout}
+        form={undefined}
+      />
+    </FormItemProvider>
+  )
+}

+ 99 - 0
packages/antd/src/compat/FormItem.tsx

@@ -0,0 +1,99 @@
+import React, { createContext, useContext } from 'react'
+import { Form } from 'antd'
+import { useFormItem } from './context'
+import { IFormItemTopProps, ICompatItemProps } from '../types'
+import { normalizeCol } from '../shared'
+
+const computeStatus = (props: ICompatItemProps) => {
+  if (props.loading) {
+    return 'validating'
+  }
+  if (props.invalid) {
+    return 'error'
+  }
+  if (props.warnings && props.warnings.length) {
+    return 'warning'
+  }
+  return ''
+}
+
+const computeHelp = (props: ICompatItemProps) => {
+  if (props.help) return props.help
+  const messages = [].concat(props.errors || [], props.warnings || [])
+  return messages.length ? messages : props.schema && props.schema.description
+}
+
+const computeLabel = (props: ICompatItemProps) => {
+  if (props.label) return props.label
+  if (props.schema && props.schema.title) {
+    return props.schema.title
+  }
+}
+
+const computeExtra = (props: ICompatItemProps) => {
+  if (props.extra) return props.extra
+}
+
+function pickProps<T = {}>(obj: T, ...keys: (keyof T)[]): Pick<T, keyof T> {
+  const result: Pick<T, keyof T> = {} as any
+  for (let i = 0; i < keys.length; i++) {
+    if (obj[keys[i]] !== undefined) {
+      result[keys[i]] = obj[keys[i]]
+    }
+  }
+  return result
+}
+
+const computeSchemaExtendProps = (
+  props: ICompatItemProps
+): IFormItemTopProps => {
+  if (props.schema) {
+    return pickProps(
+      {
+        ...props.schema.getExtendsItemProps(),
+        ...props.schema.getExtendsProps()
+      },
+      'prefix',
+      'labelAlign',
+      'labelTextAlign',
+      'size',
+      'labelCol',
+      'wrapperCol'
+    )
+  }
+}
+
+const FormItemPropsContext = createContext({})
+
+export const FormItemProps = ({ children, ...props }) => (
+  <FormItemPropsContext.Provider value={props}>
+    {children}
+  </FormItemPropsContext.Provider>
+)
+
+export const CompatNextFormItem: React.FC<ICompatItemProps> = props => {
+  const { prefixCls, labelAlign, labelCol, wrapperCol } = useFormItem()
+  const help = computeHelp(props)
+  const label = computeLabel(props)
+  const status = computeStatus(props)
+  const extra = computeExtra(props)
+  const itemProps = computeSchemaExtendProps(props)
+  const outerFormItemProps = useContext(FormItemPropsContext)
+  return (
+    <Form.Item
+      prefixCls={prefixCls}
+      label={label}
+      labelCol={label ? normalizeCol(labelCol) : undefined}
+      labelAlign={labelAlign}
+      required={props.required}
+      wrapperCol={label ? normalizeCol(wrapperCol) : undefined}
+      help={help}
+      validateStatus={status}
+      extra={extra ? <p>{extra}</p> : undefined}
+      {...itemProps}
+      {...outerFormItemProps}
+    >
+      <FormItemProps>{props.children}</FormItemProps>
+    </Form.Item>
+  )
+}

+ 35 - 0
packages/antd/src/compat/context.tsx

@@ -0,0 +1,35 @@
+import React, { createContext, useContext } from 'react'
+import { IFormItemTopProps } from '../types'
+
+const FormItemContext = createContext<IFormItemTopProps>({})
+
+export const FormItemProvider: React.FC<IFormItemTopProps> = ({
+  children,
+  prefix,
+  size,
+  labelAlign,
+  labelCol,
+  inline,
+  labelTextAlign,
+  wrapperCol
+}) => (
+  <FormItemContext.Provider
+    value={{
+      prefix,
+      labelAlign,
+      labelCol,
+      labelTextAlign,
+      wrapperCol,
+      size,
+      inline
+    }}
+  >
+    {children}
+  </FormItemContext.Provider>
+)
+
+FormItemProvider.displayName = 'FormItemProvider'
+
+export const useFormItem = () => {
+  return useContext(FormItemContext)
+}

+ 10 - 0
packages/antd/src/compat/index.ts

@@ -0,0 +1,10 @@
+import {
+  registerFormComponent,
+  registerFormItemComponent
+} from '@uform/react-schema-renderer'
+import { CompatNextForm } from './Form'
+import { CompatNextFormItem } from './FormItem'
+
+registerFormComponent(CompatNextForm)
+
+registerFormItemComponent(CompatNextFormItem)

+ 22 - 0
packages/antd/src/components/FormBlock.tsx

@@ -0,0 +1,22 @@
+import React from 'react'
+import { createVirtualBox } from '@uform/react-schema-renderer'
+import { Card } from 'antd'
+import { CardProps } from 'antd/lib/card'
+import styled from 'styled-components'
+
+export const FormBlock = createVirtualBox<CardProps>(
+  'block',
+  styled(({ children, className, ...props }) => {
+    return (
+      <Card className={className} size="small" {...props}>
+        {children}
+      </Card>
+    )
+  })`
+    margin-bottom: 10px !important;
+    &.ant-card {
+      border: none;
+      box-shadow: none;
+    }
+  `
+)

+ 18 - 0
packages/antd/src/components/FormCard.tsx

@@ -0,0 +1,18 @@
+import React from 'react'
+import { createVirtualBox } from '@uform/react-schema-renderer'
+import { Card } from 'antd'
+import { CardProps } from 'antd/lib/card'
+import styled from 'styled-components'
+
+export const FormCard = createVirtualBox<CardProps>(
+  'card',
+  styled(({ children, className, ...props }) => {
+    return (
+      <Card className={className} size="small" {...props}>
+        {children}
+      </Card>
+    )
+  })`
+    margin-bottom: 10px !important;
+  `
+)

+ 87 - 0
packages/antd/src/components/FormItemGrid.tsx

@@ -0,0 +1,87 @@
+import React, { Fragment } from 'react'
+import { CompatNextFormItem } from '../compat/FormItem'
+import { createVirtualBox } from '@uform/react-schema-renderer'
+import { toArr } from '@uform/shared'
+import { Row, Col } from 'antd'
+import { RowProps, ColProps } from 'antd/lib/grid'
+import { FormItemProps as ItemProps } from 'antd/lib/form'
+import { IFormItemGridProps, IItemProps } from '../types'
+import { normalizeCol } from '../shared'
+
+export const FormItemGrid = createVirtualBox<
+  React.PropsWithChildren<IFormItemGridProps & ItemProps>
+>('grid', props => {
+  const {
+    cols: rawCols,
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    title,
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    description,
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    help,
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    extra,
+    ...selfProps
+  } = props
+  const children = toArr(props.children)
+  const cols = toArr(rawCols).map(col => normalizeCol(col))
+  const childNum = children.length
+
+  if (cols.length < childNum) {
+    let offset: number = childNum - cols.length
+    let lastSpan: number =
+      24 -
+      cols.reduce((buf, col) => {
+        return (
+          buf +
+          Number(col.span ? col.span : 0) +
+          Number(col.offset ? col.offset : 0)
+        )
+      }, 0)
+    for (let i = 0; i < offset; i++) {
+      cols.push({ span: Math.floor(lastSpan / offset) })
+    }
+  }
+  const grids = (
+    <Row {...selfProps}>
+      {children.reduce((buf, child, key) => {
+        return child
+          ? buf.concat(
+              <Col key={key} {...cols[key]}>
+                {child}
+              </Col>
+            )
+          : buf
+      }, [])}
+    </Row>
+  )
+
+  if (title) {
+    return (
+      <CompatNextFormItem label={title} help={description} extra={extra}>
+        {grids}
+      </CompatNextFormItem>
+    )
+  }
+  return <Fragment>{grids}</Fragment>
+})
+
+export const FormGridRow = createVirtualBox<RowProps & ItemProps & IItemProps>(
+  'grid-row',
+  props => {
+    const { title, description, extra } = props
+    const grids = <Row {...props}>{props.children}</Row>
+    if (title) {
+      return (
+        <CompatNextFormItem label={title} help={description} extra={extra}>
+          {grids}
+        </CompatNextFormItem>
+      )
+    }
+    return grids
+  }
+)
+
+export const FormGridCol = createVirtualBox<ColProps>('grid-col', props => {
+  return <Col {...props}>{props.children}</Col>
+})

+ 27 - 0
packages/antd/src/components/FormLayout.tsx

@@ -0,0 +1,27 @@
+import React from 'react'
+import { FormItemProvider, useFormItem } from '../compat/context'
+import { createVirtualBox } from '@uform/react-schema-renderer'
+import cls from 'classnames'
+import { IFormItemTopProps } from '../types'
+
+export const FormLayout = createVirtualBox<IFormItemTopProps>(
+  'layout',
+  props => {
+    const { inline } = useFormItem()
+    const isInline = props.inline || inline
+    const children =
+      isInline || props.className || props.style ? (
+        <div
+          className={cls(props.className, {
+            'ant-form ant-form-inline': isInline
+          })}
+          style={props.style}
+        >
+          {props.children}
+        </div>
+      ) : (
+        props.children
+      )
+    return <FormItemProvider {...props}>{children}</FormItemProvider>
+  }
+)

+ 98 - 0
packages/antd/src/components/FormStep.tsx

@@ -0,0 +1,98 @@
+import React, { useState, useMemo, useRef } from 'react'
+import {
+  createControllerBox,
+  ISchemaVirtualFieldComponentProps,
+  FormPathPattern,
+  createEffectHook,
+  createFormActions
+} from '@uform/react-schema-renderer'
+import { toArr } from '@uform/shared'
+import { Observable } from 'rxjs/internal/Observable'
+import { Steps } from 'antd'
+import { IFormStep } from '../types'
+
+enum StateMap {
+  ON_FORM_STEP_NEXT = 'onFormStepNext',
+  ON_FORM_STEP_PREVIOUS = 'onFormStepPrevious',
+  ON_FORM_STEP_GO_TO = 'onFormStepGoto',
+  ON_FORM_STEP_CURRENT_CHANGE = 'onFormStepCurrentChange'
+}
+const EffectHooks = {
+  onStepNext$: createEffectHook<void>(StateMap.ON_FORM_STEP_NEXT),
+  onStepPrevious$: createEffectHook<void>(StateMap.ON_FORM_STEP_PREVIOUS),
+  onStepGoto$: createEffectHook<void>(StateMap.ON_FORM_STEP_GO_TO),
+  onStepCurrentChange$: createEffectHook<{
+    value: number
+    preValue: number
+  }>(StateMap.ON_FORM_STEP_CURRENT_CHANGE)
+}
+
+const effects = (relations: FormPathPattern[]) => {
+  const actions = createFormActions()
+  return EffectHooks.onStepCurrentChange$().subscribe(({ value }) => {
+    relations.forEach((pattern, index) => {
+      actions.setFieldState(pattern, (state: any) => {
+        state.display = index === value
+      })
+    })
+  })
+}
+
+type StepComponentExtendsProps = StateMap & {
+  getEffects: (
+    relations: FormPathPattern[]
+  ) => Observable<{
+    value: number
+    preValue: number
+  }>
+}
+
+export const FormStep: React.FC<IFormStep> &
+  StepComponentExtendsProps = createControllerBox<IFormStep>(
+  'step',
+  ({ props, form }: ISchemaVirtualFieldComponentProps) => {
+    const [current, setCurrent] = useState(0)
+    const ref = useRef(current)
+    const { dataSource, ...stepProps } = props['x-component-props'] || {}
+    const items = toArr(dataSource)
+    const update = (cur: number) => {
+      form.notify(StateMap.ON_FORM_STEP_CURRENT_CHANGE, {
+        value: cur,
+        preValue: current
+      })
+      setCurrent(cur)
+    }
+    useMemo(() => {
+      update(ref.current)
+      form.subscribe(({ type, payload }) => {
+        switch (type) {
+          case StateMap.ON_FORM_STEP_NEXT:
+            update(
+              ref.current + 1 > items.length - 1 ? ref.current : ref.current + 1
+            )
+            break
+          case StateMap.ON_FORM_STEP_PREVIOUS:
+            update(ref.current - 1 < 0 ? ref.current : ref.current - 1)
+            break
+          case StateMap.ON_FORM_STEP_GO_TO:
+            if (!(payload < 0 || payload > items.length)) {
+              update(payload)
+            }
+            break
+        }
+      })
+    }, [])
+    ref.current = current
+    return (
+      <Steps {...stepProps} current={current}>
+        {items.map((props, key) => {
+          return <Steps.Step {...props} key={key} />
+        })}
+      </Steps>
+    )
+  }
+) as any
+
+Object.assign(FormStep, StateMap, EffectHooks, {
+  effects
+})

+ 104 - 0
packages/antd/src/components/FormTextBox.tsx

@@ -0,0 +1,104 @@
+import React, { useRef, useEffect } from 'react'
+import { createControllerBox } from '@uform/react-schema-renderer'
+import { IFormTextBox } from '../types'
+import { toArr } from '@uform/shared'
+import { CompatNextFormItem } from '../compat/FormItem'
+import styled from 'styled-components'
+
+export const FormTextBox = createControllerBox<IFormTextBox>(
+  'text-box',
+  styled(({ props, className, children }) => {
+    const {
+      title,
+      help,
+      text,
+      name,
+      extra,
+      gutter,
+      style,
+      ...componentProps
+    } = Object.assign(
+      {
+        gutter: 5
+      },
+      props['x-component-props']
+    )
+    const ref: React.RefObject<HTMLDivElement> = useRef()
+    const arrChildren = toArr(children)
+    const split = text.split('%s')
+    let index = 0
+    useEffect(() => {
+      if (ref.current) {
+        const eles = ref.current.querySelectorAll('.text-box-field')
+        eles.forEach((el: HTMLElement) => {
+          const ctrl = el.querySelector('.next-form-item-control:first-child')
+          if (ctrl) {
+            el.style.width = getComputedStyle(ctrl).width
+          }
+        })
+      }
+    }, [])
+    const newChildren = split.reduce((buf, item, key) => {
+      return buf.concat(
+        item ? (
+          <p
+            key={index++}
+            className="text-box-words"
+            style={{
+              marginRight: gutter / 2,
+              marginLeft: gutter / 2,
+              ...style
+            }}
+          >
+            {item}
+          </p>
+        ) : null,
+        arrChildren[key] ? (
+          <div key={index++} className="text-box-field">
+            {arrChildren[key]}
+          </div>
+        ) : null
+      )
+    }, [])
+
+    const textChildren = (
+      <div
+        className={className}
+        style={{
+          marginRight: -gutter / 2,
+          marginLeft: -gutter / 2
+        }}
+        ref={ref}
+      >
+        {newChildren}
+      </div>
+    )
+
+    if (!title) return textChildren
+
+    return (
+      <CompatNextFormItem
+        {...componentProps}
+        label={title}
+        help={help}
+        extra={extra}
+      >
+        {textChildren}
+      </CompatNextFormItem>
+    )
+  })`
+    display: flex;
+    .text-box-words:nth-child(1) {
+      margin-left: 0;
+    }
+    .text-box-field {
+      display: inline-block;
+    }
+    .next-form-item {
+      margin-bottom: 0 !important;
+    }
+    .preview-text {
+      text-align: center !important;
+    }
+  `
+)

+ 39 - 0
packages/antd/src/components/Select.tsx

@@ -0,0 +1,39 @@
+import React from 'react'
+import { Select as AntSelect } from 'antd'
+import { SelectProps as AntSelectProps } from 'antd/lib/select'
+import styled from 'styled-components'
+
+type SelectOption = {
+  label: React.ReactText
+  value: any
+  [key: string]: any
+}
+
+type SelectProps = AntSelectProps & {
+  dataSource?: SelectOption[]
+}
+
+export const Select: React.FC<SelectProps> = styled((props: SelectProps) => {
+  const { dataSource = [], ...others } = props
+  const children = dataSource.map((item, index) => {
+    const { label, value, ...others } = item
+    return (
+      <AntSelect.Option
+        key={value}
+        {...others}
+        title={label as string}
+        value={value}
+      >
+        {label}
+      </AntSelect.Option>
+    )
+  })
+  return (
+    <AntSelect className={props.className} {...others}>
+      {children}
+    </AntSelect>
+  )
+})`
+  min-width: 100px;
+  width: 100%;
+`

+ 65 - 16
packages/antd/src/components/button.tsx

@@ -1,38 +1,87 @@
 import React from 'react'
-import { FormConsumer } from '@uform/react'
+import { FormSpy, LifeCycleTypes } from '@uform/react-schema-renderer'
 import { Button } from 'antd'
-import { ISubmitProps } from '../type'
+import { ButtonProps } from 'antd/lib/button'
+import { ISubmitProps, IResetProps } from '../types'
 
-export const Submit = ({ showLoading, ...props }: ISubmitProps) => {
+export const TextButton: React.FC<ButtonProps> = props => (
+  <Button type="link" {...props} />
+)
+
+export const CircleButton: React.FC<ButtonProps> = props => {
+  const hasText = String(props.className || '').indexOf('has-text') > -1
+  return (
+    <Button
+      type={hasText ? 'link' : undefined}
+      shape={hasText ? undefined : 'circle'}
+      {...props}
+    />
+  )
+}
+
+export const Submit = ({ showLoading, onSubmit, ...props }: ISubmitProps) => {
   return (
-    <FormConsumer selector={['submitting', 'submitted']}>
-      {({ status }) => {
+    <FormSpy
+      selector={[
+        LifeCycleTypes.ON_FORM_SUBMIT_START,
+        LifeCycleTypes.ON_FORM_SUBMIT_END
+      ]}
+      reducer={(state, action) => {
+        switch (action.type) {
+          case LifeCycleTypes.ON_FORM_SUBMIT_START:
+            return {
+              ...state,
+              submitting: true
+            }
+          case LifeCycleTypes.ON_FORM_SUBMIT_END:
+            return {
+              ...state,
+              submitting: false
+            }
+          default:
+            return state
+        }
+      }}
+    >
+      {({ state, form }) => {
         return (
           <Button
-            type={'primary'}
-            htmlType={'submit'}
-            disabled={showLoading ? status === 'submitting' : undefined}
+            type="primary"
+            onClick={() => form.submit(onSubmit)}
+            disabled={showLoading ? state.submitting : undefined}
             {...props}
-            loading={showLoading ? status === 'submitting' : undefined}
+            loading={showLoading ? state.submitting : undefined}
           >
             {props.children || '提交'}
           </Button>
         )
       }}
-    </FormConsumer>
+    </FormSpy>
   )
 }
 
-export const Reset: React.FC<Omit<ISubmitProps, 'showLoading'>> = props => {
+Submit.defaultProps = {
+  showLoading: true
+}
+
+export const Reset: React.FC<IResetProps> = ({
+  children,
+  forceClear,
+  validate,
+  ...props
+}) => {
   return (
-    <FormConsumer>
-      {({ reset }) => {
+    <FormSpy selector={[]}>
+      {({ form }) => {
         return (
-          <Button {...props} onClick={reset}>
-            {props.children || '重置'}
+          <Button
+            {...props}
+            onClick={() => form.reset({ forceClear, validate })}
+          >
+            {children || '重置'}
           </Button>
         )
       }}
-    </FormConsumer>
+    </FormSpy>
   )
 }

+ 72 - 92
packages/antd/src/components/formButtonGroup.tsx

@@ -1,24 +1,10 @@
-import React, { Component } from 'react'
-import ReactDOM from 'react-dom'
-import { Row, Col } from './grid'
-import { FormLayoutConsumer } from '../form'
-import { IFormButtonGroupProps } from '../type'
+import React, { useRef } from 'react'
+import { Row, Col } from 'antd'
 import Sticky from 'react-stikky'
 import cls from 'classnames'
 import styled from 'styled-components'
-
-const getAlign = align => {
-  if (align === 'start' || align === 'end') {
-    return align
-  }
-  if (align === 'left' || align === 'top') {
-    return 'flex-start'
-  }
-  if (align === 'right' || align === 'bottom') {
-    return 'flex-end'
-  }
-  return align
-}
+import { useFormItem } from '../compat/context'
+import { IFormButtonGroupProps } from '../types'
 
 export interface IOffset {
   top: number | string
@@ -27,6 +13,13 @@ export interface IOffset {
   left: number | string
 }
 
+const getAlign = align => {
+  if (align === 'start' || align === 'end') return align
+  if (align === 'left' || align === 'top') return 'flex-start'
+  if (align === 'right' || align === 'bottom') return 'flex-end'
+  return align
+}
+
 const isElementInViewport = (
   rect: ClientRect,
   {
@@ -36,7 +29,7 @@ const isElementInViewport = (
     offset?: IOffset | number
     threshold?: number
   } = {}
-) => {
+): boolean => {
   const { top, right, bottom, left, width, height } = rect
   const intersection = {
     t: bottom,
@@ -62,74 +55,28 @@ const isElementInViewport = (
   )
 }
 
-export const FormButtonGroup: React.FC<IFormButtonGroupProps> = styled(
-  class FormButtonGroup extends Component<IFormButtonGroupProps> {
-    public static defaultProps = {
-      span: 24
-    }
-
-    private formNode: HTMLElement
-
-    public render() {
-      const { sticky, style, className } = this.props
-
-      const content = (
-        <FormLayoutConsumer>
-          {({ inline } = {}) => (
-            <div
-              className={cls(className, {
-                'is-inline': !!inline
-              })}
-              style={style}
-            >
-              {this.renderChildren()}
-            </div>
-          )}
-        </FormLayoutConsumer>
-      )
-
-      if (sticky) {
-        return (
-          <div>
-            <FormLayoutConsumer>
-              {({ FormRef } = {}) => {
-                if (!FormRef) {
-                  return
-                }
-                return (
-                  <Sticky
-                    edge={'bottom'}
-                    triggerDistance={this.props.triggerDistance}
-                    zIndex={this.props.zIndex}
-                    getStickyBoundary={this.getStickyBoundaryHandler(FormRef)}
-                    style={{
-                      borderTop: '1px solid #eee',
-                      background: (style && style.background) || '#fff',
-                      padding: (style && style.padding) || '8px 0'
-                    }}
-                  >
-                    <div className={className} style={style}>
-                      {content}
-                    </div>
-                  </Sticky>
-                )
-              }}
-            </FormLayoutConsumer>
-          </div>
-        )
-      }
-
-      return content
-    }
-
-    private renderChildren() {
-      const { children, itemStyle, offset, span } = this.props
+export const FormButtonGroup = styled(
+  (props: React.PropsWithChildren<IFormButtonGroupProps>) => {
+    const {
+      span,
+      zIndex,
+      sticky,
+      style,
+      offset,
+      className,
+      children,
+      triggerDistance,
+      itemStyle
+    } = props
+    const { inline } = useFormItem()
+    const selfRef = useRef<HTMLDivElement>()
+    const renderChildren = () => {
       return (
-        <div className={'button-group'}>
+        <div className="button-group">
           <Row>
             <Col span={span}>
-              <Col offset={offset} className={'inline'}>
-                <div className={'inline-view'} style={itemStyle}>
+              <Col offset={offset} className="inline">
+                <div className="inline-view" style={itemStyle}>
                   {children}
                 </div>
               </Col>
@@ -138,20 +85,53 @@ export const FormButtonGroup: React.FC<IFormButtonGroupProps> = styled(
         </div>
       )
     }
-
-    private getStickyBoundaryHandler(ref) {
+    const getStickyBoundaryHandler = () => {
       return () => {
-        // eslint-disable-next-line react/no-find-dom-node
-        this.formNode = this.formNode || ReactDOM.findDOMNode(ref.current)
-        if (this.formNode) {
-          return isElementInViewport(this.formNode.getBoundingClientRect())
+        if (selfRef.current && selfRef.current.parentElement) {
+          const container = selfRef.current.parentElement
+          return isElementInViewport(container.getBoundingClientRect())
         }
         return true
       }
     }
+
+    const content = (
+      <div
+        className={cls(className, {
+          'is-inline': !!inline
+        })}
+        style={style}
+      >
+        {renderChildren()}
+      </div>
+    )
+
+    if (sticky) {
+      return (
+        <div ref={selfRef}>
+          <Sticky
+            edge="bottom"
+            triggerDistance={triggerDistance}
+            zIndex={zIndex}
+            getStickyBoundary={getStickyBoundaryHandler()}
+            style={{
+              borderTop: '1px solid #eee',
+              background: (style && style.background) || '#fff',
+              padding: (style && style.padding) || '8px 0'
+            }}
+          >
+            <div className={className} style={style}>
+              {content}
+            </div>
+          </Sticky>
+        </div>
+      )
+    }
+
+    return content
   }
-)`
-  ${props =>
+)<IFormButtonGroupProps>`
+  ${(props: IFormButtonGroupProps) =>
     props.align ? `display:flex;justify-content: ${getAlign(props.align)}` : ''}
   &.is-inline {
     display: inline-block;

+ 0 - 175
packages/antd/src/components/grid.tsx

@@ -1,175 +0,0 @@
-import React, { Component, Children, cloneElement } from 'react'
-import cx from 'classnames'
-import { toArr } from '@uform/utils'
-import { IColProps, IRowProps } from '../type'
-
-export class Row extends Component<IRowProps> {
-  public static defaultProps = {
-    prefix: 'ant-',
-    pure: false,
-    fixed: false,
-    gutter: 0,
-    wrap: false,
-    component: 'div'
-  }
-
-  public render() {
-    /* eslint-disable @typescript-eslint/no-unused-vars */
-    const {
-      prefix,
-      pure,
-      wrap,
-      fixed,
-      gutter,
-      fixedWidth,
-      align,
-      justify,
-      hidden,
-      className,
-      component: Tag,
-      children,
-      ...others
-    } = this.props
-    /* eslint-enable @typescript-eslint/no-unused-vars */
-
-    let hiddenClassObj
-    if (hidden === true) {
-      hiddenClassObj = { [`${prefix}row-hidden`]: true }
-    } else if (typeof hidden === 'string') {
-      hiddenClassObj = { [`${prefix}row-${hidden}-hidden`]: !!hidden }
-    } else if (Array.isArray(hidden)) {
-      hiddenClassObj = hidden.reduce((ret, point) => {
-        ret[`${prefix}row-${point}-hidden`] = !!point
-        return ret
-      }, {})
-    }
-
-    const newClassName = cx({
-      [`${prefix}row`]: true,
-      [`${prefix}row-wrap`]: wrap,
-      [`${prefix}row-fixed`]: fixed,
-      [`${prefix}row-fixed-${fixedWidth}`]: !!fixedWidth,
-      [`${prefix}row-justify-${justify}`]: !!justify,
-      [`${prefix}row-align-${align}`]: !!align,
-      ...hiddenClassObj,
-      [className]: !!className
-    })
-
-    let newChildren = toArr(children)
-    const gutterNumber = parseInt(gutter, 10)
-
-    if (gutterNumber !== 0) {
-      const halfGutterString = `${gutterNumber / 2}px`
-      others.style = {
-        marginLeft: `-${halfGutterString}`,
-        marginRight: `-${halfGutterString}`,
-        ...(others.style || {})
-      }
-      newChildren = Children.map(children, (child: React.ReactElement) => {
-        if (
-          child &&
-          child.type &&
-          typeof child.type === 'function' &&
-          (child.type as any).isNextCol
-        ) {
-          const newChild = cloneElement(child, {
-            style: {
-              paddingLeft: halfGutterString,
-              paddingRight: halfGutterString,
-              ...(child.props.style || {})
-            }
-          })
-          return newChild
-        }
-
-        return child
-      })
-    }
-
-    return (
-      <Tag role={'row'} className={newClassName} {...others}>
-        {newChildren}
-      </Tag>
-    )
-  }
-}
-
-const breakPoints = ['xxs', 'xs', 's', 'm', 'l', 'xl']
-
-export class Col extends Component<IColProps> {
-  public static isNextCol = true
-
-  public static defaultProps = {
-    prefix: 'ant-',
-    pure: false,
-    component: 'div'
-  }
-
-  public render() {
-    const {
-      prefix,
-      pure,
-      span,
-      offset,
-      fixedSpan,
-      fixedOffset,
-      hidden,
-      align,
-      xxs,
-      xs,
-      s,
-      m,
-      l,
-      xl,
-      component: Tag,
-      className,
-      children,
-      ...others
-    } = this.props
-
-    const pointClassObj = breakPoints.reduce((ret, point) => {
-      let pointProps: { span?: string; offset?: string } = {}
-      if (typeof this.props[point] === 'object') {
-        pointProps = this.props[point]
-      } else {
-        pointProps.span = this.props[point]
-      }
-
-      ret[`${prefix}col-${point}-${pointProps.span}`] = !!pointProps.span
-      ret[
-        `${prefix}col-${point}-offset-${pointProps.offset}`
-      ] = !!pointProps.offset
-      return ret
-    }, {})
-
-    let hiddenClassObj
-    if (hidden === true) {
-      hiddenClassObj = { [`${prefix}col-hidden`]: true }
-    } else if (typeof hidden === 'string') {
-      hiddenClassObj = { [`${prefix}col-${hidden}-hidden`]: !!hidden }
-    } else if (Array.isArray(hidden)) {
-      hiddenClassObj = hidden.reduce((ret, point) => {
-        ret[`${prefix}col-${point}-hidden`] = !!point
-        return ret
-      }, {})
-    }
-
-    const classes = cx({
-      [`${prefix}col`]: true,
-      [`${prefix}col-${span}`]: !!span,
-      [`${prefix}col-fixed-${fixedSpan}`]: !!fixedSpan,
-      [`${prefix}col-offset-${offset}`]: !!offset,
-      [`${prefix}col-offset-fixed-${fixedOffset}`]: !!fixedOffset,
-      [`${prefix}col-${align}`]: !!align,
-      ...pointClassObj,
-      ...hiddenClassObj,
-      [className]: className
-    })
-
-    return (
-      <Tag role={'gridcell'} className={classes} {...others}>
-        {children}
-      </Tag>
-    )
-  }
-}

+ 8 - 0
packages/antd/src/components/index.ts

@@ -0,0 +1,8 @@
+export * from './Button'
+export * from './FormButtonGroup'
+export * from './FormLayout'
+export * from './FormItemGrid'
+export * from './FormCard'
+export * from './FormBlock'
+export * from './FormTextBox'
+export * from './FormStep'

+ 0 - 326
packages/antd/src/components/layout.tsx

@@ -1,326 +0,0 @@
-import React, { Component, useEffect, useRef } from 'react'
-import { createVirtualBox, createControllerBox } from '@uform/react'
-import { toArr } from '@uform/utils'
-import { IFormItemGridProps, IFormItemProps } from '@uform/types'
-import { Card, Row, Col } from 'antd'
-import styled from 'styled-components'
-import cls from 'classnames'
-
-import { FormLayoutConsumer, FormItem, FormLayoutProvider } from '../form'
-import {
-  IFormTextBox,
-  IFormCardProps,
-  IFormBlockProps,
-  IFormLayoutProps,
-  TFormCardOrFormBlockProps,
-  IFormItemGridProps as IFormItemGridPropsAlias
-} from '../type'
-
-const normalizeCol = (
-  col: { span: number; offset?: number } | number,
-  defaultValue: { span: number } = { span: 0 }
-): { span: number; offset?: number } => {
-  if (!col) {
-    return defaultValue
-  } else {
-    return typeof col === 'object' ? col : { span: col }
-  }
-}
-
-export const FormLayoutItem: React.FC<IFormItemProps> = function(props) {
-  return React.createElement(
-    FormLayoutConsumer,
-    {},
-    ({
-      labelAlign,
-      labelTextAlign,
-      labelCol,
-      wrapperCol,
-      size,
-      autoAddColon
-    }) => {
-      return React.createElement(
-        FormItem,
-        {
-          labelAlign,
-          labelTextAlign,
-          labelCol,
-          wrapperCol,
-          autoAddColon,
-          size,
-          ...props
-        },
-        props.children
-      )
-    }
-  )
-}
-
-export const FormLayout = createVirtualBox<IFormLayoutProps>(
-  'layout',
-  ({ children, ...props }) => {
-    return (
-      <FormLayoutConsumer>
-        {value => {
-          const newValue = { ...value, ...props }
-          const child =
-            newValue.inline || newValue.className || newValue.style ? (
-              <div
-                className={cls(newValue.className, {
-                  'ant-form ant-form-inline': !!newValue.inline
-                })}
-                style={newValue.style}
-              >
-                {children}
-              </div>
-            ) : (
-              children
-            )
-          return (
-            <FormLayoutProvider value={newValue}>{child}</FormLayoutProvider>
-          )
-        }}
-      </FormLayoutConsumer>
-    )
-  }
-)
-
-export const FormItemGrid = createVirtualBox<IFormItemGridPropsAlias>(
-  'grid',
-  class extends Component<IFormItemGridProps> {
-    public render() {
-      const { title } = this.props
-      if (title) {
-        return this.renderFormItem(this.renderGrid())
-      } else {
-        return this.renderGrid()
-      }
-    }
-
-    private renderFormItem(children) {
-      const { title, help, name, extra, ...props } = this.props
-      return React.createElement(
-        FormLayoutItem,
-        {
-          label: title,
-          noMinHeight: true,
-          id: name,
-          extra,
-          help,
-          ...props
-        } as IFormItemGridProps,
-        children
-      )
-    }
-
-    private renderGrid() {
-      const {
-        children: rawChildren,
-        cols: rawCols,
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
-        title,
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
-        description,
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
-        help,
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
-        extra,
-        ...props
-      } = this.props
-
-      const children = toArr(rawChildren)
-      const childNum = children.length
-      const cols = toArr(rawCols).map(col => normalizeCol(col))
-
-      if (cols.length < childNum) {
-        const offset: number = childNum - cols.length
-        const lastSpan: number =
-          24 -
-          cols.reduce((buf, col) => {
-            return (
-              buf +
-              Number(col.span ? col.span : 0) +
-              Number(col.offset ? col.offset : 0)
-            )
-          }, 0)
-
-        for (let i = 0; i < offset; i++) {
-          cols.push({ span: Math.floor(lastSpan / offset) })
-        }
-      }
-
-      // cols = toArr(cols).map(col => normalizeCol(col))
-
-      return (
-        <Row {...props}>
-          {children.reduce((buf, child, key) => {
-            return child
-              ? buf.concat(
-                  <Col key={key} {...cols[key]}>
-                    {child}
-                  </Col>
-                )
-              : buf
-          }, [])}
-        </Row>
-      )
-    }
-  }
-)
-
-export const FormCard = createVirtualBox<TFormCardOrFormBlockProps>(
-  'card',
-  styled(
-    class extends Component<IFormCardProps> {
-      public static defaultProps = {
-        // bodyHeight: 'auto'
-      }
-      public render() {
-        const { children, className, ...props } = this.props
-        return (
-          <Card className={className} {...props}>
-            {children}
-          </Card>
-        )
-      }
-    }
-  )`
-    margin-bottom: 30px;
-    .ant-card-body {
-      padding-top: 30px;
-      padding-bottom: 0 !important;
-    }
-    &.ant-card {
-      display: block;
-      margin-bottom: 30px;
-    }
-  `
-)
-
-export const FormBlock = createVirtualBox<TFormCardOrFormBlockProps>(
-  'block',
-  styled(
-    class extends Component<IFormBlockProps> {
-      public static defaultProps = {
-        // bodyHeight: 'auto'
-      }
-
-      public render() {
-        const { children, className, ...props } = this.props
-        return (
-          <Card className={className} {...props}>
-            {children}
-          </Card>
-        )
-      }
-    }
-  )`
-    margin-bottom: 0px;
-    .ant-card-body {
-      padding-top: 20px;
-      padding-bottom: 0 !important;
-    }
-    &.ant-card {
-      border: none;
-      padding: 0 15px;
-      padding-bottom: 15px;
-      display: block;
-      box-shadow: none;
-    }
-    .ant-card-head {
-      padding: 0 !important;
-      min-height: 24px;
-      font-weight: normal;
-    }
-    .ant-card-head-title {
-      padding: 0;
-    }
-  `
-)
-
-export const FormTextBox = createControllerBox<IFormTextBox>(
-  'text-box',
-  styled(({ children, schema, className }) => {
-    const { title, help, text, name, extra, ...props } = schema['x-props']
-    const ref: React.RefObject<HTMLDivElement> = useRef()
-    const arrChildren = toArr(children)
-    const split = String(text).split('%s')
-    useEffect(() => {
-      if (ref.current) {
-        const eles = ref.current.querySelectorAll('.text-box-field')
-        eles.forEach((el: HTMLElement) => {
-          const ctrl = el.querySelector(
-            '.ant-form-item-control>*:not(.ant-form-item-space)'
-          )
-          if (ctrl) {
-            el.style.width = getComputedStyle(ctrl).width
-          }
-        })
-      }
-    }, [])
-
-    let index = 0
-    const newChildren = split.reduce((buf, item, key) => {
-      return buf.concat(
-        item ? (
-          <span key={index++} className="text-box-words">
-            {item}
-          </span>
-        ) : null,
-        arrChildren[key] ? (
-          <div key={index++} className="text-box-field">
-            {arrChildren[key]}
-          </div>
-        ) : null
-      )
-    }, [])
-
-    if (!title) {
-      return (
-        <div className={className} ref={ref}>
-          {newChildren}
-        </div>
-      )
-    }
-
-    return React.createElement(
-      FormLayoutItem,
-      {
-        label: title,
-        noMinHeight: true,
-        id: name,
-        extra,
-        help,
-        ...props
-      },
-      <div className={className} ref={ref}>
-        {newChildren}
-      </div>
-    )
-  })`
-    display: flex;
-    .text-box-words {
-      font-size: 14px;
-      line-height: 34px;
-      color: #333;
-      ${props => {
-        const { editable, schema } = props
-        const { gutter } = schema['x-props']
-        if (!editable) {
-          return {
-            margin: 0
-          }
-        }
-        return {
-          margin: `0 ${gutter === 0 || gutter ? gutter : 10}px`
-        }
-      }}
-    }
-    .text-box-words:nth-child(1) {
-      margin-left: 0;
-    }
-    .text-box-field {
-      display: inline-block;
-    }
-  `
-)

+ 0 - 177
packages/antd/src/fields/array.tsx

@@ -1,177 +0,0 @@
-import React from 'react'
-import { registerFormField, createArrayField } from '@uform/react'
-import { Icon } from 'antd'
-import styled, { css } from 'styled-components'
-
-export const CircleButton = styled['div'].attrs({ className: 'cricle-btn' })`
-  ${props => (!props.hasText ? 'width:30px; height:30px;' : '')}
-  margin-right:10px;
-  border-radius: ${props => (!props.hasText ? '100px' : 'none')};
-  border: ${props => (!props.hasText ? '1px solid #eee' : 'none')};
-  margin-bottom: 20px;
-  cursor: pointer;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  ${props =>
-    !props.hasText
-      ? `&:hover{
-        background:#f7f4f4;
-      }`
-      : ''}
-  .op-name {
-    margin-left: 3px;
-  }
-`
-
-export const TextButton = styled['div'].attrs({
-  className: 'ant-btn-text'
-})`
-  display: inline-block;
-  height: 20px;
-  line-height: 20px;
-  cursor: pointer;
-  .op-name {
-    margin-left: 4px;
-  }
-  ${props =>
-    props.inline &&
-    css`
-      display: inline-block;
-      width: auto;
-    `}
-`
-
-export const ArrayField = createArrayField({
-  CircleButton,
-  TextButton,
-  AddIcon: () => <Icon type="plus" />,
-  RemoveIcon: () => <Icon type="delete" />,
-  MoveDownIcon: () => <Icon type="down" />,
-  MoveUpIcon: () => <Icon type="up" />
-})
-
-registerFormField(
-  'array',
-  styled(
-    class extends ArrayField {
-      public render() {
-        const { className, name, value, renderField } = this.props
-        const cls = this.getProps('className')
-        const style = this.getProps('style')
-        return (
-          <div
-            className={`${className} ${cls}`}
-            style={style}
-            onClick={this.onClearErrorHandler()}
-          >
-            {value.map((item, index) => {
-              return (
-                <div className="array-item" key={`${name}.${index}`}>
-                  <div className="array-index">
-                    <span>{index + 1}</span>
-                  </div>
-                  <div className="array-item-wrapper">{renderField(index)}</div>
-                  <div className="array-item-operator">
-                    {this.renderRemove(index, item)}
-                    {this.renderMoveDown(index, item)}
-                    {this.renderMoveUp(index)}
-                    {this.renderExtraOperations(index)}
-                  </div>
-                </div>
-              )
-            })}
-            {this.renderEmpty()}
-            {value.length > 0 && this.renderAddition()}
-          </div>
-        )
-      }
-    }
-  )`
-    border: 1px solid #eee;
-    min-width: 400px;
-    .array-item {
-      padding: 20px;
-      padding-bottom: 0;
-      padding-top: 30px;
-      border-bottom: 1px solid #eee;
-      position: relative;
-      &:nth-child(even) {
-        background: #fafafa;
-      }
-      .array-index {
-        position: absolute;
-        top: 0;
-        left: 0;
-        display: block;
-        span {
-          position: absolute;
-          color: rgb(255, 255, 255);
-          z-index: 1;
-          font-size: 12px;
-          top: 3px;
-          left: 3px;
-          line-height: initial;
-        }
-        &::after {
-          content: '';
-          display: block;
-          border-top: 20px solid transparent;
-          border-left: 20px solid transparent;
-          border-bottom: 20px solid transparent;
-          border-right: 20px solid #888;
-          transform: rotate(45deg);
-          position: absolute;
-          z-index: 0;
-          top: -20px;
-          left: -20px;
-        }
-      }
-      .array-item-operator {
-        display: flex;
-        border-top: 1px solid #eee;
-        padding-top: 20px;
-      }
-    }
-    .array-empty-wrapper {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      cursor: pointer;
-      &.disabled {
-        cursor: default;
-      }
-      .array-empty {
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-        align-items: center;
-        margin: 20px;
-        img {
-          display: block;
-          height: 80px;
-        }
-        .ant-btn-text {
-          color: #999;
-          i {
-            margin-right: 3px;
-          }
-        }
-      }
-    }
-    .array-item-wrapper {
-      margin: 0 -20px;
-    }
-    .array-item-addition {
-      padding: 10px 20px;
-      line-height: normal !important;
-      background: #fbfbfb;
-      .ant-btn-text {
-        color: #888;
-        i {
-          margin-right: 3px;
-        }
-      }
-    }
-  `
-)

+ 2 - 2
packages/antd/src/fields/boolean.tsx

@@ -1,6 +1,6 @@
 import { Switch } from 'antd'
-import { connect, registerFormField } from '@uform/react'
-import { acceptEnum, mapStyledProps } from '../utils'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
+import { acceptEnum, mapStyledProps } from '../shared'
 
 registerFormField(
   'boolean',

+ 137 - 130
packages/antd/src/fields/cards.tsx

@@ -1,132 +1,132 @@
-import React, { Fragment, ReactElement } from 'react'
+import React, { Fragment } from 'react'
+import {
+  registerFormField,
+  ISchemaFieldComponentProps,
+  SchemaField
+} from '@uform/react-schema-renderer'
+import { toArr, isFn } from '@uform/shared'
+import { ArrayList } from '@uform/react-shared-components'
+import { CircleButton, TextButton } from '../components/Button'
+import { Card, Icon } from 'antd'
 import styled from 'styled-components'
-import { registerFormField } from '@uform/react'
-import { Card } from 'antd'
-import { toArr } from '@uform/utils'
-import { ArrayField } from './array'
 
-const FormCardsField = styled(
-  class extends ArrayField {
-    public renderOperations(item, index) {
-      return (
-        <Fragment>
-          {this.renderRemove(index, item)}
-          {this.renderMoveDown(index, item)}
-          {this.renderMoveUp(index)}
-          {this.renderExtraOperations(index)}
-        </Fragment>
-      )
-    }
+const ArrayComponents = {
+  CircleButton,
+  TextButton,
+  AdditionIcon: () => <Icon type="plus" />,
+  RemoveIcon: () => <Icon type="delete" />,
+  MoveDownIcon: () => <Icon type="down" />,
+  MoveUpIcon: () => <Icon type="up" />
+}
 
-    public renderCardEmpty = (title: string | ReactElement) => {
-      return (
-        <Card
-          style={this.getProps('style')}
-          title={title}
-          className="card-list"
-        >
-          {this.renderEmpty()}
-        </Card>
-      )
+const FormCardsField = styled(
+  (props: ISchemaFieldComponentProps & { className: string }) => {
+    const { value, schema, className, editable, path, mutators } = props
+    const {
+      renderAddition,
+      renderRemove,
+      renderMoveDown,
+      renderMoveUp,
+      renderEmpty,
+      renderExtraOperations,
+      ...componentProps
+    } = schema.getExtendsComponentProps() || {}
+    const onAdd = () => {
+      const items = Array.isArray(schema.items)
+        ? schema.items[schema.items.length - 1]
+        : schema.items
+      mutators.push(items.getEmptyValue())
     }
-
-    public render() {
-      const { value, className, schema, renderField } = this.props
-      const {
-        title,
-        style,
-        className: cls,
-        renderAddition,
-        renderRemove,
-        renderEmpty,
-        renderMoveDown,
-        renderMoveUp,
-        renderOperations,
-        ...others
-      } = this.getProps() || ({} as any)
-
-      return (
-        <div
-          className={`${className} ${cls}`}
-          style={style}
-          onClick={this.onClearErrorHandler()}
+    return (
+      <div className={className}>
+        <ArrayList
+          value={value}
+          minItems={schema.minItems}
+          maxItems={schema.maxItems}
+          editable={editable}
+          components={ArrayComponents}
+          renders={{
+            renderAddition,
+            renderRemove,
+            renderMoveDown,
+            renderMoveUp,
+            renderEmpty
+          }}
         >
           {toArr(value).map((item, index) => {
             return (
               <Card
-                {...others}
+                {...componentProps}
+                size="small"
+                className={`card-list-item`}
+                key={index}
                 title={
                   <span>
-                    {index + 1}. {title || schema.title}
+                    {index + 1}. {componentProps.title || schema.title}
                   </span>
                 }
-                className="card-list"
-                key={index}
-                extra={this.renderOperations(item, index)}
+                extra={
+                  <Fragment>
+                    <ArrayList.Remove
+                      index={index}
+                      onClick={() => mutators.remove(index)}
+                    />
+                    <ArrayList.MoveDown
+                      index={index}
+                      onClick={() => mutators.moveDown(index)}
+                    />
+                    <ArrayList.MoveUp
+                      index={index}
+                      onClick={() => mutators.moveUp(index)}
+                    />
+                    {isFn(renderExtraOperations)
+                      ? renderExtraOperations(index)
+                      : renderExtraOperations}
+                  </Fragment>
+                }
               >
-                {renderField(index)}
+                <SchemaField path={path.concat(index)} />
               </Card>
             )
           })}
-          {value.length === 0 && this.renderCardEmpty(title)}
-          <div className="addition-wrapper">
-            {value.length > 0 && this.renderAddition()}
-          </div>
-        </div>
-      )
-    }
-  }
-)`
-  .ant-card-body {
-    padding-top: 30px;
-    padding-bottom: 0 !important;
-  }
-  .ant-card-head-main {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
+          <ArrayList.Empty>
+            {({ children }) => {
+              return (
+                <Card
+                  {...componentProps}
+                  size="small"
+                  className={`card-list-item card-list-empty`}
+                  onClick={onAdd}
+                >
+                  <div className="empty-wrapper">{children}</div>
+                </Card>
+              )
+            }}
+          </ArrayList.Empty>
+          <ArrayList.Addition>
+            {({ children, isEmpty }) => {
+              if (!isEmpty) {
+                return (
+                  <div className="array-cards-addition" onClick={onAdd}>
+                    {children}
+                  </div>
+                )
+              }
+            }}
+          </ArrayList.Addition>
+        </ArrayList>
+      </div>
+    )
   }
+)<ISchemaFieldComponentProps>`
   .ant-card {
-    display: block;
-    margin-bottom: 0px;
-    background: #fff;
-    .array-empty-wrapper {
-      display: flex;
-      justify-content: center;
-      cursor: pointer;
-      margin-bottom: 0px;
-      &.disabled {
-        cursor: default;
-      }
-      .array-empty {
-        display: flex;
-        flex-direction: column;
-        margin-bottom: 20px;
-        align-items: center;
-        img {
-          margin-bottom: 16px;
-          height: 85px;
-        }
-        .next-btn-text {
-          color: #888;
-        }
-        .next-icon:before {
-          width: 16px !important;
-          font-size: 16px !important;
-          margin-right: 5px;
-        }
-      }
-    }
-
-    .next-card {
+    .ant-card {
       box-shadow: none;
     }
-    .card-list {
-      box-shadow: none;
-      border: 1px solid #eee;
+    .ant-card-body{
+      padding:20px 10px 0 10px;
     }
-
-    .array-item-addition {
+    .array-cards-addition {
       box-shadow: none;
       border: 1px solid #eee;
       transition: all 0.35s ease-in-out;
@@ -134,40 +134,47 @@ const FormCardsField = styled(
         border: 1px solid #ccc;
       }
     }
+    .empty-wrapper {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      margin-bottom:10px;
+      img {
+        height: 85px;
+      }
+      .ant-btn {
+        color: #888;
+      }
+    }
   }
-  .ant-card.card-list {
-    margin-top: 20px;
+  .card-list-empty.card-list-item {
+    cursor: pointer;
   }
 
-  .addition-wrapper .array-item-addition {
-    margin-top: 20px;
+  .array-cards-addition {
+    margin-top: 10px;
     margin-bottom: 3px;
-  }
-  .cricle-btn {
-    margin-bottom: 0;
-  }
-  .ant-card-extra {
-    display: flex;
-  }
-  .array-item-addition {
     background: #fff;
     display: flex;
     cursor: pointer;
-    padding: 10px 0;
+    padding: 5px 0;
     justify-content: center;
     box-shadow: 1px 1px 4px 0 rgba(0, 0, 0, 0.1);
-    .next-btn-text {
-      color: #888;
-    }
-    .next-icon:before {
-      width: 16px !important;
-      font-size: 16px !important;
-      margin-right: 5px;
-    }
   }
-  .card-list:first-child {
+  .card-list-item {
+    margin-top: 10px;
+    border: 1px solid #eee;
+  }
+  .card-list-item:first-child {
     margin-top: 0 !important;
   }
+  .ant-card-extra {
+    display: flex;
+    button {
+      margin-right: 8px;
+    }
+  }
 `
 
 registerFormField('cards', FormCardsField)
+registerFormField('array', FormCardsField)

+ 2 - 2
packages/antd/src/fields/checkbox.tsx

@@ -1,10 +1,10 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Checkbox } from 'antd'
 import {
   transformDataSourceKey,
   mapStyledProps,
   mapTextComponent
-} from '../utils'
+} from '../shared'
 
 const { Group: CheckboxGroup } = Checkbox
 

+ 22 - 32
packages/antd/src/fields/date.tsx

@@ -1,54 +1,44 @@
 import React from 'react'
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import moment from 'moment'
-import { DatePicker as AntDatePicker } from 'antd'
+import { DatePicker } from 'antd'
 import {
   mapStyledProps,
   mapTextComponent,
-  StateLoading,
   compose,
   isStr,
   isArr
-} from '../utils'
+} from '../shared'
 
-const {
-  RangePicker: AntRangePicker,
-  WeekPicker: AntWeekPicker,
-  MonthPicker: AntMonthPicker
-} = AntDatePicker
+const { RangePicker, WeekPicker, MonthPicker } = DatePicker
 
-class AntYearPicker extends React.Component {
+class YearPicker extends React.Component {
   public render() {
-    return <AntDatePicker {...this.props} mode={'year'} />
+    return <DatePicker {...this.props} mode={'year'} />
   }
 }
 
-const DatePicker = StateLoading(AntDatePicker)
-const RangePicker = StateLoading(AntRangePicker)
-const MonthPicker = StateLoading(AntMonthPicker)
-const WeekPicker = StateLoading(AntWeekPicker)
-const YearPicker = StateLoading(AntYearPicker)
-
 const transformMoment = (value, format = 'YYYY-MM-DD HH:mm:ss') => {
   return value && value.format ? value.format(format) : value
 }
 
-const mapMomentValue = (props, fieldProps) => {
-  const { value, showTime = false } = props
+const mapMomentValue = props => {
+  const { value, showTime = false, disabled = false } = props
   try {
-    if (!fieldProps.editable) return props
-    if (isStr(value) && value) {
-      props.value = moment(
-        value,
-        showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'
-      )
-    } else if (isArr(value) && value.length) {
-      props.value = value.map(
-        item =>
-          (item &&
-            moment(item, showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')) ||
-          ''
-      )
+    if (!disabled) {
+      if (isStr(value) && value) {
+        props.value = moment(
+          value,
+          showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'
+        )
+      } else if (isArr(value) && value.length) {
+        props.value = value.map(
+          item =>
+            (item &&
+              moment(item, showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')) ||
+            ''
+        )
+      }
     }
   } catch (e) {
     throw new Error(e)

+ 15 - 0
packages/antd/src/fields/index.ts

@@ -0,0 +1,15 @@
+import './string'
+import './number'
+import './boolean'
+import './date'
+import './time'
+import './range'
+import './upload'
+import './checkbox'
+import './radio'
+import './rating'
+import './transfer'
+import './cards'
+import './table'
+import './textarea'
+import './password'

+ 2 - 2
packages/antd/src/fields/number.tsx

@@ -1,6 +1,6 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { InputNumber } from 'antd'
-import { acceptEnum, mapStyledProps, mapTextComponent } from '../utils'
+import { acceptEnum, mapStyledProps, mapTextComponent } from '../shared'
 
 registerFormField(
   'number',

+ 42 - 201
packages/antd/src/fields/password.tsx

@@ -1,179 +1,53 @@
 import React, { useState } from 'react'
-import styled from 'styled-components'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Input } from 'antd'
-import { InputProps } from 'antd/es/input'
-import { connect, registerFormField } from '@uform/react'
-import { mapStyledProps } from '../utils'
+import { PasswordProps } from 'antd/lib/input'
+import { PasswordStrength } from '@uform/react-shared-components'
+import styled from 'styled-components'
+import { mapStyledProps } from '../shared'
 
-var isNum = function(c) {
-  return c >= 48 && c <= 57
-}
-var isLower = function(c) {
-  return c >= 97 && c <= 122
-}
-var isUpper = function(c) {
-  return c >= 65 && c <= 90
-}
-var isSymbol = function(c) {
-  return !(isLower(c) || isUpper(c) || isNum(c))
-}
-var isLetter = function(c) {
-  return isLower(c) || isUpper(c)
+export interface IPasswordProps extends PasswordProps {
+  checkStrength: boolean
 }
 
-const getStrength = val => {
-  if (!val) {
-    return 0
-  }
-  let num = 0
-  let lower = 0
-  let upper = 0
-  let symbol = 0
-  let MNS = 0
-  let rep = 0
-  let repC = 0
-  let consecutive = 0
-  let sequential = 0
-  const len = () => num + lower + upper + symbol
-  const require = () => {
-    var re = num > 0 ? 1 : 0
-    re += lower > 0 ? 1 : 0
-    re += upper > 0 ? 1 : 0
-    re += symbol > 0 ? 1 : 0
-    if (re > 2 && len() >= 8) {
-      return re + 1
-    } else {
-      return 0
-    }
-  }
-  for (var i = 0; i < val.length; i++) {
-    var c = val.charCodeAt(i)
-    if (isNum(c)) {
-      num++
-      if (i !== 0 && i !== val.length - 1) {
-        MNS++
-      }
-      if (i > 0 && isNum(val.charCodeAt(i - 1))) {
-        consecutive++
-      }
-    } else if (isLower(c)) {
-      lower++
-      if (i > 0 && isLower(val.charCodeAt(i - 1))) {
-        consecutive++
-      }
-    } else if (isUpper(c)) {
-      upper++
-      if (i > 0 && isUpper(val.charCodeAt(i - 1))) {
-        consecutive++
-      }
-    } else {
-      symbol++
-      if (i !== 0 && i !== val.length - 1) {
-        MNS++
-      }
-    }
-    var exists = false
-    for (var j = 0; j < val.length; j++) {
-      if (val[i] === val[j] && i !== j) {
-        exists = true
-        repC += Math.abs(val.length / (j - i))
-      }
-    }
-    if (exists) {
-      rep++
-      var unique = val.length - rep
-      repC = unique ? Math.ceil(repC / unique) : Math.ceil(repC)
-    }
-    if (i > 1) {
-      var last1 = val.charCodeAt(i - 1)
-      var last2 = val.charCodeAt(i - 2)
-      if (isLetter(c)) {
-        if (isLetter(last1) && isLetter(last2)) {
-          var v = val.toLowerCase()
-          var vi = v.charCodeAt(i)
-          var vi1 = v.charCodeAt(i - 1)
-          var vi2 = v.charCodeAt(i - 2)
-          if (vi - vi1 === vi1 - vi2 && Math.abs(vi - vi1) === 1) {
-            sequential++
-          }
-        }
-      } else if (isNum(c)) {
-        if (isNum(last1) && isNum(last2)) {
-          if (c - last1 === last1 - last2 && Math.abs(c - last1) === 1) {
-            sequential++
-          }
-        }
-      } else {
-        if (isSymbol(last1) && isSymbol(last2)) {
-          if (c - last1 === last1 - last2 && Math.abs(c - last1) === 1) {
-            sequential++
+const Password: React.FC<IPasswordProps> = styled((props: IPasswordProps) => {
+  const { className, checkStrength, onChange, ...others } = props
+  const [value, setValue] = useState(props.value || props.defaultValue)
+  return (
+    <div className={className}>
+      <Input.Password
+        {...others}
+        value={value}
+        onChange={event => {
+          setValue(event.target.value)
+          if (onChange) {
+            onChange(event)
           }
-        }
-      }
-    }
-  }
-  let sum = 0
-  let length = len()
-  sum += 4 * length
-  if (lower > 0) {
-    sum += 2 * (length - lower)
-  }
-  if (upper > 0) {
-    sum += 2 * (length - upper)
-  }
-  if (num !== length) {
-    sum += 4 * num
-  }
-  sum += 6 * symbol
-  sum += 2 * MNS
-  sum += 2 * require()
-  if (length === lower + upper) {
-    sum -= length
-  }
-  if (length === num) {
-    sum -= num
-  }
-  sum -= repC
-  sum -= 2 * consecutive
-  sum -= 3 * sequential
-  sum = sum < 0 ? 0 : sum
-  sum = sum > 100 ? 100 : sum
-
-  if (sum >= 80) {
-    return 100
-  } else if (sum >= 60) {
-    return 80
-  } else if (sum >= 40) {
-    return 60
-  } else if (sum >= 20) {
-    return 40
-  } else {
-    return 20
-  }
-}
-
-interface IStrengthProps {
-  strength: number
-  className?: string
-}
-
-// 校验强度 UI
-const StrengthFC = styled(({ strength, className }: IStrengthProps) => (
-  <div {...{ className }}>
-    <div className={'password-strength-wrapper'}>
-      <div className={'div-1 div'} />
-      <div className={'div-2 div'} />
-      <div className={'div-3 div'} />
-      <div className={'div-4 div'} />
-      <div
-        className={'password-strength-bar'}
-        style={{
-          clipPath: `polygon(0 0,${strength}% 0,${strength}% 100%,0 100%)`
         }}
       />
+      {checkStrength && (
+        <PasswordStrength value={String(value)}>
+          {score => {
+            return (
+              <div className="password-strength-wrapper">
+                <div className="div-1 div" />
+                <div className="div-2 div" />
+                <div className="div-3 div" />
+                <div className="div-4 div" />
+                <div
+                  className="password-strength-bar"
+                  style={{
+                    clipPath: `polygon(0 0,${score}% 0,${score}% 100%,0 100%)`
+                  }}
+                />
+              </div>
+            )
+          }}
+        </PasswordStrength>
+      )}
     </div>
-  </div>
-))`
+  )
+})`
   .password-strength-wrapper {
     background: #e0e0e0;
     margin-bottom: 3px;
@@ -210,42 +84,9 @@ const StrengthFC = styled(({ strength, className }: IStrengthProps) => (
   }
 `
 
-export interface IPasswordProps extends Omit<InputProps, 'onChange'> {
-  checkStrength: boolean // 是否启用密码强度校验
-  onChange: (value: InputProps['value']) => void
-}
-
-const PasswordFC = (props: Partial<IPasswordProps>) => {
-  const [strength, setStrength] = useState(0)
-
-  const { checkStrength, ...others } = props
-
-  const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
-    const value = e.target.value
-
-    // 开启才计算
-    checkStrength && setStrength(getStrength(value))
-
-    // 回调
-    props.onChange && props.onChange(value)
-  }
-
-  return (
-    <React.Fragment>
-      <Input.Password
-        {...others}
-        value={props.value || props.defaultValue}
-        onChange={onChangeHandler}
-      />
-
-      {checkStrength && <StrengthFC {...{ strength }} />}
-    </React.Fragment>
-  )
-}
-
 registerFormField(
   'password',
   connect({
     getProps: mapStyledProps
-  })(PasswordFC)
+  })(Password)
 )

+ 2 - 2
packages/antd/src/fields/radio.tsx

@@ -1,10 +1,10 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Radio } from 'antd'
 import {
   transformDataSourceKey,
   mapStyledProps,
   mapTextComponent
-} from '../utils'
+} from '../shared'
 
 const { Group: RadioGroup } = Radio
 

+ 2 - 2
packages/antd/src/fields/range.tsx

@@ -1,7 +1,7 @@
 import React from 'react'
 import { Slider } from 'antd'
-import { connect, registerFormField } from '@uform/react'
-import { mapStyledProps } from '../utils'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
+import { mapStyledProps } from '../shared'
 
 export interface ISliderMarks {
   [key: number]:

+ 2 - 2
packages/antd/src/fields/rating.tsx

@@ -1,6 +1,6 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Rate } from 'antd'
-import { mapStyledProps } from '../utils'
+import { mapStyledProps } from '../shared'
 
 registerFormField(
   'rating',

+ 2 - 2
packages/antd/src/fields/string.tsx

@@ -1,6 +1,6 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Input } from 'antd'
-import { acceptEnum, mapStyledProps, mapTextComponent } from '../utils'
+import { acceptEnum, mapStyledProps, mapTextComponent } from '../shared'
 
 registerFormField(
   'string',

+ 147 - 337
packages/antd/src/fields/table.tsx

@@ -1,355 +1,165 @@
-import React, { Component } from 'react'
+import React from 'react'
+import {
+  registerFormField,
+  ISchemaFieldComponentProps,
+  SchemaField,
+  Schema
+} from '@uform/react-schema-renderer'
+import { toArr, isFn, isArr } from '@uform/shared'
+import { ArrayList } from '@uform/react-shared-components'
+import { CircleButton, TextButton } from '../components/Button'
+import { Table, Form, Icon } from 'antd'
+import { FormItemProps } from '../compat/FormItem'
 import styled from 'styled-components'
-import { registerFormField } from '@uform/react'
-import { isFn, toArr } from '@uform/utils'
-import { ArrayField } from './array'
 
-export interface IColumnProps {
-  title?: string
-  dataIndex?: string
-  width?: string | number
-  cell: (item?: any, index?: number) => React.ReactElement
+const ArrayComponents = {
+  CircleButton,
+  TextButton,
+  AdditionIcon: () => <Icon type="plus" style={{ fontSize: 20 }} />,
+  RemoveIcon: () => <Icon type="delete" />,
+  MoveDownIcon: () => <Icon type="down" />,
+  MoveUpIcon: () => <Icon type="up" />
 }
 
-class Column extends Component<IColumnProps> {
-  public static displayName = '@schema-table-column'
-  public render() {
-    return this.props.children
-  }
-}
-
-registerFormField(
-  'table',
-  styled(
-    class extends ArrayField {
-      public createFilter(key, payload) {
-        const { schema } = this.props
-        const columnFilter: (key: string, payload: any) => boolean =
-          schema['x-props'] && schema['x-props'].columnFilter
-
-        return (render, otherwise) => {
-          if (isFn(columnFilter)) {
-            return columnFilter(key, payload)
-              ? isFn(render)
-                ? render()
-                : render
-              : isFn(otherwise)
-              ? otherwise()
-              : otherwise
-          } else {
-            return render()
-          }
-        }
-      }
-
-      public render() {
-        const {
-          value,
-          schema,
-          locale,
-          className,
-          renderField,
-          getOrderProperties
-        } = this.props
-        const cls = this.getProps('className')
-        const style = this.getProps('style')
-        const operationsWidth = this.getProps('operationsWidth')
-        return (
-          <div
-            className={`${className} ${cls}`}
-            style={style}
-            onClick={this.onClearErrorHandler()}
-          >
-            <div>
-              <Table dataSource={value}>
-                {getOrderProperties(schema.items).reduce(
-                  (buf, { key, schema }) => {
-                    const filter = this.createFilter(key, schema)
-                    const res = filter(
-                      () => {
-                        return buf.concat(
-                          <Column
-                            {...schema}
-                            key={key}
-                            title={schema.title}
-                            dataIndex={key}
-                            cell={(record, index) => {
-                              return renderField([index, key])
-                            }}
-                          />
-                        )
-                      },
-                      () => {
-                        return buf
-                      }
-                    )
-                    return res
-                  },
-                  []
-                )}
-
-                <Column
-                  key={'operations'}
-                  title={locale.operations}
-                  dataIndex={'operations'}
-                  width={operationsWidth}
-                  cell={(item, index) => {
-                    return (
-                      <div className={'array-item-operator'}>
-                        {this.renderRemove(index, item)}
-                        {this.renderMoveDown(index, item)}
-                        {this.renderMoveUp(index)}
-                        {this.renderExtraOperations(index)}
-                      </div>
-                    )
-                  }}
-                />
-              </Table>
-              {this.renderAddition()}
-            </div>
-          </div>
-        )
-      }
+const FormTableField = styled(
+  (props: ISchemaFieldComponentProps & { className: string }) => {
+    const { value, schema, className, editable, path, mutators } = props
+    const {
+      renderAddition,
+      renderRemove,
+      renderMoveDown,
+      renderMoveUp,
+      renderEmpty,
+      renderExtraOperations,
+      operations,
+      ...componentProps
+    } = schema.getExtendsComponentProps() || {}
+    const onAdd = () => {
+      const items = Array.isArray(schema.items)
+        ? schema.items[schema.items.length - 1]
+        : schema.items
+      mutators.push(items.getEmptyValue())
     }
-  )`
-    display: inline-block;
-    .array-item-addition {
-      line-height: normal !important;
-      padding: 10px;
-      background: #fbfbfb;
-      border-left: 1px solid #dcdee3;
-      border-right: 1px solid #dcdee3;
-      border-bottom: 1px solid #dcdee3;
-      .ant-btn-text {
-        color: #888;
-        i {
-          margin-right: 3px;
+    const renderColumns = (items: Schema) => {
+      return items.mapProperties((props, key) => {
+        const itemProps = {
+          ...props.getExtendsItemProps(),
+          ...props.getExtendsProps()
         }
-      }
-    }
-    .ant-table-cell-wrapper > .ant-form-item {
-      margin-bottom: 0;
-    }
-    .array-item-operator {
-      display: flex;
-    }
-  `
-)
-
-export interface ITableProps {
-  className?: string
-  dataSource: any
-}
-
-/**
- * 轻量级Table
- */
-const Table = styled(
-  class Table extends Component<ITableProps> {
-    public renderCell({ record, col, rowIndex }) {
-      return (
-        <div className={'ant-table-cell-wrapper'}>
-          {isFn(col.cell)
-            ? col.cell(
-                record ? record[col.dataIndex] : undefined,
-                rowIndex,
-                record
-              )
-            : record
-            ? record[col.dataIndex]
-            : undefined}
-        </div>
-      )
-    }
-
-    public renderTable(columns, dataSource) {
-      return (
-        <div className={'ant-table-body'}>
-          <table>
-            <thead>
-              <tr>
-                {columns.map((col, index) => {
-                  return (
-                    <th
-                      key={index}
-                      className={'ant-table-header-node'}
-                      style={{ minWidth: col.width }}
-                    >
-                      <div className={'ant-table-cell-wrapper'}>
-                        {col.title}
-                      </div>
-                    </th>
-                  )
-                })}
-              </tr>
-            </thead>
-            <tbody>
-              {dataSource.map((record, rowIndex) => {
-                return (
-                  <tr key={rowIndex} className={'ant-table-row'}>
-                    {columns.map((col, colIndex) => {
-                      return (
-                        <td key={colIndex} className={'ant-table-cell'}>
-                          {this.renderCell({
-                            record,
-                            col,
-                            rowIndex
-                          })}
-                        </td>
-                      )
-                    })}
-                  </tr>
-                )
-              })}
-              {this.renderPlacehodler(dataSource, columns)}
-            </tbody>
-          </table>
-        </div>
-      )
+        return {
+          title: props.title,
+          ...itemProps,
+          key,
+          dataIndex: key,
+          render: (value: any, record: any, index: number) => {
+            return (
+              <FormItemProps label={undefined}>
+                <SchemaField path={path.concat(index, key)} />
+              </FormItemProps>
+            )
+          }
+        }
+      })
     }
-
-    public renderPlacehodler(dataSource, columns) {
-      if (dataSource.length === 0) {
-        return (
-          <tr className={'ant-table-row'}>
-            <td className={'ant-table-cell'} colSpan={columns.length}>
-              <div className={'ant-table-empty'} style={{ padding: 10 }}>
-                <img
-                  src={
-                    '//img.alicdn.com/tfs/TB1cVncKAzoK1RjSZFlXXai4VXa-184-152.svg'
-                  }
-                  style={{ height: 60 }}
+    let columns = isArr(schema.items)
+      ? schema.items.reduce((buf, items) => {
+          return buf.concat(renderColumns(items))
+        }, [])
+      : renderColumns(schema.items)
+    if (editable) {
+      columns.push({
+        ...operations,
+        key: 'operations',
+        dataIndex: 'operations',
+        render: (value: any, record: any, index: number) => {
+          return (
+            <Form.Item>
+              <div className="array-item-operator">
+                <ArrayList.Remove
+                  index={index}
+                  onClick={() => mutators.remove(index)}
+                />
+                <ArrayList.MoveDown
+                  index={index}
+                  onClick={() => mutators.moveDown(index)}
+                />
+                <ArrayList.MoveUp
+                  index={index}
+                  onClick={() => mutators.moveUp(index)}
                 />
+                {isFn(renderExtraOperations)
+                  ? renderExtraOperations(index)
+                  : renderExtraOperations}
               </div>
-            </td>
-          </tr>
-        )
-      }
-    }
-
-    public getColumns(children) {
-      const columns: IColumnProps[] = []
-      React.Children.forEach<React.ReactElement<IColumnProps, typeof Column>>(
-        children,
-        child => {
-          if (React.isValidElement(child)) {
-            if (
-              child.type === Column ||
-              child.type.displayName === '@schema-table-column'
-            ) {
-              columns.push(child.props)
-            }
-          }
+            </Form.Item>
+          )
         }
-      )
-
-      return columns
-    }
-
-    public render() {
-      const columns = this.getColumns(this.props.children)
-      const dataSource = toArr(this.props.dataSource)
-      return (
-        <div className={this.props.className}>
-          <div className={'ant-table zebra'}>
-            <div className={'ant-table-inner'}>
-              {this.renderTable(columns, dataSource)}
-            </div>
-          </div>
-        </div>
-      )
+      })
     }
+    return (
+      <div className={className}>
+        <ArrayList
+          value={value}
+          minItems={schema.minItems}
+          maxItems={schema.maxItems}
+          editable={editable}
+          components={ArrayComponents}
+          renders={{
+            renderAddition,
+            renderRemove,
+            renderMoveDown,
+            renderMoveUp,
+            renderEmpty
+          }}
+        >
+          <Table
+            {...componentProps}
+            pagination={false}
+            columns={columns}
+            dataSource={toArr(value)}
+          ></Table>
+          <ArrayList.Addition>
+            {({ children }) => {
+              return (
+                <div className="array-table-addition" onClick={onAdd}>
+                  {children}
+                </div>
+              )
+            }}
+          </ArrayList.Addition>
+        </ArrayList>
+      </div>
+    )
   }
 )`
-  .ant-table {
-    position: relative;
-  }
-
-  .ant-table,
-  .ant-table *,
-  .ant-table :after,
-  .ant-table :before {
-    -webkit-box-sizing: border-box;
-    box-sizing: border-box;
-  }
-
-  .ant-table table {
-    border-collapse: collapse;
-    border-spacing: 0;
-    width: 100%;
-    background: #fff;
-    display: table !important;
-    margin: 0 !important;
-  }
-
-  .ant-table table tr:first-child td {
-    border-top-width: 0;
-  }
-
-  .ant-table th {
-    padding: 0;
-    background: #ebecf0;
-    color: #333;
-    text-align: left;
-    font-weight: 400;
-    min-width: 200px;
-    border: 1px solid #dcdee3;
+  min-width: 600px;
+  margin-bottom: 10px;
+  table {
+    margin-bottom: 0 !important;
+  }
+  .array-table-addition {
+    background: #fbfbfb;
+    cursor: pointer;
+    margin-top: 3px;
+    border-radius: 3px;
+    .next-btn-text {
+      color: #888;
+    }
+    .next-icon:before {
+      width: 16px !important;
+      font-size: 16px !important;
+      margin-right: 5px;
+    }
   }
-
-  .ant-table th .ant-table-cell-wrapper {
-    padding: 12px 16px;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    word-break: break-all;
+  .ant-btn {
+    color: #888;
   }
-
-  .ant-table td {
-    padding: 0;
-    border: 1px solid #dcdee3;
-  }
-
-  .ant-table td .ant-table-cell-wrapper {
-    padding: 12px 16px;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    word-break: break-all;
+  .array-item-operator {
     display: flex;
-  }
-
-  .ant-table.zebra tr:nth-child(odd) td {
-    background: #fff;
-  }
-
-  .ant-table.zebra tr:nth-child(2n) td {
-    background: #f7f8fa;
-  }
-
-  .ant-table-empty {
-    color: #a0a2ad;
-    padding: 32px 0;
-    text-align: center;
-  }
-
-  .ant-table-row {
-    -webkit-transition: all 0.3s ease;
-    transition: all 0.3s ease;
-    background: #fff;
-    color: #333;
-    border: none !important;
-  }
-
-  .ant-table-row.hidden {
-    display: none;
-  }
-
-  .ant-table-row.hovered,
-  .ant-table-row.selected {
-    background: #f2f3f7;
-    color: #333;
-  }
-
-  .ant-table-body,
-  .ant-table-header {
-    overflow: auto;
+    button {
+      margin-right: 8px;
+    }
   }
 `
+
+registerFormField('table', FormTableField)

+ 2 - 2
packages/antd/src/fields/textarea.tsx

@@ -1,6 +1,6 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Input } from 'antd'
-import { acceptEnum, mapStyledProps, mapTextComponent } from '../utils'
+import { acceptEnum, mapStyledProps, mapTextComponent } from '../shared'
 
 const { TextArea } = Input
 

+ 3 - 3
packages/antd/src/fields/time.tsx

@@ -1,7 +1,7 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import moment from 'moment'
 import { TimePicker } from 'antd'
-import { mapStyledProps, mapTextComponent } from '../utils'
+import { mapStyledProps, mapTextComponent } from '../shared'
 
 registerFormField(
   'time',
@@ -9,7 +9,7 @@ registerFormField(
     getValueFromEvent(_, value) {
       return value
     },
-    getProps: (props, fieldProps) => {
+    getProps: (props: any, fieldProps) => {
       const { value, disabled = false } = props
       try {
         if (!disabled && value) {

+ 2 - 2
packages/antd/src/fields/transfer.tsx

@@ -1,6 +1,6 @@
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Transfer } from 'antd'
-import { mapStyledProps } from '../utils'
+import { mapStyledProps } from '../shared'
 
 registerFormField(
   'transfer',

+ 2 - 2
packages/antd/src/fields/upload.tsx

@@ -1,8 +1,8 @@
 import React from 'react'
-import { connect, registerFormField } from '@uform/react'
+import { connect, registerFormField } from '@uform/react-schema-renderer'
 import { Button, Upload, Icon } from 'antd'
 import styled from 'styled-components'
-import { toArr, isArr, isEqual, mapStyledProps } from '../utils'
+import { toArr, isArr, isEqual, mapStyledProps } from '../shared'
 
 const { Dragger: UploadDragger } = Upload
 

+ 0 - 481
packages/antd/src/form.tsx

@@ -1,481 +0,0 @@
-import React from 'react'
-import classNames from 'classnames'
-import { Row, Col, Popover, Icon } from 'antd'
-import styled from 'styled-components'
-import { registerFormWrapper, registerFieldMiddleware } from '@uform/react'
-import { IFormItemProps, IFormProps } from '@uform/types'
-
-import LOCALE from './locale'
-import { isFn, moveTo, isStr, stringLength } from './utils'
-
-/**
- * 轻量级 Form,不包含任何数据管理能力
- */
-
-export const {
-  Provider: FormLayoutProvider,
-  Consumer: FormLayoutConsumer
-} = React.createContext(undefined)
-
-const normalizeCol = col => {
-  return typeof col === 'object' ? col : { span: col }
-}
-
-const getParentNode = (node, selector) => {
-  if (!node || (node && !node.matches)) {
-    return
-  }
-  if (node.matches(selector)) {
-    return node
-  } else {
-    return getParentNode(node.parentNode || node.parentElement, selector)
-  }
-}
-
-const isPopDescription = (description, maxTipsNum = 30) => {
-  if (isStr(description)) {
-    return stringLength(description) > maxTipsNum
-  } else {
-    return React.isValidElement(description)
-  }
-}
-
-export const FormItem = styled(
-  class FormItem extends React.Component<IFormItemProps> {
-    public static defaultProps = {
-      prefix: 'ant-'
-    }
-
-    public render() {
-      /* eslint-disable @typescript-eslint/no-unused-vars */
-      const {
-        className,
-        labelAlign,
-        labelTextAlign,
-        style,
-        prefix,
-        wrapperCol,
-        labelCol,
-        size,
-        help,
-        extra,
-        noMinHeight,
-        isTableColItem,
-        validateState,
-        autoAddColon,
-        maxTipsNum,
-        required,
-        type,
-        schema,
-        ...others
-      } = this.props
-      /* eslint-enable @typescript-eslint/no-unused-vars */
-      const itemClassName = classNames({
-        [`${prefix}form-item`]: true,
-        [`${prefix}${labelAlign}`]: labelAlign,
-        [`has-${validateState}`]: !!validateState,
-        [`${prefix}${size}`]: !!size,
-        [`${className}`]: !!className,
-        [`field-${type}`]: !!type
-      })
-
-      // 垂直模式并且左对齐才用到
-      const Tag = (wrapperCol || labelCol) && labelAlign !== 'top' ? Row : 'div'
-      const label = labelAlign === 'inset' ? null : this.getItemLabel()
-      return (
-        <Tag {...others} gutter={0} className={itemClassName} style={style}>
-          {label}
-          {this.getItemWrapper()}
-        </Tag>
-      )
-    }
-
-    private getItemLabel() {
-      const {
-        id,
-        required,
-        label,
-        labelCol,
-        wrapperCol,
-        prefix,
-        extra,
-        labelAlign,
-        labelTextAlign,
-        autoAddColon,
-        isTableColItem,
-        maxTipsNum
-      } = this.props
-
-      if (!label || isTableColItem) {
-        return null
-      }
-
-      const ele = (
-        // @ts-ignore
-        <label
-          htmlFor={id}
-          required={required}
-          key="label"
-          className={classNames({
-            'no-colon': !autoAddColon
-          })}
-        >
-          {label}
-        </label>
-      )
-
-      const cls = classNames({
-        [`${prefix}form-item-label`]: true,
-        [`${prefix}${labelTextAlign}`]: !!labelTextAlign
-      })
-
-      if ((wrapperCol || labelCol) && labelAlign !== 'top') {
-        return (
-          <Col {...normalizeCol(labelCol)} className={cls}>
-            {ele}
-            {isPopDescription(extra, maxTipsNum) && this.renderHelper()}
-          </Col>
-        )
-      }
-
-      return (
-        <div className={cls}>
-          {ele}
-          {isPopDescription(extra, maxTipsNum) && this.renderHelper()}
-        </div>
-      )
-    }
-
-    private getItemWrapper() {
-      const {
-        labelCol,
-        wrapperCol,
-        children,
-        extra,
-        label,
-        labelAlign,
-        help,
-        prefix,
-        noMinHeight,
-        size,
-        isTableColItem,
-        maxTipsNum
-      } = this.props
-
-      const message = (
-        <div
-          className={`${prefix}form-item-msg ${
-            !noMinHeight ? `${prefix}form-item-space` : ''
-          }`}
-        >
-          {help && <div className={`${prefix}form-item-help`}>{help}</div>}
-          {!help && !isPopDescription(extra, maxTipsNum) && (
-            <div className={`${prefix}form-item-extra`}>{extra}</div>
-          )}
-        </div>
-      )
-      const ele = (
-        <div className={`${prefix}form-item-control`}>
-          {React.cloneElement(children, { size })}
-          {message}
-        </div>
-      )
-      if (
-        (wrapperCol || labelCol) &&
-        labelAlign !== 'top' &&
-        !isTableColItem &&
-        label
-      ) {
-        return (
-          <Col {...normalizeCol(wrapperCol)} key="item">
-            {ele}
-          </Col>
-        )
-      }
-
-      return <React.Fragment>{ele}</React.Fragment>
-    }
-
-    private renderHelper() {
-      return (
-        <Popover placement="top" content={this.props.extra}>
-          {/* TODO antd 没有 size 属性 */}
-          <Icon
-            type="question-circle"
-            className={`${this.props.prefix}form-tips`}
-          />
-        </Popover>
-      )
-    }
-  }
-)`
-  margin-bottom: 0 !important;
-  .ant-form-item-control-wrapper {
-    line-height: 32px;
-  }
-  .ant-form-item-control {
-    line-height: 32px;
-  }
-  &.field-table {
-    .ant-form-item-control {
-      overflow: auto;
-    }
-  }
-  .antd-uploader {
-    display: block;
-  }
-  .ant-form-item-msg {
-    &.ant-form-item-space {
-      min-height: 18px;
-      margin-bottom: 2px;
-      .ant-form-item-help,
-      .ant-form-item-extra {
-        margin-top: 0;
-        line-height: 1.5;
-      }
-    }
-  }
-  .ant-form-tips {
-    margin-left: -5px;
-    margin-right: 10px;
-    transform: translateY(1px);
-  }
-  .ant-form-item-extra {
-    color: #888;
-    font-size: 12px;
-    line-height: 1.7;
-  }
-  .ant-col {
-    padding-right: 0;
-  }
-  .ant-card-head {
-    background: none;
-  }
-  .ant-form-item-label label {
-    color: #666;
-    font-size: 14px;
-    &.no-colon:after {
-      content: '';
-    }
-  }
-  ul {
-    padding: 0;
-    li {
-      margin: 0;
-      & + li {
-        margin: 0;
-      }
-    }
-  }
-`
-
-const toArr = val => (Array.isArray(val) ? val : val ? [val] : [])
-
-registerFormWrapper(OriginForm => {
-  OriginForm = styled(OriginForm)`
-    &.ant-form-inline,
-    .ant-form-inline {
-      display: flex;
-      .rs-uform-content {
-        margin-right: 15px;
-      }
-      .ant-form-item {
-        display: inline-block;
-        vertical-align: top;
-      }
-      .ant-form-item:not(:last-child) {
-        margin-right: 20px;
-      }
-
-      .ant-form-item.ant-left .ant-form-item-control {
-        display: inline-block;
-        display: table-cell\0;
-        vertical-align: top;
-        line-height: 0;
-      }
-    }
-    .ant-form-item-label {
-      line-height: 32px;
-    }
-    .ant-form-item-label label[required]:before {
-      margin-right: 4px;
-      content: '*';
-      color: #ff3000;
-    }
-    .ant-form-item-help {
-      margin-top: 4px;
-      font-size: 12px;
-      line-height: 1.5;
-      color: #999;
-    }
-    .ant-form-item.has-error .ant-form-item-help {
-      color: #ff3000;
-    }
-
-    .ant-table {
-      table {
-        table-layout: auto;
-      }
-    }
-  `
-
-  class Form extends React.Component<IFormProps> {
-    public static defaultProps = {
-      component: 'form',
-      prefix: 'ant-',
-      size: 'default',
-      labelAlign: 'left',
-      layout: 'horizontal',
-      locale: LOCALE,
-      autoAddColon: true
-    }
-
-    public static displayName = 'SchemaForm'
-    public static LOCALE = LOCALE
-    private FormRef = React.createRef()
-
-    public render() {
-      const {
-        className,
-        inline,
-        size,
-        labelAlign,
-        labelTextAlign,
-        autoAddColon,
-        children,
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
-        labelCol,
-        layout,
-        wrapperCol,
-        maxTipsNum,
-        style,
-        prefix,
-        ...others
-      } = this.props
-
-      const isInline = inline || layout === 'line'
-      const formClassName = classNames({
-        [`${prefix}form`]: true,
-        [`${prefix}form-${isInline ? 'inline' : layout}`]: true,
-        [`${prefix}${size}`]: size,
-        [`${prefix}form-${labelAlign}`]: !!labelAlign,
-        [className]: !!className
-      })
-      return (
-        <FormLayoutProvider
-          value={{
-            labelAlign,
-            labelTextAlign,
-            labelCol,
-            wrapperCol,
-            maxTipsNum,
-            inline: isInline,
-            size,
-            autoAddColon,
-            FormRef: this.FormRef
-          }}
-        >
-          <OriginForm
-            {...others}
-            formRef={this.FormRef}
-            onValidateFailed={this.validateFailedHandler(
-              others.onValidateFailed
-            )}
-            className={formClassName}
-            style={style}
-          >
-            {children}
-          </OriginForm>
-        </FormLayoutProvider>
-      )
-    }
-
-    private validateFailedHandler(onValidateFailed) {
-      return (...args) => {
-        if (isFn(onValidateFailed)) {
-          onValidateFailed(...args)
-        }
-        const container = this.FormRef.current as HTMLElement
-        if (container) {
-          const errors = container.querySelectorAll('.ant-form-item-help')
-          if (errors && errors.length) {
-            const node = getParentNode(errors[0], '.ant-form-item')
-            if (node) {
-              moveTo(node)
-            }
-          }
-        }
-      }
-    }
-  }
-
-  Form.LOCALE = LOCALE
-
-  return Form
-})
-
-const isTableColItem = (path, getSchema) => {
-  const schema = getSchema(path)
-  return schema && schema.type === 'array' && schema['x-component'] === 'table'
-}
-
-registerFieldMiddleware(Field => {
-  return props => {
-    const {
-      name,
-      errors,
-      editable,
-      path,
-      required,
-      schema,
-      schemaPath,
-      getSchema
-    } = props
-    if (path.length === 0) {
-      // 根节点是不需要包FormItem的
-      return React.createElement(Field, props)
-    }
-    return React.createElement(
-      FormLayoutConsumer,
-      {},
-      ({
-        labelAlign,
-        labelTextAlign,
-        labelCol,
-        maxTipsNum,
-        wrapperCol,
-        size,
-        autoAddColon
-      }) => {
-        return React.createElement(
-          FormItem,
-          {
-            labelAlign,
-            labelTextAlign,
-            labelCol,
-            maxTipsNum,
-            wrapperCol,
-            autoAddColon,
-            size,
-            required: editable === false ? false : required,
-            ...schema['x-item-props'],
-            label: schema.title,
-            noMinHeight: schema.type === 'object' && !schema['x-component'],
-            isTableColItem: isTableColItem(
-              schemaPath.slice(0, schemaPath.length - 2),
-              getSchema
-            ),
-            type: schema['x-component'] || schema.type,
-            id: name,
-            validateState: toArr(errors).length ? 'error' : undefined,
-            extra: schema.description,
-            help:
-              toArr(errors).join(' , ') ||
-              (schema['x-item-props'] && schema['x-item-props'].help)
-          },
-          React.createElement(Field, props)
-        )
-      }
-    )
-  }
-})

+ 15 - 42
packages/antd/src/index.tsx

@@ -1,44 +1,17 @@
-import './form'
-import './fields/string'
-import './fields/number'
-import './fields/boolean'
-import './fields/date'
-import './fields/time'
-import './fields/range'
-import './fields/upload'
-import './fields/checkbox'
-import './fields/radio'
-import './fields/rating'
-import './fields/transfer'
-import './fields/array'
-import './fields/table'
-import './fields/textarea'
-import './fields/password'
-import './fields/cards'
-
-export * from '@uform/react'
-export * from './components/formButtonGroup'
-export * from './components/button'
-export * from './components/layout'
 import React from 'react'
 import {
-  SchemaForm as InternalSchemaForm,
-  Field as InternalField
-} from '@uform/react'
-import { SchemaFormProps, FieldProps } from './type'
-
-export { mapStyledProps, mapTextComponent } from './utils'
-
-export default class SchemaForm<V> extends React.Component<SchemaFormProps<V>> {
-  render() {
-    return <InternalSchemaForm {...this.props} />
-  }
-}
-
-export class Field<V, T extends string> extends React.Component<
-  FieldProps<V, T>
-> {
-  render() {
-    return <InternalField {...this.props} />
-  }
-}
+  SchemaMarkupForm,
+  SchemaMarkupField
+} from '@uform/react-schema-renderer'
+import { INextSchemaFormProps, INextSchemaFieldProps } from './types'
+import './fields'
+import './compat'
+export * from '@uform/react-schema-renderer'
+export * from './components'
+export * from './types'
+export { mapStyledProps, mapTextComponent } from './shared'
+export const SchemaForm: React.FC<
+  INextSchemaFormProps
+> = SchemaMarkupForm as any
+export const Field: React.FC<INextSchemaFieldProps> = SchemaMarkupField
+export default SchemaForm

+ 0 - 7
packages/antd/src/locale.ts

@@ -1,7 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-export default {
-  addItem: '添加',
-  array_invalid_minItems: '条目数不允许小于%s条',
-  array_invalid_maxItems: '条目数不允许大于%s条',
-  operations: '操作'
-}

+ 75 - 0
packages/antd/src/shared.ts

@@ -0,0 +1,75 @@
+import React from 'react'
+import { PreviewText } from '@uform/react-shared-components'
+import {
+  IConnectProps,
+  MergedFieldComponentProps
+} from '@uform/react-schema-renderer'
+import { Select } from './components/Select'
+export * from '@uform/shared'
+
+export const mapTextComponent = (
+  Target: React.JSXElementConstructor<any>,
+  props: any = {},
+  fieldProps: any = {}
+): React.JSXElementConstructor<any> => {
+  const { editable } = fieldProps
+  if (editable !== undefined) {
+    if (editable === false) {
+      return PreviewText
+    }
+  }
+  if (Array.isArray(props.dataSource)) {
+    return Select
+  }
+  return Target
+}
+
+export const acceptEnum = (component: React.JSXElementConstructor<any>) => {
+  return ({ dataSource, ...others }) => {
+    if (dataSource) {
+      return React.createElement(Select, { dataSource, ...others })
+    } else {
+      return React.createElement(component, others)
+    }
+  }
+}
+
+export const transformDataSourceKey = (component, dataSourceKey) => {
+  return ({ dataSource, ...others }) => {
+    return React.createElement(component, {
+      [dataSourceKey]: dataSource,
+      ...others
+    })
+  }
+}
+
+export const normalizeCol = (
+  col: { span: number; offset?: number } | number,
+  defaultValue: { span: number }
+): { span: number; offset?: number } => {
+  if (!col) {
+    return defaultValue
+  } else {
+    return typeof col === 'object' ? col : { span: Number(col) }
+  }
+}
+
+export const mapStyledProps = (
+  props: IConnectProps,
+  fieldProps: MergedFieldComponentProps
+) => {
+  const { loading, errors } = fieldProps
+  if (loading) {
+    props.state = props.state || 'loading'
+  } else if (errors && errors.length) {
+    props.state = 'error'
+  }
+}
+
+export const compose = (...args: any[]) => {
+  return (payload: any, ...extra: any[]) => {
+    return args.reduce((buf, fn) => {
+      return buf !== undefined ? fn(buf, ...extra) : fn(payload, ...extra)
+    }, payload)
+  }
+}

+ 0 - 186
packages/antd/src/type.tsx

@@ -1,186 +0,0 @@
-import { ColProps } from 'antd/es/col'
-import { CardProps } from 'antd/es/card'
-import { BaseButtonProps } from 'antd/es/button/button'
-import {
-  IFormActions,
-  ISchema,
-  IEffects,
-  IFieldError,
-  TextAlign,
-  Size,
-  Layout,
-  TextEl,
-  LabelAlign,
-  IAsyncFormActions
-} from '@uform/types'
-import { SwitchProps } from 'antd/lib/switch'
-import { CheckboxGroupProps } from 'antd/lib/checkbox'
-import {
-  DatePickerProps,
-  RangePickerProps,
-  MonthPickerProps,
-  WeekPickerProps
-} from 'antd/lib/date-picker/interface'
-import { InputNumberProps } from 'antd/lib/input-number'
-import { IPasswordProps } from './fields/password'
-import { RadioGroupProps } from 'antd/lib/radio'
-import { ISliderProps } from './fields/range'
-import { RateProps } from 'antd/lib/rate'
-import { InputProps } from 'antd/lib/input'
-import { TextAreaProps } from 'antd/es/input'
-import { TimePickerProps } from 'antd/lib/time-picker'
-import { TransferProps } from 'antd/lib/transfer'
-import { IUploaderProps } from './fields/upload'
-import { SelectProps } from 'antd/lib/select'
-
-type ColSpanType = number | string
-
-export interface ColSize {
-  span?: ColSpanType
-  offset?: ColSpanType
-}
-
-export interface ILocaleMessages {
-  [key: string]: string | ILocaleMessages
-}
-
-export interface IFormLayoutProps {
-  className?: string
-  inline?: boolean
-  labelAlign?: LabelAlign
-  wrapperCol?: ColProps | number
-  labelCol?: ColProps | number
-  labelTextAlign?: TextAlign
-  size?: Size
-  style?: React.CSSProperties
-}
-
-export interface IFormItemGridProps {
-  cols?: Array<number | { span: number; offset: number }>
-  description?: TextEl
-  gutter?: number
-  title?: TextEl
-}
-
-export interface IRowProps {
-  prefix?: string
-  pure?: boolean
-  wrap?: boolean
-  fixed?: boolean
-  hidden?: boolean
-  className?: string
-  fixedWidth?: string | number
-  style?: React.CSSProperties
-  component?: keyof JSX.IntrinsicElements | React.ComponentType<any>
-  gutter?: string
-  align?: string | number
-  justify?: string | number
-  children: React.ReactNode
-}
-
-export interface IColProps extends ColProps {
-  prefix?: string
-  pure?: boolean
-  className?: string
-  fixedSpan?: string | number
-  fixedOffset?: string | number
-  hidden?: boolean
-  align?: any
-  component?: keyof JSX.IntrinsicElements | React.ComponentType<any>
-  children?: React.ReactNode
-  xxs?: ColSpanType | ColSize
-  xs?: ColSpanType | ColSize
-  s?: ColSpanType | ColSize
-  m?: ColSpanType | ColSize
-  l?: ColSpanType | ColSize
-  xl?: ColSpanType | ColSize
-}
-
-export interface IFormCardProps extends CardProps {
-  className?: string
-}
-
-export interface IFormBlockProps extends CardProps {
-  className?: string
-}
-
-export type TFormCardOrFormBlockProps = Omit<CardProps, 'children'>
-
-export interface IFormTextBox {
-  text?: string
-  name?: string
-  title?: TextEl
-  description?: TextEl
-  gutter?: number
-  required?: boolean
-}
-
-export interface IFormButtonGroupProps {
-  sticky?: boolean
-  style?: React.CSSProperties
-  itemStyle?: React.CSSProperties
-  className?: string
-  align?: 'left' | 'right' | 'start' | 'end' | 'top' | 'bottom' | 'center'
-  triggerDistance?: number
-  zIndex?: number
-  span?: ColSpanType
-  offset?: ColSpanType
-}
-
-export interface ISubmitProps extends Omit<BaseButtonProps, 'loading'> {
-  showLoading?: boolean
-}
-
-export interface SchemaFormProps<V = unknown> {
-  actions?: IFormActions | IAsyncFormActions
-  initialValues?: V
-  defaultValue?: V
-  value?: V
-  editable?: boolean | ((name: string) => boolean)
-  effects?: IEffects
-  locale?: ILocaleMessages
-  schema?: ISchema
-  onChange?: (values: V) => void
-  onReset?: (values: V) => void
-  onSubmit?: (values: V) => void
-  onValidateFailed?: (fieldErrors: IFieldError[]) => void
-  autoAddColon?: boolean
-  className?: string
-  inline?: boolean
-  layout?: Layout
-  maxTipsNum?: number
-  labelAlign?: LabelAlign
-  labelTextAlign?: TextAlign
-  labelCol?: ColSize | number
-  wrapperCol?: ColSize | number
-  size?: Size
-  style?: React.CSSProperties
-  prefix?: string
-}
-
-interface InternalFieldTypes {
-  boolean: SwitchProps | SelectProps
-  checkbox: CheckboxGroupProps
-  date: DatePickerProps
-  daterange: RangePickerProps
-  month: MonthPickerProps
-  week: WeekPickerProps
-  year: DatePickerProps
-  number: InputNumberProps | SelectProps
-  password: IPasswordProps
-  radio: RadioGroupProps
-  range: ISliderProps
-  rating: RateProps
-  string: InputProps | SelectProps
-  textarea: TextAreaProps | SelectProps
-  time: TimePickerProps
-  transfer: TransferProps
-  upload: IUploaderProps
-}
-
-export interface FieldProps<V, T extends string> extends ISchema<V> {
-  type?: T
-  name?: string
-  editable?: boolean
-  ['x-props']?: T extends keyof InternalFieldTypes ? InternalFieldTypes[T] : any
-}

+ 90 - 0
packages/antd/src/types.ts

@@ -0,0 +1,90 @@
+import { ButtonProps } from 'antd/lib/button'
+import { FormProps, FormItemProps as ItemProps } from 'antd/lib/form'
+import {
+  StepsProps as StepProps,
+  StepProps as StepItemProps
+} from 'antd/lib/steps'
+import {
+  ISchemaFormProps,
+  IMarkupSchemaFieldProps,
+  ISchemaFieldComponentProps
+} from '@uform/react-schema-renderer'
+import { StyledComponent } from 'styled-components'
+
+type ColSpanType = number | string
+
+export type INextSchemaFormProps = ISchemaFormProps &
+  FormProps &
+  IFormItemTopProps
+
+export type INextSchemaFieldProps = IMarkupSchemaFieldProps
+
+export interface ISubmitProps extends ButtonProps {
+  onSubmit?: ISchemaFormProps['onSubmit']
+  showLoading?: boolean
+}
+
+export interface IResetProps extends ButtonProps {
+  forceClear?: boolean
+  validate?: boolean
+}
+
+export type IFormItemTopProps = React.PropsWithChildren<
+  Exclude<
+    Pick<ItemProps, 'prefixCls' | 'labelCol' | 'wrapperCol' | 'labelAlign'>,
+    'labelCol' | 'wrapperCol'
+  > & {
+    inline?: boolean
+    className?: string
+    style?: React.CSSProperties
+    labelCol?: number | { span: number; offset?: number }
+    wrapperCol?: number | { span: number; offset?: number }
+  }
+>
+
+export interface ICompatItemProps
+  extends Exclude<ItemProps, 'labelCol' | 'wrapperCol'>,
+    Partial<ISchemaFieldComponentProps> {
+  labelCol?: number | { span: number; offset?: number }
+  wrapperCol?: number | { span: number; offset?: number }
+}
+
+export type StyledCP<P extends {}> = StyledComponent<
+  (props: React.PropsWithChildren<P>) => React.ReactElement,
+  any,
+  {},
+  never
+>
+
+export type StyledCC<Props, Statics = {}> = StyledCP<Props> & Statics
+
+export interface IFormButtonGroupProps {
+  sticky?: boolean
+  style?: React.CSSProperties
+  itemStyle?: React.CSSProperties
+  className?: string
+  align?: 'left' | 'right' | 'start' | 'end' | 'top' | 'bottom' | 'center'
+  triggerDistance?: number
+  zIndex?: number
+  span?: ColSpanType
+  offset?: ColSpanType
+}
+
+export interface IItemProps {
+  title?: React.ReactText
+  description?: React.ReactText
+}
+
+export interface IFormItemGridProps extends IItemProps {
+  cols?: Array<number | { span: number; offset: number }>
+  gutter?: number
+}
+
+export interface IFormTextBox extends IItemProps {
+  text?: string
+  gutter?: number
+}
+
+export interface IFormStep extends StepProps {
+  dataSource: StepItemProps[]
+}

+ 0 - 253
packages/antd/src/utils.tsx

@@ -1,253 +0,0 @@
-import React from 'react'
-import { Select as AntSelect, Icon } from 'antd'
-import ReactDOM from 'react-dom'
-import styled from 'styled-components'
-import { isFn } from '@uform/utils'
-import { IConnectProps, IFieldProps } from '@uform/react'
-export * from '@uform/utils'
-
-export interface ISelectProps {
-  dataSource: any[]
-  className: string
-}
-
-export interface IElement extends Element {
-  oldHTML?: string
-}
-const MoveTo = typeof window !== 'undefined' ? require('moveto') : null
-const WrapSelect = styled(
-  class extends React.Component<ISelectProps> {
-    public render() {
-      const { dataSource = [], ...others } = this.props
-      const children = dataSource.map(item => {
-        const { label, value, ...others } = item
-        return (
-          <AntSelect.Option key={value} {...others} label={label} value={value}>
-            {label}
-          </AntSelect.Option>
-        )
-      })
-      return (
-        <AntSelect className={this.props.className} {...others}>
-          {children}
-        </AntSelect>
-      )
-    }
-  }
-)`
-  min-width: 100px;
-  width: 100%;
-`
-
-const Text = styled(props => {
-  let value
-  if (props.dataSource && props.dataSource.length) {
-    const find = props.dataSource.filter(({ value }) =>
-      Array.isArray(props.value)
-        ? props.value.some(val => val == value)
-        : props.value == value
-    )
-    value = find.map(item => item.label).join(' , ')
-  } else {
-    value = Array.isArray(props.value)
-      ? props.value.join(' ~ ')
-      : String(
-          props.value === undefined || props.value === null ? '' : props.value
-        )
-  }
-  return (
-    <div className={`${props.className} ${props.size || ''} text-field`}>
-      {value || 'N/A'}
-      {props.innerAfter ? ' ' + props.innerAfter : ''}
-      {props.addonAfter ? ' ' + props.addonAfter : ''}
-    </div>
-  )
-})`
-  height: 32px;
-  line-height: 32px;
-  vertical-align: middle;
-  font-size: 13px;
-  color: #333;
-  &.small {
-    height: 24px;
-    line-height: 24px;
-  }
-  &.large {
-    height: 40px;
-    line-height: 40px;
-  }
-`
-
-export interface IStateLoadingProps {
-  state?: string
-  dataSource: any[]
-}
-
-const loadingSvg =
-  '<svg viewBox="0 0 1024 1024" class="anticon-spin" data-icon="loading" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path></svg>'
-
-export const StateLoading = (Target: React.ComponentClass) => {
-  return class Select extends React.Component<IStateLoadingProps> {
-    public wrapper: React.ReactInstance
-    public wrapperDOM: HTMLElement
-    public classList: string[]
-
-    public componentDidMount() {
-      if (this.wrapper) {
-        this.wrapperDOM = ReactDOM.findDOMNode(this.wrapper)
-        this.mapState()
-      }
-    }
-
-    public componentDidUpdate() {
-      this.mapState()
-    }
-
-    public render() {
-      return (
-        <Target
-          ref={inst => {
-            if (inst) {
-              this.wrapper = inst
-            }
-          }}
-          {...this.props}
-        />
-      )
-    }
-
-    public mapState() {
-      const { state } = this.props
-      const loadingName = 'anticon-spin'
-      const iconSizeClassNames = [
-        'xxs',
-        'xs',
-        'small',
-        'medium',
-        'large',
-        'xl',
-        'xxl',
-        'xxxl'
-      ]
-      this.classList = this.classList || []
-
-      if (this.wrapperDOM) {
-        const icon: IElement = this.wrapperDOM.querySelector('.anticon')
-        if (!icon || !icon.classList) {
-          return
-        }
-
-        if (state === 'loading') {
-          icon.classList.forEach(className => {
-            if (className.indexOf('anticon-') > -1) {
-              if (
-                className !== loadingName &&
-                iconSizeClassNames.every(val => `anticon-${val}` !== className)
-              ) {
-                icon.classList.remove(className)
-                this.classList.push(className)
-              }
-            }
-          })
-          if (icon.innerHTML) {
-            icon.oldHTML = icon.innerHTML
-            icon.innerHTML = loadingSvg
-          }
-          if (!icon.classList.contains(loadingName)) {
-            icon.classList.add(loadingName)
-          }
-        } else {
-          icon.classList.remove(loadingName)
-          this.classList.forEach(className => {
-            icon.classList.add(className)
-          })
-          if (icon.oldHTML) {
-            icon.innerHTML = icon.oldHTML
-          }
-          this.classList = []
-        }
-      }
-    }
-  }
-}
-
-const Select = StateLoading(WrapSelect)
-
-export const acceptEnum = component => {
-  return ({ dataSource, ...others }) => {
-    if (dataSource || others.showSearch) {
-      return React.createElement(Select, { dataSource, ...others })
-    } else {
-      return React.createElement(component, others)
-    }
-  }
-}
-
-export const mapStyledProps = (
-  props: IConnectProps,
-  { loading, size }: IFieldProps
-) => {
-  if (loading) {
-    props.state = props.state || 'loading'
-    props.suffix = props.suffix || (
-      <Icon type="loading" style={{ color: 'rgba(0, 0, 0, 0.25)' }} />
-    )
-  } else {
-    props.suffix = props.suffix || <span />
-  }
-  if (size) {
-    props.size = size
-  }
-}
-
-export const mapTextComponent = (
-  Target: React.ComponentClass,
-  props,
-  {
-    editable,
-    name
-  }: { editable: boolean | ((name: string) => boolean); name: string }
-): React.ComponentClass => {
-  if (editable !== undefined) {
-    if (isFn(editable)) {
-      if (!editable(name)) {
-        return Text
-      }
-    } else if (editable === false) {
-      return Text
-    }
-  }
-  return Target
-}
-
-export const compose = (...args) => {
-  return (payload, ...extra) => {
-    return args.reduce((buf, fn) => {
-      return buf !== undefined ? fn(buf, ...extra) : fn(payload, ...extra)
-    }, payload)
-  }
-}
-
-export const transformDataSourceKey = (component, dataSourceKey) => {
-  return ({ dataSource, ...others }) => {
-    return React.createElement(component, {
-      [dataSourceKey]: dataSource,
-      ...others
-    })
-  }
-}
-
-export const moveTo = element => {
-  if (!element || !MoveTo) {
-    return
-  }
-  if (element.scrollIntoView) {
-    element.scrollIntoView({
-      behavior: 'smooth',
-      inline: 'start',
-      block: 'start'
-    })
-  } else {
-    new MoveTo().move(element.getBoundingClientRect().top)
-  }
-}

+ 0 - 2
packages/builder-next/README.md

@@ -1,2 +0,0 @@
-# @uform/builder-next
-> UForm 可视化配置 next实现

+ 0 - 138
packages/builder-next/src/index.js

@@ -1,138 +0,0 @@
-import React from 'react'
-import SchemaForm, { FormButtonGroup, Submit, Reset } from '@uform/next'
-import Builder from '@uform/builder'
-
-import {
-  Button,
-  Collapse,
-  Message,
-  Upload,
-  Input,
-  Select,
-  DatePicker,
-  Icon,
-  Checkbox,
-  NumberPicker,
-  TimePicker,
-  Radio,
-  Form,
-  Tab
-} from '@alifd/next'
-
-// style
-import '@alifd/next/dist/next.css'
-
-SchemaForm.FormButtonGroup = FormButtonGroup
-SchemaForm.Submit = Submit
-SchemaForm.Reset = Reset
-
-const renderSchema = {}
-
-const props = {
-  UI: {
-    version: '1.x',
-    Button,
-    Accordion: Collapse,
-    Toast: Message,
-    Upload,
-    Input,
-    Select,
-    Icon,
-    DatePicker,
-    TimePicker,
-    Checkbox,
-    NumberPicker,
-    Radio,
-    RadioGroup: Radio.Group,
-    TabPane: Tab.Item,
-    Form,
-    Tab
-  },
-  // 主题: dark/light,默认dark
-  themeStyle: 'dark',
-  // 是否展示布局组件,默认为false
-  showLayoutField: true,
-  // 是否展示预览按钮,默认为true
-  showPreviewBtn: true,
-  // 是否展示源码按钮
-  showSourceCodeBtn: true,
-  // 控制返回按钮点击事件
-  onBackBtnClick: () => {
-    alert('点击了返回')
-  },
-  // 额外全局按钮
-  globalButtonList: [
-    // {
-    //   key: 'submit',
-    //   title: '自定义保存',
-    //   render: (props) => {
-    //     return <Badge dot>{props.children}</Badge>
-    //   },
-    //   props: {
-    //     // loading: true,
-    //   },
-    // }, {
-    //   key: 'cancel',
-    //   title: '取消',
-    //   props: {
-    //     onClick: () => {
-    //       alert('点击取消');
-    //     }
-    //   },
-    // }
-  ],
-  // 是否展示全局配置
-  showGlobalCfg: true,
-  // 全局配置额外项
-  extraGlobalCfgList: [
-    {
-      name: 'labelCol',
-      title: 'label宽度占比',
-      type: 'string'
-    },
-    {
-      name: 'wrapperCol',
-      title: 'wrapper宽度占比',
-      type: 'string'
-    }
-  ],
-  globalCfg: {},
-  supportFieldList: [],
-  includeFieldListKeyList: [
-    'input',
-    'multipleInput',
-    'number',
-    'radio',
-    'checkbox',
-    'date',
-    'month',
-    'daterange',
-    'time'
-  ],
-
-  // 渲染引擎
-  renderEngine: SchemaForm,
-
-  schema: renderSchema,
-  // onChange: (data) => {
-  //   console.info('index onChange data', data);
-  // },
-  onSubmit: data => {
-    console.info('index onSubmit data', data)
-  }
-}
-
-class Component extends React.Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      schema: renderSchema
-    }
-  }
-
-  render() {
-    return <Builder {...props} schema={this.state.schema} />
-  }
-}
-
-export default Component

+ 0 - 11
packages/builder-next/tsconfig.json

@@ -1,11 +0,0 @@
-{
-  "extends": "../../tsconfig.json",
-  "compilerOptions": {
-    "outDir": "./lib",
-    "declaration": false,
-    "allowJs": true,
-    "skipLibCheck": true
-  },
-  "include": ["./src/**/*.js", "./src/**/*.ts", "./src/**/*.tsx"],
-  "exclude": ["./src/__tests__/*"]
-}

+ 0 - 8
packages/builder/.npmignore

@@ -1,8 +0,0 @@
-node_modules
-config
-public
-scripts
-*.log
-src/demo
-build
-__tests__

+ 0 - 20
packages/builder/LISENCE.md

@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015-present, Alibaba Group Holding Limited. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 2
packages/builder/README.md

@@ -1,2 +0,0 @@
-# @uform/builder
-> UForm 可视化搭建实现

+ 0 - 62
packages/builder/package.json

@@ -1,62 +0,0 @@
-{
-  "name": "@uform/builder",
-  "version": "0.4.3",
-  "license": "MIT",
-  "main": "lib/index.js",
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/alibaba/uform.git"
-  },
-  "bugs": {
-    "url": "https://github.com/alibaba/uform/issues"
-  },
-  "homepage": "https://github.com/alibaba/uform#readme",
-  "engines": {
-    "npm": ">=3.0.0"
-  },
-  "scripts": {
-    "build": "tsc"
-  },
-  "peerDependencies": {
-    "@alifd/next": "^1.13.1",
-    "@babel/runtime": "^7.4.4",
-    "react": ">=16.8.0",
-    "react-dom": ">=16.8.0"
-  },
-  "resolutions": {
-    "@types/react": "16.8.23"
-  },
-  "dependencies": {
-    "@uform/react": "^0.4.3",
-    "@uform/utils": "^0.4.3",
-    "@uform/validator": "^0.4.3",
-    "classnames": "^2.2.5",
-    "immutability-helper": "^3.0.0",
-    "lodash.flow": "^3.5.0",
-    "lodash.isequal": "^4.5.0",
-    "lodash.merge": "^4.6.1",
-    "lodash.pick": "^4.4.0",
-    "lodash.pickby": "^4.6.0",
-    "lodash.remove": "^4.7.0",
-    "lodash.uniqby": "^4.7.0",
-    "moment": "^2.24.0",
-    "prop-types": "^15.6.1",
-    "react-dnd": "^7.4.1",
-    "react-dnd-html5-backend": "^7.4.0",
-    "react-powerplug": "^1.0.0",
-    "react-redux": "^5.0.7",
-    "redux": "^4.0.0",
-    "redux-logger": "^3.0.6",
-    "redux-thunk": "^2.2.0",
-    "styled-components": "^4.1.2",
-    "uuid": "^3.2.1"
-  },
-  "publishConfig": {
-    "access": "public"
-  },
-  "gitHead": "4d068dad6183e8da294a4c899a158326c0b0b050",
-  "devDependencies": {
-    "react-test-renderer": "^16.8.6",
-    "typescript": "^3.5.2"
-  }
-}

+ 0 - 366
packages/builder/src/App.js

@@ -1,366 +0,0 @@
-import React, { Component, createRef } from 'react'
-import cls from 'classnames'
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
-import {
-  changePreview,
-  changeGbConfig,
-  initSchema,
-  changeCodeMode,
-  changeComponent,
-  editComponent
-} from './actions'
-import { Divider } from './utils/util'
-
-import isEqual from 'lodash.isequal'
-import AppStyle from './style'
-
-// components
-import {
-  FieldList,
-  Preview,
-  GlobalBtnList,
-  PropsSetting
-} from './components/index'
-
-import { SchemaForm, Field } from './utils/baseForm'
-import defaultGlobalCfgList from './configs/supportGlobalCfgList'
-
-const noop = () => {}
-
-class App extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      systemError: false,
-      accordionList: []
-    }
-    this.appRef = createRef(null)
-    this.appHeaderRef = createRef(null)
-  }
-
-  generateGlobalCfgList = () => {
-    // Merge custom form global property configuration
-    const globalCfgList = [
-      ...defaultGlobalCfgList,
-      ...this.props.extraGlobalCfgList
-    ]
-    const _globalCfgList = []
-    for (let i = globalCfgList.length - 1; i >= 0; i--) {
-      if (
-        !_globalCfgList.find(cfgItem => cfgItem.name === globalCfgList[i].name)
-      ) {
-        _globalCfgList.unshift(globalCfgList[i])
-      }
-    }
-    return _globalCfgList
-  }
-
-  // global config
-  renderGlobalConfig = () => {
-    const globalCfgList = this.generateGlobalCfgList()
-
-    const content = (
-      <SchemaForm
-        onChange={value => {
-          this.props.changeGbConfig(value)
-        }}
-        defaultValue={this.props.gbConfig}
-        labelAlign="left"
-        labelCol={10}
-        labelTextAlign="right"
-      >
-        {globalCfgList.map(props => (
-          <Field {...props} key={props.name} />
-        ))}
-      </SchemaForm>
-    )
-
-    return content
-  }
-
-  getAccordionList = () => {
-    const list = [
-      {
-        title: '组件配置',
-        content: (
-          <PropsSetting
-            supportConfigList={this.props.supportConfigList}
-            renderEngine={this.props.renderEngine}
-            UI={this.props.UI}
-          />
-        ),
-        expanded: true
-      }
-    ]
-
-    if (this.props.showGlobalCfg) {
-      list.unshift({
-        title: '全局配置',
-        content: this.renderGlobalConfig(),
-        expanded: false
-      })
-    }
-    return list
-  }
-
-  componentWillMount() {
-    const {
-      schema,
-      globalCfg,
-      changeGbConfig: _changeGbConfig,
-      initSchema: _initSchema
-    } = this.props
-
-    _changeGbConfig(globalCfg)
-    _initSchema(schema)
-  }
-
-  componentDidMount() {
-    this.setState({
-      accordionList: this.getAccordionList()
-    })
-
-    const appDom = this.appRef.current
-    const appHeaderDom = this.appHeaderRef.current
-
-    if (appDom.offsetTop !== 0) {
-      document.querySelector(
-        '.schamaform-content'
-      ).style.height = `${window.innerHeight -
-        appDom.offsetTop -
-        appHeaderDom.offsetHeight}px`
-    }
-  }
-
-  componentWillUnmount() {
-    // Clear the selected componentId with the selected component
-    this.props.changeComponent()
-    this.props.editComponent(null, {
-      active: false
-    })
-  }
-
-  componentDidUpdate(prevProps) {
-    const oldProperties =
-      prevProps.schema && prevProps.schema.properties
-        ? prevProps.schema.properties
-        : {}
-    const { schema = {}, globalCfg = {}, initSchema: _initSchema } = this.props
-
-    const { properties = {} } = schema
-
-    if (!isEqual(properties, oldProperties)) {
-      _initSchema(schema)
-    }
-
-    if (!isEqual(globalCfg, this.props.globalCfg)) {
-      changeGbConfig(globalCfg)
-    }
-  }
-
-  componentDidCatch(error, info) {
-    if (window.location.href.indexOf('av_debug') > -1) {
-      console.error('Form configurator system error', error, info)
-    }
-    this.setState({
-      systemError: true
-    })
-  }
-
-  // dynamic import layout component
-  getLayoutTpl() {
-    if (!this.props.showLayoutField) return null
-
-    try {
-      const LayoutList = React.lazy(
-        () =>
-          new Promise((resolve, reject) => {
-            import('./components/fields/layout')
-              .then(result =>
-                resolve(result.default ? result : { default: result })
-              )
-              .catch(reject)
-          })
-      )
-      return (
-        <React.Suspense fallback={<div>Loading...</div>}>
-          <LayoutList />
-          <Divider />
-        </React.Suspense>
-      )
-    } catch (e) {
-      console.error('getEditor function error', e)
-      return null
-    }
-  }
-
-  // dynamic import editor component
-  getEditorTpl() {
-    if (!this.props.showSourceCodeBtn) return null
-
-    try {
-      const Editor = React.lazy(
-        () =>
-          new Promise((resolve, reject) => {
-            import('./components/editor/index')
-              .then(result =>
-                resolve(result.default ? result : { default: result })
-              )
-              .catch(reject)
-          })
-      )
-      return (
-        <React.Suspense fallback={<div>Loading...</div>}>
-          <Editor themeStyle={this.props.themeStyle} />
-        </React.Suspense>
-      )
-    } catch (e) {
-      console.error('getEditor function error', e)
-      return null
-    }
-  }
-
-  render() {
-    const { initSchemaData, renderEngine } = this.props
-    const { Accordion, version: UIVersion } = this.props.UI
-
-    const contentHeight = window.innerHeight
-
-    return this.state.systemError ? (
-      <p>系统发生异常</p>
-    ) : (
-      <AppStyle
-        ref={this.appRef}
-        className={cls('schemaform-app', this.props.className)}
-      >
-        <div ref={this.appHeaderRef} className="schemaform-header">
-          <a
-            href="javascript:;"
-            className="schemaform-back"
-            onClick={() => {
-              this.props.onBackBtnClick()
-            }}
-          >
-            后退
-          </a>
-          <h1>编辑表单</h1>
-          <div className="schemaform-header-btns">
-            <GlobalBtnList {...this.props} />
-          </div>
-        </div>
-        <div className="schamaform-content" style={{ height: contentHeight }}>
-          <div className="content-col content-col-left">
-            {this.getLayoutTpl()}
-            <FieldList
-              supportFieldList={this.props.supportFieldList}
-              includeFieldListKeyList={this.props.includeFieldListKeyList}
-            />
-          </div>
-          <div className="content-col content-col-main">
-            <Preview
-              schema={initSchemaData}
-              renderEngine={renderEngine}
-              UI={this.props.UI}
-            />
-          </div>
-          <div className="content-col content-col-right">
-            {UIVersion === '1.x' ? (
-              <Accordion
-                dataSource={this.state.accordionList}
-                defaultExpandedKeys={['1']}
-              />
-            ) : (
-              <Accordion
-                dataSource={this.state.accordionList}
-                onChange={(status, list) => {
-                  this.setState({
-                    accordionList: list
-                  })
-                }}
-              />
-            )}
-          </div>
-        </div>
-        {this.getEditorTpl()}
-      </AppStyle>
-    )
-  }
-}
-
-App.propTypes = {
-  // 左上角返回按钮事件绑定
-  onBackBtnClick: PropTypes.func,
-  // 是否展示源码编辑按钮
-  showSourceCodeBtn: PropTypes.bool,
-  changeGbConfig: PropTypes.func,
-  // 当前是否是预览状态
-  preview: PropTypes.bool,
-  changePreview: PropTypes.func,
-  componentProps: PropTypes.object,
-  schema: PropTypes.object,
-  showGlobalCfg: PropTypes.bool,
-  // 额外注入的全局配置
-  extraGlobalCfgList: PropTypes.arrayOf(
-    PropTypes.objectOf(PropTypes.any, PropTypes.any)
-  ),
-  // 全局配置
-  globalCfg: PropTypes.object,
-  // 全局的组件列表
-  supportFieldList: PropTypes.array,
-  // 过滤全局组件列表
-  includeFieldListKeyList: PropTypes.arrayOf(PropTypes.string),
-  supportConfigList: PropTypes.array,
-  beforeSubmit: PropTypes.func,
-  onSubmit: PropTypes.func,
-  onChange: PropTypes.func,
-  renderEngine: PropTypes.any.isRequired,
-  formSubmitUrl: PropTypes.string,
-  showPreviewBtn: PropTypes.bool,
-  globalButtonList: PropTypes.arrayOf(
-    PropTypes.objectOf(PropTypes.any, PropTypes.any)
-  )
-}
-
-App.defaultProps = {
-  onBackBtnClick: () => {
-    window.history.back()
-  },
-  showGlobalCfg: false,
-  showSourceCodeBtn: false,
-  extraGlobalCfgList: [],
-  supportFieldList: [],
-  includeFieldListKeyList: [],
-  supportConfigList: [],
-  globalCfg: {},
-  schema: {},
-  renderEngine: SchemaForm,
-  beforeSubmit: noop,
-  onSubmit: data => {},
-  onChange: noop,
-  formSubmitUrl: '',
-  showPreviewBtn: true,
-  globalButtonList: []
-}
-
-const mapStateToProps = state => state
-
-const mapDispatchToProps = dispatch => ({
-  changePreview: preview => dispatch(changePreview(preview)),
-  changeGbConfig: data => dispatch(changeGbConfig(data)),
-  initSchema: data => dispatch(initSchema(data)),
-  changeCodeMode: codemode => dispatch(changeCodeMode(codemode)),
-  changeComponent: componentId => dispatch(changeComponent(componentId)),
-  editComponent: (...args) => dispatch(editComponent(...args))
-})
-
-class StyledAppComp extends React.Component {
-  render() {
-    return <App {...this.props} />
-  }
-}
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(StyledAppComp)

+ 0 - 154
packages/builder/src/actions/index.js

@@ -1,154 +0,0 @@
-import uuid from 'uuid'
-
-/**
- * 添加组件
- * @param {Object} component
- */
-export const addComponent = (component, existId, id, type, containerId) => ({
-  type: 'ADD_COMPONENT',
-  data: {
-    id: id || uuid(),
-    component,
-    existId,
-    addType: type,
-    containerId
-  }
-})
-
-/**
- * 添加组件并置于编辑状态
- * @param {Object} component
- */
-export const addComponentAndEdit = (
-  component,
-  existId,
-  type,
-  containerId = []
-) => dispatch => {
-  const id = component.id || uuid()
-
-  dispatch(addComponent(component, existId, id, type, containerId))
-  dispatch(changeComponent(Array.isArray(id) ? id : [...containerId, id]))
-  dispatch(
-    showComponentProps(Array.isArray(id) ? id : [...containerId, id], component)
-  )
-  dispatch(
-    editComponent(Array.isArray(id) ? id : [...containerId, id], {
-      active: true
-    })
-  )
-}
-
-/**
- * 移动组件
- * @param {Array} sourceId 源ID
- * @param {Array} targetId 目标ID
- */
-export const moveComponent = (sourceId, targetId) => ({
-  type: 'MOVE_COMOPNENT',
-  data: {
-    id: sourceId,
-    targetId
-  }
-})
-
-/**
- * 改变组件顺序
- */
-export const changeComponentOrder = (sourceId, targetId, containerId) => ({
-  type: 'CHANGE_COMPONENT_ORDER',
-  data: {
-    id: sourceId,
-    targetId,
-    containerId
-  }
-})
-
-/**
- * 修改组件数据
- */
-export const editComponent = (id, propsData) => ({
-  type: 'EDIT_COMPONENT',
-  data: {
-    id,
-    propsData
-  }
-})
-
-/**
- * 删除组件
- */
-export const deleteComponent = id => ({
-  type: 'DELETE_COMPONENT',
-  data: {
-    id
-  }
-})
-
-/**
- * 展示组件属性
- */
-export const showComponentProps = (id, comp) => ({
-  type: 'SHOW_COMPONENT_PROPS',
-  data: {
-    id,
-    comp
-  }
-})
-
-/**
- * 编辑组件属性
- */
-export const editComponentProps = (id, propsData) => ({
-  type: 'EDIT_COMPONENT_PROPS',
-  data: {
-    id,
-    propsData
-  }
-})
-
-/**
- * 改变预览状态
- */
-export const changePreview = preview => ({
-  type: 'CHANGE_PREVIEW',
-  data: {
-    preview
-  }
-})
-
-/**
- * 改变源码编辑状态
- */
-export const changeCodeMode = codemode => ({
-  type: 'CHANGE_CODEMODE',
-  data: {
-    codemode
-  }
-})
-
-/**
- * 改变当前编辑的组件
- */
-export const changeComponent = componentId => ({
-  type: 'CHANGE_COMPONENT',
-  data: {
-    componentId
-  }
-})
-
-/**
- * 修改全局配置
- */
-export const changeGbConfig = data => ({
-  type: 'CHANGE_GB_CONFIG',
-  data
-})
-
-/**
- * 初始化schema
- */
-export const initSchema = data => ({
-  type: 'INIT_SCHEMA',
-  data
-})

+ 0 - 137
packages/builder/src/components/editor/index.js

@@ -1,137 +0,0 @@
-import React from 'react'
-import cls from 'classnames'
-
-import { connect } from 'react-redux'
-import { initSchema, changeGbConfig, changeCodeMode } from '../../actions/index'
-import EditorStyle from './style'
-
-class Component extends React.Component {
-  componentDidMount() {
-    /* eslint-disable */
-    const defaultValue = this.getValueFromProps()
-    const theme = this.props.themeStyle === 'dark' ? 'vs-dark' : 'vs'
-
-    if (window.loadedMonaco === true) {
-      self.monacoInstance = monaco.editor.create(
-        document.getElementById('J_uformEditor'),
-        {
-          language: 'javascript',
-          theme: theme,
-          value: defaultValue
-        }
-      )
-      return false
-    }
-
-    const script = document.createElement('script')
-    script.src =
-      '//g.alicdn.com/ascp-comp/common-monaco-editor/5.0.1/min/vs/loader.js'
-    document.head.appendChild(script)
-
-    const tpl1 = `data:text/javascript;charset=utf-8,${encodeURIComponent(`
-      self.MonacoEnvironment = {
-        baseUrl: "https://g.alicdn.com/ascp-comp/common-monaco-editor/5.0.1/min/"
-      };
-      importScripts(
-        "https://g.alicdn.com/ascp-comp/common-monaco-editor/5.0.1/min/vs/base/worker/workerMain.js"
-      )`)}`
-
-    script.onload = () => {
-      const script2 = document.createElement('script')
-      const tpl = `
-        require.config({
-          paths: {
-            vs: "https://g.alicdn.com/ascp-comp/common-monaco-editor/5.0.1/min/vs" 
-          }
-        });
-        window.MonacoEnvironment = {
-          getWorkerUrl: function(workerId, label) {
-            return "${tpl1}"
-          }
-        };
-        require(["vs/editor/editor.main"], function() {
-          window.loadedMonaco = true;
-          self.monacoInstance = self.monacoInstance || monaco.editor.create(document.getElementById("J_uformEditor"), {
-            language: "javascript",
-            theme: "${theme}",
-            value: ${JSON.stringify(defaultValue)}
-          })
-        })
-      `
-      script2.innerHTML = tpl
-      document.head.appendChild(script2)
-    }
-    /* eslint-enable */
-  }
-
-  getValueFromProps() {
-    const { initSchemaData, gbConfig } = this.props
-    const val = JSON.stringify(
-      {
-        schema: initSchemaData,
-        gbConfig
-      },
-      null,
-      '\t'
-    )
-
-    return val
-  }
-
-  componentDidUpdate() {
-    window.monacoInstance &&
-      window.monacoInstance.setValue(this.getValueFromProps())
-  }
-
-  render() {
-    const { className, codemode } = this.props
-
-    return (
-      <EditorStyle className={cls(className, codemode ? 'active' : '')}>
-        <div id="J_uformEditor" className="editor" />
-        <a
-          href="javascript:;"
-          className="editor-btn"
-          onClick={() => {
-            try {
-              // eslint-disable-next-line
-              const newValue = new Function(
-                `return ${window.monacoInstance.getValue()}`
-              )()
-              const { schema = {}, gbConfig = {} } = newValue
-              const {
-                initSchema: _initSchema,
-                changeGbConfig: _changeGbConfig
-              } = this.props
-              _initSchema(schema)
-              _changeGbConfig(gbConfig)
-            } catch (e) {
-              throw new Error(`格式转换失败,请检查代码:  + ${e.message}`)
-            }
-          }}
-        >
-          保存源码
-        </a>
-      </EditorStyle>
-    )
-  }
-}
-
-class StyledEditorComp extends React.Component {
-  render() {
-    return <Component {...this.props} />
-  }
-}
-
-const mapStateToProps = state => state
-
-const mapDispatchToProps = dispatch => ({
-  initSchema: data => dispatch(initSchema(data)),
-  changeGbConfig: data => dispatch(changeGbConfig(data)),
-  changeCodeMode: codemode => dispatch(changeCodeMode(codemode))
-})
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(StyledEditorComp)

+ 0 - 33
packages/builder/src/components/editor/style.js

@@ -1,33 +0,0 @@
-import styled from 'styled-components'
-
-export default styled.div`
-  position: absolute;
-  min-width: 500px;
-  top: 64px;
-  right: 0;
-  bottom: 0;
-  overflow-y: scroll;
-  box-shadow: 0 -1px 3px 0 rgba(0, 0, 0, 0.2);
-  transition: transform 0.2s ease-in;
-  transform: translate3d(500px, 0, 0);
-  &.active {
-    transform: translate3d(0, 0, 0);
-  }
-  z-index: 2000;
-  .editor {
-    position: absolute;
-    top: 0;
-    right: 0;
-    width: 100%;
-    height: 100%;
-  }
-  .editor-btn {
-    position: absolute;
-    top: 10px;
-    right: 10px;
-    padding: 4px;
-    background: rgba(90, 96, 255, 0.95);
-    color: #fff;
-    border-radius: 3px;
-  }
-`

+ 0 - 103
packages/builder/src/components/fields/field.js

@@ -1,103 +0,0 @@
-import React from 'react'
-import { DragSource } from 'react-dnd'
-import ItemTypes from '../../constants/itemType'
-import uuid from 'uuid'
-
-const DEFAULT_ICON_URL =
-  '//gw.alicdn.com/tfs/TB10xa4DbrpK1RjSZTEXXcWAVXa-116-60.png'
-
-const wrapFieldItem = fieldItem =>
-  !!fieldItem && typeof fieldItem === 'object'
-    ? {
-        iconUrl: DEFAULT_ICON_URL,
-        ...fieldItem
-      }
-    : {
-        type: fieldItem,
-        icon: '',
-        iconUrl: DEFAULT_ICON_URL,
-        width: '58',
-        height: '30',
-        title: '自定义组件'
-      }
-
-const Box = ({
-  addComponentAndEdit,
-  fieldItem,
-  isDragging,
-  connectDragSource
-}) => {
-  const style = {
-    opacity: isDragging ? 0.4 : 1
-  }
-
-  if (isDragging) {
-    style.filter = 'blur(2px) brightness(.6)'
-  }
-
-  const newFieldItem = wrapFieldItem(fieldItem)
-  const { key, iconUrl, width, height, title } = newFieldItem
-
-  return connectDragSource(
-    <li
-      key={key}
-      onClick={() => {
-        addComponentAndEdit(newFieldItem)
-      }}
-      style={style}
-    >
-      <i
-        className="field-icon"
-        style={{
-          backgroundImage: `url(${iconUrl})`,
-          width: '100%',
-          backgroundSize: `${width}px ${height}px`
-        }}
-      />
-      <span>{title}</span>
-    </li>
-  )
-}
-
-export default DragSource(
-  ItemTypes.FIELD,
-  {
-    beginDrag: props => {
-      const { fieldItem } = props
-      const id = uuid()
-      return { fieldItem, id }
-    },
-    endDrag(props, monitor) {
-      console.info('endDrag')
-      if (!monitor.didDrop()) {
-        return
-      }
-      console.info('endDrag success')
-      const item = monitor.getItem()
-      const dropResult = monitor.getDropResult()
-
-      // @note: 不要直接拿fieldItem,避免下面删掉属性直接影响到原有的fieldItem
-      const fieldItem = { ...item.fieldItem }
-      const { addComponentAndEdit } = props
-
-      // 删除多余的跟渲染无关的属性
-      try {
-        ;['height', 'icon', 'iconUrl', 'width'].forEach(key => {
-          delete fieldItem[key]
-        })
-      } catch (e) {}
-
-      if (dropResult) {
-        if (dropResult.targetType === 'layout') {
-          addComponentAndEdit(fieldItem, '', 'layout', dropResult.targetId)
-        } else {
-          addComponentAndEdit(fieldItem)
-        }
-      }
-    }
-  },
-  (connect, monitor) => ({
-    connectDragSource: connect.dragSource(),
-    isDragging: monitor.isDragging()
-  })
-)(Box)

+ 0 - 58
packages/builder/src/components/fields/index.js

@@ -1,58 +0,0 @@
-import React from 'react'
-import cls from 'classnames'
-import defaultSupportFieldList from '../../configs/supportFieldList'
-import { Header, wrapComp2Class } from '../../utils/util'
-import { connect } from 'react-redux'
-import { addComponentAndEdit } from '../../actions'
-import uniqBy from 'lodash.uniqby'
-import { indexStyle as IndexStyle } from './style'
-import Field from './field'
-
-function FieldList(props) {
-  const {
-    addComponentAndEdit,
-    supportFieldList = [],
-    includeFieldListKeyList = []
-  } = props
-
-  let fieldList = defaultSupportFieldList
-  if (supportFieldList.length) {
-    fieldList = uniqBy([...supportFieldList, ...defaultSupportFieldList], 'key')
-  }
-  if (includeFieldListKeyList.length) {
-    fieldList = fieldList.filter(
-      fieldItem => includeFieldListKeyList.indexOf(fieldItem.key) > -1
-    )
-  }
-
-  return (
-    <IndexStyle className={cls('col-card col-fields', props.className)}>
-      <Header>
-        <h2>组件</h2>
-        <p>可将选项拖动到主面板进行编辑</p>
-      </Header>
-      <ul className="field-list">
-        {fieldList.map((fieldItem, i) => {
-          return (
-            <Field
-              fieldItem={fieldItem}
-              key={i}
-              addComponentAndEdit={addComponentAndEdit}
-            />
-          )
-        })}
-      </ul>
-    </IndexStyle>
-  )
-}
-
-const mapStateToProps = state => state
-
-const mapDispatchToProps = dispatch => ({
-  addComponentAndEdit: (...args) => dispatch(addComponentAndEdit(...args))
-})
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(wrapComp2Class(FieldList))

+ 0 - 63
packages/builder/src/components/fields/layout.js

@@ -1,63 +0,0 @@
-// 布局
-import React from 'react'
-import cls from 'classnames'
-import PropTypes from 'prop-types'
-import supportLayoutList from '../../configs/supportLayoutList'
-import { Header, wrapComp2Class } from '../../utils/util'
-import { connect } from 'react-redux'
-import { addComponentAndEdit } from '../../actions'
-import Field from './layoutField'
-import { layoutStyle as LayoutStyle } from './style'
-
-class Component extends React.Component {
-  constructor(props) {
-    super(props)
-
-    this.layoutList = supportLayoutList
-  }
-
-  renderList() {
-    return (
-      <ul className="layout-list">
-        {this.layoutList.map((item, i) => {
-          return (
-            <Field
-              fieldItem={item}
-              key={i}
-              addComponentAndEdit={this.props.addComponentAndEdit}
-            />
-          )
-        })}
-      </ul>
-    )
-  }
-
-  render() {
-    return (
-      <LayoutStyle className={cls('col-card col-layout', this.props.className)}>
-        <Header>
-          <h2>布局</h2>
-          <p>单击将布局添加入主面板</p>
-        </Header>
-        {this.renderList()}
-      </LayoutStyle>
-    )
-  }
-}
-
-Component.propTypes = {
-  addComponentAndEdit: PropTypes.func
-}
-
-Component.defaultProps = {}
-
-const mapStateToProps = state => state
-
-const mapDispatchToProps = dispatch => ({
-  addComponentAndEdit: (...args) => dispatch(addComponentAndEdit(...args))
-})
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(wrapComp2Class(Component))

+ 0 - 85
packages/builder/src/components/fields/layoutField.js

@@ -1,85 +0,0 @@
-import React from 'react'
-import { DragSource } from 'react-dnd'
-import ItemTypes from '../../constants/itemType'
-import uuid from 'uuid'
-
-const Box = ({
-  addComponentAndEdit,
-  fieldItem,
-  isDragging,
-  connectDragSource
-}) => {
-  const opacity = isDragging ? 0.4 : 1
-  const { key, title } = fieldItem
-  return (
-    <li
-      ref={connectDragSource}
-      key={key}
-      onClick={() => {
-        const id = uuid()
-        const newFieldItem = {
-          type: 'object',
-          key: fieldItem.key,
-          id,
-          ...fieldItem.__key__data__,
-          properties: {},
-          'x-props': {
-            ...fieldItem.__key__data__['x-props'],
-            _extra: fieldItem
-          }
-        }
-        addComponentAndEdit(newFieldItem)
-      }}
-      style={Object.assign({}, { opacity })}
-    >
-      {title}
-    </li>
-  )
-}
-
-export default DragSource(
-  ItemTypes.LAYOUT,
-  {
-    beginDrag: props => {
-      const { fieldItem } = props
-      const id = uuid()
-      return { fieldItem, id }
-    },
-    endDrag(props, monitor) {
-      if (!monitor.didDrop()) {
-        return
-      }
-
-      const item = monitor.getItem()
-      const dropResult = monitor.getDropResult()
-      const { id } = item
-      const fieldItem = { ...item.fieldItem }
-      const { addComponentAndEdit } = props
-      try {
-        ;['height', 'icon', 'iconUrl', 'width'].forEach(key => {
-          delete fieldItem[key]
-        })
-      } catch (e) {}
-
-      if (dropResult) {
-        const newFieldItem = {
-          type: 'object',
-          key: fieldItem.key,
-          id,
-          ...fieldItem.__key__data__,
-          properties: {},
-          'x-props': {
-            ...fieldItem.__key__data__['x-props'],
-            _extra: fieldItem
-          }
-        }
-
-        addComponentAndEdit(newFieldItem)
-      }
-    }
-  },
-  (connect, monitor) => ({
-    connectDragSource: connect.dragSource(),
-    isDragging: monitor.isDragging()
-  })
-)(Box)

+ 0 - 87
packages/builder/src/components/fields/style.js

@@ -1,87 +0,0 @@
-import styled from 'styled-components'
-
-export const indexStyle = styled.div`
-  .field-list {
-    font-size: 0;
-    li {
-      overflow: hidden;
-      margin-bottom: 12px;
-      padding: 0 8px;
-      display: inline-block;
-      width: 33.33%;
-      height: 75px;
-      font-size: 12px;
-      text-align: center;
-      color: ${props => props.theme.whiteColor};
-      box-sizing: border-box;
-      transition: all 0.1s ease;
-      cursor: pointer;
-      &:hover {
-        background: ${props => props.theme.compHoverBgColor};
-      }
-      span {
-        display: block;
-        margin: auto;
-        max-width: 50px;
-        height: 32px;
-        word-break: break-all;
-      }
-    }
-  }
-  .field-icon {
-    display: block;
-    margin: 0 auto 12px;
-    height: 30px;
-    background-repeat: no-repeat;
-    background-position: 50% 50%;
-  }
-  @media screen and (max-width: 834px) {
-    .field-list {
-      li {
-        width: 100%;
-      }
-    }
-  }
-`
-
-export const layoutStyle = styled.div`
-  .layout-list {
-    margin-bottom: 15px;
-    padding: 0 8px;
-    font-size: 0;
-    li {
-      overflow: hidden;
-      margin-right: 7px;
-      width: 70px;
-      height: 90px;
-      line-height: 90px;
-      border-radius: 4px;
-      display: inline-block;
-      font-size: 12px;
-      text-align: center;
-      background: ${props => props.theme.compHoverBgColor};
-      color: ${props => props.theme.whiteColor};
-      border: 1px solid ${props => props.theme.compHoverBgColor};
-      box-sizing: border-box;
-      transition: all 0.1s ease;
-      cursor: pointer;
-      &:hover {
-        background: ${props => props.theme.compHoverBgColor};
-        border-color: ${props => props.theme.whiteColor};
-      }
-      &:nth-child(3n) {
-        margin-right: 0;
-      }
-      span {
-        display: block;
-        margin: auto;
-        word-break: break-all;
-      }
-    }
-  }
-`
-
-export default {
-  indexStyle,
-  layoutStyle
-}

+ 0 - 115
packages/builder/src/components/globalBtnList/index.js

@@ -1,115 +0,0 @@
-import React from 'react'
-import { GLOBAL_BTN_ICON_URL } from '../../configs/theme'
-import { wrapSubmitSchema, CustomIcon } from '../../utils/util'
-import merge from 'lodash.merge'
-
-export default props => {
-  const {
-    preview,
-    codemode,
-    onSubmit,
-    themeStyle,
-    changeCodeMode: _changeCodeMode,
-    globalButtonList,
-    showPreviewBtn,
-    showSourceCodeBtn,
-    UI
-  } = props
-
-  // 获取主题下的默认icon图片地址
-  const globalBtnIconUrlWithTheme = GLOBAL_BTN_ICON_URL[themeStyle]
-
-  // 默认按钮
-  const defaultBtnList = [
-    {
-      key: 'preview',
-      show: showPreviewBtn,
-      title: preview ? '返回编辑' : '预览',
-      props: {
-        onClick: () => {
-          props.changePreview(!props.preview)
-        }
-      },
-      iconType: 'eye',
-      iconUrl: globalBtnIconUrlWithTheme.preview,
-      iconWidth: 16,
-      iconHeight: 16
-    },
-    {
-      key: 'submit',
-      title: '保存',
-      props: {
-        type: 'primary',
-        onClick: () => {
-          onSubmit &&
-            typeof onSubmit === 'function' &&
-            onSubmit({
-              schema: wrapSubmitSchema(props.initSchemaData),
-              globalCfg: props.gbConfig
-            })
-        }
-      },
-      iconType: 'save',
-      iconUrl: globalBtnIconUrlWithTheme.submit,
-      iconWidth: 15,
-      iconHeight: 15
-    },
-    {
-      key: 'code',
-      show: showSourceCodeBtn,
-      title: codemode ? '关闭源码' : '源码',
-      props: {
-        onClick: () => {
-          _changeCodeMode(!props.codemode)
-        }
-      },
-      iconUrl: globalBtnIconUrlWithTheme.code,
-      iconWidth: 21,
-      iconHeight: 16
-    }
-  ]
-
-  // 合并相同key的数据
-  const _globalButtonList = defaultBtnList.map(btnItem => {
-    const { key } = btnItem
-    const customBtnItem = globalButtonList.find(btn => btn.key === key)
-    return customBtnItem ? merge({}, btnItem, customBtnItem) : btnItem
-  })
-
-  // 注入额外的数据
-  globalButtonList.forEach(btnItem => {
-    if (['preview', 'submit', 'preview'].indexOf(btnItem.key) === -1) {
-      _globalButtonList.push(btnItem)
-    }
-  })
-
-  return _globalButtonList.map(btnItem => {
-    const {
-      props = {},
-      key,
-      show = true,
-      title,
-      iconUrl,
-      iconWidth,
-      iconHeight,
-      render
-    } = btnItem
-
-    if (!title || !show || !key) return null
-
-    const customIconTpl = iconUrl ? (
-      <CustomIcon iconUrl={iconUrl} width={iconWidth} height={iconHeight} />
-    ) : null
-
-    const originalBtn = (
-      <UI.Button key={key} {...props}>
-        {customIconTpl}
-        <span>{title}</span>
-      </UI.Button>
-    )
-
-    return render
-      ? React.createElement(render, btnItem, originalBtn)
-      : originalBtn
-  })
-}

+ 0 - 8
packages/builder/src/components/index.js

@@ -1,8 +0,0 @@
-import PropsSetting from './props/propsSetting'
-import FieldList from './fields/index'
-import Preview from './preview/index'
-import GlobalBtnList from './globalBtnList/index'
-
-export { PropsSetting, FieldList, Preview, GlobalBtnList }
-
-export default {}

+ 0 - 191
packages/builder/src/components/preview/card.js

@@ -1,191 +0,0 @@
-import React, { useImperativeHandle, useRef, forwardRef } from 'react'
-import { DragSource, DropTarget } from 'react-dnd'
-import cls from 'classnames'
-import ItemTypes from '../../constants/itemType'
-import { isLayoutWrapper } from '../../utils/util'
-import flow from 'lodash.flow'
-const style = {
-  cursor: 'move'
-}
-const Card = forwardRef(
-  (
-    {
-      Field,
-      props,
-      canDrop,
-      isOver,
-      that,
-      isDragging,
-      connectDragSource,
-      connectDropTarget,
-      id
-    },
-    ref
-  ) => {
-    const elementRef = useRef(null)
-    connectDragSource(elementRef)
-    connectDropTarget(elementRef)
-    useImperativeHandle(ref, () => ({
-      getNode: () => elementRef.current
-    }))
-
-    const opacity = isDragging ? 0.2 : 1
-    const isActive = canDrop && isOver
-    let backgroundColor = '#fff'
-    if (isActive) {
-      backgroundColor = '#f5f5f5'
-    }
-
-    const { active = false } = props.schema
-    const comp = {
-      ...props.schema
-    }
-
-    return isLayoutWrapper(comp) ? (
-      connectDropTarget(
-        <div
-          key={id}
-          className={cls(
-            'comp-item-layout',
-            'next-form-item',
-            'preview-line',
-            active ? 'preview-line-active' : ''
-          )}
-          style={Object.assign({}, style, { opacity, backgroundColor })}
-        >
-          {!Object.keys(props.schema.properties).length ? (
-            <p className="comp-item-layout-empty">
-              请从左边字段<strong>拖拽</strong>组件进来这里
-            </p>
-          ) : (
-            React.createElement(Field, props)
-          )}
-          <div
-            className="preview-line-layer"
-            onClick={ev => {
-              ev.preventDefault()
-              that.onMouseClick(id, comp)
-            }}
-          />
-          <div className="comp-item-layout-tool">
-            <a
-              className="preview-line-del"
-              type="delete"
-              size="small"
-              onClick={() => {
-                that.props.changeComponent()
-                that.deleteComponent(id)
-              }}
-            />
-          </div>
-        </div>
-      )
-    ) : (
-      <div
-        ref={elementRef}
-        key={id}
-        className={cls(
-          'comp-item',
-          'next-form-item',
-          'preview-line',
-          active ? 'preview-line-active' : ''
-        )}
-        style={Object.assign({}, style, { opacity, backgroundColor })}
-      >
-        {React.createElement(Field, { ...props })}
-        <div
-          className="preview-line-layer"
-          onClick={ev => {
-            ev.preventDefault()
-            that.onMouseClick(id, comp)
-          }}
-        />
-        <div className="comp-item-layout-tool">
-          <a
-            className="preview-line-del"
-            type="delete"
-            size="small"
-            onClick={() => {
-              that.props.changeComponent()
-              that.deleteComponent(id)
-            }}
-          />
-        </div>
-        <div className="comp-item-barline" />
-      </div>
-    )
-  }
-)
-
-export default flow(
-  DragSource(
-    ItemTypes.CARD,
-    {
-      beginDrag: props => {
-        const { id } = props
-        return {
-          source: 'card',
-          id
-        }
-      },
-      endDrag(props, monitor) {
-        if (!monitor.didDrop()) {
-          return
-        }
-
-        const dropResult = monitor.getDropResult()
-        const { id: droppedId } = props
-        if (dropResult) {
-          const { targetId, targetType } = dropResult
-
-          if (targetType === 'layout') {
-            // props.move(droppedId, targetId)
-          } else {
-            props.moveCard(droppedId, targetId, targetType)
-          }
-        }
-      }
-    },
-    (connect, monitor) => ({
-      connectDragSource: connect.dragSource(),
-      isDragging: monitor.isDragging()
-    })
-  ),
-  DropTarget(
-    [ItemTypes.CARD, ItemTypes.FIELD],
-    {
-      drop(props, monitor) {
-        const comp = props.props.schema
-
-        return {
-          name: 'card',
-          targetId: props.id,
-          targetType: isLayoutWrapper(comp) ? 'layout' : ''
-        }
-      },
-      hover(props, monitor, component) {
-        const node = component.getNode()
-        if (!node) {
-          return null
-        }
-        const hoverBoundingRect = node.getBoundingClientRect()
-        // Get vertical middle
-        const hoverMiddleY =
-          (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
-        // Determine mouse position
-        const clientOffset = monitor.getClientOffset()
-        // Get pixels to the top
-        const hoverClientY = clientOffset.y - hoverBoundingRect.top
-
-        const isOverHalf = hoverClientY > hoverMiddleY
-        monitor.getItem().isOverHalf = isOverHalf
-      }
-    },
-    (connect, monitor) => ({
-      connectDropTarget: connect.dropTarget(),
-      isOver: monitor.isOver(),
-      isOverCurrent: monitor.isOver({ shallow: true }),
-      canDrop: monitor.canDrop()
-    })
-  )
-)(Card)

+ 0 - 45
packages/builder/src/components/preview/fieldMiddleware.js

@@ -1,45 +0,0 @@
-import React from 'react'
-import { registerFieldMiddleware } from '../../utils/baseForm'
-import Card from './card'
-import { FormConsumer } from '../../constants/context'
-
-export default that => {
-  // 判断注册过则不再注册
-  const hasRegisted = window.__hasRegisted__ || false
-  if (hasRegisted) {
-    return false
-  }
-  window.__hasRegisted__ = true
-
-  const moveCard = (dragIndex, hoverIndex) => {
-    that.props.changeComponentOrder(dragIndex, hoverIndex)
-  }
-
-  const move = (sourceId, targetId) => {
-    that.props.moveComponent(sourceId, targetId)
-  }
-
-  registerFieldMiddleware(Field => props =>
-    React.createElement(FormConsumer, {}, (obj = {}) => {
-      const { type } = obj
-
-      // 根节点或者非预览直接返回
-      if (props.path.length === 0 || type !== 'preview') {
-        return React.createElement(Field, props)
-      }
-
-      return (
-        <Card
-          key={props.schemaPath}
-          id={props.schemaPath}
-          moveCard={moveCard}
-          move={move}
-          props={props}
-          that={that}
-          obj={obj}
-          Field={Field}
-        />
-      )
-    })
-  )
-}

+ 0 - 63
packages/builder/src/components/preview/index.js

@@ -1,63 +0,0 @@
-import React, { Component } from 'react'
-import cls from 'classnames'
-
-import { connect } from 'react-redux'
-import {
-  changeComponentOrder,
-  moveComponent,
-  deleteComponent,
-  showComponentProps,
-  changeComponent
-} from '../../actions'
-
-import { Header, wrapComp2Class } from '../../utils/util'
-import registerPreviewFieldMiddleware from './fieldMiddleware'
-import MainBox from './mainBox'
-
-import PreviewStyle from './style'
-
-class Preview extends Component {
-  componentDidMount() {
-    registerPreviewFieldMiddleware(this)
-  }
-
-  onMouseClick = (id, comp) => {
-    this.props.changeComponent(id)
-    this.props.showComponentProps(id, comp)
-  }
-
-  deleteComponent = id => {
-    this.props.deleteComponent && this.props.deleteComponent(id)
-  }
-
-  render() {
-    return (
-      <PreviewStyle
-        className={cls('col-card preview-card', this.props.className)}
-      >
-        <Header>
-          <h2>预览区域</h2>
-          <p>组件过多时可下拉查看更多</p>
-        </Header>
-        <MainBox props={this.props} />
-      </PreviewStyle>
-    )
-  }
-}
-
-const mapStateToProps = state => state
-
-const mapDispatchToProps = dispatch => ({
-  changeComponentOrder: (sourceId, targetId, containerId) =>
-    dispatch(changeComponentOrder(sourceId, targetId, containerId)),
-  moveComponent: (sourceId, targetId) =>
-    dispatch(moveComponent(sourceId, targetId)),
-  deleteComponent: id => dispatch(deleteComponent(id)),
-  showComponentProps: (id, comp) => dispatch(showComponentProps(id, comp)),
-  changeComponent: componentId => dispatch(changeComponent(componentId))
-})
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(wrapComp2Class(Preview))

+ 0 - 133
packages/builder/src/components/preview/mainBox.js

@@ -1,133 +0,0 @@
-import React, { useRef, forwardRef } from 'react'
-import { DropTarget } from 'react-dnd'
-import ItemTypes from '../../constants/itemType'
-import { SchemaForm } from '../../utils/baseForm'
-import { isEmptyObj } from '../../utils/util'
-import pick from 'lodash.pick'
-import { normalizeSchema } from '../../utils/lang'
-import { FormProvider } from '../../constants/context'
-
-const RenderPreviewList = ({ props }) => {
-  const { preview, gbConfig = {}, schema = {}, renderEngine, onChange } = props
-  const { properties = {} } = schema
-  const { FormButtonGroup, Submit, Reset } = renderEngine
-  const { needFormButtonGroup } = gbConfig
-
-  if (isEmptyObj(properties)) {
-    return <p className="preview-tips">请从左边字段添加组件进来吧</p>
-  }
-
-  let children = ' '
-  try {
-    children =
-      needFormButtonGroup === true || needFormButtonGroup === 'true' ? (
-        <FormButtonGroup align="center" sticky>
-          <Submit>提交</Submit>
-          <Reset>重置</Reset>
-        </FormButtonGroup>
-      ) : (
-        ' '
-      )
-  } catch (e) {
-    if (window.location.href.indexOf('av_debug=true') > -1) {
-      console.error(`RenderPreviewList function error: ${e.message}`)
-    }
-  }
-
-  // @see: https://alibaba.github.io/uform/#/aAUeUD/qAI7IVFnsJ
-  const globalCfg = pick(gbConfig, [
-    'labelCol',
-    'wrapperCol',
-    'action',
-    'labelAlign',
-    'labelTextAlign',
-    'autoAddColon',
-    'inline',
-    'size',
-    'editable',
-    'defaultValue',
-    'value',
-    'locale',
-    'schema',
-    'effects',
-    'actions',
-    'editable',
-    'onValidateFailed',
-    'onReset',
-    'onSubmit',
-    'onChange'
-  ])
-
-  return (
-    <FormProvider
-      value={{
-        type: preview ? '' : 'preview'
-      }}
-    >
-      <SchemaForm
-        {...globalCfg}
-        onChange={onChange}
-        schema={normalizeSchema(schema)}
-      >
-        {children}
-      </SchemaForm>
-    </FormProvider>
-  )
-}
-
-const MainBox = forwardRef(
-  ({ props, canDrop, isOver, connectDropTarget }, ref) => {
-    const elementRef = useRef(null)
-    connectDropTarget(elementRef)
-
-    const isActive = canDrop && isOver
-    let backgroundColor = '#fff'
-    if (isActive) {
-      backgroundColor = '#f1f1f1'
-    }
-
-    return (
-      <div
-        className="preview-main"
-        style={Object.assign({}, { backgroundColor })}
-      >
-        <RenderPreviewList props={props} />
-        <div
-          ref={elementRef}
-          className="main-drop"
-          style={{
-            position: 'absolute',
-            left: 0,
-            top: 0,
-            width: '100%',
-            height: '100%'
-          }}
-        />
-      </div>
-    )
-  }
-)
-
-export default DropTarget(
-  [ItemTypes.FIELD, ItemTypes.LAYOUT],
-  {
-    drop: (props, monitor, component) => {
-      // console.info('drop', component)
-      if (!component) {
-        return
-      }
-      const hasDroppedOnChild = monitor.didDrop()
-      if (hasDroppedOnChild) {
-        return
-      }
-      // console.info('drop child')
-      component.onDrop(hasDroppedOnChild)
-    }
-  },
-  (connect, monitor) => ({
-    connectDropTarget: connect.dropTarget(),
-    isOver: monitor.isOver(),
-    isOverCurrent: monitor.isOver({ shallow: true }),
-    canDrop: monitor.canDrop()
-  })
-)(MainBox)

+ 0 - 161
packages/builder/src/components/preview/style.js

@@ -1,161 +0,0 @@
-import styled from 'styled-components'
-
-export default styled.div`
-  position: relative;
-  height: 100%;
-  .preview-main {
-    position: absolute;
-    top: 75px;
-    left: 20px;
-    right: 20px;
-    bottom: 20px;
-    padding: 20px;
-    background: #fff;
-    overflow-y: scroll;
-    border-radius: 4px;
-  }
-  .next-card-head {
-    margin-bottom: 10px;
-  }
-  .next-card-body {
-    padding-top: 0 !important;
-  }
-  .preview-line {
-    position: relative;
-    overflow: hidden;
-    margin-bottom: 0 !important;
-    padding: 10px !important;
-    border: 1px solid #e9e9e9;
-    outline: 1px solid #outline;
-    border-radius: 2px;
-    transition: all 0.1s ease;
-    user-select: none;
-    .preview-line-del {
-      cursor: pointer;
-      z-index: 101;
-      opacity: 0;
-      width: 30px;
-      height: 16px;
-      font-size: 12px;
-      color: #333;
-      text-align: center;
-      &::before {
-        content: '';
-        display: block;
-        margin: 0 auto 5px;
-        background: url('https://gw.alicdn.com/tfs/TB1j5fABkvoK1RjSZFDXXXY3pXa-30-32.png')
-          no-repeat center center;
-        background-size: 15px 16px;
-        height: 16px;
-      }
-    }
-    &:hover {
-      > .comp-item-layout-tool .preview-line-del {
-        opacity: 1;
-      }
-    }
-    .preview-line-layer {
-      position: absolute;
-      left: 0;
-      top: 0;
-      right: 0;
-      bottom: 0;
-      z-index: 100;
-      cursor: move;
-    }
-    .next-form-item-label {
-      text-align: right;
-    }
-  }
-  .preview-line-bar {
-    height: 10px;
-    &.active {
-      overflow: hidden;
-      height: 60px;
-      &::after {
-        content: '';
-        display: block;
-        border: 1px dashed #ddd;
-        border-radius: 4px;
-        margin: 6px 0;
-        height: 40px;
-      }
-    }
-    &:last-child {
-      padding-bottom: 999px;
-    }
-  }
-  .preview-line-enter {
-    border-color: #419bf9;
-  }
-  .preview-line-active {
-    cursor: pointer;
-    border-color: #5a60ff;
-    outline-color: #e6e7ff;
-  }
-  .preview-tips {
-    position: absolute;
-    left: 0;
-    top: 72px;
-    width: 100%;
-    text-align: center;
-    color: #999;
-  }
-
-  .comp-item,
-  .comp-item-layout {
-    position: relative;
-    width: 100%;
-    .next-row {
-      width: 100%;
-    }
-  }
-  .comp-item {
-    z-index: 110;
-    &.is-over-half {
-      &::after {
-        content: '';
-        display: block;
-        width: 100%;
-        height: 10px;
-        background: #222;
-      }
-    }
-    &.is-not-over-half {
-      &::before {
-        content: '';
-        display: block;
-        width: 100%;
-        height: 10px;
-        background: #222;
-      }
-    }
-  }
-  .comp-item-layout {
-    margin: 10px 0;
-    padding: 20px 10px;
-    min-height: 200px;
-    border: 1px dashed #ccc;
-    border-radius: 5px;
-    &.active {
-      border-color: #3f486b;
-    }
-  }
-  .comp-item-layout-tool {
-    position: absolute;
-    top: 5px;
-    right: 5px;
-    z-index: 101;
-    > * {
-      float: right;
-      margin-left: 8px;
-    }
-  }
-  .comp-item-layout-empty {
-    margin-top: 0;
-    padding-top: 20px;
-    width: 100%;
-    text-align: center;
-    color: #999;
-  }
-`

+ 0 - 53
packages/builder/src/components/props/colsDetail.js

@@ -1,53 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-
-class ColsDetail extends React.Component {
-  static propTypes = {
-    value: PropTypes.arrayOf(PropTypes.any),
-    onChange: PropTypes.func
-  }
-
-  handleChange = (idx, val) => {
-    const { UI } = this.props
-    if (!val) {
-      UI.Toast.error('请确保列宽是有效整数')
-      return false
-    }
-    const { onChange, value } = this.props
-    let newValue = [...value]
-    const diff = val - newValue[idx]
-
-    if (diff >= newValue[newValue.length - 1]) {
-      UI.Toast.error('请确保4列宽度加起来等于24')
-      return false
-    }
-
-    newValue = newValue.map((_val, i) => {
-      if (i === idx) {
-        return val
-      }
-      if (i === newValue.length - 1) {
-        return _val - diff
-      }
-      if (i < idx) {
-        return _val
-      }
-      return _val
-    })
-
-    onChange(newValue)
-  }
-
-  render() {
-    const { value = [], UI } = this.props
-    return value.map((item, idx) => (
-      <UI.NumberPicker
-        key={idx}
-        value={item}
-        onChange={val => this.handleChange(idx, val)}
-      />
-    ))
-  }
-}
-
-export default ColsDetail

+ 0 - 42
packages/builder/src/components/props/dataSourceEditor/index.js

@@ -1,42 +0,0 @@
-import React from 'react'
-import { connect, registerFormFields } from '../../../utils/baseForm'
-import DataSourceEditor from '../editors/fieldAttrEditors/dataSourceEditor'
-
-class Component extends React.Component {
-  constructor(props) {
-    super(props)
-    this.handleFieldAttrChange = this.handleFieldAttrChange.bind(this)
-  }
-
-  handleFieldAttrChange() {
-    return v => {
-      const { onChange } = this.props
-      onChange(v)
-    }
-  }
-
-  render() {
-    const { fieldStore = {}, value, UI } = this.props
-
-    return (
-      <div
-        style={{
-          marginBottom: 20
-        }}
-      >
-        <DataSourceEditor
-          UI={UI}
-          fieldStore={fieldStore}
-          value={value}
-          onChange={this.handleFieldAttrChange()}
-        />
-      </div>
-    )
-  }
-}
-
-registerFormFields({
-  dataSourceEditor: connect()(Component)
-})
-
-export default () => {}

+ 0 - 36
packages/builder/src/components/props/defaultValueCascader/index.js

@@ -1,36 +0,0 @@
-import React, { Component } from 'react'
-import { connect, registerFormFields } from '../../../utils/baseForm'
-import DefaultValueEditor from '../editors/fieldAttrEditors/defaultValueEditor/index'
-
-class defaultValueCascader extends Component {
-  constructor(props) {
-    super(props)
-    this.handleFieldAttrChange = this.handleFieldAttrChange.bind(this)
-  }
-
-  handleFieldAttrChange() {
-    return v => {
-      const { onChange } = this.props
-      onChange(v)
-    }
-  }
-
-  render() {
-    const { fieldStore = {}, value, UI } = this.props
-
-    return (
-      <DefaultValueEditor
-        store={fieldStore}
-        value={value}
-        onChange={this.handleFieldAttrChange()}
-        UI={UI}
-      />
-    )
-  }
-}
-
-registerFormFields({
-  defaultValueCascader: connect()(defaultValueCascader)
-})
-
-export default () => {}

+ 0 - 310
packages/builder/src/components/props/editors/fieldAttrEditors/dataSourceEditor.js

@@ -1,310 +0,0 @@
-import React, { Component } from 'react'
-import DataSourceEnum from './dataSourceEnum'
-import styled from 'styled-components'
-
-const LABEL_COL = { fixedSpan: 4 }
-const STYLE_W = { width: 220 }
-const JSON_EXAMPLE = `
-[{
-  "label": "foo",
-  "value": "bar"
-}]
-`
-const REQ_OPT_EXAMPLE = `
-  {
-    key1: aa,
-    key2: bb
-  }
-`
-
-class DataSourceEditor extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      dataSourceType: this.getDefaultDataSourceType(props),
-      error: ''
-    }
-  }
-
-  componentDidUpdate(prevProps, prevState) {
-    const _dataSourceType = this.getDefaultDataSourceType(
-      this.props,
-      prevState.dataSourceType
-    )
-    if (_dataSourceType !== prevState.dataSourceType) {
-      this.setState({
-        dataSourceType: _dataSourceType
-      })
-    }
-  }
-
-  getDefaultDataSourceType = (props = this.props, defaultType) => {
-    const { fieldStore, value } = props
-    const xProps = fieldStore['x-props'] || {}
-    const enums = value.enum
-
-    const url = xProps.url || ''
-    if (enums) return 'local'
-    if (url) return 'remote'
-
-    return defaultType || 'local'
-  }
-
-  handleTypeChange = v => {
-    const { onChange } = this.props
-    if (v === 'local') {
-      this.setState({ dataSourceType: 'local' }, () => {
-        onChange({
-          url: ''
-        })
-      })
-    } else {
-      this.setState({ dataSourceType: 'remote' }, () => {
-        onChange({
-          enum: ''
-        })
-      })
-    }
-  }
-
-  handleReqOptValueChange = v => {
-    const { onChange } = this.props
-
-    if (this.timer1) clearTimeout(this.timer1)
-    this.timer1 = setTimeout(() => {
-      if (!v) {
-        onChange({
-          requestOptions: {}
-        })
-      } else {
-        onChange({
-          requestOptions: {
-            data: this.transformData(v, false)
-          }
-        })
-      }
-    }, 10)
-  }
-
-  handleReqOptChange = ev => {
-    const { onChange } = this.props
-    const v = ev.target.value
-
-    try {
-      JSON.parse(v)
-    } catch (e) {
-      this.setState({ error: e.message || '不是合法的json格式!' })
-      return
-    }
-
-    this.setState({ error: '' })
-
-    ev.preventDefault()
-    ev.stopPropagation()
-
-    if (this.timer1) clearTimeout(this.timer1)
-    this.timer1 = setTimeout(() => {
-      if (!v) {
-        onChange({
-          requestOptions: {}
-        })
-      } else {
-        onChange({
-          requestOptions: {
-            data: JSON.parse(v)
-          }
-        })
-      }
-    }, 10)
-  }
-
-  handleEnumChange = ev => {
-    const v = ev.target.value
-    if (!v) {
-      this.setState({ error: '' })
-      return
-    }
-
-    try {
-      JSON.parse(v)
-    } catch (e) {
-      this.setState({ error: e.message || '不是合法的json格式!' })
-      return
-    }
-
-    this.setState({ error: '' })
-
-    ev.preventDefault()
-    ev.stopPropagation()
-
-    const { onChange } = this.props
-    if (this.timer) clearTimeout(this.timer)
-    this.timer = setTimeout(() => {
-      onChange({
-        enum: JSON.parse(v)
-      })
-    }, 10)
-  }
-
-  handleEnumValueChange = value => {
-    if (this.timer) clearTimeout(this.timer)
-    this.timer = setTimeout(() => {
-      this.props.onChange({
-        enum: value
-      })
-    }, 10)
-  }
-
-  handleUrlChange = v => {
-    const { onChange } = this.props
-    onChange({
-      url: v
-    })
-  }
-
-  /**
-   * 对象跟数组互转
-   * { a: 1, b: 2 } => [{value: 1, label: a}, {value: 2, label: b}]
-   */
-  transformData = (data, toArr = true) => {
-    if (toArr) {
-      return (
-        !!data &&
-        typeof data === 'object' &&
-        Object.keys(data).map(key => ({
-          value: data[key],
-          label: key
-        }))
-      )
-    } else {
-      const obj = {}
-      data &&
-        Array.isArray(data) &&
-        data.forEach(item => {
-          item.label !== undefined && (obj[item.label] = item.value)
-        })
-      return obj
-    }
-  }
-
-  render() {
-    const { fieldStore = {}, UI } = this.props
-    const { dataSourceType, error } = this.state
-    const xProps = fieldStore['x-props'] || {}
-    const { requestOptions = {} } = xProps
-    const { data = {} } = requestOptions
-
-    const reqDataArr = this.transformData(data, true)
-    const { Form, Input, Tab, RadioGroup, TabPane, version: UIVersion } = UI
-
-    const dataSource = [
-      {
-        label: '手动填写',
-        value: 'local'
-      }
-    ]
-
-    const defaultSource = xProps.enum || fieldStore.enum || ''
-
-    if (Object.hasOwnProperty.call(xProps, 'url')) {
-      // xprops带有url的则支持远程拉取数据
-      dataSource.push({
-        label: '远程接口获取',
-        value: 'remote'
-      })
-    }
-
-    const tabProps = {}
-    tabProps[UIVersion === '1.x' ? 'shape' : 'type'] = 'text'
-
-    const formItemProps = {}
-    const _key = UIVersion === '1.x' ? 'validateState' : 'validateStatus'
-    formItemProps[_key] = error ? 'error' : 'success'
-
-    return (
-      <Form.Item labelCol={LABEL_COL} className={this.props.className}>
-        <RadioGroup
-          dataSource={dataSource}
-          value={this.state.dataSourceType}
-          onChange={this.handleTypeChange}
-        />
-        {dataSourceType === 'local' ? (
-          <Form.Item
-            {...formItemProps}
-            extra={<span style={{ color: 'red' }}>{error}</span>}
-          >
-            <Tab {...tabProps} size="small">
-              <TabPane title="可视化" tab="可视化" key="visual">
-                <DataSourceEnum
-                  dataSource={defaultSource}
-                  onChange={this.handleEnumValueChange}
-                  UI={UI}
-                />
-              </TabPane>
-              <TabPane title="可视化" tab="源码" key="code">
-                <Input
-                  key={`${Math.random()}-enum`}
-                  multiple
-                  rows={6}
-                  placeholder={`请输入JSON,e.g.\n ${JSON_EXAMPLE}`}
-                  defaultValue={
-                    defaultSource ? JSON.stringify(defaultSource) : ''
-                  }
-                  onBlur={this.handleEnumChange}
-                  style={{
-                    ...STYLE_W,
-                    height: 50
-                  }}
-                />
-              </TabPane>
-            </Tab>
-          </Form.Item>
-        ) : null}
-        {dataSourceType === 'remote' ? (
-          <Form.Item
-            {...formItemProps}
-            extra={<span style={{ color: 'red' }}>{error}</span>}
-          >
-            <Input
-              key="url"
-              placeholder="请输入接口url"
-              value={xProps.url}
-              onChange={this.handleUrlChange}
-              style={STYLE_W}
-            />
-            <Tab {...tabProps} size="small">
-              <TabPane title="可视化" tab="可视化" key="visual">
-                <div style={{ marginTop: 10 }}>
-                  <DataSourceEnum
-                    dataSource={reqDataArr}
-                    onChange={this.handleReqOptValueChange}
-                  />
-                </div>
-              </TabPane>
-              <TabPane title="可视化" tab="源码" key="code">
-                <Input
-                  key={`${Math.random()}-requestOption`}
-                  style={STYLE_W}
-                  multiple
-                  rows={6}
-                  placeholder={`请输入额外请求参数JSON,e.g.\n ${REQ_OPT_EXAMPLE}`}
-                  defaultValue={data ? JSON.stringify(data) : ''}
-                  onBlur={this.handleReqOptChange}
-                />
-              </TabPane>
-            </Tab>
-          </Form.Item>
-        ) : null}
-      </Form.Item>
-    )
-  }
-}
-
-export default styled(DataSourceEditor)`
-  .next-form-item-control {
-    width: 100%;
-  }
-  .next-tabs-medium .next-tabs-content {
-    padding: 0;
-  }
-`

+ 0 - 126
packages/builder/src/components/props/editors/fieldAttrEditors/dataSourceEnum.js

@@ -1,126 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-
-class Component extends React.Component {
-  state = {}
-
-  // 新增一行记录
-  handleAddNewItem = () => {
-    const newDataSource = [...this.props.dataSource]
-    newDataSource.push({
-      value: '',
-      label: ''
-    })
-    this.props.onChange && this.props.onChange(newDataSource)
-  }
-
-  // 删除某一行
-  handleDeleteItem = idx => {
-    const newDataSource = [...this.props.dataSource]
-    newDataSource.splice(idx, 1)
-    this.props.onChange && this.props.onChange(newDataSource)
-  }
-
-  // 修改某行记录
-  handleChangeItemRow = (e, idx, key) => {
-    const { value } = e.target
-    const newDataSource = [...this.props.dataSource]
-    newDataSource[idx][key] = value
-    this.props.onChange && this.props.onChange(newDataSource)
-  }
-
-  renderItemRow = (item = {}, idx) => {
-    const { value = '', label = '' } = item
-    const { UI } = this.props
-    const btnProps = {}
-    if (UI.version === '1.x') {
-      btnProps.text = true
-    } else {
-      btnProps.shape = 'text'
-    }
-    return (
-      <div className="source-row" key={`${idx}`}>
-        <ul>
-          <li>
-            <label>字段名:</label>
-            <UI.Input
-              defaultValue={label}
-              onBlur={e => this.handleChangeItemRow(e, idx, 'label')}
-            />
-          </li>
-          <li>
-            <label>值:</label>
-            <UI.Input
-              defaultValue={value}
-              onBlur={e => this.handleChangeItemRow(e, idx, 'value')}
-            />
-          </li>
-        </ul>
-        <UI.Button
-          className="ashbin-btn"
-          {...btnProps}
-          onClick={() => this.handleDeleteItem(idx)}
-        >
-          <UI.Icon type="ashbin" />
-        </UI.Button>
-      </div>
-    )
-  }
-
-  renderNewBtn() {
-    const { UI } = this.props
-    return (
-      <div className="source-btn-new">
-        <UI.Button size="small" onClick={this.handleAddNewItem}>
-          <UI.Icon type="add" />
-          添加
-        </UI.Button>
-      </div>
-    )
-  }
-
-  render() {
-    const { dataSource = [], className } = this.props
-
-    return (
-      <div className={className}>
-        {dataSource && dataSource.map(this.renderItemRow)}
-        {this.renderNewBtn()}
-      </div>
-    )
-  }
-}
-
-export default styled(Component)`
-  .source-row {
-    position: relative;
-    margin-bottom: 4px;
-    li {
-      display: inline-block;
-      width: 50%;
-      > label,
-      .next-input {
-        display: inline-block;
-      }
-      > label {
-        color: ${props => props.theme.whiteColor};
-        text-align: right;
-      }
-      .next-input {
-        width: 50px;
-      }
-    }
-    .ashbin-btn {
-      position: absolute;
-      top: 50%;
-      right: 5px;
-      transform: translate3d(0, -50%, 0);
-      opacity: 0.5;
-    }
-    &:hover {
-      .ashbin-btn {
-        opacity: 1;
-      }
-    }
-  }
-`

+ 0 - 41
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/arrayDefaultEditor.js

@@ -1,41 +0,0 @@
-import React, { Component } from 'react'
-import DefaultValueGenerator from './defaultValueGenerator'
-
-const ds = [
-  {
-    label: '手动输入',
-    value: 'specify'
-  },
-  {
-    label: '从url获取',
-    value: 'url'
-  }
-]
-class Editor extends Component {
-  handleChange = v => {
-    const { store } = this.props
-    store.setAttr('default', v)
-  }
-
-  render() {
-    const { store, UI } = this.props
-    const { enums } = store
-
-    return (
-      <DefaultValueGenerator
-        flag="array"
-        ds={ds}
-        {...this.props}
-        customEditor={{
-          specify: (
-            <div>
-              <UI.Checkbox.Group dataSource={enums || []} />
-            </div>
-          )
-        }}
-      />
-    )
-  }
-}
-
-export default Editor

+ 0 - 29
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/boolDefaultEditor.js

@@ -1,29 +0,0 @@
-import React, { Component } from 'react'
-import DefaultValueGenerator from './defaultValueGenerator'
-
-const ds = [
-  {
-    label: '手动输入',
-    value: 'specify'
-  },
-  {
-    label: '从url获取',
-    value: 'url'
-  }
-]
-class Editor extends Component {
-  render() {
-    return (
-      <DefaultValueGenerator
-        flag="switch"
-        ds={ds}
-        {...this.props}
-        customEditor={{
-          specify: <this.props.UI.Switch style={{ marginLeft: 20 }} />
-        }}
-      />
-    )
-  }
-}
-
-export default Editor

+ 0 - 79
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateDefaultEditor.js

@@ -1,79 +0,0 @@
-import React, { Component } from 'react'
-import DefaultValueGenerator from './defaultValueGenerator'
-
-const ds = [
-  {
-    label: '当前日期',
-    value: 'now'
-  },
-  {
-    label: '未来',
-    value: 'future'
-  },
-  {
-    label: '过去',
-    value: 'past'
-  },
-  {
-    label: '固定日期',
-    value: 'specify'
-  },
-  {
-    label: '从url获取',
-    value: 'url'
-  }
-]
-
-const DatePickerDefault = props => (
-  <props.UI.DatePicker
-    {...props}
-    onChange={(v, vStr) => {
-      props.onChange(vStr)
-    }}
-    popupAlign={'tr br'}
-    style={{
-      verticalAlign: 'top',
-      marginLeft: 10,
-      maxWidth: 90
-    }}
-  />
-)
-
-class Editor extends Component {
-  render() {
-    const { UI } = this.props
-    return (
-      <DefaultValueGenerator
-        flag="date"
-        ds={ds}
-        {...this.props}
-        customEditor={{
-          now: <div />,
-          future: (
-            <UI.NumberPicker
-              addonAfter="天"
-              inputWidth={75}
-              style={{
-                verticalAlign: 'top',
-                marginLeft: 10
-              }}
-            />
-          ),
-          past: (
-            <UI.NumberPicker
-              addonAfter="天"
-              inputWidth={75}
-              style={{
-                verticalAlign: 'top',
-                marginLeft: 10
-              }}
-            />
-          ),
-          specify: <DatePickerDefault UI={UI} />
-        }}
-      />
-    )
-  }
-}
-
-export default Editor

+ 0 - 47
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateRangeDefaultEditor.js

@@ -1,47 +0,0 @@
-import React, { Component } from 'react'
-import DateDefaultEditor from './dateDefaultEditor'
-
-class Editor extends Component {
-  constructor(props) {
-    super(props)
-    this.handleEndDateChange = this.handleEndDateChange.bind(this)
-    this.handleEndDateChange = this.handleEndDateChange.bind(this)
-  }
-
-  handleStartDateChange = v => {
-    this.props.onChange([v, this.props.value[1]])
-  }
-
-  handleEndDateChange = v => {
-    this.props.onChange([this.props.value[0], v])
-  }
-
-  render() {
-    const { store = {}, value = [], UI } = this.props
-    const style = {
-      fontSize: 12,
-      marginBottom: 5
-    }
-
-    return (
-      <div>
-        <div style={style}>开始日期</div>
-        <DateDefaultEditor
-          onChange={this.handleStartDateChange}
-          value={value[0]}
-          store={store}
-          UI={UI}
-        />
-        <div style={style}>结束日期</div>
-        <DateDefaultEditor
-          onChange={this.handleEndDateChange}
-          value={value[1]}
-          store={store}
-          UI={UI}
-        />
-      </div>
-    )
-  }
-}
-
-export default Editor

+ 0 - 52
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateTimeDefaultEditor.js

@@ -1,52 +0,0 @@
-import React, { Component } from 'react'
-import DefaultValueGenerator from './defaultValueGenerator'
-
-const ds = [
-  {
-    label: '当前时间',
-    value: 'now'
-  },
-  {
-    label: '固定时间',
-    value: 'specify'
-  },
-  {
-    label: '从url获取',
-    value: 'url'
-  }
-]
-
-const DatePickerDefault = props => (
-  <props.UI.TimePicker
-    onChange={(v, vStr) => {
-      if (vStr) {
-        props.onChange(vStr)
-      } else {
-        props.onChange(v.format('HH:mm:ss'))
-      }
-    }}
-    style={{
-      verticalAlign: 'top',
-      marginLeft: 5
-    }}
-  />
-)
-
-class Editor extends Component {
-  render() {
-    const { UI } = this.props
-    return (
-      <DefaultValueGenerator
-        flag="time"
-        ds={ds}
-        {...this.props}
-        customEditor={{
-          now: <div />,
-          specify: <DatePickerDefault UI={UI} />
-        }}
-      />
-    )
-  }
-}
-
-export default Editor

+ 0 - 35
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/dateTimeRangeDefaultEditor.js

@@ -1,35 +0,0 @@
-import React, { Component } from 'react'
-import DateTimeDefaultEditor from './dateTimeDefaultEditor'
-
-class Editor extends Component {
-  handleStartDateChange = (v, vStr) => {
-    this.props.onChange([vStr, this.props.value[1]])
-  }
-
-  handleEndDateChange = (v, vStr) => {
-    this.props.onChange([this.props.value[0], vStr])
-  }
-
-  render() {
-    return (
-      <div>
-        <div style={{ color: '#fff', fontSize: 12, marginBottom: 5 }}>
-          开始时间
-        </div>
-        <DateTimeDefaultEditor
-          onChange={this.handleStartDateChange}
-          value={this.props.value[0]}
-        />
-        <div style={{ color: '#fff', fontSize: 12, marginBottom: 5 }}>
-          结束时间
-        </div>
-        <DateTimeDefaultEditor
-          onChange={this.handleEndDateChange}
-          value={this.props.value[1]}
-        />
-      </div>
-    )
-  }
-}
-
-export default Editor

+ 0 - 110
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/defaultValueGenerator.js

@@ -1,110 +0,0 @@
-import React, { Component } from 'react'
-
-class DefaultValueGenerator extends Component {
-  static defaultProps = {
-    customEditor: {}
-  }
-
-  constructor(props) {
-    super(props)
-    const value = props.value || {}
-    this.state = {
-      type: value.type || '',
-      value: value.value || '',
-      flag: value.flag || props.flag
-    }
-  }
-
-  componentDidUpdate(prevProps, prevState) {
-    const value = this.props.value || {}
-    const preValue = prevProps.value || {}
-    if (JSON.stringify(value) !== JSON.stringify(preValue)) {
-      this.setState({
-        type: value.type || '',
-        value: value.value || '',
-        flag: value.flag || this.props.flag
-      })
-    }
-  }
-
-  handleValueTypeChange = v => {
-    const { store } = this.props
-    const { name } = store
-
-    this.setState(
-      {
-        type: v,
-        value: v === 'url' ? name : ''
-      },
-      () => {
-        this.props.onChange({
-          ...this.state
-        })
-      }
-    )
-  }
-
-  handleValueChange = v => {
-    this.setState(
-      {
-        value: v
-      },
-      () => {
-        this.props.onChange({
-          ...this.state
-        })
-      }
-    )
-  }
-
-  getValueEditor = (type, value) => {
-    if (this.props.customEditor[type]) {
-      return React.cloneElement(this.props.customEditor[type], {
-        onChange: this.handleValueChange,
-        value
-      })
-    }
-
-    if (type === 'url') {
-      return (
-        <span
-          style={{
-            color: '#fff',
-            marginLeft: 20,
-            display: 'inline-block',
-            verticalAlign: 'top'
-          }}
-        >
-          <this.props.UI.Input
-            value={value}
-            onChange={this.handleValueChange}
-            placeholder="url上的key"
-            style={{
-              verticalAlign: 'top',
-              width: 75,
-              marginLeft: 0
-            }}
-          />
-        </span>
-      )
-    } else {
-      return null
-    }
-  }
-
-  render() {
-    const { type, value, flag } = this.state
-    return (
-      <div>
-        <this.props.UI.Select
-          value={type}
-          dataSource={this.props.ds}
-          onChange={this.handleValueTypeChange}
-        />
-        {this.getValueEditor(type, value, flag)}
-      </div>
-    )
-  }
-}
-
-export default DefaultValueGenerator

+ 0 - 118
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/index.js

@@ -1,118 +0,0 @@
-import React, { Component } from 'react'
-import ArrayDefaultEditor from './arrayDefaultEditor'
-import BoolDefaultEditor from './boolDefaultEditor'
-import DateDefaultEditor from './dateDefaultEditor'
-import DateRangeDefaultEditor from './dateRangeDefaultEditor'
-import DateTimeDefaultEditor from './dateTimeDefaultEditor'
-import DateTimeRangeDefaultEditor from './dateTimeRangeDefaultEditor'
-import MonthDefaultEditor from './monthDefaultEditor'
-import StringDefaultEditor from './stringDefaultEditor'
-
-class DefaultValueEditor extends Component {
-  constructor(props) {
-    super(props)
-    this.handleOnChange = this.handleOnChange.bind(this)
-  }
-
-  getEditorType = () => {
-    const { store } = this.props
-    const { type, enums } = store
-    const xComponent = store['x-component']
-    if (type === 'date') {
-      return 'date' // 当前日期/前${d}天/未来${d}天/日期选择
-    } else if (type === 'month') {
-      return 'month' // 当前月/前${d}月/后${d}月/月份选择
-    } else if (type === 'daterange') {
-      return 'daterange' // 当前日期/前${d}天/未来${d}天/日期选择- 当前日期/前${d}天/未来${d}天/日期选择
-    } else if (type === 'time') {
-      return 'time' // 当前时间/时间选择
-    } else if (type === 'datetimerange') {
-      return 'datetimerange' // 当前时间/时间选择 - 当前时间/时间选择
-    } else if (type === 'boolean') {
-      return 'boolean' // switch
-    } else if (type === 'string') {
-      if (xComponent === 'radio' || xComponent === 'checkbox' || enums) {
-        return 'array' // 数组选择
-      } else {
-        return 'string'
-      }
-    } else {
-      return 'string'
-    }
-  }
-
-  handleOnChange = v => {
-    this.props.onChange(v)
-  }
-
-  createDefaultValueByType = editorType => {
-    const { store, value } = this.props
-    const { enums } = store
-    const xComponent = store['x-component']
-
-    switch (editorType) {
-      case 'date':
-      case 'time':
-      case 'month':
-        return value || {}
-      case 'daterange':
-      case 'datetimerange':
-        // @todo: 不知道为啥这里会传入一个object
-        return Array.isArray(value) && value.length ? value : [{}, {}]
-      case 'boolean':
-        return value || {}
-      case 'string':
-        if (xComponent === 'radio' || xComponent === 'checkbox' || enums) {
-          return value || [] // 数组选择
-        } else {
-          return value || {}
-        }
-      default:
-        return value || {}
-    }
-  }
-
-  createEditorProps = editorType => {
-    const { store } = this.props
-
-    return {
-      store,
-      value: this.createDefaultValueByType(editorType),
-      onChange: this.handleOnChange
-    }
-  }
-
-  getEditor = editorType => {
-    const props = this.createEditorProps(editorType)
-    const { UI } = this.props
-    switch (editorType) {
-      case 'string':
-        return <StringDefaultEditor {...props} UI={UI} />
-      case 'array':
-        return <ArrayDefaultEditor {...props} UI={UI} />
-      case 'boolean':
-        return <BoolDefaultEditor {...props} UI={UI} />
-      case 'month':
-        return <MonthDefaultEditor {...props} UI={UI} />
-      case 'date':
-        return <DateDefaultEditor {...props} UI={UI} />
-      case 'daterange':
-        return <DateRangeDefaultEditor {...props} UI={UI} />
-      case 'time':
-        return <DateTimeDefaultEditor {...props} UI={UI} />
-      case 'datetimerange':
-        return <DateTimeRangeDefaultEditor {...props} UI={UI} />
-      default:
-        return <StringDefaultEditor {...props} UI={UI} />
-    }
-  }
-
-  render() {
-    const editorType = this.getEditorType()
-    const editor = this.getEditor(editorType)
-
-    return <div style={{ minWidth: '300px', marginBottom: 20 }}>{editor}</div>
-  }
-}
-
-export default DefaultValueEditor

+ 0 - 80
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/monthDefaultEditor.js

@@ -1,80 +0,0 @@
-import React, { Component } from 'react'
-import DefaultValueGenerator from './defaultValueGenerator'
-
-const ds = [
-  {
-    label: '当前月',
-    value: 'now'
-  },
-  {
-    label: '未来',
-    value: 'future'
-  },
-  {
-    label: '过去',
-    value: 'past'
-  },
-  {
-    label: '固定月',
-    value: 'specify'
-  },
-  {
-    label: '从url获取',
-    value: 'url'
-  }
-]
-
-const MonthPickerDefault = props => {
-  const { UI } = props
-  const { MonthPicker } = UI.DatePicker
-  return (
-    <MonthPicker
-      onChange={(v, vStr) => {
-        props.onChange(vStr)
-      }}
-      style={{
-        verticalAlign: 'top',
-        marginLeft: 20
-      }}
-    />
-  )
-}
-
-class Editor extends Component {
-  render() {
-    const { UI } = this.props
-    return (
-      <DefaultValueGenerator
-        flag="month"
-        ds={ds}
-        {...this.props}
-        customEditor={{
-          now: <div />,
-          future: (
-            <UI.NumberPicker
-              addonAfter="月"
-              inputWidth={100}
-              style={{
-                verticalAlign: 'top',
-                marginLeft: 20
-              }}
-            />
-          ),
-          past: (
-            <UI.NumberPicker
-              addonAfter="月"
-              inputWidth={100}
-              style={{
-                verticalAlign: 'top',
-                marginLeft: 20
-              }}
-            />
-          ),
-          specify: <MonthPickerDefault />
-        }}
-      />
-    )
-  }
-}
-
-export default Editor

+ 0 - 39
packages/builder/src/components/props/editors/fieldAttrEditors/defaultValueEditor/stringDefaultEditor.js

@@ -1,39 +0,0 @@
-import React, { Component } from 'react'
-import DefaultValueGenerator from './defaultValueGenerator'
-
-const ds = [
-  {
-    label: '手动输入',
-    value: 'specify'
-  },
-  {
-    label: '从url获取',
-    value: 'url'
-  }
-]
-
-class Editor extends Component {
-  render() {
-    const { UI } = this.props
-
-    return (
-      <DefaultValueGenerator
-        flag="string"
-        ds={ds}
-        {...this.props}
-        customEditor={{
-          specify: (
-            <UI.Input
-              placeholder="请输入默认值"
-              style={{
-                verticalAlign: 'top'
-              }}
-            />
-          )
-        }}
-      />
-    )
-  }
-}
-
-export default Editor

+ 0 - 196
packages/builder/src/components/props/fileSetting.js

@@ -1,196 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { SchemaForm, Field } from '../../utils/baseForm'
-import remove from 'lodash.remove'
-
-const showUploadListData = [
-  { value: 'text', label: '文字' },
-  { value: 'text-image', label: '图文' },
-  { value: 'picture-card', label: '卡片' }
-]
-
-const apiHost =
-  window.location.href.indexOf('.tmall.com') > -1
-    ? '//sop.tmall.com'
-    : '//sop.daily.tmall.net'
-const uploadUrl = `${apiHost}/workflow/instance/formUpload.do`
-
-// 文件特殊设置
-class fileSetting extends Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      xprops: props.xprops || {}
-    }
-  }
-
-  componentDidUpdate(prevProps) {
-    const preXprops = prevProps.xprops || {}
-    const curXprops = this.props.xprops || {}
-    if (JSON.stringify(preXprops) !== JSON.stringify(curXprops)) {
-      this.setState({
-        xprops: curXprops
-      })
-    }
-  }
-
-  onChangeDefaultFile(newDefaultFileList) {
-    const { onChange } = this.props
-    const newXprops = this.state.xprops
-    newXprops.defaultFileList = newDefaultFileList
-
-    this.setState(
-      {
-        xprops: newXprops
-      },
-      () => {
-        onChange && onChange(newXprops)
-      }
-    )
-  }
-
-  onChangeHandler = formdata => {
-    const { onChange } = this.props
-    const newXprops = Object.assign({}, this.state.xprops, formdata)
-
-    if (newXprops.file) {
-      newXprops.defaultFileList = newXprops.file
-      delete newXprops.file
-    }
-
-    this.setState(
-      {
-        xprops: newXprops
-      },
-      () => {
-        onChange && onChange(newXprops)
-      }
-    )
-  }
-
-  getSchemaValue() {
-    const { xprops = {} } = this.props
-    const {
-      action = '',
-      limit = 10,
-      showUploadList = true,
-      listType = 'text',
-      defaultFileList = []
-    } = xprops
-    return {
-      action,
-      limit,
-      showUploadList,
-      listType,
-      file: defaultFileList
-    }
-  }
-
-  renderProps() {
-    return (
-      <SchemaForm
-        value={this.getSchemaValue()}
-        onChange={this.onChangeHandler}
-        labelAlign="top"
-      >
-        <Field title="文件上传地址" type="string" name="action" />
-        <Field title="文件限制个数" type="number" name="limit" />
-        <Field title="展示文件列表" type="boolean" name="showUploadList" />
-        <Field
-          title="上传列表样式"
-          type="string"
-          enum={showUploadListData}
-          name="listType"
-        />
-      </SchemaForm>
-    )
-  }
-
-  renderUploadComp() {
-    const { xprops = {}, UI } = this.props
-    const { defaultFileList = [] } = xprops
-    return (
-      <div className="next-form">
-        <div className="next-form-item">
-          <label className="next-col-8 next-form-item-label">
-            <span>模板文件:</span>
-          </label>
-          <div className="next-form-item-control">
-            <div className="schema-inline-field">
-              <div className="schema-form-field">
-                <UI.Upload
-                  name="file"
-                  listType="text"
-                  withCredentials
-                  action={uploadUrl}
-                  data={{
-                    // eslint-disable-next-line @typescript-eslint/camelcase
-                    _scm_token_: window._scm_token_
-                  }}
-                  formatter={res => {
-                    const imgKey =
-                      res.data && Object.keys(res.data).length
-                        ? Object.keys(res.data)[0]
-                        : null
-
-                    return {
-                      code: res.succ === true ? '0' : '1',
-                      name: imgKey,
-                      imgURL: imgKey && res.data[imgKey],
-                      downloadURL: imgKey && res.data[imgKey],
-                      fileURL: imgKey && res.data[imgKey]
-                    }
-                  }}
-                  fileList={defaultFileList}
-                  onRemove={res => {
-                    const newDefaultFileList =
-                      this.props.xprops.defaultFileList || []
-                    remove(
-                      newDefaultFileList,
-                      item => item.fileURL === res.fileURL
-                    )
-                    this.onChangeDefaultFile(newDefaultFileList)
-                  }}
-                  onSuccess={res => {
-                    const newDefaultFileList =
-                      this.props.xprops.defaultFileList || []
-                    newDefaultFileList.push(res)
-                    this.onChangeDefaultFile(newDefaultFileList)
-                  }}
-                  onError={() => {
-                    this.props.UI.Toast.error('文件上传失败')
-                  }}
-                >
-                  <UI.Button>上传文件</UI.Button>
-                </UI.Upload>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    )
-  }
-
-  render() {
-    return (
-      <div className="file-setting">
-        {this.renderProps()}
-        {this.renderUploadComp()}
-      </div>
-    )
-  }
-}
-
-fileSetting.propTypes = {
-  // eslint-disable-next-line
-  xprops: PropTypes.object,
-  onChange: PropTypes.func
-}
-
-fileSetting.defaultProps = {
-  xprops: {},
-  // eslint-disable-next-line
-  onChange: xprops => {}
-}
-
-export default fileSetting

+ 0 - 263
packages/builder/src/components/props/propsSetting.js

@@ -1,263 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import {
-  SchemaForm,
-  registerFormFields,
-  connect as formConnect
-} from '../../utils/baseForm'
-import { connect } from 'react-redux'
-import {
-  showComponentProps,
-  editComponentProps,
-  editComponent
-} from '../../actions'
-import { State } from 'react-powerplug'
-import { getCompDetailById, flatObj } from '../../utils/util'
-
-import PropsStyle from './style'
-
-import FileSetting from './fileSetting'
-
-import './defaultValueCascader/index'
-import './dataSourceEditor/index'
-import ColsDetail from './colsDetail'
-
-import pickBy from 'lodash.pickby'
-
-// 属性设置
-class PropsSetting extends Component {
-  static propTypes = {
-    componentId: PropTypes.arrayOf(PropTypes.string),
-    editComponent: PropTypes.func,
-    editComponentProps: PropTypes.func,
-    componentProps: PropTypes.object
-  }
-
-  constructor(props) {
-    super(props)
-    registerFormFields({
-      colsDetail: formConnect({
-        defaultProps: {
-          UI: this.props.UI
-        }
-      })(ColsDetail)
-    })
-  }
-
-  onChangeHandler = formdata => {
-    const { componentId = [] } = this.props
-    if (!componentId.length) return false
-
-    const propsData = pickBy(formdata, x => x !== undefined)
-
-    // 是否隐藏属性
-    propsData['x-props'] = propsData['x-props'] || {}
-    propsData['x-props'].style = propsData['x-props'].style || {}
-
-    if (propsData['x-props.htmltype'] === true) {
-      propsData['x-props'].htmlType = 'hidden'
-      propsData['x-props'].style.display = 'none'
-    } else {
-      propsData['x-props'].htmlType = ''
-      propsData['x-props'].style.display = 'block'
-    }
-
-    // 配置选项
-    if (propsData.dataSource !== undefined) {
-      propsData['x-props'] = {
-        ...propsData['x-props'],
-        ...propsData.dataSource
-      }
-    }
-
-    // key1.key2.key3...keyx 格式转换
-    const submitPropsData = flatObj(propsData)
-
-    this.updateComponentPropsData(componentId, submitPropsData)
-  }
-
-  getSchemaValue() {
-    const { componentId, componentProps = {}, initSchemaData = {} } = this.props
-
-    if (!componentId.length) return {}
-
-    const curComponentProps = componentProps[componentId.toString()] || []
-
-    const result = {}
-    curComponentProps.forEach(compProp => {
-      const { name, value } = compProp
-      result[name] = value
-    })
-
-    const curComponentAttr = getCompDetailById(componentId, initSchemaData)
-
-    if (curComponentAttr['x-props']) {
-      result['x-props'] = curComponentAttr['x-props']
-      Object.keys(result['x-props']).forEach(key => {
-        if (
-          Object.hasOwnProperty.call(result, `x-props.${key}`) &&
-          result[`x-props.${key}`] === undefined
-        ) {
-          result[`x-props.${key}`] = result['x-props'][key]
-        }
-      })
-    }
-
-    return result
-  }
-
-  updateComponentPropsData = (componentId, propsData) => {
-    this.props.editComponent(componentId, propsData)
-    this.props.editComponentProps(componentId, propsData)
-  }
-
-  generatePropsSchema() {
-    const {
-      initSchemaData = {},
-      componentId,
-      componentProps = {},
-      UI
-    } = this.props
-
-    if (!componentId.length) {
-      return {
-        type: 'object',
-        properties: {}
-      }
-    }
-
-    const curComponentProps = componentProps[componentId.toString()] || []
-    const curComponentAttr = getCompDetailById(componentId, initSchemaData)
-
-    const finalSchema = {}
-    curComponentProps.forEach(configItem => {
-      const xcomponent = configItem['x-component']
-      const xProps = configItem['x-props'] || {}
-      let newXprops = {
-        ...xProps
-      }
-
-      if (
-        ['defaultValueCascader', 'dataSourceEditor'].indexOf(xcomponent) > -1
-      ) {
-        newXprops = {
-          ...newXprops,
-          fieldStore: curComponentAttr,
-          UI
-        }
-      }
-
-      finalSchema[configItem.name] = {
-        ...configItem,
-        'x-props': newXprops
-      }
-    })
-
-    return {
-      type: 'object',
-      properties: finalSchema
-    }
-  }
-
-  renderConfigList() {
-    const { componentId } = this.props
-
-    if (!componentId.length) {
-      return <p className="props-tips">请选择待编辑的表单字段</p>
-    }
-
-    return (
-      <State initial={{ visible: false }}>
-        {({ state, setState }) => (
-          <SchemaForm
-            effects={($, { setFieldState, getFieldState }) => {
-              $('onFormInit').subscribe(() => {
-                setFieldState('x-props.cols', state => {
-                  if (
-                    !state.value ||
-                    (Array.isArray(state.value) && !state.length)
-                  ) {
-                    state.visible = false
-                  } else {
-                    state.visible = true
-                  }
-                })
-              })
-              $('onFieldChange', 'x-props.cols-num').subscribe(fieldState => {
-                if (!fieldState.value) return
-                setFieldState('x-props.cols', state => {
-                  const arr = new Array(fieldState.value).fill(
-                    24 / fieldState.value
-                  )
-                  state.visible = true
-                  state.value = arr
-                })
-              })
-            }}
-            value={this.getSchemaValue()}
-            onChange={this.onChangeHandler}
-            schema={this.generatePropsSchema()}
-            labelAlign="left"
-            labelTextAlign="right"
-            labelCol={8}
-          >
-            {' '}
-          </SchemaForm>
-        )}
-      </State>
-    )
-  }
-
-  renderOptions() {
-    const { componentId, initSchemaData = {} } = this.props
-
-    if (!componentId.length) return null
-
-    const curComponentAttr = getCompDetailById(componentId, initSchemaData)
-
-    switch (curComponentAttr.type) {
-      case 'upload':
-        return (
-          <FileSetting
-            UI={this.props.UI}
-            xprops={curComponentAttr['x-props'] || {}}
-            onChange={xprops => {
-              this.props.editComponent(componentId, {
-                'x-props': xprops
-              })
-            }}
-          />
-        )
-      default:
-        return null
-    }
-  }
-
-  render() {
-    return (
-      <PropsStyle className={this.props.className}>
-        {this.renderConfigList()}
-        {this.renderOptions()}
-      </PropsStyle>
-    )
-  }
-}
-
-const mapStateToProps = state => state
-
-const mapDispatchToProps = dispatch => ({
-  showComponentProps: (id, comp) => dispatch(showComponentProps(id, comp)),
-  editComponentProps: (...args) => dispatch(editComponentProps(...args)),
-  editComponent: (...args) => dispatch(editComponent(...args))
-})
-
-class StyledPropsSettingComp extends React.Component {
-  render() {
-    return <PropsSetting {...this.props} />
-  }
-}
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(StyledPropsSettingComp)

+ 0 - 60
packages/builder/src/components/props/style.js

@@ -1,60 +0,0 @@
-import styled from 'styled-components'
-
-export default styled.div`
-  .schema-form-container .schema-form-content > .schema-form-field {
-    &.option-item {
-      padding: 10px !important;
-      border: 1px solid transparent;
-      white-space: nowrap;
-      .option-item-row {
-        &:last-child {
-          margin-bottom: 0 !important;
-        }
-      }
-      &.hover {
-        border-color: #ccc;
-      }
-      &.active {
-        border-color: #419bf9;
-        background: rgba(16, 141, 233, 0.1);
-      }
-    }
-    .option-action {
-      position: relative;
-      z-index: 1000;
-      display: inline-block;
-      padding: 3px 8px;
-      vertical-align: middle;
-      cursor: pointer;
-      &.option-del {
-        &::after {
-          content: '';
-          position: absolute;
-          right: 0;
-          top: 50%;
-          transform: translate3d(0, -50%, 0);
-          width: 1px;
-          height: 15px;
-          background: #ccc;
-        }
-      }
-    }
-  }
-
-  .props-tips {
-    padding-top: 60px;
-    text-align: center;
-    color: #999;
-  }
-
-  .schema-form-container
-    .schema-form-field.schema-object
-    .schema-object-item
-    > .next-form-item-label {
-    font-size: 14px !important;
-    font-weight: normal !important;
-    margin-top: 0 !important;
-    border-bottom: none !important;
-    padding-bottom: 0 !important;
-  }
-`

+ 0 - 7
packages/builder/src/configs/index.js

@@ -1,7 +0,0 @@
-import defaultSupportFieldList from './supportFieldList'
-import supportGlobalCfgList from './supportGlobalCfgList'
-
-export default {
-  defaultSupportFieldList: defaultSupportFieldList,
-  supportGlobalCfgList: supportGlobalCfgList
-}

+ 0 - 284
packages/builder/src/configs/supportConfigList.js

@@ -1,284 +0,0 @@
-// 可配置属性
-const FIELDLIST = {
-  ID: {
-    name: '__id__',
-    title: '字段名称',
-    type: 'string',
-    description: '字段名称:发起请求时带上的参数id,必填,全局保证唯一。',
-    required: true
-  },
-  PLACEHOLDER: {
-    name: 'x-props.placeholder',
-    title: '占位符',
-    type: 'string'
-  },
-  DESCRIPTION: {
-    name: 'description',
-    title: '提示文案',
-    type: 'string'
-  },
-  TITLE: {
-    name: 'title',
-    title: '标题',
-    type: 'string',
-    placeholder: '请输入字段名称,不超过50个字符'
-  },
-  DEFAULT: {
-    name: 'default',
-    title: '默认值',
-    type: 'object',
-    'x-component': 'defaultValueCascader'
-  },
-  DATASOURCE: {
-    name: 'dataSource',
-    title: '配置选项',
-    type: 'object',
-    'x-component': 'dataSourceEditor'
-  },
-  REQUIRED: {
-    name: 'required',
-    title: '是否必填',
-    type: 'boolean'
-  },
-  READONLY: {
-    name: 'x-props.readOnly',
-    title: '是否只读',
-    type: 'boolean'
-  },
-  DISABLED: {
-    name: 'x-props.disabled',
-    title: '是否禁用',
-    type: 'boolean'
-  },
-  HIDDEN: {
-    name: 'x-props.htmltype',
-    title: '是否隐藏',
-    type: 'boolean'
-  }
-}
-
-// 远程获取数据源请求选项,返回的数据的value/label根据下面设置进行转换
-const REMOTE_OPT = [
-  {
-    name: 'x-props.labelKey',
-    title: 'labelKey',
-    type: 'string',
-    description: '默认为label'
-  },
-  {
-    name: 'x-props.valueKey',
-    title: 'valueKey',
-    type: 'string',
-    description: '默认为value'
-  }
-]
-
-// 默认组件配置
-const defaultProps = Object.keys(FIELDLIST).map(item => FIELDLIST[item])
-
-// 默认各个组件的key配置项,key跟supportConfigList的key做映射
-export const getPropsByKey = key => {
-  switch (key) {
-    case 'multipleSelect':
-      return generateProps(null, [
-        {
-          name: 'x-props.multiple',
-          'x-props': {
-            htmlType: 'hidden'
-          },
-          type: 'string'
-        },
-        ...REMOTE_OPT
-      ])
-    case 'select':
-    case 'cascaderSelect':
-    case 'treeSelect':
-      return generateProps(null, REMOTE_OPT)
-    case 'multipleInput':
-      return generateProps(
-        [
-          'ID',
-          'TITLE',
-          'DEFAULT',
-          'DESCRIPTION',
-          'PLACEHOLDER',
-          'REQUIRED',
-          'READONLY',
-          'DISABLED',
-          'HIDDEN'
-        ],
-        [
-          {
-            name: 'x-props.multiple',
-            'x-props': {
-              style: {
-                display: 'none'
-              }
-            },
-            type: 'boolean'
-          }
-        ]
-      )
-    case 'input':
-    case 'number':
-      return generateProps([
-        'ID',
-        'TITLE',
-        'DEFAULT',
-        'DESCRIPTION',
-        'PLACEHOLDER',
-        'REQUIRED',
-        'READONLY',
-        'DISABLED',
-        'HIDDEN'
-      ])
-    case 'date':
-    case 'month':
-    case 'daterange':
-    case 'time':
-      return generateProps(
-        [
-          'ID',
-          'TITLE',
-          'DEFAULT',
-          'DESCRIPTION',
-          'REQUIRED',
-          'READONLY',
-          'DISABLED',
-          'HIDDEN',
-          'PLACEHOLDER'
-        ],
-        [
-          {
-            name: 'x-props.showTime',
-            title: '是否展示时间',
-            type: 'boolean'
-          }
-        ]
-      )
-    case 'imgUpload':
-    case 'fileUpload':
-      return generateProps(
-        [
-          'ID',
-          'TITLE',
-          'DESCRIPTION',
-          'REQUIRED',
-          'READONLY',
-          'DISABLED',
-          'HIDDEN'
-        ],
-        []
-      )
-    case 'wrapper_layout':
-      return generateProps(
-        ['ID'],
-        [
-          {
-            name: 'x-props.labelCol',
-            title: '文本占比',
-            type: 'number',
-            description: '按照24份等比分,输入需要占的份数'
-          },
-          {
-            name: 'x-props.wrapperCol',
-            title: '容器占比',
-            type: 'number',
-            description: '按照24份等比分,输入需要占的份数'
-          }
-        ]
-      )
-    case 'wrapper_grid':
-      return generateProps(
-        ['ID'],
-        [
-          {
-            name: 'x-props.gutter',
-            title: '组件间距',
-            type: 'number'
-          },
-          {
-            name: 'x-props.cols-num',
-            title: '组件列数',
-            type: 'string',
-            enum: [2, 3, 4, 6, 8, 12, 24],
-            description:
-              '默认根据组件个数动态计算等比分列,若有精确控制列宽度请指定列数'
-          },
-          {
-            name: 'x-props.cols',
-            title: '列宽度',
-            type: 'string',
-            'x-component': 'colsDetail'
-          },
-          {
-            name: 'x-props.title',
-            title: '标题',
-            type: 'string'
-          }
-        ]
-      )
-    case 'wrapper_card':
-      return generateProps(
-        ['ID'],
-        [
-          {
-            name: 'x-props.title',
-            title: '标题',
-            type: 'string'
-          },
-          {
-            name: 'x-props.subTitle',
-            title: '副标题',
-            type: 'string'
-          },
-          {
-            name: 'x-props.showHeadDivider',
-            title: '是否展示标题底部横线',
-            type: 'boolean'
-          }
-        ]
-      )
-    default:
-      return generateProps([
-        'ID',
-        'TITLE',
-        'DEFAULT',
-        'DESCRIPTION',
-        'PLACEHOLDER',
-        'REQUIRED',
-        'READONLY',
-        'DISABLED',
-        'HIDDEN'
-      ])
-  }
-}
-
-/**
- * 自由组合需要展示的配置项
- * @param {Array} includeKeys
- */
-export const generateProps = (includeKeys = [], extraProps = []) => {
-  const result = []
-
-  // 若不传入则返回默认的组件配置
-  if (!includeKeys || !includeKeys.length) {
-    // 简单不去重合并
-    return [...defaultProps, ...extraProps]
-  }
-
-  includeKeys.forEach(key => {
-    const item = FIELDLIST[key]
-    if (key && item) {
-      result.push(FIELDLIST[key.toUpperCase()])
-    }
-  })
-  return [...result, ...extraProps]
-}
-
-export const maxShowFieldListLen = 8
-
-export default {
-  getPropsByKey,
-  generateProps
-}

+ 0 - 246
packages/builder/src/configs/supportFieldList.js

@@ -1,246 +0,0 @@
-export default [
-  {
-    key: 'input',
-    icon: 'info',
-    iconUrl: '//gw.alicdn.com/tfs/TB11eW6DmzqK1RjSZFpXXakSXXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'string',
-    title: '单行文本框',
-    placeholder: '请输入'
-  },
-  {
-    key: 'multipleInput',
-    icon: 'file-text',
-    iconUrl: '//gw.alicdn.com/tfs/TB1zk14DjTpK1RjSZKPXXa3UpXa-116-78.png',
-    width: '58',
-    height: '39',
-    type: 'string',
-    title: '多行文本框',
-    placeholder: '请输入',
-    'x-props.multiple': true,
-    'x-props': {
-      multiple: true
-    }
-  },
-  {
-    key: 'number',
-    icon: 'file-text',
-    iconUrl: '//gw.alicdn.com/tfs/TB1f7i1DhTpK1RjSZFGXXcHqFXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'number',
-    title: '数字选择器'
-  },
-  {
-    key: 'radio',
-    icon: 'check-circle-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1zQaYDlLoK1RjSZFuXXXn0XXa-56-56.png',
-    width: '28',
-    height: '28',
-    type: 'radio',
-    title: '单选框',
-    'x-component': 'radio',
-    enum: [
-      {
-        value: '1',
-        label: '选项1'
-      },
-      {
-        value: '2',
-        label: '选项2'
-      }
-    ],
-    'x-props': {
-      enum: [
-        {
-          value: '1',
-          label: '选项1'
-        },
-        {
-          value: '2',
-          label: '选项2'
-        }
-      ]
-    }
-  },
-  {
-    key: 'checkbox',
-    icon: 'check-square-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1ELO7DgHqK1RjSZFPXXcwapXa-56-56.png',
-    width: '28',
-    height: '28',
-    type: 'checkbox',
-    title: '复选框',
-    'x-component': 'checkbox',
-    enum: [
-      {
-        value: '1',
-        label: '选项1'
-      },
-      {
-        value: '2',
-        label: '选项2'
-      }
-    ],
-    'x-props': {
-      enum: [
-        {
-          value: '1',
-          label: '选项1'
-        },
-        {
-          value: '2',
-          label: '选项2'
-        }
-      ]
-    }
-  },
-  {
-    key: 'imgUpload',
-    icon: 'picture',
-    iconUrl: '//gw.alicdn.com/tfs/TB1YC52DkvoK1RjSZPfXXXPKFXa-128-66.png',
-    width: '64',
-    height: '33',
-    type: 'upload',
-    title: '图片上传'
-  },
-  {
-    key: 'fileUpload',
-    icon: 'file',
-    iconUrl: '//gw.alicdn.com/tfs/TB17eq5DcbpK1RjSZFyXXX_qFXa-128-62.png',
-    width: '64',
-    height: '31',
-    type: 'upload',
-    title: '文件上传'
-  },
-  {
-    key: 'select',
-    icon: 'down-square-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1MA14DjTpK1RjSZKPXXa3UpXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'string',
-    title: '单选下拉框',
-    'x-component': 'enhanceSelect',
-    'x-props': {
-      url: '',
-      enum: [
-        {
-          value: '1',
-          label: '选项1'
-        }
-      ]
-    }
-  },
-  {
-    key: 'multipleSelect',
-    icon: 'down-square-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1Ysm3DbvpK1RjSZPiXXbmwXXa-140-56.png',
-    width: '70',
-    height: '28',
-    type: 'string',
-    title: '多选下拉框',
-    'x-component': 'enhanceSelect',
-    'x-props': {
-      multiple: true,
-      url: '',
-      enum: [
-        {
-          value: '1',
-          label: '选项1'
-        }
-      ]
-    }
-  },
-  {
-    key: 'date',
-    icon: 'calendar',
-    iconUrl: '//gw.alicdn.com/tfs/TB10ZW.DkzoK1RjSZFlXXai4VXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'date',
-    title: '日期选择器'
-  },
-  {
-    key: 'month',
-    icon: 'calendar',
-    iconUrl: '//gw.alicdn.com/tfs/TB1aey5DbvpK1RjSZFqXXcXUVXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'month',
-    title: '月份选择器'
-  },
-  {
-    key: 'daterange',
-    icon: 'calendar',
-    iconUrl: '//gw.alicdn.com/tfs/TB1k4C3Db2pK1RjSZFsXXaNlXXa-140-56.png',
-    width: '70',
-    height: '28',
-    type: 'daterange',
-    title: '日期范围选择器'
-  },
-  {
-    key: 'time',
-    icon: 'clock-circle-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1D4a8DkPoK1RjSZKbXXX1IXXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'time',
-    title: '时间选择器'
-  },
-  {
-    key: 'cascaderSelect',
-    icon: 'clock-circle-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1nGG8DkvoK1RjSZFDXXXY3pXa-100-72.png',
-    width: '50',
-    height: '36',
-    type: 'string',
-    title: '级联选择器',
-    'x-component': 'cascaderSelect',
-    'x-props': {
-      url: ''
-    }
-  },
-  {
-    key: 'multiInput',
-    icon: 'clock-circle-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1Pym.DcfpK1RjSZFOXXa6nFXa-140-56.png',
-    width: '70',
-    height: '28',
-    type: 'string',
-    title: '批量输入框',
-    'x-component': 'multiInput'
-  },
-  {
-    key: 'treeSelect',
-    icon: 'clock-circle-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1PWG8DkvoK1RjSZFDXXXY3pXa-116-56.png',
-    width: '58',
-    height: '28',
-    type: 'string',
-    title: '树形下拉框',
-    'x-component': 'treeSelect',
-    'x-props': {
-      url: ''
-    }
-  },
-  {
-    key: 'tabSelect',
-    icon: 'clock-circle-o',
-    iconUrl: '//gw.alicdn.com/tfs/TB1ch9.DgHqK1RjSZFEXXcGMXXa-132-58.png',
-    width: '67',
-    height: '29',
-    type: 'string',
-    title: 'tab选择框',
-    'x-component': 'tabSelect',
-    'x-props': {
-      dataSource: [
-        {
-          value: 1,
-          label: 1
-        }
-      ]
-    }
-  }
-]

+ 0 - 80
packages/builder/src/configs/supportGlobalCfgList.js

@@ -1,80 +0,0 @@
-// 全局属性配置
-
-const labelAlignEnum = [
-  { value: 'left', label: '左侧' },
-  { value: 'top', label: '上方' }
-]
-const labelTextAlignEnum = [
-  { value: 'left', label: '左对齐' },
-  { value: 'right', label: '右对齐' }
-]
-const autoAddColonEnum = [
-  { value: true, label: '是' },
-  { value: false, label: '否' }
-]
-const needFormButtonGroupEnum = [...autoAddColonEnum]
-const inlineEnum = [...autoAddColonEnum]
-const sizeEnum = [
-  { value: 'large', label: '大' },
-  { value: 'medium', label: '中' },
-  { value: 'small', label: '小' }
-]
-
-// 默认全局配置值
-export const defaultGlobalCfgValue = {
-  labelAlign: 'left',
-  labelTextAlign: 'right',
-  autoAddColon: true,
-  needFormButtonGroup: false,
-  inline: false,
-  size: 'medium',
-  labelCol: 8,
-  wrapperCol: 16,
-  editable: true
-}
-
-// 默认全局配置属性列表
-export default [
-  {
-    name: 'labelAlign',
-    title: '标签位置',
-    type: 'string',
-    enum: labelAlignEnum,
-    'x-component': 'radio'
-  },
-  {
-    name: 'labelTextAlign',
-    title: '标签对齐方式',
-    type: 'string',
-    enum: labelTextAlignEnum,
-    'x-component': 'radio'
-  },
-  {
-    name: 'inline',
-    title: '是否单行布局',
-    type: 'string',
-    enum: inlineEnum,
-    'x-component': 'radio'
-  },
-  {
-    name: 'size',
-    title: '组件尺寸',
-    type: 'string',
-    enum: sizeEnum,
-    'x-component': 'radio'
-  },
-  {
-    name: 'autoAddColon',
-    title: '是否加冒号',
-    type: 'string',
-    enum: autoAddColonEnum,
-    'x-component': 'radio'
-  },
-  {
-    name: 'needFormButtonGroup',
-    title: '有提交按钮',
-    type: 'string',
-    enum: needFormButtonGroupEnum,
-    'x-component': 'radio'
-  }
-]

+ 0 - 44
packages/builder/src/configs/supportLayoutList.js

@@ -1,44 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-export default [
-  {
-    key: 'wrapper_layout',
-    icon: 'clock-circle-o',
-    type: 'object',
-    title: 'Layout布局',
-    __key__: 'layout',
-    __key__data__: {
-      'x-component': 'layout',
-      'x-props': {
-        labelCol: 8,
-        wrapperCol: 6
-      }
-    }
-  },
-  {
-    key: 'wrapper_grid',
-    icon: 'clock-circle-o',
-    type: 'object',
-    title: 'Grid布局',
-    __key__: 'layout',
-    __key__data__: {
-      'x-component': 'grid',
-      'x-props': {
-        gutter: 20
-      }
-    }
-  },
-  {
-    key: 'wrapper_card',
-    icon: 'clock-circle-o',
-    type: 'object',
-    title: 'FormCard卡片式布局',
-    __key__: 'layout',
-    __key__data__: {
-      'x-component': 'card',
-      'x-props': {
-        title: '卡片式布局',
-        showHeadDivider: true
-      }
-    }
-  }
-]

+ 0 - 57
packages/builder/src/configs/theme.js

@@ -1,57 +0,0 @@
-// 主题
-export const dark = {
-  headerBgColor: '#3F486B',
-  leftColBgColor: '#272D44',
-  mainColBgColor: '#3F486B',
-  rightColBgColor: '#313853',
-  whiteColor: '#fff',
-  backIconUrl: '//gw.alicdn.com/tfs/TB1mw6TBhjaK1RjSZKzXXXVwXXa-18-34.png',
-  compHoverBgColor: '#1D2236',
-  dividerBgColor: '#1E2336',
-  dividerShadow: '0 1px 0 0 #313853',
-  backDividerBgColor: '#3F486B',
-  backDividerShadow: '1px 0 0 0 #313853, 2px 0 0 0 rgba(96, 107, 149, 0.65)',
-  btnNormalBgColor: '#48527A',
-  btnPrimaryBgColor: '#5A60FF',
-  btnPrimaryTxtColor: '#fff'
-}
-
-export const light = {
-  headerBgColor: '#fff',
-  leftColBgColor: '#fff',
-  mainColBgColor: '#f2f2f2',
-  rightColBgColor: '#fff',
-  whiteColor: '#555',
-  backIconUrl: '//gw.alicdn.com/tfs/TB1t0bMBhTpK1RjSZFMXXbG_VXa-18-34.png',
-  compHoverBgColor: '#f3f3f3',
-  dividerBgColor: '#f9f9f9',
-  dividerShadow: '0 1px 0 0 #f2f2f2',
-  backDividerBgColor: '#f9f9f9',
-  backDividerShadow: '1px 0 0 0 #999',
-  btnNormalBgColor: '#f7f8fa',
-  btnPrimaryBgColor: '#5A60FF',
-  btnPrimaryTxtColor: '#fff'
-}
-
-export const THEME_ENUM = ['dark', 'light']
-
-export const DEFAULT_THEME = THEME_ENUM[0]
-
-// 全局操作栏按钮icon
-export const GLOBAL_BTN_ICON_URL = {
-  [THEME_ENUM[0]]: {
-    preview: '//gw.alicdn.com/tfs/TB1t3egCkvoK1RjSZPfXXXPKFXa-32-32.png',
-    submit: '//gw.alicdn.com/tfs/TB1UnehCcbpK1RjSZFyXXX_qFXa-30-30.png',
-    code: '//gw.alicdn.com/tfs/TB1lT5hCXzqK1RjSZFvXXcB7VXa-42-32.png'
-  },
-  [THEME_ENUM[1]]: {
-    preview: '//gw.alicdn.com/tfs/TB1y1GKCiLaK1RjSZFxXXamPFXa-32-32.png',
-    submit: '//gw.alicdn.com/tfs/TB1UnehCcbpK1RjSZFyXXX_qFXa-30-30.png',
-    code: '//gw.alicdn.com/tfs/TB15bGkCXzqK1RjSZSgXXcpAVXa-42-32.png'
-  }
-}
-
-export default {
-  dark,
-  light
-}

+ 0 - 5
packages/builder/src/constants/context.js

@@ -1,5 +0,0 @@
-import React from 'react'
-export const {
-  Consumer: FormConsumer,
-  Provider: FormProvider
-} = React.createContext()

+ 0 - 5
packages/builder/src/constants/itemType.js

@@ -1,5 +0,0 @@
-export default {
-  CARD: 'card',
-  FIELD: 'field',
-  LAYOUT: 'layout'
-}

+ 0 - 147
packages/builder/src/demo/index-1-x.js

@@ -1,147 +0,0 @@
-import React from 'react'
-import SchemaForm, { FormButtonGroup, Submit, Reset } from '@uform/next'
-import Index from '../index'
-import {
-  Button,
-  Collapse,
-  Message,
-  Upload,
-  Input,
-  Select,
-  DatePicker,
-  Icon,
-  Checkbox,
-  NumberPicker,
-  TimePicker,
-  Radio,
-  Form,
-  Tab
-} from '@alifd/next'
-
-// style
-import '@alifd/next/dist/next.css'
-
-SchemaForm.FormButtonGroup = FormButtonGroup
-SchemaForm.Submit = Submit
-SchemaForm.Reset = Reset
-
-const renderSchema = {}
-
-const props = {
-  UI: {
-    version: '1.x',
-    Button,
-    Accordion: Collapse,
-    Toast: Message,
-    Upload,
-    Input,
-    Select,
-    Icon,
-    DatePicker,
-    TimePicker,
-    Checkbox,
-    NumberPicker,
-    Radio,
-    RadioGroup: Radio.Group,
-    TabPane: Tab.Item,
-    Form,
-    Tab
-  },
-  // 主题: dark/light,默认dark
-  // themeStyle: 'light',
-  // 是否展示布局组件,默认为false
-  showLayoutField: false,
-  showPreviewBtn: true,
-  showSourceCodeBtn: true,
-  // 控制返回按钮点击事件
-  onBackBtnClick: () => {
-    alert('点击了返回')
-  },
-  // 额外全局按钮
-  globalButtonList: [
-    // {
-    //   key: 'submit',
-    //   title: '自定义保存',
-    //   render: (props) => {
-    //     return <Badge dot>{props.children}</Badge>
-    //   },
-    //   props: {
-    //     // loading: true,
-    //   },
-    // }, {
-    //   key: 'cancel',
-    //   title: '取消',
-    //   props: {
-    //     onClick: () => {
-    //       alert('点击取消');
-    //     }
-    //   },
-    // }
-  ],
-  // 是否展示全局配置
-  showGlobalCfg: true,
-  // 全局配置额外项
-  extraGlobalCfgList: [
-    {
-      name: 'labelCol',
-      title: 'label宽度占比',
-      type: 'string'
-    },
-    {
-      name: 'wrapperCol',
-      title: 'wrapper宽度占比',
-      type: 'string'
-    },
-    {
-      name: 'editable',
-      title: '表单是否可编辑',
-      description:
-        '若设置为false,则可快速搭建出表单详情页,只需设置每个组件的默认值',
-      type: 'boolean'
-    }
-  ],
-  globalCfg: {},
-  supportFieldList: [],
-  includeFieldListKeyList: [
-    'input',
-    'multipleInput',
-    'number',
-    'radio',
-    'checkbox',
-    'date',
-    'month',
-    'daterange',
-    'time'
-  ],
-
-  // 渲染引擎
-  renderEngine: SchemaForm,
-
-  schema: renderSchema,
-  // onChange: (data) => {
-  //   console.info('index onChange data', data);
-  // },
-  onSubmit: data => {
-    alert(`保存数据:${JSON.stringify(data)}`)
-    console.info('index onSubmit data', data)
-  }
-}
-
-class Comp extends React.Component {
-  constructor(props) {
-    super(props)
-    this.state = {
-      schema: renderSchema
-    }
-  }
-
-  render() {
-    return (
-      <div style={{ marginTop: -20 }}>
-        <Index {...props} schema={this.state.schema} />
-      </div>
-    )
-  }
-}
-
-export default Comp

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.