├── .nojekyll ├── index.js ├── .prettierrc ├── src ├── widgets │ ├── antd │ │ ├── map.jsx │ │ ├── html.jsx │ │ ├── select.jsx │ │ ├── number.jsx │ │ ├── multiSelect.jsx │ │ ├── slider.jsx │ │ ├── switch.jsx │ │ ├── checkbox.jsx │ │ ├── radio.jsx │ │ ├── dateRange.jsx │ │ ├── date.jsx │ │ ├── textarea.jsx │ │ ├── checkboxes.jsx │ │ ├── list.jsx │ │ ├── range.jsx │ │ ├── color.jsx │ │ ├── input.jsx │ │ ├── upload.jsx │ │ └── index.jsx │ └── fusion │ │ ├── html.jsx │ │ ├── map.jsx │ │ ├── select.jsx │ │ ├── number.jsx │ │ ├── multiSelect.jsx │ │ ├── slider.jsx │ │ ├── radio.jsx │ │ ├── checkbox.jsx │ │ ├── switch.jsx │ │ ├── textarea.jsx │ │ ├── list.jsx │ │ ├── dateRange.jsx │ │ ├── color.jsx │ │ ├── input.jsx │ │ ├── checkboxes.jsx │ │ ├── date.jsx │ │ ├── upload.jsx │ │ └── index.jsx ├── hooks.js ├── components │ ├── html.jsx │ ├── previewContent.jsx │ ├── radioHoc.jsx │ ├── numberHoc.jsx │ ├── foldIcon.jsx │ ├── rangeHoc.jsx │ ├── multiSelectHoc.jsx │ ├── selectHoc.jsx │ ├── dateHoc.jsx │ ├── map.jsx │ ├── sliderHoc.jsx │ └── descList.jsx ├── base │ ├── subFieldGenerator.jsx │ ├── getField.js │ ├── resolve.js │ ├── isHidden.js │ ├── parser.js │ ├── validate.js │ ├── utils.js │ └── asField.jsx ├── fusion.js ├── antd.js └── index.js ├── .eslintignore ├── .prettierignore ├── .npmignore ├── .gitignore ├── test └── index-spec.js ├── docs ├── css.md ├── _coverpage.md ├── _navbar.md ├── _sidebar.md ├── depend.md ├── question.md ├── used.md ├── why.md ├── field-ui.md ├── demo │ └── index.html ├── function.md ├── typescript.md ├── dist │ └── sw.js ├── proptypes.md ├── widget.md ├── ui-schema.md └── prop-schema.md ├── .editorconfig ├── demo ├── json │ ├── simplest.json │ ├── date.json │ ├── select.json │ ├── input.json │ ├── function.json │ ├── basic.json │ ├── new-feature.json │ └── demo.json ├── FrDemo.js ├── index.html ├── index2.js ├── monaco │ ├── index.js │ └── snippets.js ├── customized │ └── AsyncSelect.js ├── main.js ├── index.js └── index1.js ├── .babelrc ├── CONTRIBUTING.md ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── FUNDING.yml ├── .eslintrc ├── LICENSE ├── webpack.config.prod.js ├── index.html ├── webpack.config.js ├── package.json ├── CODE_OF_CONDUCT.md ├── CHANGELOG.md ├── index.css └── README.md /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/index.js'); 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5" 4 | } 5 | -------------------------------------------------------------------------------- /src/widgets/antd/map.jsx: -------------------------------------------------------------------------------- 1 | import map from '../../components/map'; 2 | export default map; 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | docs/ 3 | demo/ 4 | examples/ 5 | webpack.config.js 6 | test/ 7 | -------------------------------------------------------------------------------- /src/widgets/antd/html.jsx: -------------------------------------------------------------------------------- 1 | import html from '../../components/html'; 2 | export default html; 3 | -------------------------------------------------------------------------------- /src/widgets/fusion/html.jsx: -------------------------------------------------------------------------------- 1 | import html from '../../components/html'; 2 | export default html; 3 | -------------------------------------------------------------------------------- /src/widgets/fusion/map.jsx: -------------------------------------------------------------------------------- 1 | import map from '../../components/map'; 2 | export default map; 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.bundle.js 2 | *.min.js 3 | dist 4 | docs/dist 5 | lib 6 | node_modules 7 | atom.css -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | **/.* 2 | .DS_Store 3 | Thumbs.db 4 | .dist/ 5 | node_modules/ 6 | mochawesome-reports/ 7 | demo/ 8 | src/ 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | .build 4 | .dist/ 5 | lib/ 6 | dist/ 7 | !docs/dist 8 | node_modules/ 9 | npm-debug.log 10 | .idea/ 11 | .vscode/ 12 | -------------------------------------------------------------------------------- /test/index-spec.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect.js'; 2 | import Component from '../index'; 3 | 4 | describe('index.js', () => { 5 | it('should export.', () => { 6 | expect(Component).to.not.eql(undefined); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /src/widgets/antd/select.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 选择组件 4 | */ 5 | 6 | import { Select } from 'antd'; 7 | import selectHoc from '../../components/selectHoc'; 8 | 9 | export default selectHoc(Select); 10 | -------------------------------------------------------------------------------- /src/widgets/fusion/select.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 选择组件 4 | */ 5 | 6 | import { Select } from '@alifd/next'; 7 | import selectHoc from '../../components/selectHoc'; 8 | 9 | export default selectHoc(Select); 10 | -------------------------------------------------------------------------------- /src/widgets/antd/number.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 数字输入组件 4 | */ 5 | 6 | import { InputNumber } from 'antd'; 7 | import numberHoc from '../../components/numberHoc'; 8 | 9 | export default numberHoc(InputNumber); 10 | -------------------------------------------------------------------------------- /src/widgets/antd/multiSelect.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 多选组件 4 | */ 5 | 6 | import { Select } from 'antd'; 7 | import multiSelectHoc from '../../components/multiSelectHoc'; 8 | 9 | export default multiSelectHoc(Select); 10 | -------------------------------------------------------------------------------- /src/widgets/antd/slider.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 滑动组件 4 | */ 5 | 6 | import { InputNumber, Slider } from 'antd'; 7 | import sliderHoc from '../../components/sliderHoc'; 8 | 9 | export default sliderHoc(Slider, InputNumber); 10 | -------------------------------------------------------------------------------- /src/widgets/fusion/number.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 数字输入组件 4 | */ 5 | 6 | import { NumberPicker } from '@alifd/next'; 7 | import numberHoc from '../../components/numberHoc'; 8 | 9 | export default numberHoc(NumberPicker); 10 | -------------------------------------------------------------------------------- /src/widgets/fusion/multiSelect.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 多选组件 4 | */ 5 | 6 | import { Select } from '@alifd/next'; 7 | import multiSelectHoc from '../../components/multiSelectHoc'; 8 | 9 | export default multiSelectHoc(Select); 10 | -------------------------------------------------------------------------------- /src/widgets/fusion/slider.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 滑动组件 4 | */ 5 | 6 | import { NumberPicker, Range } from '@alifd/next'; 7 | import sliderHoc from '../../components/sliderHoc'; 8 | 9 | export default sliderHoc(Range, NumberPicker); 10 | -------------------------------------------------------------------------------- /docs/css.md: -------------------------------------------------------------------------------- 1 | # 样式覆盖 2 | 3 | ### 概述 4 | - FormRender 其实是有一个默认的布局样式,比如说表单之间的间距,label 字号、颜色等场景 5 | - 假如使用上有特殊定制,或者认为不符合要求的地方,可以通过常规 CSS 样式覆盖的方式,写到业务 global 样式代码中 6 | 7 | ### 如何使用 8 | 9 | ![](https://img.alicdn.com/tfs/TB1NEHdKpzqK1RjSZFoXXbfcXXa-2782-1488.png) 10 | 11 | -------------------------------------------------------------------------------- /src/hooks.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from 'react'; 2 | 3 | export function usePrevious(value) { 4 | const ref = useRef(); 5 | useEffect(() => { 6 | ref.current = value; 7 | }, [value]); // Only re-run if value changes 8 | return ref.current; 9 | } 10 | -------------------------------------------------------------------------------- /src/widgets/antd/switch.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Switch } from 'antd'; 3 | 4 | export default function sw(p) { 5 | return ( 6 | p.onChange(p.name, checked)} 9 | defaultChecked={p.value} 10 | /> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/widgets/fusion/radio.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 单选组件 4 | */ 5 | import { Radio } from '@alifd/next'; 6 | import radioHoc from '../../components/radioHoc'; 7 | 8 | export default function radio(p) { 9 | const onChange = v => p.onChange(p.name, v); 10 | return radioHoc(p, onChange, Radio); 11 | } 12 | -------------------------------------------------------------------------------- /src/widgets/antd/checkbox.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Checkbox } from 'antd'; 3 | 4 | export default function radio(p) { 5 | return ( 6 | p.onChange(p.name, e.target.checked)} 9 | checked={p.value} 10 | /> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/widgets/antd/radio.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-07. 3 | * 单选组件 4 | */ 5 | 6 | import { Radio } from 'antd'; 7 | import radioHoc from '../../components/radioHoc'; 8 | 9 | export default function radio(p) { 10 | const onChange = e => p.onChange(p.name, e.target.value); 11 | return radioHoc(p, onChange, Radio); 12 | } 13 | -------------------------------------------------------------------------------- /src/widgets/fusion/checkbox.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Checkbox } from '@alifd/next'; 3 | 4 | export default function radio(p) { 5 | return ( 6 | p.onChange(p.name, checked)} 9 | checked={p.value} 10 | /> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/widgets/fusion/switch.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Switch } from '@alifd/next'; 3 | 4 | export default function sw(p) { 5 | return ( 6 | p.onChange(p.name, checked)} 9 | defaultChecked={p.value} 10 | /> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/components/html.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function html({ value, schema, ...rest }) { 4 | let __html = ''; 5 | try { 6 | __html = value ? value : schema.default; 7 | if (typeof __html !== 'string') { 8 | __html = ''; 9 | } 10 | } catch (error) {} 11 | return
; 12 | } 13 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # FormRender 4 | 5 | > 通过 JSON Schema 生成标准 Form,常用于自定义搭建配置界面生成 6 | 7 | [Playground](https://alibaba.github.io/form-render/docs/demo/index.html) 8 | [快速开始](README) 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | # Apply for all files 8 | [*] 9 | 10 | charset = utf-8 11 | 12 | indent_style = space 13 | indent_size = 2 14 | 15 | end_of_line = lf 16 | insert_final_newline = true 17 | trim_trailing_whitespace = true 18 | -------------------------------------------------------------------------------- /demo/json/simplest.json: -------------------------------------------------------------------------------- 1 | { 2 | "propsSchema": { 3 | "type": "object", 4 | "properties": { 5 | "string": { 6 | "title": "字符串", 7 | "type": "string" 8 | }, 9 | "select": { 10 | "title": "单选", 11 | "type": "string", 12 | "enum": ["a", "b", "c"], 13 | "enumNames": ["选项1", "选项2", "选项3"] 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/previewContent.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const defaultImg = 4 | 'https://img.alicdn.com/tfs/TB14tSiKhTpK1RjSZFKXXa2wXXa-354-330.png'; 5 | 6 | export default (format, value) => { 7 | return format === 'image' ? ( 8 | 图片地址错误 13 | ) : null; 14 | }; 15 | -------------------------------------------------------------------------------- /src/widgets/antd/dateRange.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by Tw93 on 2019-12-08. 3 | * 日历多选组件 4 | */ 5 | 6 | import { DatePicker } from 'antd'; 7 | import rangeHoc from '../../components/rangeHoc'; 8 | 9 | const { RangePicker } = DatePicker; 10 | 11 | export default function dateRange(p) { 12 | const onChange = (value, string) => p.onChange(p.name, string); 13 | return rangeHoc(p, onChange, RangePicker); 14 | } 15 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react", "stage-0"], 3 | "plugins": [ 4 | [ 5 | "import", 6 | { 7 | "libraryName": "antd", 8 | "libraryDirectory": "lib", 9 | "style": "css" 10 | }, 11 | "ant" 12 | ], 13 | [ 14 | "import", 15 | { 16 | "libraryName": "@alifd/next", 17 | "style": true 18 | } 19 | ], 20 | "transform-decorators-legacy" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/base/subFieldGenerator.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const subFieldGenerator = ({ 4 | fieldCanRedefine: can, 5 | Field: SourceField = null, 6 | props = {}, 7 | }) => args => { 8 | const { name, Field: RedefineField = null, ...others } = args; 9 | const Field = (can && RedefineField) || SourceField; 10 | if (Field) { 11 | return ; 12 | } 13 | return null; 14 | }; 15 | 16 | export default subFieldGenerator; 17 | -------------------------------------------------------------------------------- /src/widgets/antd/date.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Updated by fateriddle on 2019-12-12. 3 | * 日期组件 4 | */ 5 | 6 | import { DatePicker, TimePicker } from 'antd'; 7 | import dateHoc from '../../components/dateHoc'; 8 | 9 | export default function date(p) { 10 | const { format = 'dateTime' } = p.schema; 11 | const onChange = (value, string) => p.onChange(p.name, string); 12 | const DateComponent = format === 'time' ? TimePicker : DatePicker; 13 | return dateHoc(p, onChange, DateComponent); 14 | } 15 | -------------------------------------------------------------------------------- /docs/_navbar.md: -------------------------------------------------------------------------------- 1 | - 开源社区群 2 |
3 | 4 |
5 | 6 | -------------------------------------------------------------------------------- /src/widgets/fusion/textarea.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Input } from '@alifd/next'; 3 | 4 | const { TextArea } = Input; 5 | 6 | export default function ta(p) { 7 | const { options, invalid } = p; 8 | const style = invalid 9 | ? { borderColor: '#f5222d', width: '100%' } 10 | : { width: '100%' }; 11 | const onChange = value => p.onChange(p.name, value); 12 | return ( 13 |