├── widgets ├── RichText │ ├── README.md │ ├── .fatherrc.js │ └── package.json ├── template │ ├── README.md │ ├── src │ │ └── index.js │ ├── .fatherrc.js │ └── package.json └── AsyncOptions │ ├── README.md │ ├── src │ └── index.js │ ├── .fatherrc.js │ └── package.json ├── packages ├── data-render │ ├── CONTRIBUTING.md │ ├── src │ │ ├── core │ │ │ └── index.less │ │ ├── widgets │ │ │ ├── FPanel │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FTooltip │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FSteps │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FCard │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── components │ │ │ │ ├── RequestTable │ │ │ │ │ └── index.less │ │ │ │ ├── BaseTable │ │ │ │ │ └── index.less │ │ │ │ ├── CopyLabel │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── IconLabel │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── TextEllipsis │ │ │ │ │ └── index.less │ │ │ │ ├── IconView │ │ │ │ │ └── index.tsx │ │ │ │ ├── InnerHtml │ │ │ │ │ └── index.tsx │ │ │ │ ├── Encryption │ │ │ │ │ └── index.less │ │ │ │ └── ReactNode │ │ │ │ │ └── index.tsx │ │ │ ├── FButton │ │ │ │ └── index.less │ │ │ ├── FButtonFold │ │ │ │ └── index.less │ │ │ ├── utils │ │ │ │ ├── createIconFont.ts │ │ │ │ └── hooks.ts │ │ │ ├── FLabel │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FText │ │ │ │ └── index.less │ │ │ ├── FRow │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FImage │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FTitle │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── FTabs │ │ │ │ └── index.tsx │ │ │ ├── FSpace │ │ │ │ └── index.tsx │ │ │ ├── FProgress │ │ │ │ ├── index.tsx │ │ │ │ └── index.less │ │ │ ├── FTextEllipsis │ │ │ │ └── index.tsx │ │ │ ├── FTimeline │ │ │ │ └── index.tsx │ │ │ ├── FSuckNav │ │ │ │ └── index.tsx │ │ │ └── FIconLabel │ │ │ │ └── index.tsx │ │ ├── type.ts │ │ ├── models │ │ │ ├── context.ts │ │ │ └── store.ts │ │ └── index.ts │ ├── CHANGELOG.md │ ├── .fatherrc.js │ ├── tsconfig.json │ └── LICENSE ├── form-render-mobile │ ├── src │ │ ├── widgets │ │ │ ├── index.less │ │ │ ├── Group │ │ │ │ ├── index.tsx │ │ │ │ └── index.less │ │ │ ├── Radio │ │ │ │ └── index.tsx │ │ │ ├── utils.ts │ │ │ ├── Collapse │ │ │ │ └── index.tsx │ │ │ ├── Card │ │ │ │ └── index.less │ │ │ └── Cascader │ │ │ │ └── index.tsx │ │ ├── locales │ │ │ ├── index.ts │ │ │ ├── zh_CN.ts │ │ │ └── en_US.ts │ │ ├── render-core │ │ │ ├── FieldList │ │ │ │ └── index.less │ │ │ └── FieldItem │ │ │ │ └── field.tsx │ │ ├── models │ │ │ ├── context.ts │ │ │ └── store.ts │ │ ├── form-core │ │ │ ├── connectForm.tsx │ │ │ └── index.less │ │ └── index.tsx │ ├── CHANGELOG.md │ ├── .fatherrc.js │ ├── CONTRIBUTING.md │ ├── tsconfig.json │ └── LICENSE ├── form-render │ ├── src │ │ ├── widgets │ │ │ ├── listTab │ │ │ │ └── index.less │ │ │ ├── components │ │ │ │ ├── HeaderTitle │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── PanelView │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── TimePicker │ │ │ │ │ └── index.tsx │ │ │ │ ├── FButton │ │ │ │ │ └── index.tsx │ │ │ │ └── DatePicker │ │ │ │ │ └── index.tsx │ │ │ ├── fields │ │ │ │ ├── slider │ │ │ │ │ └── index.less │ │ │ │ ├── imageInput │ │ │ │ │ └── index.less │ │ │ │ ├── rate │ │ │ │ │ └── index.tsx │ │ │ │ ├── input │ │ │ │ │ └── index.tsx │ │ │ │ ├── select │ │ │ │ │ └── index.tsx │ │ │ │ ├── switch │ │ │ │ │ └── index.tsx │ │ │ │ ├── number │ │ │ │ │ └── index.tsx │ │ │ │ ├── treeSelect │ │ │ │ │ └── index.tsx │ │ │ │ ├── textArea │ │ │ │ │ └── index.tsx │ │ │ │ ├── checkbox │ │ │ │ │ └── index.tsx │ │ │ │ ├── color │ │ │ │ │ └── index.less │ │ │ │ ├── upload │ │ │ │ │ └── index.less │ │ │ │ ├── time │ │ │ │ │ └── index.tsx │ │ │ │ ├── radio │ │ │ │ │ └── index.tsx │ │ │ │ └── checkboxes │ │ │ │ │ └── index.tsx │ │ │ ├── voidTitle │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── listDrawer │ │ │ │ ├── index.less │ │ │ │ └── drawerForm.tsx │ │ │ ├── listCard │ │ │ │ └── index.less │ │ │ ├── boxcard │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── boxLineTitle │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── boxSubInline │ │ │ │ └── index.less │ │ │ ├── utils │ │ │ │ ├── hooks.ts │ │ │ │ └── withFieldWrap.tsx │ │ │ ├── ErrorSchema │ │ │ │ └── index.tsx │ │ │ ├── listSimple │ │ │ │ └── index.less │ │ │ ├── listTable │ │ │ │ └── index.less │ │ │ └── listVirtual │ │ │ │ └── index.less │ │ ├── locales │ │ │ ├── index.ts │ │ │ ├── zh_CN.ts │ │ │ └── en_US.ts │ │ ├── models │ │ │ ├── context.ts │ │ │ ├── store.ts │ │ │ ├── sortProperties.ts │ │ │ └── formDataSkeleton.ts │ │ ├── derivative │ │ │ ├── SlimRender │ │ │ │ └── index.tsx │ │ │ └── SearchForm │ │ │ │ └── index.less │ │ ├── form-core │ │ │ ├── connectForm.tsx │ │ │ └── index.less │ │ ├── render-core │ │ │ └── index.less │ │ └── index.ts │ ├── .fatherrc.js │ ├── __tests__ │ │ ├── core-utils.spec.ts │ │ └── form.spec.tsx │ ├── CONTRIBUTING.md │ ├── tsconfig.json │ └── LICENSE ├── chart-render │ ├── src │ │ ├── components │ │ │ ├── ChartContainer │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── ChartProvider │ │ │ │ └── index.tsx │ │ │ └── Search │ │ │ │ └── index.less │ │ ├── utils │ │ │ ├── index.ts │ │ │ └── store.ts │ │ ├── index.ts │ │ └── widgets │ │ │ └── Pie │ │ │ └── index.tsx │ ├── .fatherrc.ts │ ├── tsconfig.json │ └── CHANGELOG.md ├── x-flow │ ├── src │ │ ├── components │ │ │ ├── NodesPopover │ │ │ │ └── index.less │ │ │ ├── TextEllipsis │ │ │ │ └── index.less │ │ │ ├── IconView │ │ │ │ └── index.tsx │ │ │ ├── CustomEdge │ │ │ │ └── index.less │ │ │ └── NodeContainer │ │ │ │ └── TitleMenuTooltip.tsx │ │ ├── index.less │ │ ├── utils │ │ │ ├── createIconFont.ts │ │ │ └── flow.ts │ │ ├── nodes │ │ │ ├── node-common │ │ │ │ └── index.less │ │ │ ├── node-end │ │ │ │ └── index.less │ │ │ ├── node-start │ │ │ │ └── index.less │ │ │ ├── index.tsx │ │ │ └── index.less │ │ ├── models │ │ │ ├── context.ts │ │ │ └── event-emitter.tsx │ │ ├── operator │ │ │ ├── UndoRedo │ │ │ │ └── index.less │ │ │ ├── index.less │ │ │ ├── ZoomInOut │ │ │ │ ├── shortcuts-name.tsx │ │ │ │ └── index.less │ │ │ └── Control │ │ │ │ └── index.less │ │ ├── index.ts │ │ └── hooks │ │ │ ├── useNodes.ts │ │ │ ├── useEdges.ts │ │ │ └── useTemporalStore.ts │ ├── CHANGELOG.md │ ├── .fatherrc.js │ ├── CONTRIBUTING.md │ ├── tsconfig.json │ └── LICENSE └── table-render │ ├── src │ ├── locales │ │ ├── index.ts │ │ ├── zh_CN.ts │ │ └── en_US.ts │ └── core │ │ ├── ToolbarView │ │ ├── index.less │ │ └── InteriorTool │ │ │ └── ReloadIcon.tsx │ │ ├── index.less │ │ ├── TableView │ │ ├── copy.tsx │ │ └── widgets.tsx │ │ └── ErrorBoundary │ │ └── index.tsx │ ├── CONTRIBUTION.md │ ├── 开发文档.md │ ├── .fatherrc.ts │ ├── CHANGELOG.md │ ├── tsconfig.json │ ├── __tests__ │ └── utils.spec.ts │ └── LICENSE ├── .npmrc ├── tools └── schema-builder │ ├── CHANGELOG.md │ ├── src │ ├── index.ts │ ├── settings │ │ └── meta │ │ │ ├── color.ts │ │ │ ├── imageInput.ts │ │ │ ├── date.ts │ │ │ ├── time.ts │ │ │ ├── checkbox.ts │ │ │ ├── urlInput.ts │ │ │ ├── slider.ts │ │ │ ├── timeRange.ts │ │ │ └── dateRange.ts │ └── type.ts │ ├── README.md │ ├── .fatherrc.js │ └── LICENSE ├── typing.d.ts ├── docs ├── table-render │ ├── .test │ │ └── test.md │ ├── basic.md │ ├── custom-table.md │ ├── toolbar.md │ ├── noSearch.md │ ├── static │ │ └── request.ts │ ├── tabs.md │ └── demo │ │ └── display │ │ └── custom-table.tsx ├── form-render-mobile │ ├── test │ │ └── test.md │ └── disaply.md ├── xflow │ ├── demo │ │ ├── flow-provider │ │ │ ├── edges.ts │ │ │ └── nodes.ts │ │ ├── nodeWidget │ │ │ └── index.less │ │ ├── nodeSetting │ │ │ └── fullDemo │ │ │ │ └── CustomImg.tsx │ │ ├── custom-flow │ │ │ ├── fullCase │ │ │ │ └── components │ │ │ │ │ └── ReadOnlyPanel.tsx │ │ │ ├── customWidget.tsx │ │ │ └── index.tsx │ │ ├── best │ │ │ ├── basic │ │ │ │ ├── TextEllipsis │ │ │ │ │ └── index.less │ │ │ │ ├── tools.tsx │ │ │ │ ├── header.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── showSwitchNode.tsx │ │ │ └── demo2 │ │ │ │ ├── TextEllipsis │ │ │ │ └── index.less │ │ │ │ ├── tools.tsx │ │ │ │ ├── header.tsx │ │ │ │ └── showSwitchNode.tsx │ │ ├── log │ │ │ ├── utils.tsx │ │ │ ├── runNode │ │ │ │ └── utils.tsx │ │ │ ├── buildIn-log │ │ │ │ ├── utils.tsx │ │ │ │ └── CustomGroupTittle.tsx │ │ │ └── custom-log │ │ │ │ └── utils.tsx │ │ ├── switchNode │ │ │ └── customSwitchNode │ │ │ │ └── index.tsx │ │ └── basic │ │ │ └── index.tsx │ ├── best-practices.md │ ├── updateLog.md │ └── custom-node-view.md ├── playground │ ├── index.md │ ├── controller │ │ └── index.css │ └── json │ │ ├── dynamic-function.js │ │ ├── test.json │ │ ├── format.json │ │ └── select.json ├── form-render │ ├── changelog.md │ ├── utils │ │ └── index.js │ ├── demo │ │ ├── FormRender.jsx │ │ ├── widget │ │ │ ├── label-widget.tsx │ │ │ └── desc-widget.tsx │ │ └── form-slim │ │ │ ├── basic.tsx │ │ │ └── form-list.tsx │ ├── test │ │ └── test.md │ ├── schema │ │ ├── basic.ts │ │ ├── simple.ts │ │ ├── cellSpan.ts │ │ └── span.ts │ └── faq.md └── schema-builder-online │ └── index.md ├── .dumi ├── tmp-production │ ├── core │ │ ├── helmetContext.ts │ │ ├── EmptyRoute.tsx │ │ ├── exportStaticRuntimePlugin.ts │ │ ├── helmet.ts │ │ ├── defineApp.ts │ │ └── pluginConfigJoi.d.ts │ └── dumi │ │ ├── meta │ │ ├── tabs.ts │ │ └── atoms.ts │ │ ├── theme │ │ ├── slots │ │ │ ├── Hero.ts │ │ │ ├── Logo.ts │ │ │ ├── Toc.ts │ │ │ ├── Content.ts │ │ │ ├── Footer.ts │ │ │ ├── Header.ts │ │ │ ├── Navbar.ts │ │ │ ├── Sidebar.ts │ │ │ ├── Features.ts │ │ │ ├── HeadeExtra.ts │ │ │ ├── HeroTitle.ts │ │ │ ├── LangSwitch.ts │ │ │ ├── NotFound.ts │ │ │ ├── RtlSwitch.ts │ │ │ ├── SocialIcon.ts │ │ │ ├── ColorSwitch.ts │ │ │ ├── ContentTabs.ts │ │ │ ├── NavbarExtra.ts │ │ │ ├── SearchResult.ts │ │ │ ├── PreviewerActions.ts │ │ │ ├── PreviewerActionsExtra.ts │ │ │ └── SearchBar.ts │ │ ├── builtins │ │ │ ├── API.ts │ │ │ ├── Badge.ts │ │ │ ├── Table.ts │ │ │ ├── Container.ts │ │ │ ├── Previewer.ts │ │ │ └── SourceCode.ts │ │ └── layouts │ │ │ └── DocLayout.ts │ │ ├── exports.ts │ │ └── exportStaticRuntimePlugin.ts ├── loading.tsx └── theme │ ├── layouts │ └── GlobalLayout │ │ └── index.tsx │ └── slots │ └── Header │ └── GithubLink.tsx ├── lerna.json ├── scripts └── dumi-plugin │ ├── publicPath.ts │ └── redirect.ts ├── .fatherrc.js ├── turbo.json ├── app.ts ├── .prettierrc ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug-report.md └── workflows │ ├── emoji-helper.yml │ ├── mirror.yml │ ├── coverage.yml │ ├── deploy.yml │ └── ci.yml ├── tsconfig.jest.json ├── vitest.config.ts ├── .prettierignore ├── .gitignore └── .turbo └── daemon └── ae401ef4dd981f33-turbo.log.2024-08-26 /widgets/RichText/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /widgets/template/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /widgets/AsyncOptions/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/data-render/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/data-render/src/core/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ 2 | -------------------------------------------------------------------------------- /tools/schema-builder/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FPanel/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/widgets/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/listTab/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/data-render/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/components/HeaderTitle/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /typing.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | publicPath: string; 3 | } 4 | -------------------------------------------------------------------------------- /docs/table-render/.test/test.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/form-render-mobile/test/test.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/schema-builder/src/index.ts: -------------------------------------------------------------------------------- 1 | import Main from './main'; 2 | 3 | export default Main -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FTooltip/index.less: -------------------------------------------------------------------------------- 1 | .dr-tooltip { 2 | margin-top: 8px; 3 | } 4 | -------------------------------------------------------------------------------- /docs/xflow/demo/flow-provider/edges.ts: -------------------------------------------------------------------------------- 1 | export const edges = [{ source: '1', target: '2', id: '234123' }]; 2 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FSteps/index.less: -------------------------------------------------------------------------------- 1 | .dr-steps { 2 | width: 100%; 3 | padding: 10px 15px; 4 | } 5 | -------------------------------------------------------------------------------- /packages/chart-render/src/components/ChartContainer/index.less: -------------------------------------------------------------------------------- 1 | .cr-chart-container { 2 | position: relative; 3 | } 4 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FCard/index.less: -------------------------------------------------------------------------------- 1 | .dr-card { 2 | margin-top: 16px; 3 | border-color: #f4f4f4; 4 | } 5 | -------------------------------------------------------------------------------- /packages/data-render/src/type.ts: -------------------------------------------------------------------------------- 1 | export interface DataVProps { 2 | [key: string]: any; 3 | } 4 | 5 | export default DataVProps; 6 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/RequestTable/index.less: -------------------------------------------------------------------------------- 1 | .custom-table { 2 | width: 100%; 3 | margin: 10px 0; 4 | } 5 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/slider/index.less: -------------------------------------------------------------------------------- 1 | .fr-slider { 2 | display: flex; 3 | width: 100%; 4 | align-items: center; 5 | } -------------------------------------------------------------------------------- /packages/x-flow/src/components/NodesPopover/index.less: -------------------------------------------------------------------------------- 1 | .nodes-popover { 2 | .ant-popover-inner-content { 3 | padding: 0; 4 | } 5 | } -------------------------------------------------------------------------------- /widgets/AsyncOptions/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function index() { 4 | return
haha
; 5 | } 6 | -------------------------------------------------------------------------------- /widgets/template/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function Template() { 4 | return
hello world
; 5 | } 6 | -------------------------------------------------------------------------------- /docs/xflow/demo/nodeWidget/index.less: -------------------------------------------------------------------------------- 1 | .node-llm-style { 2 | .custom-node-container{ 3 | background-color: rgba(97, 113, 243,0.3); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /docs/playground/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 0 3 | mobile: false 4 | title: '' 5 | sidebar: false 6 | --- 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/chart-render/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | esm: 'rollup', 3 | cjs: 'rollup', 4 | lessInBabelMode: true, 5 | lessInRollupMode: {}, 6 | }; 7 | -------------------------------------------------------------------------------- /.dumi/tmp-production/core/helmetContext.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export const context = {}; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/meta/tabs.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export const tabs = { 5 | } 6 | -------------------------------------------------------------------------------- /packages/form-render/src/locales/index.ts: -------------------------------------------------------------------------------- 1 | import enUS from './en_US'; 2 | import zhCN from './zh_CN'; 3 | 4 | export default { 5 | 'en-US': enUS, 6 | 'zh-CN': zhCN, 7 | } -------------------------------------------------------------------------------- /packages/table-render/src/locales/index.ts: -------------------------------------------------------------------------------- 1 | import enUS from './en_US'; 2 | import zhCN from './zh_CN'; 3 | 4 | export default { 5 | 'en-US': enUS, 6 | 'zh-CN': zhCN, 7 | } -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/meta/atoms.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export const components = null; 5 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/*", "widgets/*", "tools/schema-generator"], 3 | "version": "independent", 4 | "npmClient": "yarn", 5 | "useWorkspaces": true 6 | } 7 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/locales/index.ts: -------------------------------------------------------------------------------- 1 | import enUS from './en_US'; 2 | import zhCN from './zh_CN'; 3 | 4 | export default { 5 | 'en-US': enUS, 6 | 'zh-CN': zhCN, 7 | } -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/imageInput/index.less: -------------------------------------------------------------------------------- 1 | .fr-preview-image { 2 | width: 160px; 3 | } 4 | 5 | .fr-preview { 6 | position: relative; 7 | cursor: pointer; 8 | } -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/rate/index.tsx: -------------------------------------------------------------------------------- 1 | import { Rate } from 'antd'; 2 | import withFieldWrap from '../../utils/withFieldWrap'; 3 | 4 | export default withFieldWrap(Rate); -------------------------------------------------------------------------------- /packages/form-render-mobile/src/render-core/FieldList/index.less: -------------------------------------------------------------------------------- 1 | .frm-list { 2 | .frm-widget-card { 3 | margin-left: 0; 4 | margin-right: 0; 5 | margin-top: 0; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/input/index.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from 'antd'; 2 | import withFieldWrap from '../../utils/withFieldWrap'; 3 | 4 | export default withFieldWrap(Input); -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/select/index.tsx: -------------------------------------------------------------------------------- 1 | import { Select } from 'antd'; 2 | import withFieldWrap from '../../utils/withFieldWrap'; 3 | 4 | export default withFieldWrap(Select); -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/switch/index.tsx: -------------------------------------------------------------------------------- 1 | import { Switch } from 'antd'; 2 | import withFieldWrap from '../../utils/withFieldWrap'; 3 | 4 | export default withFieldWrap(Switch); -------------------------------------------------------------------------------- /scripts/dumi-plugin/publicPath.ts: -------------------------------------------------------------------------------- 1 | import { IApi } from 'dumi'; 2 | 3 | export default (api: IApi) => { 4 | api.modifyPublicPathStr(() => { 5 | return '/x-render/'; 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /packages/form-render/src/models/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | export const FRContext = createContext(null); 4 | 5 | export const ConfigContext = createContext(null); -------------------------------------------------------------------------------- /.fatherrc.js: -------------------------------------------------------------------------------- 1 | // 通用的配置,可以在每个package里写 fatherrc.js 来覆盖 2 | export default { 3 | esm: 'rollup', 4 | disableTypeCheck: false, // 如果出了问题,这个可以改成true 5 | cjs: { type: 'babel', lazy: true }, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/data-render/src/models/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | export const FRContext = createContext(null); 4 | 5 | export const ConfigContext = createContext(null); 6 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/BaseTable/index.less: -------------------------------------------------------------------------------- 1 | .dv-base-table { 2 | width: 100%; 3 | 4 | .ant-table-cell { 5 | color: #141414; 6 | font-weight: normal; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/models/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | export const FRContext = createContext(null); 4 | 5 | export const ConfigContext = createContext(null); -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/number/index.tsx: -------------------------------------------------------------------------------- 1 | import { InputNumber } from 'antd'; 2 | import withFieldWrap from '../../utils/withFieldWrap'; 3 | 4 | export default withFieldWrap(InputNumber); -------------------------------------------------------------------------------- /packages/form-render/src/widgets/voidTitle/index.less: -------------------------------------------------------------------------------- 1 | .fr-void-title { 2 | height: 24px; 3 | color: #000000e0; 4 | font-weight: 600; 5 | font-size: 16px; 6 | line-height: 24px; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/treeSelect/index.tsx: -------------------------------------------------------------------------------- 1 | import { TreeSelect } from 'antd'; 2 | import withFieldWrap from '../../utils/withFieldWrap'; 3 | 4 | export default withFieldWrap(TreeSelect); -------------------------------------------------------------------------------- /docs/table-render/basic.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 2 3 | title: '基础交互' 4 | mobile: false 5 | group: 6 | title: 最佳展示 7 | order: 2 8 | --- 9 | # 基础交互 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/components/PanelView/index.less: -------------------------------------------------------------------------------- 1 | .fr-panel-bordered { 2 | border-radius: 4px; 3 | border: 1px solid #f4f4f4; 4 | padding: 52px 24px 0px 24px; 5 | margin-bottom: 24px; 6 | } -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/form-render/changelog.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 2 3 | toc: content 4 | mobile: false 5 | group: 6 | title: 其他 7 | order: 5 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/CopyLabel/index.less: -------------------------------------------------------------------------------- 1 | .icon-label-view { 2 | display: inline-flex; 3 | align-items: center; 4 | margin-right: 5px; 5 | .anticon { 6 | cursor: pointer; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/x-flow/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ### 1.0.3 4 | - [+] xflow 初始版本发布 5 | 6 | ### 1.0.4 7 | - [+] 增加自定义组件完整案例,修复下拉框在全屏模式下无法显示的问题,增加撤销与重做按钮的隐藏配置 8 | 9 | ### 1.0.5 10 | - [+] 补充节点图标配置文档,以及更新图标的SVG形式的用法 11 | -------------------------------------------------------------------------------- /packages/x-flow/src/index.less: -------------------------------------------------------------------------------- 1 | #xflow-container { 2 | height: 100%; 3 | width: 100%; 4 | background: #F0F2F7; 5 | position: relative; 6 | 7 | .react-flow__attribution { 8 | display: none; 9 | } 10 | } -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/IconLabel/index.less: -------------------------------------------------------------------------------- 1 | .custom-icon-label-view { 2 | display: inline-flex; 3 | align-items: center; 4 | margin-right: 5px; 5 | 6 | .content { 7 | margin: 0 2px; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app.ts: -------------------------------------------------------------------------------- 1 | window.publicPath = '/'; 2 | 3 | if (location.origin.includes('gitee')) { 4 | location.href = 'https://xrender.fun/'; 5 | } 6 | 7 | if (location.origin.includes('alibaba')) { 8 | window.publicPath = '/x-render/'; 9 | } 10 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Hero.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Hero/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Logo.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Logo/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Toc.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Toc/index.js'; 5 | -------------------------------------------------------------------------------- /packages/form-render/src/derivative/SlimRender/index.tsx: -------------------------------------------------------------------------------- 1 | import FormCore from '../../form-core'; 2 | import withProvider from '../../withProvider'; 3 | import Html from '../../widgets/fields/html'; 4 | 5 | export default withProvider(FormCore, { Html }); 6 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/builtins/API.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/builtins/API/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Content.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Content/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Footer.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Footer/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Header.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Header/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Navbar.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Navbar/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Sidebar.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Sidebar/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/exports.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export * from '../exports'; 5 | export * from '/Users/zhanbo/happy/x-render/node_modules/dumi/dist/client/theme-api/index.js'; 6 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/builtins/Badge.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/builtins/Badge/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/builtins/Table.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/builtins/Table/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/Features.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/Features/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/HeadeExtra.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/HeadeExtra/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/HeroTitle.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/HeroTitle/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/LangSwitch.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/LangSwitch/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/NotFound.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/NotFound/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/RtlSwitch.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/RtlSwitch/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/SocialIcon.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/SocialIcon/index.js'; 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "printWidth": 80, 5 | "arrowParens": "avoid", 6 | "overrides": [ 7 | { 8 | "files": ".prettierrc", 9 | "options": { "parser": "json" } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/builtins/Container.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/builtins/Container/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/builtins/Previewer.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/builtins/Previewer/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/layouts/DocLayout.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/layouts/DocLayout/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/ColorSwitch.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/ColorSwitch/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/ContentTabs.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/ContentTabs/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/NavbarExtra.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/NavbarExtra/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/SearchResult.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/SearchResult/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/builtins/SourceCode.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/builtins/SourceCode/index.js'; 5 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/PreviewerActions.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/PreviewerActions/index.js'; 5 | -------------------------------------------------------------------------------- /docs/form-render/utils/index.js: -------------------------------------------------------------------------------- 1 | export const delay = ms => new Promise(res => setTimeout(res, ms)); 2 | 3 | export const fakeApi = (url, data) => { 4 | console.group('request:', url); 5 | console.log('params:', data); 6 | console.groupEnd(); 7 | return delay(500); 8 | }; 9 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FButton/index.less: -------------------------------------------------------------------------------- 1 | .dr-button { 2 | height: 22px; 3 | padding: 0; 4 | line-height: 22px; 5 | } 6 | 7 | .dr-button-modal { 8 | .ant-modal-confirm-content { 9 | margin-left: 0 !important; 10 | overflow: auto; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FButtonFold/index.less: -------------------------------------------------------------------------------- 1 | .dr-button { 2 | height: 22px; 3 | padding: 0; 4 | line-height: 22px; 5 | } 6 | 7 | .dr-button-modal { 8 | .ant-modal-confirm-content { 9 | margin-left: 0 !important; 10 | overflow: auto; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/utils/createIconFont.ts: -------------------------------------------------------------------------------- 1 | import { createFromIconfontCN } from '@ant-design/icons'; 2 | 3 | export default (url?: string) => { 4 | return createFromIconfontCN({ 5 | scriptUrl: url || '//at.alicdn.com/t/a/font_2750617_sax751jyfjl.js', 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/PreviewerActionsExtra.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/PreviewerActionsExtra/index.js'; 5 | -------------------------------------------------------------------------------- /docs/xflow/demo/nodeSetting/fullDemo/CustomImg.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const CustomImg = ({ setting }) => { 4 | console.log('props', setting); 5 | return ( 6 | logo 7 | ); 8 | } 9 | 10 | export default CustomImg; -------------------------------------------------------------------------------- /scripts/dumi-plugin/redirect.ts: -------------------------------------------------------------------------------- 1 | import { IApi } from 'dumi' 2 | 3 | export default (api: IApi) => { 4 | api.addEntryCodeAhead(() => { 5 | const code = ` 6 | if(location.origin.includes('gitee')) location.href = 'https://xrender.fun' 7 | ` 8 | return code 9 | }) 10 | }; -------------------------------------------------------------------------------- /.dumi/loading.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Spin } from 'antd'; 3 | 4 | export default () => { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } -------------------------------------------------------------------------------- /docs/xflow/demo/custom-flow/fullCase/components/ReadOnlyPanel.tsx: -------------------------------------------------------------------------------- 1 | import '../index.less'; 2 | 3 | const ReadOnlyPanel = (props) => { 4 | const { value } = props; 5 | 6 | return
{value?? '-'}
; 7 | }; 8 | 9 | export default ReadOnlyPanel; 10 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FLabel/index.less: -------------------------------------------------------------------------------- 1 | .dr-label { 2 | font-size: 14px; 3 | line-height: 24px; 4 | 5 | .label { 6 | display: inline-block; 7 | font-weight: bold; 8 | text-align: right; 9 | } 10 | 11 | .content { 12 | color: #141414; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/xflow/best-practices.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 1 3 | title: '最佳实践' 4 | mobile: false 5 | group: 6 | title: 最佳实践 7 | order: 3 8 | --- 9 | 10 | # 最佳实践 11 | 12 | 13 | ## 案例1 14 | 15 | 16 | ## 案例2 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/xflow/demo/best/basic/TextEllipsis/index.less: -------------------------------------------------------------------------------- 1 | .text-ellipsis { 2 | display: inline-block; 3 | max-width: 100%; 4 | overflow: hidden; 5 | white-space: nowrap; 6 | text-overflow: ellipsis; 7 | } 8 | 9 | .paragraph-ellipsis { 10 | display: block; 11 | width: 100%; 12 | word-break: break-all; 13 | } 14 | -------------------------------------------------------------------------------- /docs/xflow/demo/best/demo2/TextEllipsis/index.less: -------------------------------------------------------------------------------- 1 | .text-ellipsis { 2 | display: inline-block; 3 | max-width: 100%; 4 | overflow: hidden; 5 | white-space: nowrap; 6 | text-overflow: ellipsis; 7 | } 8 | 9 | .paragraph-ellipsis { 10 | display: block; 11 | width: 100%; 12 | word-break: break-all; 13 | } 14 | -------------------------------------------------------------------------------- /packages/chart-render/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { MetaItem } from './type'; 2 | 3 | export function splitMeta(meta: MetaItem[] = []) { 4 | const metaDim: MetaItem[] = []; 5 | const metaInd: MetaItem[] = []; 6 | meta.forEach(item => (item.isDim ? metaDim : metaInd).push(item)); 7 | return { metaDim, metaInd }; 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: lhbxs 7 | --- 8 | 9 | ### 期望的新功能 (describe the expected new feature) 10 | 11 | ### 简述一下使用场景,便于开发者更好理解新功能的必要性 (describe your scenario for us to understand the need) 12 | -------------------------------------------------------------------------------- /docs/xflow/updateLog.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 2 3 | title: '更新日志' 4 | mobile: false 5 | group: 6 | title: '其他' 7 | order: 5 8 | --- 9 | 10 | # 更新日志 11 | 12 | ### 1.0.3 13 | - [+] xflow 初始版本发布 14 | 15 | ### 1.0.4 16 | - [+] 增加自定义组件完整案例,修复下拉框在全屏模式下无法显示的问题,增加撤销与重做按钮的隐藏配置 17 | 18 | ### 1.0.5 19 | - [+] 补充节点图标配置文档,以及更新图标的SVG形式的用法 20 | -------------------------------------------------------------------------------- /packages/x-flow/src/components/TextEllipsis/index.less: -------------------------------------------------------------------------------- 1 | .text-ellipsis { 2 | display: inline-block; 3 | max-width: 100%; 4 | overflow: hidden; 5 | text-overflow: ellipsis; 6 | white-space: nowrap; 7 | } 8 | 9 | 10 | .paragraph-ellipsis { 11 | display: block; 12 | width: 100%; 13 | word-break: break-all; 14 | } 15 | -------------------------------------------------------------------------------- /packages/data-render/src/index.ts: -------------------------------------------------------------------------------- 1 | import DRender from './core'; 2 | import withProvider from './withProvider'; 3 | import * as defaultWidgets from './widgets'; 4 | 5 | export { default as FRender } from './core/renderer'; 6 | 7 | export const DataSlimRender = withProvider(DRender); 8 | export default withProvider(DRender, defaultWidgets); 9 | -------------------------------------------------------------------------------- /docs/form-render/demo/FormRender.jsx: -------------------------------------------------------------------------------- 1 | import FormRender, { useForm } from 'form-render'; 2 | import React from 'react'; 3 | 4 | const Demo = ({ schema, ...otherProps }) => { 5 | const form = useForm(); 6 | 7 | return 8 | }; 9 | 10 | export default Demo; 11 | -------------------------------------------------------------------------------- /docs/table-render/custom-table.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 6 3 | mobile: false 4 | title: 'Table 包裹容器' 5 | group: 6 | title: 最佳展示 7 | order: 0 8 | --- 9 | 10 | # tableWrapper 包裹容器 11 | 12 | 有些情况下,你会希望在搜索栏和表格之间增加一些内容。这时可以通过 `tableWrapper` 实现你的需求。 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/TextEllipsis/index.less: -------------------------------------------------------------------------------- 1 | .text-ellipsis-hidden { 2 | visibility: hidden; 3 | } 4 | .text-ellipsis-box { 5 | overflow: hidden; 6 | 7 | .text-ellipsis-all { 8 | padding: 0 16px; 9 | color: rgba(63, 127, 251, 1); 10 | font-size: 14px; 11 | cursor: pointer; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FText/index.less: -------------------------------------------------------------------------------- 1 | .dv-text { 2 | display: inline-flex; 3 | align-items: center; 4 | min-width: 20px; 5 | min-height: 18px; 6 | margin-right: 10px; 7 | font-size: 14px; 8 | 9 | .left-icon { 10 | margin-right: 4px; 11 | } 12 | 13 | .right-icon { 14 | margin-left: 4px; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/table-render/src/core/ToolbarView/index.less: -------------------------------------------------------------------------------- 1 | .tr-toolbar { 2 | display: flex; 3 | align-items: center; 4 | justify-content: space-between; 5 | height: 64px; 6 | } 7 | 8 | .tr-toolbar-nohead { 9 | height: 24px; 10 | } 11 | 12 | 13 | .tr-toolbar-right { 14 | display: flex; 15 | align-items: flex-start; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /.github/workflows/emoji-helper.yml: -------------------------------------------------------------------------------- 1 | name: Emoji Helper 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | emoji: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions-cool/emoji-helper@v1.0.0 12 | with: 13 | type: 'release' 14 | emoji: '+1, laugh, heart, hooray, rocket, eyes' 15 | -------------------------------------------------------------------------------- /packages/form-render/src/form-core/connectForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import useForm from '../models/useForm'; 3 | 4 | export default (Component: React.FC) => { 5 | return forwardRef((props, ref) => { 6 | const form = useForm(); 7 | 8 | return ; 9 | }); 10 | } -------------------------------------------------------------------------------- /packages/table-render/CONTRIBUTION.md: -------------------------------------------------------------------------------- 1 | ## 如何贡献代码 2 | 3 | ``` 4 | # fork项目 & git clone 5 | 6 | # 安装依赖 7 | tnpm i 8 | 9 | # 切到 dev 分支 10 | git checkout dev 11 | 12 | # 跑起来 13 | npm start 14 | 15 | # 发布 16 | ## 1. 更新版本 17 | npm version patch (major, minor) 18 | 19 | ## 2. 修改 README.md / CHANGELOG.md 20 | 21 | ## 3. 发布 22 | tnpm publish 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/x-flow/src/utils/createIconFont.ts: -------------------------------------------------------------------------------- 1 | import { createFromIconfontCN } from '@ant-design/icons'; 2 | 3 | export default (url?: string) => { 4 | return createFromIconfontCN({ 5 | // scriptUrl: url || '//at.alicdn.com/t/a/font_4201076_frx3c9x07if.js', 6 | scriptUrl: url || '//at.alicdn.com/t/a/font_4069358_dd524fgnynb.js', 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /docs/playground/controller/index.css: -------------------------------------------------------------------------------- 1 | .playground-controller .fr-field { 2 | margin-bottom: 4px; 3 | } 4 | 5 | .playground-controller { 6 | margin-bottom: 1px; 7 | background-color: #fff; 8 | padding: 12px 30px 6px 30px; 9 | border-radius: 3px; 10 | } 11 | 12 | .playground-controller .fr-inline-field { 13 | margin-right: 60px !important; 14 | } -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FRow/index.less: -------------------------------------------------------------------------------- 1 | .dr-row { 2 | height: 100%; 3 | 4 | .col-item { 5 | width: 0; 6 | } 7 | 8 | .col-item-background { 9 | position: relative; 10 | padding: 10px 15px; 11 | background: #fff; 12 | border-radius: 3px; 13 | 14 | box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.06); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/form-core/connectForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import useForm from '../models/useForm'; 3 | 4 | export default (Component: React.FC) => { 5 | return forwardRef((props, ref) => { 6 | const form = useForm(); 7 | 8 | return ; 9 | }); 10 | } -------------------------------------------------------------------------------- /packages/table-render/开发文档.md: -------------------------------------------------------------------------------- 1 | # 开发文档 2 | 3 | ## 启动 4 | 5 | ``` 6 | # 安装依赖 7 | yarn 8 | # 起项目 9 | npm start 10 | ``` 11 | 12 | ## 开发 13 | 14 | 小需求 & 简单的 bug fix,在 dev 分支开发,大改动另起一个分支,分支名表达改动内容就行 15 | 16 | ## 发布 17 | 18 | ``` 19 | # tag版本号 20 | npm version 1.0.0 或者 npm version patch 21 | # 发版 22 | npm publish 23 | # 部署文档 24 | npm run deploy 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/x-flow/src/nodes/node-common/index.less: -------------------------------------------------------------------------------- 1 | .custom-node-start { 2 | width: 240px; 3 | padding: 0 12px; 4 | background: #fff; 5 | border-radius: 12px; 6 | 7 | .title { 8 | display: flex; 9 | height: 50px; 10 | align-items: center; 11 | span { 12 | font-weight: bold; 13 | margin-left: 8px; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /packages/x-flow/src/nodes/node-end/index.less: -------------------------------------------------------------------------------- 1 | .custom-node-start { 2 | width: 240px; 3 | padding: 0 12px; 4 | background: #fff; 5 | border-radius: 12px; 6 | 7 | .title { 8 | display: flex; 9 | height: 50px; 10 | align-items: center; 11 | span { 12 | font-weight: bold; 13 | margin-left: 8px; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /packages/x-flow/src/nodes/node-start/index.less: -------------------------------------------------------------------------------- 1 | .custom-node-start { 2 | width: 240px; 3 | padding: 0 12px; 4 | background: #fff; 5 | border-radius: 12px; 6 | 7 | .title { 8 | display: flex; 9 | height: 50px; 10 | align-items: center; 11 | span { 12 | font-weight: bold; 13 | margin-left: 8px; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /.dumi/tmp-production/core/EmptyRoute.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | import React from 'react'; 5 | import { Outlet, useOutletContext } from 'umi'; 6 | export default function EmptyRoute() { 7 | const context = useOutletContext(); 8 | return ; 9 | } 10 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/theme/slots/SearchBar.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export { default } from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/SearchBar/index.js'; 5 | export * from '/Users/zhanbo/happy/x-render/node_modules/dumi/theme-default/slots/SearchBar/index.js'; 6 | -------------------------------------------------------------------------------- /docs/xflow/demo/flow-provider/nodes.ts: -------------------------------------------------------------------------------- 1 | export const nodes = [ 2 | { 3 | id: '1', 4 | type: 'Start', 5 | data: {}, 6 | position: { 7 | x: 40, 8 | y: 240, 9 | }, 10 | }, 11 | { 12 | id: '2', 13 | type: 'End', 14 | data: {}, 15 | position: { 16 | x: 500, 17 | y: 240, 18 | }, 19 | }, 20 | ]; 21 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FImage/index.less: -------------------------------------------------------------------------------- 1 | .custom-image-widget { 2 | width: 170px; 3 | height: 100px; 4 | margin: 8px 0; 5 | background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.25) 100%); 6 | border-radius: 2px; 7 | 8 | img { 9 | width: 100%; 10 | height: 100%; 11 | border-radius: 2px; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/voidTitle/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | import './index.less'; 4 | 5 | export default ({ schema }) => { 6 | return ( 7 |
8 | {schema.title} 9 |
10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /packages/chart-render/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { Schema } from 'formRenderV1'; 2 | export { ChartProvider, withChart } from './components/ChartProvider'; 3 | export { default as Search } from './components/Search'; 4 | export { useChart } from './utils/store'; 5 | 6 | export { default as Column } from './widgets/Column'; 7 | export { default as Pie } from './widgets/Pie'; 8 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/IconView/index.tsx: -------------------------------------------------------------------------------- 1 | 2 | import { createFromIconfontCN } from '@ant-design/icons'; 3 | 4 | /** 5 | * icon 图标库 6 | * 7 | * 图标库资源变动需要更新 scriptUrl 资源路径 8 | */ 9 | 10 | const IconView = createFromIconfontCN({ 11 | scriptUrl: '//at.alicdn.com/t/font_2750617_db4bg3gyled.js', 12 | }); 13 | 14 | export default IconView; 15 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/components/PanelView/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | import './index.less'; 4 | 5 | const PanelView = ({ children, bordered } : any) => { 6 | return
{children}
; 7 | } 8 | 9 | export default PanelView; 10 | -------------------------------------------------------------------------------- /.dumi/tmp-production/dumi/exportStaticRuntimePlugin.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export function modifyClientRenderOpts(memo: any) { 5 | const { history, hydrate } = memo; 6 | 7 | return { 8 | ...memo, 9 | hydrate: hydrate && !history.location.pathname.startsWith('/~demos'), 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /.dumi/theme/layouts/GlobalLayout/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ConfigProvider } from 'antd'; 3 | import { useOutlet } from 'dumi'; 4 | 5 | const GlobalLayout: React.FC = () => { 6 | const outlet = useOutlet(); 7 | return ( 8 | 10 | {outlet} 11 | 12 | ); 13 | }; 14 | 15 | export default GlobalLayout; 16 | -------------------------------------------------------------------------------- /.dumi/tmp-production/core/exportStaticRuntimePlugin.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | export function modifyClientRenderOpts(memo: any) { 5 | const { history, hydrate } = memo; 6 | 7 | return { 8 | ...memo, 9 | hydrate: hydrate && !["/~demos/:id"].includes(history.location.pathname), 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /docs/xflow/demo/custom-flow/customWidget.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from 'antd'; 2 | 3 | const customWidget = ({ value, onChange,...rest }) => { 4 | console.log("参数", { value, onChange, ...rest }) 5 | return ( 6 | onChange({ inputVal: e.target.value })} 9 | /> 10 | ); 11 | }; 12 | 13 | export default customWidget; 14 | -------------------------------------------------------------------------------- /packages/table-render/src/locales/zh_CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | "search": "查询", 3 | "reset": "重置", 4 | "copy_success": "复制成功", 5 | "column_setting": "列设置", 6 | "default": "默认", 7 | "middle": "中等", 8 | "small": "紧凑", 9 | "table_density": "表格密度", 10 | "exit_full_screen": "退出全屏", 11 | "full_screen": "全屏", 12 | "cannot_full_screen": "当前页面不支持全屏功能", 13 | "reload": "刷新" 14 | }; -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FTitle/index.less: -------------------------------------------------------------------------------- 1 | .dr-title { 2 | display: flex; 3 | align-items: center; 4 | margin-bottom: 10px; 5 | 6 | .view-title { 7 | margin: 0; 8 | color: #141414; 9 | } 10 | 11 | .view-title-icon { 12 | width: 6px; 13 | height: 6px; 14 | margin-right: 10px; 15 | background-color: #3f7ffb; 16 | border-radius: 6px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/widgets/Group/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | const prefix = 'frm-widget-group'; 5 | 6 | export default (props: any) => { 7 | const { children, title } = props; 8 | 9 | return ( 10 |
11 |
{title}
12 | {children} 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /widgets/RichText/.fatherrc.js: -------------------------------------------------------------------------------- 1 | // 通用的配置,可以在每个package里写 fatherrc.js 来覆盖 2 | export default { 3 | esm: 'rollup', 4 | cjs: 'rollup', 5 | disableTypeCheck: false, // 如果出了问题,这个可以改成true 6 | extraBabelPlugins: [ 7 | [ 8 | 'babel-plugin-import', 9 | { 10 | libraryName: 'antd', 11 | libraryDirectory: 'lib', 12 | style: true, 13 | }, 14 | ], 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /widgets/template/.fatherrc.js: -------------------------------------------------------------------------------- 1 | // 通用的配置,可以在每个package里写 fatherrc.js 来覆盖 2 | export default { 3 | esm: 'rollup', 4 | cjs: 'rollup', 5 | disableTypeCheck: false, // 如果出了问题,这个可以改成true 6 | extraBabelPlugins: [ 7 | [ 8 | 'babel-plugin-import', 9 | { 10 | libraryName: 'antd', 11 | libraryDirectory: 'lib', 12 | style: true, 13 | }, 14 | ], 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /widgets/AsyncOptions/.fatherrc.js: -------------------------------------------------------------------------------- 1 | // 通用的配置,可以在每个package里写 fatherrc.js 来覆盖 2 | export default { 3 | esm: 'rollup', 4 | cjs: 'rollup', 5 | disableTypeCheck: false, // 如果出了问题,这个可以改成true 6 | extraBabelPlugins: [ 7 | [ 8 | 'babel-plugin-import', 9 | { 10 | libraryName: 'antd', 11 | libraryDirectory: 'lib', 12 | style: true, 13 | }, 14 | ], 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/widgets/Group/index.less: -------------------------------------------------------------------------------- 1 | .frm-widget-group { 2 | 3 | &-title { 4 | font-size: 15px; 5 | color: #999; 6 | padding: 6px 16px; 7 | border-top: 1px solid rgb(238, 238, 238); 8 | border-bottom: 1px solid rgb(238, 238, 238); 9 | } 10 | 11 | .adm-grid-item:first-of-type { 12 | .adm-list-item-content { 13 | border-top: none; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/x-flow/src/components/IconView/index.tsx: -------------------------------------------------------------------------------- 1 | import { createFromIconfontCN } from '@ant-design/icons'; 2 | 3 | /** 4 | * icon 图标库 5 | * 图标库资源变动需要更新 scriptUrl 资源路径 6 | * https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4201076 7 | */ 8 | 9 | const Icon = createFromIconfontCN({ 10 | scriptUrl: '//at.alicdn.com/t/a/font_4069358_dd524fgnynb.js', 11 | }); 12 | 13 | export default Icon; 14 | -------------------------------------------------------------------------------- /tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES5", 4 | "types": ["jest", "jest-enzyme"], 5 | "allowJs": true, 6 | "skipLibCheck": false, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "jsx": "react", 10 | "paths": { 11 | "@@/*": [".dumi/tmp/*"] 12 | } 13 | }, 14 | "exclude": ["./packages/*/esm", "./packages/*/lib"] 15 | } 16 | -------------------------------------------------------------------------------- /packages/x-flow/src/models/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | import { FlowProps } from '../types'; 3 | import { FlowStore } from './store'; 4 | 5 | type Config = FlowProps & Record 6 | export const ConfigContext = createContext(null); 7 | 8 | const StoreContext = createContext(null); 9 | export const Provider = StoreContext.Provider; 10 | export default StoreContext; 11 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { defineConfig } from 'vitest/config'; 4 | import react from '@vitejs/plugin-react'; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | react({ 9 | babel: { 10 | plugins: ['@babel/plugin-transform-react-jsx'], 11 | }, 12 | }) as any, 13 | ], 14 | test: { 15 | globals: true, 16 | environment: 'jsdom', 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/listDrawer/index.less: -------------------------------------------------------------------------------- 1 | @ant-prefix: ant; 2 | 3 | .fr-list-drawer { 4 | margin-bottom: 24px; 5 | 6 | &-table-header { 7 | width: 100%; 8 | display: flex; 9 | justify-content: right; 10 | align-items: center; 11 | margin-bottom: 10px; 12 | } 13 | 14 | .@{ant-prefix}-form-item { 15 | margin-bottom: 0; 16 | } 17 | 18 | .fr-list-item-operate { 19 | gap: 0 !important; 20 | } 21 | } -------------------------------------------------------------------------------- /packages/form-render-mobile/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ### 1.0.15 4 | - [!] 修复 removeHidden 配置不生效 5 | 6 | ### 1.0.14 7 | - [+] labelWidget、descWidget 增加 addons 访问属性 8 | - [-] 兼容 widget 大小写配置 9 | ### 1.0.13 10 | - [+] 增加输入控件单独配置布局 layout = 'row' | 'column' 11 | - [+] 补齐 tooltip 字段,与 PC 端保持一致 12 | - [!] 修复 title 不存在时,校验信息不提示 13 | ### 1.0.5 14 | - [+] 增加 form.getFieldRef API,自定义组件可以暴露实例,供 getFieldRef 使用 15 | ### 1.0.0 16 | 17 | - [+] form-render-mobile 1.0 正式发版 18 | -------------------------------------------------------------------------------- /packages/x-flow/src/operator/UndoRedo/index.less: -------------------------------------------------------------------------------- 1 | .fai-reactflow-undoredo { 2 | display: flex; 3 | align-items: center; 4 | padding: 2px 1px; 5 | border-radius: 8px; 6 | border: 0.5px solid #f3f4f6; 7 | background-color: #ffffff; 8 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); 9 | color: #667085; 10 | margin-right: 10px; 11 | 12 | .ant-btn { 13 | display: inline-flex; 14 | align-items: center; 15 | justify-content: center; 16 | } 17 | } -------------------------------------------------------------------------------- /docs/form-render/test/test.md: -------------------------------------------------------------------------------- 1 | --- 2 | mobile: false 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/form-core/index.less: -------------------------------------------------------------------------------- 1 | .frm-form { 2 | .adm-list-item { 3 | padding: 0 16px; 4 | } 5 | 6 | .adm-collapse-panel-content-inner > .adm-list-item { 7 | padding: 0; 8 | 9 | .adm-list-item-content { 10 | padding-right: 0; 11 | } 12 | } 13 | 14 | .adm-list-body { 15 | background: transparent; 16 | } 17 | } 18 | 19 | .frm-form-card { 20 | .adm-list-body { 21 | border: none !important; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.dumi/tmp-production/core/helmet.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | // This file is generated by Umi automatically 3 | // DO NOT CHANGE IT MANUALLY! 4 | import React from 'react'; 5 | import { HelmetProvider } from '/Users/zhanbo/happy/x-render/node_modules/@umijs/preset-umi/node_modules/@umijs/renderer-react'; 6 | import { context } from './helmetContext'; 7 | 8 | export const innerProvider = (container) => { 9 | return React.createElement(HelmetProvider, { context }, container); 10 | } 11 | -------------------------------------------------------------------------------- /docs/form-render/schema/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | type: 'object', 3 | column: 3, 4 | displayType: 'row', 5 | properties: { 6 | input1: { 7 | title: 'Field A', 8 | type: 'string' 9 | }, 10 | input2: { 11 | title: 'Field B', 12 | type: 'string' 13 | }, 14 | input3: { 15 | title: 'Field C', 16 | type: 'string' 17 | }, 18 | input4: { 19 | title: 'Field D', 20 | type: 'string' 21 | } 22 | } 23 | }; -------------------------------------------------------------------------------- /packages/form-render/src/widgets/components/HeaderTitle/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | const HeaderTitle = (props: any) => { 5 | const { title, description } = props; 6 | 7 | return ( 8 |
9 | {title} 10 | {description && ( {description} )} 11 |
12 | ); 13 | } 14 | 15 | export default HeaderTitle 16 | -------------------------------------------------------------------------------- /docs/playground/json/dynamic-function.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | schema: { 3 | type: 'object', 4 | properties: { 5 | input: { 6 | title: '动态函数检验', 7 | tooltip: '动态函数检验,存储的是纯函数', 8 | type: 'string', 9 | labelWidth: 120, 10 | rules: [ 11 | { 12 | validator: (rule, value) => value === 'muji', 13 | message: '输入的值不等于muji,请重新输入!', 14 | }, 15 | ], 16 | }, 17 | }, 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/textArea/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Input } from 'antd'; 3 | import withFieldWrap from '../../utils/withFieldWrap'; 4 | 5 | const TextArea = (props: any) => { 6 | let finalProps = { 7 | autoSize: { 8 | minRows: 3, 9 | }, 10 | ...props, 11 | }; 12 | if (finalProps.rows) delete finalProps.autoSize; 13 | 14 | return ; 15 | }; 16 | 17 | 18 | export default withFieldWrap(TextArea) -------------------------------------------------------------------------------- /packages/table-render/src/locales/en_US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | "search": "Search", 3 | "reset": "Reset", 4 | "copy_success": "Copy Success", 5 | "column_setting": "ColumnSetting", 6 | "default": "Default", 7 | "middle": "Middle", 8 | "small": "small", 9 | "table_density": "Table Density", 10 | "exit_full_screen": "Exit FullScreen", 11 | "full_screen": "FullScreen", 12 | "cannot_full_screen": "The current page does not support full screen function", 13 | "reload": "Reload" 14 | } -------------------------------------------------------------------------------- /packages/form-render/src/widgets/listCard/index.less: -------------------------------------------------------------------------------- 1 | .fr-list-card { 2 | margin-bottom: 24px; 3 | 4 | .fr-list-item { 5 | display: flex; 6 | align-items: flex-start; 7 | position: relative; 8 | } 9 | 10 | .fr-list-item-operate { 11 | padding: 0 20px; 12 | height: 32px; 13 | gap: 0 !important; 14 | } 15 | 16 | .fr-list-item-operate-fixed { 17 | position: absolute; 18 | right: 8px; 19 | } 20 | 21 | .fr-list-add-btn { 22 | padding: 0 8px; 23 | } 24 | } -------------------------------------------------------------------------------- /packages/data-render/src/widgets/utils/hooks.ts: -------------------------------------------------------------------------------- 1 | import { useReducer, useRef, useEffect } from 'react'; 2 | 3 | export function usePrevious(value: any) { 4 | const ref = useRef(null); 5 | useEffect(() => { 6 | ref.current = value; 7 | }, [value]); 8 | return ref.current; 9 | } 10 | 11 | // 类似于class component的setState 12 | export const useSet = (initState: any) => { 13 | return useReducer((state: any, newState: any) => { 14 | return { ...state, ...newState }; 15 | }, initState); 16 | }; 17 | -------------------------------------------------------------------------------- /docs/form-render/schema/simple.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | type: 'object', 3 | properties: { 4 | input: { 5 | title: '输入框', 6 | type: 'string', 7 | widget: 'input' 8 | }, 9 | select: { 10 | title: '下拉框', 11 | type: 'string', 12 | widget: 'select', 13 | props: { 14 | options: [ 15 | { label: '早', value: 'a' }, 16 | { label: '中', value: 'b' }, 17 | { label: '晚', value: 'c' } 18 | ] 19 | } 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /docs/xflow/demo/best/basic/tools.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Space } from 'antd'; 2 | import React from 'react' 3 | 4 | 5 | export const Tools = () => { 6 | return ( 7 | 8 | 11 | 14 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /docs/xflow/demo/best/demo2/tools.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Space } from 'antd'; 2 | import React from 'react' 3 | 4 | 5 | export const Tools = () => { 6 | return ( 7 | 8 | 11 | 14 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/boxcard/index.less: -------------------------------------------------------------------------------- 1 | @ant-prefix: ant; 2 | 3 | .fr-obj-card { 4 | border-radius: 4px; 5 | border-color: #f4f4f4; 6 | margin-bottom: 24px !important; 7 | 8 | .@{ant-prefix}-card-head { 9 | border: none 10 | } 11 | 12 | .@{ant-prefix}-card-body { 13 | padding: 12px 24px !important; 14 | } 15 | 16 | .fr-header-desc { 17 | word-break: break-all; 18 | color: rgba(0, 0, 0, .45); 19 | margin-left: 6px; 20 | font-weight: normal; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /docs/table-render/toolbar.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 7 3 | title: '工具栏' 4 | mobile: false 5 | group: 6 | title: 最佳展示 7 | --- 8 | 9 | # 工具栏 10 | 11 | Table Render 内置工具栏,通过 `toolbarAction` 开启。默认四种功能,刷新表格、更改表格 `size`、全屏显示表格、表格列设置。 12 | 13 | :::warning 14 | 使用表格列设置功能,必须为每个 `column` 指定 `key` 或 `dataIndex`。大多数场景下使用 `dataIndex` 就足够了,但前提是必须保证其是唯一的,如果不是,需要另外指定 `key` 的值。 15 | ::: 16 | 17 | 18 | 19 | 可以通过传入一个对象控制具体使用哪些工具,例如只显示列设置功能。 20 | 21 | -------------------------------------------------------------------------------- /packages/chart-render/src/components/ChartContainer/index.tsx: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React, { CSSProperties, FC, memo } from 'react'; 3 | import './index.less'; 4 | 5 | const ChartContainer: FC<{ 6 | children: React.ReactNode; 7 | className?: string; 8 | style?: CSSProperties; 9 | }> = ({ children, className, style }) => ( 10 |
11 | {children} 12 |
13 | ); 14 | 15 | export default memo(ChartContainer); 16 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/boxLineTitle/index.less: -------------------------------------------------------------------------------- 1 | .fr-obj-line-title { 2 | .fr-obj-header { 3 | line-height: 36px; 4 | border-bottom: 1px solid #e9e9e9; 5 | } 6 | 7 | .fr-header-title { 8 | color: #000000e0; 9 | font-size: 16px; 10 | font-weight: 600; 11 | } 12 | 13 | .fr-header-desc { 14 | word-break: break-all; 15 | color: rgba(0, 0, 0, .45); 16 | margin-left: 6px; 17 | font-weight: normal; 18 | } 19 | 20 | .fr-obj-content { 21 | padding: 24px 0 0 0; 22 | } 23 | } -------------------------------------------------------------------------------- /packages/form-render/src/widgets/boxSubInline/index.less: -------------------------------------------------------------------------------- 1 | @ant-prefix: ant; 2 | 3 | .fr-obj-subinline-label-hidden > .@{ant-prefix}-form-item-row > .@{ant-prefix}-form-item-label { 4 | visibility: hidden; 5 | } 6 | 7 | .fr-obj-subinline-background > .@{ant-prefix}-form-item-row > .@{ant-prefix}-form-item-control { 8 | background-color: #f6f6f6; 9 | padding: 24px 24px 0 24px; 10 | border-radius: 4px; 11 | } 12 | 13 | .fr-obj-subinline { 14 | .@{ant-prefix}-form-item-row { 15 | flex-wrap: nowrap; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/x-flow/src/index.ts: -------------------------------------------------------------------------------- 1 | import XFlow from './XFlow'; 2 | import withProvider from './withProvider'; 3 | 4 | import * as nodes from './nodes'; 5 | import FlowProps from './types'; 6 | 7 | export type { 8 | default as FR, 9 | } from './types'; 10 | 11 | export { FlowProvider } from './components/FlowProvider'; 12 | export { useFlow } from './hooks/useFlow'; 13 | export { useNodes } from './hooks/useNodes'; 14 | export { useEdges } from './hooks/useEdges'; 15 | 16 | export default withProvider(XFlow, nodes); 17 | -------------------------------------------------------------------------------- /packages/x-flow/src/nodes/index.tsx: -------------------------------------------------------------------------------- 1 | export { default as StartNode } from './node-start'; 2 | export { default as EndNode } from './node-end'; 3 | export { default as CommonNode } from './node-common'; 4 | export { default as SwitchNode } from './node-switch'; 5 | export { default as SwitchNodeSettingWidget } from './node-switch/setting'; 6 | export { default as ParallelNode } from './node-parallel'; 7 | export { default as ParallelNodeSettingWidget } from './node-parallel/setting'; 8 | export { default as NoteNode } from './node-note'; 9 | -------------------------------------------------------------------------------- /packages/form-render-mobile/src/render-core/FieldItem/field.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useUpdateEffect } from 'ahooks'; 3 | 4 | const FieldWrapper = (props: any) => { 5 | const { Field, fieldProps, defaultValue, ...otherProps } = props; 6 | 7 | useUpdateEffect(() => { 8 | otherProps.onChange(defaultValue); 9 | }, [JSON.stringify(defaultValue)]); 10 | 11 | return ( 12 | 16 | ); 17 | } 18 | 19 | export default FieldWrapper; -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/checkbox/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Checkbox } from 'antd'; 3 | import withFieldWrap from '../../utils/withFieldWrap'; 4 | 5 | interface Props { 6 | title: string; 7 | [key: string]: any; 8 | } 9 | 10 | const CheckBox: React.FC = ({ title, ...rest }) => { 11 | return ( 12 | <> 13 | 14 | {title} 15 | 16 | ); 17 | } 18 | 19 | export default withFieldWrap(CheckBox); 20 | 21 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/fields/color/index.less: -------------------------------------------------------------------------------- 1 | .fr-color-picker { 2 | width: 100%; 3 | display: flex; 4 | flex-direction: row; 5 | align-items: center; 6 | color: #666; 7 | } 8 | 9 | .fr-color-picker .rc-color-picker-trigger { 10 | margin-right: 12px; 11 | height: 32px; 12 | width: 60px; 13 | border: 1px solid #e5e5e5; 14 | } 15 | 16 | .fr-color-picker > p { 17 | margin: 0; 18 | font-size: 14px; 19 | line-height: 28px; 20 | } 21 | 22 | .fr-color-picker .rc-color-picker-wrap { 23 | display: flex; 24 | } -------------------------------------------------------------------------------- /packages/data-render/src/widgets/components/InnerHtml/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | const InnerHtml = (props: any) => { 5 | const { data, style, className } = props; 6 | 7 | if (typeof data === 'object') { 8 | return null; 9 | } 10 | 11 | return ( 12 | 17 | ); 18 | }; 19 | 20 | export default InnerHtml; 21 | -------------------------------------------------------------------------------- /packages/x-flow/src/utils/flow.ts: -------------------------------------------------------------------------------- 1 | import { uuid } from './'; 2 | 3 | /** 4 | * 获取所有子节点 5 | */ 6 | export const generateCopyNodes = (parentNode: any) => { 7 | // 1、定义 childNodeIds 数组,用于存储找到的所有节点的 id,默认把 rootNode 添加到数组中 8 | const childNodes: any[] = []; 9 | const rootNode = { 10 | id: uuid(), 11 | type: parentNode.type, 12 | data: { 13 | ...parentNode.data, 14 | }, 15 | position: { x: 0, y: 0 }, 16 | sourceId: parentNode.id, 17 | }; 18 | childNodes.push(rootNode); 19 | 20 | return childNodes; 21 | }; 22 | -------------------------------------------------------------------------------- /docs/playground/json/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": { 3 | "type": "object", 4 | "properties": { 5 | "listName": { 6 | "title": "对象数组", 7 | "description": "对象数组嵌套功能", 8 | "type": "array", 9 | "items": { 10 | "type": "object", 11 | "properties": { 12 | "inputName": { 13 | "title": "简单输入框", 14 | "type": "string" 15 | } 16 | } 17 | } 18 | } 19 | }, 20 | "required": [] 21 | }, 22 | "formData": {} 23 | } 24 | -------------------------------------------------------------------------------- /packages/form-render/src/widgets/utils/hooks.ts: -------------------------------------------------------------------------------- 1 | import { message } from 'antd'; 2 | import { useReducer, useRef, useEffect, useState } from 'react'; 3 | 4 | export function usePrevious(value: any) { 5 | const ref = useRef(null); 6 | useEffect(() => { 7 | ref.current = value; 8 | }, [value]); 9 | return ref.current; 10 | } 11 | 12 | // 类似于class component的setState 13 | export const useSet = (initState: any) => { 14 | return useReducer((state: any, newState: any) => { 15 | return { ...state, ...newState }; 16 | }, initState); 17 | }; -------------------------------------------------------------------------------- /packages/form-render/src/widgets/ErrorSchema/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { translation } from '../utils'; 3 | import { ConfigProvider } from 'antd'; 4 | 5 | const ErrorSchema = (schema: any) => { 6 | const configCtx = useContext(ConfigProvider.ConfigContext); 7 | const t = translation(configCtx); 8 | 9 | return ( 10 |
11 |
{t('schema_not_match')}
12 |
{JSON.stringify(schema)}
13 |
14 | ); 15 | } 16 | 17 | export default ErrorSchema; -------------------------------------------------------------------------------- /packages/form-render/src/widgets/utils/withFieldWrap.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const getProps = (props: any, filter: any[]) => { 4 | const result = {}; 5 | 6 | Object.keys(props).forEach(key => { 7 | if (filter.includes(key)) { 8 | return; 9 | } 10 | result[key] = props[key]; 11 | }); 12 | 13 | return result; 14 | } 15 | 16 | export default (Field: any, filterProps = ['addons', 'schema', 'dependValues']) => { 17 | return (props: any) => { 18 | return ; 19 | }; 20 | } -------------------------------------------------------------------------------- /packages/x-flow/src/components/CustomEdge/index.less: -------------------------------------------------------------------------------- 1 | 2 | .custom-edge-line { 3 | position: absolute; 4 | z-index: 1000; 5 | pointer-events: all; 6 | 7 | .line-content { 8 | width: 60px; 9 | display: flex; 10 | justify-content: space-around; 11 | align-items: center; 12 | } 13 | 14 | .line-icon-box { 15 | width: 16px; 16 | height: 16px; 17 | border-radius: 16px; 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | background: #296dff; 22 | visibility: visible; 23 | } 24 | } -------------------------------------------------------------------------------- /packages/form-render/src/widgets/components/TimePicker/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import DatePicker from '../DatePicker'; 3 | 4 | const TimePicker: any = React.forwardRef((props: any, ref: any) => { 5 | return ; 6 | }); 7 | 8 | TimePicker.displayName = 'TimePicker'; 9 | 10 | TimePicker.RangePicker = React.forwardRef((props: any, ref: any) => { 11 | return ; 12 | }); 13 | 14 | export default TimePicker; -------------------------------------------------------------------------------- /packages/form-render-mobile/src/widgets/Radio/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Radio, Space } from 'antd-mobile'; 3 | import { omit } from 'lodash-es'; 4 | 5 | export default (props: any) => { 6 | const { options, ...rest } = omit(props, ['addons', 'schema']) 7 | return ( 8 | 9 | 10 | {options.map((item: any) => { 11 | return {item.label} 12 | })} 13 | 14 | 15 | ) 16 | } -------------------------------------------------------------------------------- /packages/form-render/src/widgets/components/FButton/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'antd'; 3 | 4 | const HeaderTitle = (props: any) => { 5 | const { icon, children, btnType, ...otherProps } = props; 6 | 7 | let btnProps = { ...otherProps }; 8 | if (btnType === 'icon') { 9 | btnProps.icon = icon; 10 | btnProps.size = 'small' 11 | } else { 12 | btnProps.children = children; 13 | } 14 | 15 | return ( 16 | 25 | 28 | 29 | } 30 | > 31 | {children} 32 | 33 | ); 34 | }; 35 | 36 | export default DrawerForm; 37 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FTextEllipsis/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { combineClass } from '../utils/common'; 3 | import TextEllipsis from '../components/TextEllipsis'; 4 | 5 | /** 6 | * 7 | * 文本组件 8 | */ 9 | const FTextEllipsis = (props: any) => { 10 | const { 11 | className, 12 | style, 13 | data, 14 | addons, 15 | 16 | contentStyle, 17 | height = 24, 18 | leftSlot = [], 19 | rightSlot = [], 20 | 21 | } = props; 22 | 23 | const parentData = addons.getParentData(); 24 | 25 | return ( 26 |
27 | 38 |
39 | ); 40 | }; 41 | 42 | export default FTextEllipsis; 43 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FTimeline/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Timeline } from 'antd'; 3 | import { combineClass } from '../utils/common'; 4 | import FTitle from '../FTitle'; 5 | 6 | const FTimeline = (props: any) => { 7 | const { data = [], title, className, style, lineItem = {}, addons, ...otherProps } = props; 8 | const { 9 | timeKey = 'time', 10 | contenKey = 'content', 11 | colorKey = 'color', 12 | ...otherLineItem 13 | } = lineItem; 14 | 15 | return ( 16 | <> 17 | 18 | 19 | {(data || []).map((item: any = {}, index: number) => ( 20 | 21 | {item[timeKey]} 22 | {item[contenKey]} 23 | 24 | ))} 25 | 26 | 27 | ); 28 | }; 29 | 30 | export default FTimeline; 31 | -------------------------------------------------------------------------------- /.turbo/daemon/ae401ef4dd981f33-turbo.log.2024-08-26: -------------------------------------------------------------------------------- 1 | 2024-08-26T15:23:25.560565Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf("packages/form-render/package.json")} 2 | 2024-08-26T15:23:25.560588Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Other("form-render"), path: AnchoredSystemPathBuf("packages/form-render") }})) 3 | 2024-08-26T15:24:27.958664Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf("packages/form-render/CHANGELOG.md")} 4 | 2024-08-26T15:24:27.958679Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Other("form-render"), path: AnchoredSystemPathBuf("packages/form-render") }})) 5 | 2024-08-26T15:26:43.157922Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf("packages/form-render/CHANGELOG.md")} 6 | 2024-08-26T15:26:43.157934Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Other("form-render"), path: AnchoredSystemPathBuf("packages/form-render") }})) 7 | -------------------------------------------------------------------------------- /docs/table-render/static/request.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | const requestData = (params: any) => { 4 | return request 5 | .get( 6 | 'https://www.fastmock.site/mock/62ab96ff94bc013592db1f67667e9c76/getTableList/api/basic', 7 | { params } 8 | ) 9 | .then(res => ({ success: true, data: res.data })) 10 | .catch(() => ({ success: false, data: {} })) 11 | } 12 | 13 | 14 | export const searchApi = async (params) => { 15 | const { success, data } = await requestData(params); 16 | if (success) { 17 | return { 18 | data: data, 19 | total: data.length, 20 | } 21 | } else { 22 | // 必须返回 data 和 total 23 | return { 24 | data: [], 25 | total: 0, 26 | } 27 | } 28 | }; 29 | 30 | export const searchApi2 = async (params) => { 31 | const { success, data } = await requestData(params); 32 | if (success) { 33 | return { 34 | data: data.slice(1), 35 | total: data.length - 1, 36 | } 37 | } else { 38 | // 必须返回 data 和 total 39 | return { 40 | data: [], 41 | total: 0, 42 | } 43 | } 44 | }; -------------------------------------------------------------------------------- /widgets/AsyncOptions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@form-render/async-options", 3 | "version": "1.0.0", 4 | "keywords": [ 5 | "FormRender", 6 | "Render", 7 | "React", 8 | "Json Schema", 9 | "Ant Design" 10 | ], 11 | "main": "dist/index.js", 12 | "module": "dist/index.esm.js", 13 | "scripts": { 14 | "beta": "npm publish --tag beta", 15 | "build": "father-build", 16 | "prepare": "npm run build", 17 | "prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"", 18 | "postpublish": "git push --tags", 19 | "release": "npm publish --access public", 20 | "test": "umi-test", 21 | "test:coverage": "umi-test --coverage" 22 | }, 23 | "lint-staged": { 24 | "*.{js,jsx,less,md,json}": [ 25 | "prettier --write" 26 | ], 27 | "*.ts?(x)": [ 28 | "prettier --parser=typescript --write" 29 | ] 30 | }, 31 | "dependencies": { 32 | "axios": "^0.21.1" 33 | }, 34 | "peerDependencies": { 35 | "antd": "^4.x", 36 | "react": ">=16.8.0" 37 | }, 38 | "gitHooks": { 39 | "pre-commit": "lint-staged" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /widgets/RichText/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@form-render/rich-text", 3 | "version": "1.0.2", 4 | "keywords": [ 5 | "FormRender", 6 | "Render", 7 | "React", 8 | "Json Schema", 9 | "Ant Design" 10 | ], 11 | "main": "dist/index.js", 12 | "module": "dist/index.esm.js", 13 | "scripts": { 14 | "beta": "npm publish --tag beta", 15 | "build": "father-build", 16 | "prepare": "npm run build", 17 | "prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"", 18 | "postpublish": "git push --tags", 19 | "release": "npm publish --access public", 20 | "test": "umi-test", 21 | "test:coverage": "umi-test --coverage" 22 | }, 23 | "lint-staged": { 24 | "*.{js,jsx,less,md,json}": [ 25 | "prettier --write" 26 | ], 27 | "*.ts?(x)": [ 28 | "prettier --parser=typescript --write" 29 | ] 30 | }, 31 | "dependencies": { 32 | "braft-editor": "^2.3.9" 33 | }, 34 | "peerDependencies": { 35 | "antd": "^4.x", 36 | "react": ">=16.8.0" 37 | }, 38 | "gitHooks": { 39 | "pre-commit": "lint-staged" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/table-render/tabs.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 6 3 | mobile: false 4 | title: 'Tab 数据分类' 5 | group: 6 | title: 最佳展示 7 | order: 2 8 | --- 9 | 10 | # 数据分类 11 | ```jsx 12 | /** 13 | * transform: true 14 | * defaultShowCode: true 15 | * background: 'rgb(245,245,245)' 16 | */ 17 | import React, { useRef } from 'react'; 18 | import TableRender, { TableContext } from 'table-render'; 19 | 20 | import { schema } from './static/search'; 21 | import { columns, toolbarRender } from './static/table'; 22 | import { searchApi, searchApi2 } from './static/request'; 23 | 24 | const Demo = () => { 25 | const tableRef = useRef(null); 26 | 27 | return ( 28 | { 34 | console.log('onTabChange'); 35 | }} 36 | request={[ 37 | { name: '我的', api: searchApi }, 38 | { name: '全部', api: searchApi2 } 39 | ]} 40 | columns={columns} 41 | toolbarRender={toolbarRender} 42 | /> 43 | ) 44 | }; 45 | 46 | export default Demo; 47 | ``` 48 | 49 | 50 | -------------------------------------------------------------------------------- /docs/xflow/custom-node-view.md: -------------------------------------------------------------------------------- 1 | --- 2 | order: 1 3 | title: '自定义节点展示' 4 | mobile: false 5 | group: 6 | title: 高级用法 7 | order: 2 8 | --- 9 | 10 | # 自定义节点展示 11 | 12 | 当默认的节点内容展示不满足要求时,可以通过 `nodeWidget` 进行自定义渲染。 13 | 14 | 1. 定义自定义组件 15 | 2. 在 XFlow 组件中通过 `widgets` 属性注册组件 16 | 3. 在节点配置中通过 `nodeWidget` 指定使用的组件 17 | 18 | ```js 19 | // 1.自定义节点 20 | const LLMNodeWidget = ({ data }) => { 21 | const { model, temperature, maxTokens, systemPrompt } = data; // data为配置面板数据 22 | return ( 23 | 27 | // 自定义渲染节点内容 28 | 29 | ); 30 | }; 31 | ``` 32 | 注册自定义组件 33 | ```js 34 | 41 | 42 | ``` 43 | 在settings中使用自定义组件 44 | ```js 45 | { 46 | type: 'LLM', 47 | title: 'LLM 处理', 48 | icon: { 49 | type: 'icon-model', 50 | bgColor: '#6172F3', 51 | }, 52 | nodeWidget: 'LLMNodeWidget' // 3.使用自定义组件 53 | } 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /packages/x-flow/src/operator/Control/index.less: -------------------------------------------------------------------------------- 1 | .fai-reactflow-control { 2 | display: flex; 3 | align-items: center; 4 | padding: 2px 1px; 5 | border-radius: 8px; 6 | border: 0.5px solid #f3f4f6; 7 | background-color: #fff; 8 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); 9 | color: #667085; 10 | 11 | .ant-btn { 12 | display: inline-flex; 13 | align-items: center; 14 | justify-content: center; 15 | } 16 | } 17 | 18 | // .control-item { 19 | // display: flex; 20 | // align-items: center; 21 | // justify-content: center; 22 | // width: 2rem; 23 | // height: 2rem; 24 | // border-radius: 0.5rem; 25 | // cursor: pointer; 26 | 27 | // &.inactive:hover { 28 | // background-color: rgba(0, 0, 0, 0.05); 29 | // color: #374151; 30 | // } 31 | 32 | // &.active { 33 | // background-color: #ecfdf5; 34 | // color: #10b981; 35 | // } 36 | 37 | // &.disabled { 38 | // cursor: not-allowed; 39 | // opacity: 0.5; 40 | // } 41 | // } 42 | 43 | .separator { 44 | margin: 0 4px; 45 | width: 1px; 46 | height:18px; 47 | background-color: #e5e7eb; 48 | } 49 | -------------------------------------------------------------------------------- /docs/table-render/demo/display/custom-table.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * defaultShowCode: true 3 | */ 4 | import React, { useRef } from 'react'; 5 | import TableRender, { TableContext } from 'table-render'; 6 | import { Alert } from 'antd'; 7 | 8 | import { schema } from '../../static/search'; 9 | import { columns, toolbarRender } from '../../static/table'; 10 | import { searchApi } from '../../static/request'; 11 | 12 | const Demo = () => { 13 | const tableRef = useRef(null); 14 | 15 | return ( 16 | ( 25 |
26 | 32 | {table} 33 |
34 | )} 35 | /> 36 | ) 37 | }; 38 | 39 | export default Demo; 40 | -------------------------------------------------------------------------------- /packages/table-render/src/core/TableView/widgets.tsx: -------------------------------------------------------------------------------- 1 | import { Tag, Tooltip } from 'antd'; 2 | import React from 'react'; 3 | import { getDate, getDateTime } from '../../utils'; 4 | 5 | const PrompText = ({ text = '', prompText = '' }) => ( 6 | 7 | {text} 8 | 9 | ); 10 | 11 | export default { 12 | tags: tags => ( 13 |
14 | {tags.map(tag => { 15 | return ( 16 | 17 | {tag.toUpperCase()} 18 | 19 | ); 20 | })} 21 |
22 | ), 23 | dateTime: value => getDateTime(value), 24 | date: value => getDate(value), 25 | tooltip: text => , 26 | status: value => { 27 | switch (value.status) { 28 | case 'Default': 29 | return {value.text}; 30 | case 'Error': 31 | return {value.text}; 32 | case 'Success': 33 | return {value.text}; 34 | default: 35 | return {value.text}; 36 | } 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /packages/chart-render/src/widgets/Pie/index.tsx: -------------------------------------------------------------------------------- 1 | import { Pie as AntPie } from '@ant-design/plots'; 2 | import { PieConfig } from '@ant-design/plots/es/components/pie'; 3 | import React, { FC, memo } from 'react'; 4 | import ChartContainer from '../../components/ChartContainer'; 5 | import { splitMeta } from '../../utils'; 6 | import { useChart } from '../../utils/store'; 7 | 8 | export interface IPieProps extends Omit, 'data'> {} 9 | 10 | const Pie: FC = ({ className, style, ...props }) => { 11 | const loading = useChart(state => state.loading); 12 | const { meta, data } = useChart(state => state.dataSource) || {}; 13 | 14 | const { metaDim, metaInd } = splitMeta(meta); 15 | const colorField = metaDim[0]?.id; 16 | const angleField = metaInd[0]?.id; 17 | 18 | return ( 19 | 20 | 27 | 28 | ); 29 | }; 30 | 31 | export default memo(Pie); 32 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FSuckNav/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { combineClass } from '../utils/common'; 3 | import Tabs from '../components/SuckTabs'; 4 | 5 | /** 6 | * 7 | * 自定义 Tabs组件 8 | */ 9 | const FSuckNav = (props: any) => { 10 | const { 11 | scrollContainer, 12 | items = [], 13 | tabsId = 'tab', 14 | startY = 68, 15 | className, 16 | style, 17 | fixed = true, 18 | addons, 19 | ...otherProps 20 | } = props; 21 | 22 | const childSchema: any[] = []; 23 | const tabs = items.map((item: any) => { 24 | const { children, ...otherItem } = item; 25 | childSchema.push(children); 26 | return otherItem; 27 | }); 28 | 29 | return ( 30 | 39 | {childSchema.map((item: any, index: number) => 40 | addons.renderer({ key: index, schema: item, addons, ...otherProps }), 41 | )} 42 | 43 | ); 44 | }; 45 | 46 | export default FSuckNav; 47 | -------------------------------------------------------------------------------- /.dumi/tmp-production/core/pluginConfigJoi.d.ts: -------------------------------------------------------------------------------- 1 | // This file is generated by Umi automatically 2 | // DO NOT CHANGE IT MANUALLY! 3 | // Created by Umi Plugin 4 | 5 | export interface IConfigFromPluginsJoi { 6 | verifyCommit?: { 7 | scope?: string[] 8 | allowEmoji?: boolean 9 | } 10 | run?: { 11 | globals?: string[] 12 | } 13 | logo?: string 14 | themeConfig?: { 15 | 16 | } 17 | extraRehypePlugins?: unknown[] 18 | extraRemarkPlugins?: unknown[] 19 | resolve?: { 20 | docDirs?: unknown[] 21 | atomDirs?: { 22 | type?: string 23 | dir?: string 24 | }[] 25 | entityDirs?: unknown 26 | codeBlockMode?: ("active" | "passive") 27 | entryFile?: string 28 | forceKebabCaseRouting?: boolean 29 | } 30 | autoAlias?: boolean 31 | analytics?: ({ 32 | baidu?: string 33 | ga?: string 34 | ga_v2?: string 35 | } | boolean) 36 | locales?: ({ 37 | id?: string 38 | name?: string 39 | base?: string 40 | }[] | { 41 | id?: string 42 | name?: string 43 | suffix?: "" 44 | }[]) 45 | apiParser?: { 46 | unpkgHost?: string 47 | resolveFilter?: (() => any) 48 | parseOptions?: { 49 | 50 | } 51 | } 52 | assets?: { 53 | 54 | } 55 | sitemap?: { 56 | hostname?: string 57 | exclude?: string[] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FSteps/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Steps } from 'antd'; 3 | import { get } from 'lodash-es'; 4 | import { combineClass } from '../utils/common'; 5 | 6 | import './index.less'; 7 | 8 | const { Step } = Steps; 9 | 10 | const FSteps = (props: any) => { 11 | const { 12 | data = [], 13 | stautsKey = 'status', 14 | titleKey = 'title', 15 | descriptionKey = 'description', 16 | subTitleKey = 'subTitle', 17 | size = 'small', 18 | className, 19 | style, 20 | addons, 21 | ...otherProps 22 | } = props; 23 | 24 | return ( 25 | 31 | {data.map((item: any, index: number) => ( 32 | 39 | ))} 40 | 41 | ); 42 | }; 43 | 44 | export default FSteps; 45 | -------------------------------------------------------------------------------- /packages/data-render/src/widgets/FIconLabel/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import IconLabel from '../components/IconLabel'; 3 | 4 | const FIconLabel = (props: any) => { 5 | const { 6 | data, 7 | leftText, 8 | rightText, 9 | icon, 10 | method, 11 | href, 12 | target = '_blank', 13 | addons, 14 | ...otherProps 15 | } = props; 16 | 17 | const parentData = addons.getParentData(); 18 | const dataKey = addons.dataKey; 19 | 20 | const handleClick = async (ev: any) => { 21 | if (href) { 22 | if (target === '_self') { 23 | window.location.href = href; 24 | } else { 25 | window.open(href); 26 | } 27 | return; 28 | } 29 | // 传人外置方法,实现按钮点击事件 30 | const func = addons.getMethod(method?.name || method); 31 | func({ dataKey, method, data: parentData }, ev); 32 | }; 33 | 34 | return ( 35 | 42 | ); 43 | }; 44 | 45 | export default FIconLabel; 46 | -------------------------------------------------------------------------------- /packages/form-render/src/models/formDataSkeleton.ts: -------------------------------------------------------------------------------- 1 | import { _cloneDeep, isObjType, isListType } from '../utils/index'; 2 | 3 | export const createDataSkeleton = (schema: any, formData?: any) => { 4 | let _formData = _cloneDeep(formData); 5 | let result = _formData; 6 | 7 | if (isObjType(schema)) { 8 | if (_formData === undefined || typeof _formData !== 'object') { 9 | _formData = {}; 10 | result = {}; 11 | } 12 | Object.keys(schema.properties).forEach(key => { 13 | const childSchema = schema.properties[key]; 14 | const childData = _formData[key]; 15 | const childResult = createDataSkeleton(childSchema, childData); 16 | result[key] = childResult; 17 | }); 18 | } else if (_formData !== undefined) { 19 | // result = _formData; 20 | } else if (schema.default !== undefined) { 21 | result = _cloneDeep(schema.default); 22 | } else if (isListType(schema)) { 23 | result = [createDataSkeleton(schema.items)]; 24 | } else if (schema.type === 'boolean' && !schema.widget) { 25 | // result = false; 26 | result = undefined; 27 | } else { 28 | result = undefined; 29 | } 30 | return result; 31 | }; -------------------------------------------------------------------------------- /packages/x-flow/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present XRender Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/data-render/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present XRender Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/form-render/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present XRender Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/table-render/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present XRender Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tools/schema-builder/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present XRender Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/form-render-mobile/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present XRender Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------