├── src ├── formDesigner │ ├── service │ │ ├── index.ts │ │ └── schema.ts │ ├── playground │ │ ├── components │ │ │ ├── form-button-group │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── form │ │ │ │ └── style.ts │ │ │ ├── form-grid │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── array-items │ │ │ │ └── style.ts │ │ │ ├── form-layout │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── input │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── radio │ │ │ │ └── style.ts │ │ │ ├── space │ │ │ │ └── style.ts │ │ │ ├── form-step │ │ │ │ └── style.ts │ │ │ ├── password │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── reset │ │ │ │ └── style.ts │ │ │ ├── select │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── submit │ │ │ │ └── style.ts │ │ │ ├── switch │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── upload │ │ │ │ └── style.ts │ │ │ ├── cascader │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── checkbox │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── form-item │ │ │ │ ├── var.less │ │ │ │ └── style.ts │ │ │ ├── transfer │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── __builtins__ │ │ │ │ ├── configs │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── shared │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── loading.ts │ │ │ │ │ ├── resolve-component.ts │ │ │ │ │ ├── portal.ts │ │ │ │ │ ├── utils.ts │ │ │ │ │ └── create-context.ts │ │ │ │ ├── styles │ │ │ │ │ └── common.less │ │ │ │ └── moment.ts │ │ │ ├── date-picker │ │ │ │ └── style.ts │ │ │ ├── input-number │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── time-picker │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── tree-select │ │ │ │ ├── style.ts │ │ │ │ └── index.ts │ │ │ ├── color-picker │ │ │ │ ├── index.ts │ │ │ │ ├── style │ │ │ │ │ └── style.less │ │ │ │ ├── lib │ │ │ │ │ ├── validators.ts │ │ │ │ │ └── draggable.ts │ │ │ │ ├── type │ │ │ │ │ └── types.ts │ │ │ │ └── useOptions.ts │ │ │ ├── array-base │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── preview-text │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── array-tabs │ │ │ │ └── style.ts │ │ │ ├── form-tab │ │ │ │ └── style.ts │ │ │ ├── form-dialog │ │ │ │ └── style.ts │ │ │ ├── form-collapse │ │ │ │ └── style.ts │ │ │ ├── form-drawer │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── editable │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── array-cards │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── array-collapse │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── array-table │ │ │ │ ├── style.ts │ │ │ │ └── style.less │ │ │ ├── style.ts │ │ │ ├── __tests__ │ │ │ │ └── reset.spec.ts │ │ │ └── index.ts │ │ ├── settings-form │ │ │ ├── components │ │ │ │ ├── ValueInput │ │ │ │ │ └── styles.less │ │ │ │ ├── DisplayStyleSetter │ │ │ │ │ └── styles.less │ │ │ │ ├── ImageInput │ │ │ │ │ └── styles.less │ │ │ │ ├── index.ts │ │ │ │ ├── SizeInput │ │ │ │ │ └── styles.less │ │ │ │ ├── ColorInput │ │ │ │ │ ├── styles.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── CornerInput │ │ │ │ │ ├── styles.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── PositionInput │ │ │ │ │ └── styles.less │ │ │ │ ├── FlexStyleSetter │ │ │ │ │ └── styles.less │ │ │ │ ├── PolyInput │ │ │ │ │ └── styles.less │ │ │ │ ├── BorderRadiusStyleSetter │ │ │ │ │ └── index.tsx │ │ │ │ ├── CollapseItem │ │ │ │ │ └── styles.less │ │ │ │ ├── DrawerSetter │ │ │ │ │ └── styles.less │ │ │ │ └── FoldItem │ │ │ │ │ └── styles.less │ │ │ ├── effects │ │ │ │ ├── index.ts │ │ │ │ └── useSnapshot.tsx │ │ │ ├── index.ts │ │ │ ├── locales │ │ │ │ ├── index.ts │ │ │ │ ├── zh-CN.ts │ │ │ │ └── en-US.ts │ │ │ ├── shared │ │ │ │ ├── context.ts │ │ │ │ └── loadScript.ts │ │ │ ├── types.ts │ │ │ └── SchemaField.tsx │ │ ├── setters │ │ │ ├── components │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── locales │ │ │ │ └── index.ts │ │ ├── renderer │ │ │ ├── components │ │ │ │ ├── Card │ │ │ │ │ └── index.ts │ │ │ │ ├── Form │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.less │ │ │ │ ├── Input │ │ │ │ │ └── index.ts │ │ │ │ ├── Object │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Radio │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Rate │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Select │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Slider │ │ │ │ │ └── index.ts │ │ │ │ ├── Space │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Switch │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Text │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.less │ │ │ │ ├── Upload │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── ArrayCards │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.less │ │ │ │ ├── ArrayTable │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.less │ │ │ │ ├── Cascader │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Checkbox │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── DatePicker │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── FormGrid │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.less │ │ │ │ ├── FormLayout │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.ts │ │ │ │ ├── FormTab │ │ │ │ │ └── index.ts │ │ │ │ ├── Password │ │ │ │ │ └── index.ts │ │ │ │ ├── TimePicker │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── Transfer │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── TreeSelect │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.tsx │ │ │ │ ├── FormCollapse │ │ │ │ │ └── index.ts │ │ │ │ ├── NumberPicker │ │ │ │ │ ├── index.ts │ │ │ │ │ └── preview.ts │ │ │ │ ├── Field │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ └── useDropTemplate.ts │ │ │ ├── locales │ │ │ │ ├── index.ts │ │ │ │ ├── Void.ts │ │ │ │ ├── Object.ts │ │ │ │ ├── Password.ts │ │ │ │ ├── ArrayCards.ts │ │ │ │ ├── Card.ts │ │ │ │ ├── Checkbox.ts │ │ │ │ ├── Rate.ts │ │ │ │ ├── Radio.ts │ │ │ │ ├── TextArea.ts │ │ │ │ ├── Text.ts │ │ │ │ ├── TimePicker.ts │ │ │ │ ├── Switch.ts │ │ │ │ ├── Space.ts │ │ │ │ ├── FormCollapse.ts │ │ │ │ ├── Component.ts │ │ │ │ ├── all.ts │ │ │ │ ├── Transfer.ts │ │ │ │ ├── Input.ts │ │ │ │ ├── Cascader.ts │ │ │ │ ├── Slider.ts │ │ │ │ ├── ArrayBase.ts │ │ │ │ └── FormGrid.ts │ │ │ ├── schemas │ │ │ │ ├── index.ts │ │ │ │ ├── ArrayCards.ts │ │ │ │ ├── Form.ts │ │ │ │ ├── Password.ts │ │ │ │ ├── Text.ts │ │ │ │ ├── Card.ts │ │ │ │ ├── FormCollapse.ts │ │ │ │ ├── all.ts │ │ │ │ ├── Radio.ts │ │ │ │ ├── Rate.ts │ │ │ │ ├── Checkbox.ts │ │ │ │ ├── Space.ts │ │ │ │ └── CSSStyle.ts │ │ │ ├── index.ts │ │ │ ├── common │ │ │ │ ├── Container │ │ │ │ │ ├── styles.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── FormItemSwitcher │ │ │ │ │ └── index.tsx │ │ │ │ └── LoadTemplate │ │ │ │ │ └── index.tsx │ │ │ └── styles.less │ │ └── prototypes │ │ │ ├── simulators │ │ │ ├── index.tsx │ │ │ ├── PCSimulator │ │ │ │ ├── styles.less │ │ │ │ └── index.tsx │ │ │ ├── MobileSimulator │ │ │ │ ├── styles.less │ │ │ │ └── index.tsx │ │ │ └── ResponsiveSimulator │ │ │ │ ├── handle.tsx │ │ │ │ └── styles.less │ │ │ ├── variables.less │ │ │ ├── widgets │ │ │ ├── ComponentTreeWidget │ │ │ │ └── styles.less │ │ │ ├── OutlineWidget │ │ │ │ └── context.ts │ │ │ ├── DroppableWidget │ │ │ │ └── styles.less │ │ │ ├── NodePathWidget │ │ │ │ └── styles.less │ │ │ ├── IconWidget │ │ │ │ └── styles.less │ │ │ ├── GhostWidget │ │ │ │ └── styles.less │ │ │ ├── index.ts │ │ │ ├── HistoryWidget │ │ │ │ └── styles.less │ │ │ ├── EmptyWidget │ │ │ │ └── styles.less │ │ │ ├── NodeTitleWidget │ │ │ │ └── index.tsx │ │ │ ├── DesignerToolsWidget │ │ │ │ └── styles.less │ │ │ ├── AuxToolWidget │ │ │ │ ├── Delete.tsx │ │ │ │ ├── Copy.tsx │ │ │ │ ├── DragHandler.tsx │ │ │ │ └── DragFocus.tsx │ │ │ └── NodeActionsWidget │ │ │ │ └── styles.less │ │ │ ├── hooks │ │ │ ├── useComponents.ts │ │ │ ├── useTreeNode.ts │ │ │ ├── useRegistry.ts │ │ │ ├── useCursor.ts │ │ │ ├── useSelection.ts │ │ │ ├── useWorkbench.ts │ │ │ ├── useScreen.ts │ │ │ ├── useHover.ts │ │ │ ├── useHistory.ts │ │ │ ├── useOutline.ts │ │ │ ├── useTree.ts │ │ │ ├── useViewport.ts │ │ │ ├── useOperation.ts │ │ │ ├── useViewportDragon.ts │ │ │ ├── useOutlineDragon.ts │ │ │ ├── usePrefix.ts │ │ │ ├── useTheme.ts │ │ │ ├── useStyle.ts │ │ │ ├── useCurrentNodeSelected.ts │ │ │ ├── useCurrentNode.ts │ │ │ ├── useNodeIdProps.ts │ │ │ ├── useDesigner.ts │ │ │ ├── useSelected.ts │ │ │ ├── index.ts │ │ │ ├── useWorkspace.ts │ │ │ └── observer.ts │ │ │ ├── containers │ │ │ ├── index.ts │ │ │ ├── styles.less │ │ │ ├── Workbench.tsx │ │ │ ├── Layout.tsx │ │ │ ├── Simulator.tsx │ │ │ └── Workspace.tsx │ │ │ ├── icons │ │ │ ├── add.tsx │ │ │ ├── logo.tsx │ │ │ ├── return.tsx │ │ │ ├── close.tsx │ │ │ ├── expand.tsx │ │ │ ├── outline.tsx │ │ │ ├── redo.tsx │ │ │ ├── undo.tsx │ │ │ ├── menu.tsx │ │ │ ├── move.tsx │ │ │ ├── help.tsx │ │ │ ├── container.tsx │ │ │ ├── pc.tsx │ │ │ ├── remove.tsx │ │ │ ├── mobile.tsx │ │ │ ├── shift.tsx │ │ │ ├── upload.tsx │ │ │ ├── focus.tsx │ │ │ ├── code.tsx │ │ │ ├── boolean.tsx │ │ │ ├── play.tsx │ │ │ ├── dragmove.tsx │ │ │ ├── delete.tsx │ │ │ ├── eyes.tsx │ │ │ ├── component.tsx │ │ │ ├── page.tsx │ │ │ └── recover.tsx │ │ │ ├── panels │ │ │ ├── index.ts │ │ │ ├── ViewportPanel.tsx │ │ │ ├── ToolbarPanel.tsx │ │ │ └── WorkspacePanel.tsx │ │ │ ├── locales │ │ │ ├── index.ts │ │ │ ├── global.ts │ │ │ ├── panels.ts │ │ │ └── operations.ts │ │ │ ├── index.ts │ │ │ ├── shared │ │ │ ├── useEffect.ts │ │ │ └── index.ts │ │ │ ├── context.ts │ │ │ └── types.ts │ └── widgets │ │ ├── index.ts │ │ ├── logo-widget.vue │ │ └── schema-editor-widget.tsx ├── assets │ └── logo.png ├── main.ts ├── env.d.ts ├── App.vue └── components │ └── HelloWorld.vue ├── public └── favicon.ico ├── tsconfig.node.json ├── .gitignore ├── index.html ├── vite.config.ts ├── tsconfig.json ├── package.json └── LICENSE /src/formDesigner/service/index.ts: -------------------------------------------------------------------------------- 1 | export * from './schema' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-button-group/style.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form/style.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/ValueInput/styles.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-grid/style.ts: -------------------------------------------------------------------------------- 1 | import './style.less' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-items/style.ts: -------------------------------------------------------------------------------- 1 | import './style.less' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-layout/style.ts: -------------------------------------------------------------------------------- 1 | import './style.less' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/setters/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ValidatorSetter' -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Card/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Form/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Input/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Object/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Radio/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Rate/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Select/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Slider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Space/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Switch/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Text/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Upload/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useDropTemplate' 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelvin0926/formily-antdv3/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/ArrayCards/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/ArrayTable/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Cascader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/DatePicker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/FormGrid/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/FormLayout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/FormTab/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Password/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/TimePicker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Transfer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/TreeSelect/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/setters/index.ts: -------------------------------------------------------------------------------- 1 | import './locales' 2 | export * from './components' -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelvin0926/formily-antdv3/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/formDesigner/playground/components/input/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/input/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/radio/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/radio/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/space/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/space/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/FormCollapse/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/NumberPicker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-step/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/steps/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/password/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/input/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/reset/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/button/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/select/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/select/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/submit/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/button/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/switch/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/switch/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/upload/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/upload/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/cascader/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/cascader/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/checkbox/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/checkbox/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-item/var.less: -------------------------------------------------------------------------------- 1 | @form-item-cls: ~'@{formily-prefix}-form-item'; 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/transfer/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/transfer/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/configs/index.ts: -------------------------------------------------------------------------------- 1 | export const stylePrefix = 'formily-antdv' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/date-picker/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/date-picker/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/input-number/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/input-number/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/time-picker/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/time-picker/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/tree-select/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/tree-select/style/index' 2 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Field/index.ts: -------------------------------------------------------------------------------- 1 | export * from './preview' 2 | export * from './shared' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-item/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/form/style' 2 | import './style.less' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/index.ts: -------------------------------------------------------------------------------- 1 | import * as AllLocales from './all' 2 | 3 | export { AllLocales } 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/index.ts: -------------------------------------------------------------------------------- 1 | import * as AllSchemas from './all' 2 | 3 | export { AllSchemas } 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/effects/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useLocales' 2 | export * from './useSnapshot' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/color-picker/index.ts: -------------------------------------------------------------------------------- 1 | import ColorPicker from './main.vue' 2 | 3 | export { ColorPicker } 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-base/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/button/style/index' 2 | import './style.less' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/color-picker/style/style.less: -------------------------------------------------------------------------------- 1 | @namespace: 'ant'; 2 | @ant-separator: '__'; 3 | @state-prefix: 'is-'; -------------------------------------------------------------------------------- /src/formDesigner/playground/components/preview-text/style.ts: -------------------------------------------------------------------------------- 1 | import './style.less' 2 | import 'ant-design-vue/lib/tag/style/index' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/index.ts: -------------------------------------------------------------------------------- 1 | import './locales' 2 | export * from './components' 3 | export * from './SettingsForm' 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/index.ts: -------------------------------------------------------------------------------- 1 | export * from './configs' 2 | export * from './shared' 3 | export * from './moment' 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-tabs/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/badge/style/index' 2 | import 'ant-design-vue/lib/tabs/style/index' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-tab/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/badge/style/index' 2 | import 'ant-design-vue/lib/tabs/style/index' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-dialog/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/modal/style/index' 2 | import 'ant-design-vue/lib/button/style/index' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-button-group/style.ts: -------------------------------------------------------------------------------- 1 | import './style.less' 2 | 3 | // 依赖 4 | import '../form-item/style' 5 | import '../space/style' 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-collapse/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/collapse/style/index' 2 | import 'ant-design-vue/lib/badge/style/index' 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './PCSimulator' 2 | export * from './MobileSimulator' 3 | export * from './ResponsiveSimulator' 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/FormGrid/styles.less: -------------------------------------------------------------------------------- 1 | .dn-grid-column { 2 | margin: 4px; 3 | min-height: 60px; 4 | border: 1px dashed #aaa; 5 | } 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-grid/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | .@{formily-prefix}-form-grid { 4 | display: grid; 5 | } 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/variables.less: -------------------------------------------------------------------------------- 1 | @prefix-cls: ~'dn'; 2 | @border-color-split: #f0f0f0; 3 | @text-color-secondary: #666666; 4 | @primary-color: #999999; 5 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Void.ts: -------------------------------------------------------------------------------- 1 | export const Void = { 2 | 'zh-CN': { 3 | title: '虚拟容器', 4 | }, 5 | 'en-US': { 6 | title: 'Void', 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-drawer/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/button/style/index' 2 | import 'ant-design-vue/lib/drawer/style/index' 3 | import './style.less' 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/ComponentTreeWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-component-tree { 4 | min-height: 90%; 5 | } 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components' 2 | export * from './schemas' 3 | export * from './locales' 4 | 5 | export * from './common/FormItemSwitcher' -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Object.ts: -------------------------------------------------------------------------------- 1 | export const ObjectLocale = { 2 | 'zh-CN': { 3 | title: '对象容器', 4 | }, 5 | 'en-US': { 6 | title: 'Object', 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-layout/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | .@{formily-prefix}-form-inline { 4 | display: flex; 5 | flex-wrap: wrap; 6 | } 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/color-picker/lib/validators.ts: -------------------------------------------------------------------------------- 1 | export const isValidComponentSize = (val: string): boolean => { 2 | return ['', 'large', 'default', 'small'].includes(val) 3 | } 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useComponents.ts: -------------------------------------------------------------------------------- 1 | import { DesignerComponentsSymbol, useContext } from '../context' 2 | export const useComponents = () => useContext(DesignerComponentsSymbol) 3 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useTreeNode.ts: -------------------------------------------------------------------------------- 1 | import { TreeNodeSymbol, useContext } from '../context' 2 | 3 | export const useTreeNode = () => { 4 | return useContext(TreeNodeSymbol) 5 | } 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/common/Container/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-form-container { 4 | margin: 0 !important; 5 | padding: 20px; 6 | border: 1px solid @border-color-split; 7 | } 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/ArrayCards.ts: -------------------------------------------------------------------------------- 1 | import { ArrayTable } from './ArrayTable' 2 | import { Card } from './Card' 3 | 4 | export const ArrayCards = Card 5 | ArrayCards.Addition = ArrayTable.Addition 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/setters/locales/index.ts: -------------------------------------------------------------------------------- 1 | import { GlobalRegistry } from '@designable/core' 2 | import zhCN from './zh-CN' 3 | import enUS from './en-US' 4 | 5 | GlobalRegistry.registerDesignerLocales(zhCN, enUS) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/editable/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/form/style/index' 2 | import 'ant-design-vue/lib/space/style/index' 3 | import 'ant-design-vue/lib/popover/style/index' 4 | import './style.less' 5 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-cards/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/card/style/index' 2 | import 'ant-design-vue/lib/empty/style/index' 3 | import 'ant-design-vue/lib/button/style/index' 4 | import './style.less' 5 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/locales/index.ts: -------------------------------------------------------------------------------- 1 | import { GlobalRegistry } from '@designable/core' 2 | import zhCN from './zh-CN' 3 | import enUS from './en-US' 4 | 5 | GlobalRegistry.registerDesignerLocales(zhCN, enUS) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/ArrayCards/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-array-cards { 4 | background-color: @component-background; 5 | 6 | .formily-antdv-array-base-addition { 7 | flex: 1; 8 | } 9 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/ArrayTable/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-array-table { 4 | background-color: @component-background; 5 | 6 | .formily-antdv-array-base-addition { 7 | flex: 1; 8 | } 9 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Text/styles.less: -------------------------------------------------------------------------------- 1 | .dn-text { 2 | &:empty::before { 3 | content: 'Please Input'; 4 | display: block; 5 | opacity: 0.6; 6 | } 7 | &:focus { 8 | padding: 4px; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/types.ts: -------------------------------------------------------------------------------- 1 | import type { Component, VNode } from 'vue' 2 | 3 | export type SlotTypes = 4 | | Component 5 | | string 6 | | number 7 | | ((props: Record) => VNode[] | VNode) 8 | | VNode 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-cards/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | @array-cards-prefix-cls: ~'@{formily-prefix}-array-cards'; 4 | 5 | .@{array-cards-prefix-cls}-item { 6 | margin-bottom: 10px !important; 7 | } 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useRegistry.ts: -------------------------------------------------------------------------------- 1 | import { GlobalRegistry, IDesignerRegistry } from '@designable/core' 2 | 3 | export const useRegistry = (): IDesignerRegistry => { 4 | return window['__DESIGNER_REGISTRY__'] || GlobalRegistry 5 | } 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/containers/index.ts: -------------------------------------------------------------------------------- 1 | import './styles.less' 2 | export * from './Layout' 3 | export * from './Designer' 4 | export * from './Workspace' 5 | export * from './Simulator' 6 | export * from './Viewport' 7 | export * from './Workbench' 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-collapse/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | @array-collapse-prefix-cls: ~'@{formily-prefix}-array-collapse'; 4 | 5 | .@{array-collapse-prefix-cls}-item { 6 | margin-bottom: 10px !important; 7 | } 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/shared/context.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue-demi' 2 | import { ISettingFormProps } from '../types' 3 | 4 | export const SettingsFormSymbol: InjectionKey> = Symbol( 5 | 'SettingsFormContext' 6 | ) 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 3 | ################################################################################ 4 | 5 | /node_modules 6 | /.vs 7 | /yarn.lock 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/color-picker/type/types.ts: -------------------------------------------------------------------------------- 1 | export interface Options { 2 | enableAlpha: boolean 3 | format: string 4 | value?: string 5 | } 6 | 7 | export type Nullable = T | null 8 | 9 | export type ComponentSize = 'large' | 'default' | 'small' 10 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-collapse/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/collapse/style/index' 2 | import 'ant-design-vue/lib/card/style/index' 3 | import 'ant-design-vue/lib/badge/style/index' 4 | import 'ant-design-vue/lib/empty/style/index' 5 | 6 | import './style.less' 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './transform-component' 2 | export * from './resolve-component' 3 | export * from './create-context' 4 | export * from './utils' 5 | export * from './portal' 6 | export * from './loading' 7 | export * from './types' 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/add.tsx: -------------------------------------------------------------------------------- 1 | export const Add = ( 2 | 3 | 4 | 5 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/logo.tsx: -------------------------------------------------------------------------------- 1 | export const Logo = { 2 | light: 3 | '//img.alicdn.com/imgextra/i3/O1CN01Eib3GC1c7JthHYQnI_!!6000000003553-55-tps-1783-385.svg', 4 | dark: '//img.alicdn.com/imgextra/i1/O1CN018hbWup1QhhyhiElX0_!!6000000002008-55-tps-1783-385.svg', 5 | } 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'zh-CN': { 3 | SettingComponents: { 4 | ValueInput: { 5 | expression: '表达式', 6 | }, 7 | MonacoInput: { 8 | helpDocument: '帮助文档', 9 | }, 10 | }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Password.ts: -------------------------------------------------------------------------------- 1 | import { createLocales } from '@designable/core' 2 | import { Input } from './Input' 3 | 4 | export const Password = createLocales(Input, { 5 | 'zh-CN': { 6 | title: '密码输入', 7 | }, 8 | 'en-US': { 9 | title: 'Password', 10 | }, 11 | }) 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'en-US': { 3 | SettingComponents: { 4 | ValueInput: { 5 | expression: 'Expression', 6 | }, 7 | MonacoInput: { 8 | helpDocument: 'Help Documents', 9 | }, 10 | }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/panels/index.ts: -------------------------------------------------------------------------------- 1 | import './styles.less' 2 | export * from './StudioPanel' 3 | export * from './CompositePanel' 4 | export * from './SettingsPanel' 5 | export * from './WorkspacePanel' 6 | export * from './ToolbarPanel' 7 | export * from './ViewportPanel' 8 | export * from './ViewPanel' 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/styles/common.less: -------------------------------------------------------------------------------- 1 | @formily-prefix: formily-antdv; 2 | // @namespace: 'el'; 3 | @root-entry-name:default; 4 | @import 'ant-design-vue/lib/style/themes/index.less'; 5 | 6 | // height rules as antd 7 | @height-base: 32px; 8 | @height-lg: 40px; 9 | @height-sm: 24px; 10 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/switch/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps } from '@formily/vue' 2 | import { Switch as AntdSwitch } from 'ant-design-vue' 3 | 4 | export const Switch = connect( 5 | AntdSwitch, 6 | mapProps({ readOnly: 'read-only', value: 'checked' }) 7 | ) 8 | 9 | export default Switch 10 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/locales/index.ts: -------------------------------------------------------------------------------- 1 | import { GlobalRegistry } from '@designable/core' 2 | import icons from './icons' 3 | import panels from './panels' 4 | import global from './global' 5 | import operations from './operations' 6 | 7 | GlobalRegistry.registerDesignerLocales(icons, panels, global, operations) 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/PCSimulator/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-pc-simulator { 4 | background-color: var(--dn-pc-simulator-bg-color); 5 | position: absolute; 6 | top: 0; 7 | left: 0; 8 | right: 0; 9 | bottom: 0; 10 | box-sizing: border-box; 11 | } 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/index.ts: -------------------------------------------------------------------------------- 1 | import './locales' 2 | import './theme.less' 3 | export * from './panels' 4 | export * from './widgets' 5 | export * from './context' 6 | export * from './hooks' 7 | export * from './containers' 8 | export * from './simulators' 9 | export * from './types' 10 | export * from './shared' 11 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import Antdv from 'ant-design-vue' 4 | import 'ant-design-vue/dist/antd.css'; 5 | import WidgetsInstaller from './formDesigner/widgets' 6 | 7 | const app = createApp(App) 8 | .use(Antdv) 9 | .use(WidgetsInstaller) 10 | 11 | app.mount('#app'); 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useCursor.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useDesigner } from './useDesigner' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useCursor = () => { 6 | const designer = useDesigner() 7 | return reactiveComputed(() => designer.value?.cursor) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useSelection.ts: -------------------------------------------------------------------------------- 1 | import { useOperation } from './useOperation' 2 | import { computed as reactiveComputed } from '../shared' 3 | 4 | export const useSelection = (workspaceId?: string) => { 5 | const operation = useOperation(workspaceId) 6 | return reactiveComputed(() => operation.value?.selection) 7 | } 8 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any> 7 | export default component 8 | } 9 | 10 | declare module 'lodash' -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useWorkbench.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useDesigner } from './useDesigner' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useWorkbench = () => { 6 | const designer = useDesigner() 7 | return reactiveComputed(() => designer.value.workbench) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Form.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | import { FormLayout } from './FormLayout' 3 | import { CSSStyle } from './CSSStyle' 4 | 5 | export const Form: ISchema = { 6 | type: 'object', 7 | properties: { 8 | ...(FormLayout.properties as any), 9 | style: CSSStyle, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useScreen.ts: -------------------------------------------------------------------------------- 1 | import { useDesigner } from './useDesigner' 2 | import { computed as reactiveComputed } from '../shared' 3 | import { Engine } from '@designable/core' 4 | 5 | export const useScreen = () => { 6 | const designer = useDesigner() 7 | return reactiveComputed(() => designer.value?.screen) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/color-picker/useOptions.ts: -------------------------------------------------------------------------------- 1 | import { inject } from 'vue' 2 | 3 | import type { ComputedRef } from 'vue' 4 | 5 | export interface IUseOptions { 6 | currentColor: ComputedRef 7 | } 8 | 9 | export const OPTIONS_KEY = Symbol() 10 | 11 | export const useOptions = () => { 12 | return inject(OPTIONS_KEY) 13 | } 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useHover.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useOperation } from './useOperation' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useHover = (workspaceId?: string) => { 6 | const operation = useOperation(workspaceId) 7 | return reactiveComputed(() => operation.value?.hover) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/locales/global.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'zh-CN': { 3 | save: '保存', 4 | submit: '提交', 5 | cancel: '取消', 6 | reset: '重置', 7 | publish: '发布', 8 | }, 9 | 'en-US': { 10 | save: 'Save', 11 | submit: 'Submit', 12 | cancel: 'Cancel', 13 | reset: 'Reset', 14 | publish: 'Publish', 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/preview-text/style.less: -------------------------------------------------------------------------------- 1 | @root-entry-name:default; 2 | @import 'ant-design-vue/lib/style/themes/index.less'; 3 | 4 | @form-text-prefix-cls: ~'@{ant-prefix}-form-text'; 5 | 6 | .@{form-text-prefix-cls} { 7 | font-size: 14px; 8 | font-weight: 500; 9 | 10 | .@{ant-prefix}-tag:last-child { 11 | margin-right: 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useHistory.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useWorkspace } from './useWorkspace' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useHistory = (workspaceId?: string) => { 6 | const workspace = useWorkspace(workspaceId) 7 | return reactiveComputed(() => workspace.value?.history) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useOutline.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useWorkspace } from './useWorkspace' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useOutline = (workspaceId?: string) => { 6 | const workspace = useWorkspace(workspaceId) 7 | return reactiveComputed(() => workspace.value?.outline) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useTree.ts: -------------------------------------------------------------------------------- 1 | import { computed, markRaw } from 'vue-demi' 2 | import { useOperation } from './useOperation' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useTree = (workspaceId?: string) => { 6 | const operation = useOperation(workspaceId) 7 | return reactiveComputed(() => operation.value?.tree) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useViewport.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useWorkspace } from './useWorkspace' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useViewport = (workspaceId?: string) => { 6 | const workspace = useWorkspace(workspaceId) 7 | return reactiveComputed(() => workspace.value?.viewport) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-table/style.ts: -------------------------------------------------------------------------------- 1 | import 'ant-design-vue/lib/table/style/index' 2 | import 'ant-design-vue/lib/pagination/style/index' 3 | import 'ant-design-vue/lib/button/style/index' 4 | import 'ant-design-vue/lib/space/style/index' 5 | import 'ant-design-vue/lib/select/style/index' 6 | import 'ant-design-vue/lib/badge/style/index' 7 | 8 | import './style.less' 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/input-number/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapReadPretty } from '@formily/vue' 2 | import { InputNumber as AntdInputNumber } from 'ant-design-vue' 3 | import { PreviewText } from '../preview-text' 4 | 5 | export const InputNumber = connect( 6 | AntdInputNumber, 7 | mapReadPretty(PreviewText.Input) 8 | ) 9 | 10 | export default InputNumber 11 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useOperation.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useWorkspace } from './useWorkspace' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useOperation = (workspaceId?: string) => { 6 | const workspace = useWorkspace(workspaceId) 7 | return reactiveComputed(() => workspace.value?.operation) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useViewportDragon.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useOperation } from './useOperation' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useDragon = (workspaceId?: string) => { 6 | const operation = useOperation(workspaceId) 7 | return reactiveComputed(() => operation.value?.viewportDragon) 8 | } 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useOutlineDragon.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useOperation } from './useOperation' 3 | import { computed as reactiveComputed } from '../shared' 4 | 5 | export const useOutlineDragon = (workspaceId?: string) => { 6 | const operation = useOperation(workspaceId) 7 | return reactiveComputed(() => operation.value?.outlineDragon) 8 | } 9 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/OutlineWidget/context.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from '@designable/core' 2 | import { InjectionKey, Ref } from 'vue-demi' 3 | 4 | interface INodeContext { 5 | renderTitle?: (node: TreeNode) => any 6 | renderActions?: (node: TreeNode) => any 7 | } 8 | 9 | export const NodeSymbol: InjectionKey> = 10 | Symbol('INodeContext') 11 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Password.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | import { Input } from './Input' 3 | export const Password: ISchema = { 4 | type: 'object', 5 | properties: { 6 | ...(Input.properties as any), 7 | checkStrength: { 8 | type: 'boolean', 9 | 'x-decorator': 'FormItem', 10 | 'x-component': 'Switch', 11 | }, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/DroppableWidget/styles.less: -------------------------------------------------------------------------------- 1 | .dn-droppable-placeholder { 2 | height: 60px; 3 | background-color: var(--dn-droppable-bg-color); 4 | border: 1px dashed var(--dn-droppable-border-color); 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | color: var(--dn-droppable-color); 9 | font-weight: lighter; 10 | font-size: 13px; 11 | } 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/return.tsx: -------------------------------------------------------------------------------- 1 | export const Return = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/time-picker/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps, mapReadPretty } from '@formily/vue' 2 | import { TimePicker as AntdTimePicker } from 'ant-design-vue' 3 | import { PreviewText } from '../preview-text' 4 | 5 | export const TimePicker = connect( 6 | AntdTimePicker, 7 | mapProps({ readOnly: 'read-only' }), 8 | mapReadPretty(PreviewText.TimePicker) 9 | ) 10 | 11 | export default TimePicker 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/usePrefix.ts: -------------------------------------------------------------------------------- 1 | import { computed, unref } from 'vue-demi' 2 | import { DesignerLayoutSymbol, useContext } from '../context' 3 | 4 | export const usePrefix = (after = '') => { 5 | const DesignerLayoutContext = useContext(DesignerLayoutSymbol) 6 | const usePrefixContext = computed( 7 | () => unref(DesignerLayoutContext)?.prefixCls + after 8 | ) 9 | return usePrefixContext 10 | } 11 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/ArrayCards.ts: -------------------------------------------------------------------------------- 1 | import { createLocales } from '@designable/core' 2 | import { Card } from './Card' 3 | 4 | export const ArrayCards = createLocales(Card, { 5 | 'zh-CN': { 6 | title: '自增卡片', 7 | addIndex: '添加索引', 8 | addOperation: '添加操作', 9 | }, 10 | 'en-US': { 11 | title: 'Array Cards', 12 | addIndex: 'Add Index', 13 | addOperation: 'Add Operations', 14 | }, 15 | }) 16 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Card.ts: -------------------------------------------------------------------------------- 1 | export const Card = { 2 | 'zh-CN': { 3 | title: '卡片', 4 | settings: { 5 | 'x-component-props': { 6 | shadow: { title: '阴影显示时机' }, 7 | title: '标题', 8 | }, 9 | }, 10 | }, 11 | 'en-US': { 12 | title: 'Card', 13 | settings: { 14 | 'x-component-props': { 15 | shadow: { title: '阴影显示时机' }, 16 | }, 17 | }, 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/styles.less: -------------------------------------------------------------------------------- 1 | @formily-antdv-prefix: ~'formily-antdv'; 2 | @antdv-prefix: ~'a'; 3 | 4 | @text-color: rgba(0, 0, 0, 0.85); 5 | @border-color-split: #f0f0f0; 6 | @border-color-base: #d9d9d9; 7 | @component-background: #fff; 8 | 9 | 10 | 11 | /** 添加样式解决一些错位问题 kelvin0926 20221221 */ 12 | .cm-editor { 13 | height: 100%; 14 | } 15 | 16 | .dn-viewport { 17 | padding-right: 5px; 18 | padding-top: 5px; 19 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/close.tsx: -------------------------------------------------------------------------------- 1 | export const Close = ( 2 | 3 | 4 | 5 | ) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useTheme.ts: -------------------------------------------------------------------------------- 1 | import { computed, inject, ref, ComputedRef } from 'vue-demi' 2 | import { DesignerLayoutSymbol } from '../context' 3 | import { IDesignerLayoutContext } from '../types' 4 | 5 | export const useTheme = (): ComputedRef => { 6 | return computed( 7 | () => 8 | window['__DESINGER_THEME__'] || 9 | inject(DesignerLayoutSymbol, ref()).value?.theme 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/locales/panels.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'zh-CN': { 3 | panels: { 4 | Component: '组件', 5 | OutlinedTree: '大纲树', 6 | PropertySettings: '属性配置', 7 | History: '历史记录', 8 | }, 9 | }, 10 | 'en-US': { 11 | panels: { 12 | Component: 'Component', 13 | OutlinedTree: 'Outlined Tree', 14 | PropertySettings: 'Property Settings', 15 | History: 'History', 16 | }, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/NodePathWidget/styles.less: -------------------------------------------------------------------------------- 1 | // @import '~antd/lib/style/themes/default.less'; 2 | @border-color-split: #f0f0f0; 3 | .dn-node-path { 4 | padding: 4px 10px !important; 5 | border-bottom: 1px solid @border-color-split; 6 | .dn-icon { 7 | font-size: 11px; 8 | } 9 | // .@{antdv-prefix}-breadcrumb-separator { 10 | // margin: 0 4px !important; 11 | // } 12 | 13 | a { 14 | font-size: 12px; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/types.ts: -------------------------------------------------------------------------------- 1 | import { Form } from '@formily/core' 2 | import { VueComponent } from '@formily/vue' 3 | import { CSSProperties } from '@vue/runtime-dom' 4 | 5 | export interface ISettingFormProps { 6 | className?: string 7 | style?: CSSProperties 8 | uploadAction?: string 9 | components?: Record> 10 | effects?: (form: Form) => void 11 | scope?: any 12 | headers?: Record 13 | } 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/DisplayStyleSetter/styles.less: -------------------------------------------------------------------------------- 1 | // @import '~antd/lib/style/themes/default.less'; 2 | 3 | .dn-display-style-setter { 4 | &-radio { 5 | display: flex !important; 6 | width: 100%; 7 | 8 | // .@{ant-prefix}-radio-button-wrapper { 9 | // flex-grow: 1; 10 | // display: flex; 11 | // justify-content: center; 12 | // align-items: center; 13 | // padding: 0; 14 | // } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/containers/styles.less: -------------------------------------------------------------------------------- 1 | @import '../variables.less'; 2 | 3 | .@{prefix-cls}-viewport { 4 | height: 100%; 5 | width: 100%; 6 | min-height: 100px; 7 | position: relative; 8 | outline: none; 9 | box-sizing: border-box; 10 | user-select: none; 11 | overflow: overlay; 12 | 13 | // & > * { 14 | // width: fit-content; 15 | // height: fit-content; 16 | // min-width: 100%; 17 | // min-height: 100%; 18 | // } 19 | } 20 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/password/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps, mapReadPretty } from '@formily/vue' 2 | import { Input } from 'ant-design-vue' 3 | import { PreviewText } from '../preview-text' 4 | 5 | const { Password: AntdPassword } = Input 6 | 7 | export const Password = connect( 8 | AntdPassword, 9 | mapProps((props) => { 10 | return { 11 | ...props, 12 | } 13 | }), 14 | mapReadPretty(PreviewText.Input) 15 | ) 16 | 17 | export default Password 18 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Checkbox.ts: -------------------------------------------------------------------------------- 1 | export const CheckboxGroup = { 2 | 'zh-CN': { 3 | title: '复选框组', 4 | settings: { 5 | 'x-component-props': { 6 | optionType: { title: '选项类型', dataSource: ['默认', '按钮'] }, 7 | }, 8 | }, 9 | }, 10 | 'en-US': { 11 | title: 'Checkbox', 12 | settings: { 13 | 'x-component-props': { 14 | optionType: { title: '选项类型', dataSource: ['默认', '按钮'] }, 15 | }, 16 | }, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/ImageInput/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-image-input { 4 | width: 100%; 5 | .@{antdv-prefix}-popover-inner-content { 6 | padding: 0 !important; 7 | user-select: none; 8 | } 9 | 10 | .@{antdv-prefix}-input__prefix { 11 | display: flex; 12 | color: @text-color; 13 | align-items: center; 14 | } 15 | .el-input--prefix { 16 | .@{antdv-prefix}-input__inner { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/IconWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-icon { 4 | display: inline-block; 5 | color: inherit; 6 | font-style: normal; 7 | line-height: 0; 8 | text-align: center; 9 | text-transform: none; 10 | vertical-align: -0.125em; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | svg { 15 | pointer-events: none; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/style.ts: -------------------------------------------------------------------------------- 1 | // auto generated code 2 | import './array-base/style.less' 3 | import './array-cards/style.less' 4 | import './array-collapse/style.less' 5 | import './array-items/style.less' 6 | import './array-table/style.less' 7 | import './editable/style.less' 8 | import './form-button-group/style.less' 9 | import './form-drawer/style.less' 10 | import './form-grid/style.less' 11 | import './form-item/style.less' 12 | import './form-layout/style.less' 13 | import './preview-text/style.less' 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/expand.tsx: -------------------------------------------------------------------------------- 1 | export const Expand = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/outline.tsx: -------------------------------------------------------------------------------- 1 | export const Outline = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/widgets/index.ts: -------------------------------------------------------------------------------- 1 | import ActionsWidget from './actions-widget.vue' 2 | import SchemaEditorWidget from './schema-editor-widget' 3 | import PreviewWidget from './preview-widget' 4 | import LogoWidget from './logo-widget.vue' 5 | import { App } from 'vue' 6 | 7 | export default function install(app: App) { 8 | app.component('ActionsWidget', ActionsWidget) 9 | app.component('SchemaEditorWidget', SchemaEditorWidget) 10 | app.component('PreviewWidget', PreviewWidget) 11 | app.component('LogoWidget', LogoWidget) 12 | } 13 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CollapseItem' 2 | export * from './SizeInput' 3 | export * from './DisplayStyleSetter' 4 | export * from './DrawerSetter' 5 | export * from './BackgroundStyleSetter' 6 | export * from './BoxShadowStyleSetter' 7 | export * from './FontStyleSetter' 8 | export * from './BoxStyleSetter' 9 | export * from './BorderRadiusStyleSetter' 10 | export * from './BorderStyleSetter' 11 | export * from './ValueInput' 12 | export * from './ColorInput' 13 | export * from './FoldItem' 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useStyle.ts: -------------------------------------------------------------------------------- 1 | import { isStr } from '@designable/shared' 2 | import { useAttrs, getCurrentInstance, StyleValue, CSSProperties } from 'vue' 3 | 4 | const css2obj = (css) => { 5 | const r = /(?<=^|;)\s*([^:]+)\s*:\s*([^;]+)\s*/g, 6 | o = {} 7 | css.replace(r, (m, p, v) => (o[p] = v)) 8 | return o 9 | } 10 | export const useStyle = () => { 11 | let { style = {} } = useAttrs() 12 | if (isStr(style)) { 13 | style = css2obj(style) 14 | } 15 | return style as CSSProperties 16 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useCurrentNodeSelected.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useCurrentNode } from './useCurrentNode' 3 | import { useSelected } from './useSelected' 4 | import { computed as reactiveComputed } from '../shared' 5 | 6 | export const useCurrentNodeSelected = () => { 7 | const nodeRef = useCurrentNode() 8 | const selectedRef = useSelected() 9 | return reactiveComputed( 10 | () => 11 | selectedRef.value.length === 1 && 12 | nodeRef.value.id === selectedRef.value?.[0] 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/panels/ViewportPanel.tsx: -------------------------------------------------------------------------------- 1 | import { defineComponent } from 'vue-demi' 2 | import { WorkspacePanel } from './WorkspacePanel' 3 | import { Simulator } from '../containers' 4 | 5 | export const ViewportPanel = defineComponent({ 6 | name: 'DnViewportPanel', 7 | setup(props, { attrs, slots }) { 8 | return () => { 9 | return ( 10 | 11 | {slots.default?.()} 12 | 13 | ) 14 | } 15 | }, 16 | }) 17 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/GhostWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-ghost { 4 | padding-left: 25px; 5 | padding-right: 15px; 6 | height: 30px; 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | position: fixed; 11 | color: var(--dn-ghost-color); 12 | font-size: 12px; 13 | z-index: 9999; 14 | border-radius: 50px; 15 | background-color: var(--dn-ghost-bg-color); 16 | pointer-events: none; 17 | left: 0; 18 | top: 0; 19 | transform: translate3d(0, 0, 0); 20 | } 21 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Text.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const Text: ISchema = { 4 | type: 'object', 5 | properties: { 6 | content: { 7 | type: 'string', 8 | 'x-decorator': 'FormItem', 9 | 'x-component': 'Input.TextArea', 10 | }, 11 | mode: { 12 | default: 'normal', 13 | type: 'string', 14 | 'x-decorator': 'FormItem', 15 | 'x-component': 'Select', 16 | 'x-component-props': {}, 17 | enum: ['h1', 'h2', 'h3', 'p', 'normal'], 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/SizeInput/styles.less: -------------------------------------------------------------------------------- 1 | @border-color-base: #f0f0f0; 2 | 3 | .dn-size-input { 4 | display: flex; 5 | width: 100%; 6 | 7 | // .@{ant-prefix}-input-number { 8 | // flex-grow: 2; 9 | // margin-right: 2px; 10 | // } 11 | 12 | .dn-size-input-unit { 13 | border: 1px solid @border-color-base; 14 | border-radius: 2px; 15 | cursor: pointer; 16 | height: 32px; 17 | padding: 0 8px; 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | flex-grow: 0; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/loading.ts: -------------------------------------------------------------------------------- 1 | import { message } from 'ant-design-vue' 2 | import type { MessageType } from 'ant-design-vue/types/message' 3 | 4 | export const loading = async ( 5 | loadingText = 'Loading...', 6 | processor: () => Promise 7 | ) => { 8 | let loadingInstance: MessageType = null 9 | const loading = setTimeout(() => { 10 | loadingInstance = message.loading(loadingText) 11 | }, 100) 12 | try { 13 | return await processor() 14 | } finally { 15 | loadingInstance?.() 16 | clearTimeout(loading) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Rate.ts: -------------------------------------------------------------------------------- 1 | export const Rate = { 2 | 'zh-CN': { 3 | title: '评分器', 4 | settings: { 5 | 'x-component-props': { 6 | allowHalf: '允许半选', 7 | tooltips: { title: '提示信息', tooltip: '格式:string[]' }, 8 | count: '总数', 9 | }, 10 | }, 11 | }, 12 | 'en-US': { 13 | title: 'Rate', 14 | settings: { 15 | 'x-component-props': { 16 | allowHalf: 'Allow Half', 17 | tooltips: { title: 'Tooltips', tooltip: 'Format:string[]' }, 18 | count: 'Count', 19 | }, 20 | }, 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/redo.tsx: -------------------------------------------------------------------------------- 1 | export const Redo = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AuxToolWidget' 2 | export * from './ComponentTreeWidget' 3 | export * from './DesignerToolsWidget' 4 | export * from './ViewToolsWidget' 5 | export * from './ResourceWidget' 6 | export * from './GhostWidget' 7 | export * from './EmptyWidget' 8 | export * from './OutlineWidget' 9 | export * from './IconWidget' 10 | export * from './TextWidget' 11 | export * from './HistoryWidget' 12 | export * from './NodePathWidget' 13 | export * from './NodeTitleWidget' 14 | export * from './DroppableWidget' 15 | export * from './NodeActionsWidget' 16 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/undo.tsx: -------------------------------------------------------------------------------- 1 | export const Undo = ( 2 | 3 | 4 | 5 | ) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useCurrentNode.ts: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue-demi' 2 | import { useSelected } from './useSelected' 3 | import { useTree } from './useTree' 4 | import { computed as reactiveComputed } from '../shared' 5 | 6 | export const useCurrentNode = (workspaceId?: string) => { 7 | // TODO:: selected changes cause Vue computed to change, however when treenode changes there is no reaction 8 | const selected = useSelected(workspaceId) 9 | 10 | const tree = useTree(workspaceId) 11 | 12 | return reactiveComputed(() => { 13 | return tree.value?.findById?.(selected.value[0]) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/HistoryWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-history { 4 | &-item { 5 | display: flex; 6 | justify-content: space-between; 7 | min-height: 32px; 8 | padding: 0 10px; 9 | align-items: center; 10 | cursor: pointer; 11 | color: var(--dn-outline-tree-node-header-color); 12 | &-timestamp { 13 | font-size: 10px; 14 | } 15 | &:hover { 16 | background-color: var(--dn-panel-active-bg-color); 17 | } 18 | 19 | &.active { 20 | background-color: var(--dn-panel-active-bg-color); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useNodeIdProps.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from '@designable/core' 2 | import { computed } from 'vue-demi' 3 | import { useDesigner } from './useDesigner' 4 | import { useTreeNode } from './useTreeNode' 5 | import { computed as reactiveComputed } from '../shared' 6 | 7 | export const useNodeIdProps = (node?: TreeNode) => { 8 | const targetRef = useTreeNode() 9 | const designerRef = useDesigner() 10 | 11 | return reactiveComputed(() => { 12 | return { 13 | [designerRef.value.props.nodeIdAttrName]: node 14 | ? node.id 15 | : targetRef.value.id, 16 | } 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/menu.tsx: -------------------------------------------------------------------------------- 1 | export const Menu = ( 2 | 3 | 4 | 5 | ) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Card.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const Card: ISchema & { Addition?: ISchema } = { 4 | type: 'object', 5 | properties: { 6 | title: { 7 | type: 'string', 8 | 'x-decorator': 'FormItem', 9 | 'x-component': 'Input', 10 | 'x-component-props': { size: 'small', clearable: true }, 11 | }, 12 | shadow: { 13 | type: 'string', 14 | enum: ['always', 'hover', 'never'], 15 | 'x-decorator': 'FormItem', 16 | 'x-component': 'Select', 17 | 'x-component-props': { 18 | 19 | }, 20 | }, 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Radio.ts: -------------------------------------------------------------------------------- 1 | export const RadioGroup = { 2 | 'zh-CN': { 3 | title: '单选框组', 4 | settings: { 5 | 'x-component-props': { 6 | buttonStyle: { title: '按钮风格', dataSource: ['空心', '实心'] }, 7 | optionType: { title: '选项类型', dataSource: ['默认', '按钮'] }, 8 | }, 9 | }, 10 | }, 11 | 'en-US': { 12 | title: 'Radio', 13 | settings: { 14 | 'x-component-props': { 15 | buttonStyle: { title: 'Button style', dataSource: ['Hollow', 'Solid'] }, 16 | optionType: { title: 'Option type', dataSource: ['Default', 'Button'] }, 17 | }, 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/shared/useEffect.ts: -------------------------------------------------------------------------------- 1 | import { onBeforeUnmount, onMounted, watch, WatchSource } from 'vue-demi' 2 | import { watch as reactiveWatch } from './reactive' 3 | 4 | export function useEffect( 5 | func: () => void | (() => void | null), 6 | dependency: WatchSource | WatchSource[] 7 | ) { 8 | const disposes: Array<(() => void) | void> = [] 9 | const disposeAll = () => disposes.forEach((fn) => fn?.()) 10 | 11 | reactiveWatch( 12 | dependency, 13 | () => { 14 | disposeAll() 15 | disposes.push(func?.()) 16 | }, 17 | { immediate: true } 18 | ) 19 | 20 | onBeforeUnmount(disposeAll) 21 | } 22 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/select/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps, mapReadPretty } from '@formily/vue' 2 | import { Select as AntdSelect } from 'ant-design-vue' 3 | import { PreviewText } from '../preview-text' 4 | 5 | export const Select = connect( 6 | AntdSelect, 7 | mapProps( 8 | { 9 | dataSource: 'options', 10 | loading: true, 11 | }, 12 | (props, field) => { 13 | return { 14 | ...props, 15 | loading: 16 | field?.['loading'] || field?.['validating'] ? true : props.loading, 17 | } 18 | } 19 | ), 20 | mapReadPretty(PreviewText.Select) 21 | ) 22 | 23 | export default Select 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/TextArea.ts: -------------------------------------------------------------------------------- 1 | export const TextArea = { 2 | 'zh-CN': { 3 | title: '多行输入', 4 | settings: { 5 | 'x-component-props': { 6 | maxLength: '最大长度', 7 | autoSize: { 8 | title: '自适应高度', 9 | tooltip: '可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }', 10 | }, 11 | showCount: '是否展示字数', 12 | }, 13 | }, 14 | }, 15 | 'en-US': { 16 | title: 'TextArea', 17 | settings: { 18 | 'x-component-props': { 19 | maxLength: 'Max Length', 20 | autoSize: 'Auto Size', 21 | showCount: 'Show Count', 22 | }, 23 | }, 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/containers/Workbench.tsx: -------------------------------------------------------------------------------- 1 | import { observer } from '@formily/reactive-vue' 2 | import { useWorkbench } from '../hooks' 3 | import { Workspace } from './Workspace' 4 | import { defineComponent } from 'vue-demi' 5 | 6 | 7 | const WrokbenchComponent = defineComponent({ 8 | name: 'Workbench', 9 | setup(props, { slots }) { 10 | const workbench = useWorkbench() 11 | return () => { 12 | return ( 13 | 14 | {slots.default?.()} 15 | 16 | ) 17 | } 18 | }, 19 | }) 20 | 21 | export const Workbench = observer(WrokbenchComponent) 22 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Text.ts: -------------------------------------------------------------------------------- 1 | export const Text = { 2 | 'zh-CN': { 3 | title: '文本', 4 | settings: { 5 | 'x-component-props': { 6 | content: '文本内容', 7 | mode: { 8 | title: '文本类型', 9 | dataSource: ['H1', 'H2', 'H3', 'Paragraph', 'Normal'], 10 | }, 11 | }, 12 | }, 13 | }, 14 | 'en-US': { 15 | title: 'Text', 16 | settings: { 17 | 'x-component-props': { 18 | content: 'Text Content', 19 | mode: { 20 | title: 'Text Mode', 21 | dataSource: ['H1', 'H2', 'H3', 'Paragraph', 'Normal'], 22 | }, 23 | }, 24 | }, 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/TimePicker.ts: -------------------------------------------------------------------------------- 1 | import { createLocales } from '@designable/core' 2 | import { DatePicker } from './DatePicker' 3 | 4 | export const TimePicker = createLocales(DatePicker, { 5 | 'zh-CN': { 6 | title: '时间选择', 7 | settings: { 8 | 'x-component-props': { 9 | 'is-range': { title: '时间范围选择' }, 10 | 'arrow-control': { title: '使用箭头' }, 11 | }, 12 | }, 13 | }, 14 | 'en-US': { 15 | title: 'Time Picker', 16 | settings: { 17 | 'x-component-props': { 18 | 'is-range': { title: '时间范围选择' }, 19 | 'arrow-control': { title: '使用箭头' }, 20 | }, 21 | }, 22 | }, 23 | }) 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/ColorInput/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-color-input { 4 | width: 100%; 5 | 6 | .@{antdv-prefix}-popover-inner-content { 7 | padding: 0 !important; 8 | user-select: none; 9 | } 10 | 11 | .@{antdv-prefix}-input__prefix { 12 | display: flex; 13 | align-items: center; 14 | } 15 | .ant-input--prefix { 16 | .@{antdv-prefix}-input__inner { 17 | padding-left: 0; 18 | } 19 | } 20 | 21 | &-color-tips { 22 | width: 20px; 23 | height: 20px; 24 | border-radius: 2px; 25 | border: 1px solid @border-color-base; 26 | cursor: pointer; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/CornerInput/styles.less: -------------------------------------------------------------------------------- 1 | .dn-corner-input { 2 | display: flex; 3 | &-column { 4 | display: flex; 5 | justify-content: center; 6 | flex-direction: column; 7 | align-items: center; 8 | } 9 | 10 | &-cell { 11 | width: 26px; 12 | height: 26px; 13 | box-sizing: border-box; 14 | display: flex; 15 | align-items: center; 16 | justify-content: center; 17 | cursor: pointer; 18 | border-radius: 3px; 19 | color: rgba(0, 0, 0, 0.6); 20 | margin: 5px; 21 | &.active { 22 | background: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.2)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/tree-select/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps, h } from '@formily/vue' 2 | import { TreeSelect as AntdTreeSelect, } from 'ant-design-vue' 3 | import Icon from '@ant-design/icons-vue' 4 | 5 | export const TreeSelect = connect( 6 | AntdTreeSelect, 7 | mapProps( 8 | { 9 | dataSource: 'treeData', 10 | }, 11 | (props, field) => { 12 | return { 13 | ...props, 14 | suffixIcon: 15 | field?.['loading'] || field?.['validating'] 16 | ? h(Icon, { props: { type: 'loading' } }, {}) 17 | : props.suffixIcon, 18 | } 19 | } 20 | ) 21 | ) 22 | 23 | export default TreeSelect 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/EmptyWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-empty { 4 | transform: perspective(1px) translate3d(0, 0, 0); 5 | position: absolute; 6 | top: 0; 7 | left: 0; 8 | right: 0; 9 | bottom: 0; 10 | height: 100%; 11 | width: 100%; 12 | pointer-events: none; 13 | display: flex; 14 | align-items: center; 15 | justify-content: center; 16 | background: var(--dn-empty-bg-color); 17 | .animations { 18 | display: flex; 19 | flex-wrap: wrap; 20 | justify-content: center; 21 | } 22 | .hotkeys-list { 23 | text-align: center; 24 | line-height: 30px; 25 | color: #888; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/formDesigner/widgets/logo-widget.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/panels/ToolbarPanel.tsx: -------------------------------------------------------------------------------- 1 | import { defineComponent } from 'vue-demi' 2 | import { useStyle } from '../shared' 3 | import { WorkspacePanel } from './WorkspacePanel' 4 | 5 | export const ToolbarPanel = defineComponent({ 6 | setup(props, { slots }) { 7 | const style = useStyle() 8 | return () => ( 9 | 19 | {slots.default?.()} 20 | 21 | ) 22 | }, 23 | }) 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Switch.ts: -------------------------------------------------------------------------------- 1 | export const Switch = { 2 | 'zh-CN': { 3 | title: '开关', 4 | settings: { 5 | 'x-component-props': { 6 | width: { title: '宽' }, 7 | 'active-icon-class': { title: '打开时所显示图标' }, 8 | 'inactive-icon-class': { title: '关闭时所显示图标' }, 9 | 'active-text': { title: '打开时的文字描述' }, 10 | 'inactive-text': { title: '关闭时的文字描述' }, 11 | 'active-value': { title: '打开时的值' }, 12 | 'inactive-value': { title: '关闭时的值' }, 13 | 'active-color': { title: '打开时的背景色' }, 14 | 'inactive-color': { title: '关闭时的背景色' }, 15 | }, 16 | }, 17 | }, 18 | 'en-US': { 19 | title: 'Switch', 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useDesigner.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '@designable/core' 2 | import { DesignerEngineSymbol } from '../context' 3 | import { isFn } from '@designable/shared' 4 | import { inject, onBeforeUnmount, ref, Ref } from 'vue-demi' 5 | export interface IEffects { 6 | (engine: Engine): void 7 | } 8 | 9 | export const useDesigner = (effects?: IEffects): Ref => { 10 | const designer = window['__DESINGER_ENGINE__'] 11 | ? ref(window['__DESINGER_ENGINE__']) 12 | : inject(DesignerEngineSymbol, ref()) 13 | 14 | let unRef: any = isFn(effects) ? effects(designer.value) : undefined 15 | 16 | onBeforeUnmount(() => { 17 | unRef?.() 18 | }) 19 | return designer 20 | } 21 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/move.tsx: -------------------------------------------------------------------------------- 1 | export const Move = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/transfer/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps } from '@formily/vue' 2 | import { Transfer as AntdTransfer } from 'ant-design-vue' 3 | import { isVoidField } from '@formily/core' 4 | 5 | export const Transfer = connect( 6 | AntdTransfer, 7 | mapProps({ value: 'targetKeys' }, (props, field) => { 8 | if (isVoidField(field)) return props 9 | return { 10 | ...props, 11 | dataSource: 12 | field.dataSource?.map((item) => { 13 | return { 14 | ...item, 15 | title: item.title || item.label, 16 | key: item.key || item.value, 17 | } 18 | }) || [], 19 | } 20 | }) 21 | ) 22 | 23 | export default Transfer 24 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/PositionInput/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-position-input { 4 | display: flex; 5 | flex-direction: column; 6 | 7 | &-row { 8 | display: flex; 9 | justify-content: center; 10 | } 11 | 12 | &-cell { 13 | width: 26px; 14 | height: 26px; 15 | box-sizing: border-box; 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | cursor: pointer; 20 | border-radius: 3px; 21 | color: rgba(0, 0, 0, 0.6); 22 | margin: 5px; 23 | color: @text-color; 24 | 25 | &.active { 26 | background: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.2)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/form-drawer/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | .@{formily-prefix}-form-drawer { 4 | .@{ant-prefix}-drawer-wrapper-body { 5 | display: flex; 6 | flex-direction: column; 7 | } 8 | .@{ant-prefix}-drawer-body { 9 | display: flex; 10 | flex-direction: column; 11 | flex: 1; 12 | padding: 0; 13 | overflow: auto; 14 | } 15 | 16 | &-body { 17 | flex: 1; 18 | overflow: auto; 19 | padding: @drawer-body-padding; 20 | } 21 | 22 | &-footer { 23 | border-top: 1px solid @border-color-base; 24 | padding: @drawer-body-padding; 25 | display: flex; 26 | justify-content: flex-end; 27 | align-items: center; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useSelected.ts: -------------------------------------------------------------------------------- 1 | import { observe, toJS } from '@formily/reactive' 2 | import { onBeforeUnmount, ref } from 'vue-demi' 3 | import { useSelection } from './useSelection' 4 | import { computed as reactiveComputed } from '../shared' 5 | 6 | export const useSelected = (workspaceId?: string) => { 7 | const selection = useSelection(workspaceId) 8 | // const result = ref(toJS(selection.value?.selected) || []) 9 | // const dispose = observe(selection.value, () => { 10 | // result.value = toJS(selection.value.selected) 11 | // }) 12 | // onBeforeUnmount(() => { 13 | // dispose() 14 | // }) 15 | return reactiveComputed(() => { 16 | return toJS(selection.value.selected) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/FlexStyleSetter/styles.less: -------------------------------------------------------------------------------- 1 | // @import '~antd/lib/style/themes/default.less'; 2 | @import '../../styles.less'; 3 | 4 | .dn-flex-style-setter { 5 | .dn-input-items { 6 | margin-top: -10px; 7 | margin-left: -10px; 8 | margin-right: -10px; 9 | margin-bottom: 10px; 10 | padding: 10px 10px 0 10px; 11 | background-color: @border-color-split; 12 | 13 | // .@{ant-prefix}-radio-group { 14 | // display: flex; 15 | // width: 100%; 16 | 17 | // .@{ant-prefix}-radio-button-wrapper { 18 | // flex-grow: 1; 19 | // display: flex; 20 | // justify-content: center; 21 | // padding: 0; 22 | // } 23 | // } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/help.tsx: -------------------------------------------------------------------------------- 1 | export const Help = ( 2 | 3 | 4 | 5 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/MobileSimulator/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-mobile-simulator { 4 | position: relative; 5 | min-height: 100px; 6 | height: 100%; 7 | width: 100%; 8 | background-color: var(--dn-mobile-simulator-bg-color); 9 | 10 | &-content { 11 | width: 100%; 12 | top: 0; 13 | left: 0; 14 | height: 100%; 15 | position: absolute; 16 | overflow: overlay; 17 | } 18 | 19 | &-body { 20 | display: flex; 21 | justify-content: center; 22 | height: 100%; 23 | 24 | &-content { 25 | background-color: var(--dn-mobile-simulator-body-bg-color); 26 | border: 3px solid var(--dn-mobile-simulator-border-color); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/cascader/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps, mapReadPretty, h } from '@formily/vue' 2 | import { Cascader as AntdCascader, } from 'ant-design-vue' 3 | import Icon from '@ant-design/icons-vue' 4 | import { PreviewText } from '../preview-text' 5 | 6 | export const Cascader = connect( 7 | AntdCascader, 8 | mapProps( 9 | { 10 | dataSource: 'options', 11 | }, 12 | (props, field) => { 13 | return { 14 | ...props, 15 | suffixIcon: 16 | field?.['loading'] || field?.['validating'] 17 | ? h(Icon, { props: { type: 'loading' } }, {}) 18 | : props.suffixIcon, 19 | } 20 | } 21 | ), 22 | mapReadPretty(PreviewText.Cascader) 23 | ) 24 | 25 | export default Cascader 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/common/FormItemSwitcher/index.tsx: -------------------------------------------------------------------------------- 1 | import { Switch } from '../../../components' 2 | import { defineComponent } from 'vue-demi' 3 | 4 | export interface IFormItemSwitcherProps { 5 | value?: string 6 | // onChange?: (value: string) => void 7 | } 8 | 9 | export const FormItemSwitcher = defineComponent({ 10 | props: { value: {} }, 11 | setup(props, { emit }) { 12 | return () => { 13 | console.log('这是?', props) 14 | return ( 15 | { 19 | emit('change', value ? 'FormItem' : undefined) 20 | } 21 | }} 22 | /> 23 | ) 24 | } 25 | }, 26 | }) 27 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/PCSimulator/index.tsx: -------------------------------------------------------------------------------- 1 | import cls from 'classnames' 2 | import { defineComponent } from 'vue-demi' 3 | import { usePrefix } from '../../hooks' 4 | import './styles.less' 5 | // export interface IPCSimulatorProps extends HTMLDivElement { 6 | // className?: string 7 | // style?: any // CSSProperties 8 | // } 9 | export const PCSimulator = defineComponent({ 10 | name: 'DnPCSimulator', 11 | props: { 12 | className: {}, 13 | }, 14 | setup(props, { attrs, slots }) { 15 | const prefix = usePrefix('pc-simulator') 16 | 17 | return () => { 18 | return ( 19 |
20 | {slots.default?.()} 21 |
22 | ) 23 | } 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import { connect, mapProps, mapReadPretty } from '@formily/vue' 2 | import { Checkbox as AntdCheckbox } from 'ant-design-vue' 3 | import { PreviewText } from '../preview-text' 4 | import { composeExport } from '../__builtins__/shared' 5 | const { Group } = AntdCheckbox 6 | 7 | const CheckboxGroup = connect( 8 | Group, 9 | mapProps({ 10 | dataSource: 'options', 11 | }), 12 | mapReadPretty(PreviewText.Select, { 13 | mode: 'tags', 14 | }) 15 | ) 16 | 17 | const _CheckBox = connect( 18 | AntdCheckbox, 19 | mapProps({ 20 | value: 'checked', 21 | onInput: 'onChange', 22 | }) 23 | ) 24 | 25 | export const Checkbox = composeExport(_CheckBox, { 26 | Group: CheckboxGroup, 27 | }) 28 | 29 | export default Checkbox 30 | -------------------------------------------------------------------------------- /src/formDesigner/service/schema.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from '@designable/core' 2 | import { 3 | transformToSchema, 4 | transformToTreeNode, 5 | } from '@designable/formily-transformer' 6 | import { message } from 'ant-design-vue' 7 | 8 | export const saveSchema = (designer: Engine) => { 9 | const schema = transformToSchema(designer.getCurrentTree()); 10 | localStorage.setItem( 11 | 'formily-schema', 12 | JSON.stringify(schema) 13 | ) 14 | message.success('Save Success'); 15 | console.log('schema', schema) 16 | } 17 | 18 | export const loadInitialSchema = (designer: Engine) => { 19 | try { 20 | const tree = transformToTreeNode( 21 | JSON.parse(localStorage.getItem('formily-schema')) 22 | ) 23 | designer.setCurrentTree(tree) 24 | } catch (err) { } 25 | } 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/resolve-component.ts: -------------------------------------------------------------------------------- 1 | import type { Component } from 'vue' 2 | import { h, toRaw } from 'vue' 3 | import type { SlotTypes } from '.' 4 | import { isVnode } from './utils' 5 | 6 | export const resolveComponent = ( 7 | child?: SlotTypes, 8 | props?: Record 9 | ) => { 10 | if (child) { 11 | if (typeof child === 'string' || typeof child === 'number') { 12 | return child 13 | } else if (typeof child === 'function') { 14 | // eslint-disable-next-line @typescript-eslint/ban-types 15 | return (child as Function)(props) 16 | } else if (isVnode(child)) { 17 | return child 18 | } else { 19 | return h(toRaw(child as Component), { props }) 20 | } 21 | } 22 | 23 | return null 24 | } 25 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/container.tsx: -------------------------------------------------------------------------------- 1 | export const Container = ( 2 | 3 | 4 | 5 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/FormCollapse.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const FormCollapse: ISchema & { CollapsePanel?: ISchema } = { 4 | type: 'object', 5 | properties: { 6 | accordion: { 7 | default: true, 8 | type: 'boolean', 9 | 'x-decorator': 'FormItem', 10 | 'x-component': 'Switch', 11 | }, 12 | }, 13 | } 14 | 15 | FormCollapse.CollapsePanel = { 16 | type: 'object', 17 | properties: { 18 | title: { 19 | type: 'boolean', 20 | 'x-decorator': 'FormItem', 21 | 'x-component': 'Input', 22 | 'x-component-props': { clearable: true }, 23 | }, 24 | disabled: { 25 | default: false, 26 | type: 'boolean', 27 | 'x-decorator': 'FormItem', 28 | 'x-component': 'Switch', 29 | }, 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import vueJsx from '@vitejs/plugin-vue-jsx'; 4 | const path = require('path'); 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue(), vueJsx()], 9 | resolve: { 10 | alias: { 11 | // '@ant-design-vue/pro-layout': fileURLToPath(new URL('./src', import.meta.url)), 12 | '@': path.resolve(__dirname, './src'), 13 | '@form-designer': path.resolve(__dirname, './src/formDesigner'), 14 | }, 15 | extensions: ['.js', '.ts', '.vue', '.tsx', '.json'] 16 | }, 17 | // css相关配置 18 | css: { 19 | postcss: {}, 20 | preprocessorOptions: { 21 | less: { 22 | // DO NOT REMOVE THIS LINE 23 | javascriptEnabled: true, 24 | 25 | }, 26 | }, 27 | } 28 | }) 29 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/pc.tsx: -------------------------------------------------------------------------------- 1 | export const PC = ( 2 | 3 | 4 | 5 | ) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Field' 2 | export * from './Form' 3 | export * from './Input' 4 | export * from './Select' 5 | export * from './TreeSelect' 6 | export * from './Cascader' 7 | export * from './Radio' 8 | export * from './Checkbox' 9 | export * from './Slider' 10 | export * from './Rate' 11 | export * from './NumberPicker' 12 | export * from './Transfer' 13 | export * from './Password' 14 | export * from './DatePicker' 15 | export * from './TimePicker' 16 | export * from './Upload' 17 | export * from './Switch' 18 | export * from './Text' 19 | export * from './Card' 20 | export * from './Space' 21 | export * from './Object' 22 | export * from './ArrayCards' 23 | export * from './ArrayTable' 24 | export * from './FormTab' 25 | export * from './FormCollapse' 26 | export * from './FormGrid' 27 | export * from './FormLayout' 28 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/all.ts: -------------------------------------------------------------------------------- 1 | export * from './Input' 2 | export * from './Text' 3 | export * from './FormLayout' 4 | export * from './CSSStyle' 5 | export * from './Form' 6 | export * from './FormItem' 7 | export * from './Select' 8 | export * from './Card' 9 | export * from './Cascader' 10 | export * from './Checkbox' 11 | export * from './Radio' 12 | export * from './DatePicker' 13 | export * from './NumberPicker' 14 | export * from './Password' 15 | export * from './Rate' 16 | export * from './Slider' 17 | export * from './TimePicker' 18 | export * from './TreeSelect' 19 | export * from './Transfer' 20 | export * from './Upload' 21 | export * from './Switch' 22 | export * from './FormGrid' 23 | export * from './Space' 24 | export * from './FormTab' 25 | export * from './FormCollapse' 26 | export * from './ArrayTable' 27 | export * from './ArrayCards' 28 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/remove.tsx: -------------------------------------------------------------------------------- 1 | export const Remove = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/common/Container/index.tsx: -------------------------------------------------------------------------------- 1 | import { DroppableWidget } from '../../../prototypes' 2 | import { VueComponent } from '@formily/vue' 3 | import './styles.less' 4 | import { defineComponent } from 'vue-demi' 5 | import { VNode } from 'vue' 6 | 7 | export const Container = defineComponent({ 8 | name: 'DnContainer', 9 | setup(props, { slots }) { 10 | return () => { 11 | return 12 | } 13 | }, 14 | }) 15 | 16 | export const withContainer = (Target: VNode) => { 17 | return defineComponent({ 18 | setup(props, { attrs, slots }) { 19 | console.log({attrs}) 20 | return () => { 21 | return ( 22 | 23 | 24 | 25 | ) 26 | } 27 | }, 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/MobileSimulator/index.tsx: -------------------------------------------------------------------------------- 1 | import { MobileBody } from './body' 2 | import { usePrefix } from '../../hooks' 3 | import cls from 'classnames' 4 | import './styles.less' 5 | import { defineComponent } from 'vue-demi' 6 | // export interface IMobileSimulatorProps 7 | // extends React.HTMLAttributes { 8 | // className?: string 9 | // style?: React.CSSProperties 10 | // } 11 | 12 | export const MobileSimulator = defineComponent({ 13 | setup(props, { attrs, slots }) { 14 | const prefixRef = usePrefix('mobile-simulator') 15 | return () => { 16 | return ( 17 |
18 |
19 | {slots.default?.()} 20 |
21 |
22 | ) 23 | } 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useDesigner' 2 | export * from './useCursor' 3 | export * from './useScreen' 4 | export * from './useTree' 5 | export * from './useTheme' 6 | export * from './useTreeNode' 7 | export * from './useHover' 8 | export * from './useViewport' 9 | export * from './useOutline' 10 | export * from './useSelection' 11 | export * from './useOperation' 12 | export * from './useWorkbench' 13 | export * from './useWorkspace' 14 | export * from './useHistory' 15 | export * from './usePrefix' 16 | export * from './useRegistry' 17 | export * from './useValidNodeOffsetRect' 18 | export * from './useCurrentNodeSelected' 19 | export * from './useViewportDragon' 20 | export * from './useOutlineDragon' 21 | export * from './useNodeIdProps' 22 | export * from './useCurrentNode' 23 | export * from './useSelected' 24 | export * from './useComponents' 25 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/mobile.tsx: -------------------------------------------------------------------------------- 1 | export const Mobile = ( 2 | 3 | 4 | 5 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/NodeTitleWidget/index.tsx: -------------------------------------------------------------------------------- 1 | import { observer } from '@formily/reactive-vue' 2 | import { defineComponent } from 'vue-demi' 3 | import { TreeNode } from '@designable/core' 4 | import { PropType } from 'vue' 5 | 6 | const NodeTitleWidgetComponent = defineComponent({ 7 | name: 'DnNodeTitleWidget', 8 | props: { 9 | node: Object as PropType 10 | }, 11 | setup(props) { 12 | const takeNode = () => { 13 | const node = props.node! 14 | if (node.componentName === '$$ResourceNode$$') { 15 | return node.children[0] 16 | } 17 | return node 18 | } 19 | 20 | return () => { 21 | const node = takeNode() 22 | return ( 23 | <>{node.getMessage('title') || node.componentName} 24 | ) 25 | } 26 | }, 27 | }) 28 | export const NodeTitleWidget = observer(NodeTitleWidgetComponent) 29 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Space.ts: -------------------------------------------------------------------------------- 1 | export const Space = { 2 | 'zh-CN': { 3 | title: '弹性间距', 4 | settings: { 5 | 'x-component-props': { 6 | direction: { title: '方向', dataSource: ['垂直', '水平'] }, 7 | split: '分割内容', 8 | wrap: '自动换行', 9 | align: { 10 | title: '对齐', 11 | dataSource: ['头部', '尾部', '居中', '基准线'], 12 | }, 13 | }, 14 | }, 15 | }, 16 | 'en-US': { 17 | title: 'Space', 18 | settings: { 19 | 'x-component-props': { 20 | direction: { 21 | title: 'Direction', 22 | dataSource: ['Vertical', 'Horizontal'], 23 | }, 24 | split: 'Split', 25 | wrap: 'Word Wrap', 26 | align: { 27 | title: 'Align', 28 | dataSource: ['Start', 'End', 'Center', 'Baseline'], 29 | }, 30 | }, 31 | }, 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './reactive' 2 | export * from './useEffect' 3 | import { isStr } from '@designable/shared' 4 | import { cloneVNode, CSSProperties } from '@vue/runtime-dom' 5 | import { useAttrs } from 'vue' 6 | 7 | /** 8 | * 复制一个现有VNode对象 9 | * @param VNode 10 | * @param props 11 | * @returns 12 | */ 13 | export const cloneElement = cloneVNode 14 | 15 | const css2obj = (css: string) => { 16 | const r = /(?<=^|;)\s*([^:]+)\s*:\s*([^;]+)\s*/g, 17 | o = {} 18 | css.replace(r, (m, p, v) => (o[p] = v)) 19 | return o 20 | } 21 | 22 | export const useStyle = () => { 23 | let { style = {} } = useAttrs() 24 | if (isStr(style)) { 25 | style = css2obj(style) 26 | } 27 | return style as CSSProperties 28 | } 29 | 30 | const isObj = (val: unknown): val is any => typeof val === 'object' 31 | export { isVNode } from 'vue' 32 | 33 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/FormCollapse.ts: -------------------------------------------------------------------------------- 1 | export const FormCollapse = { 2 | 'zh-CN': { 3 | title: '折叠面板', 4 | addCollapsePanel: '添加面板', 5 | settings: { 6 | 'x-component-props': { 7 | accordion: '手风琴模式', 8 | }, 9 | }, 10 | }, 11 | 'en-US': { 12 | title: 'Collapse', 13 | addCollapsePanel: 'Add Panel', 14 | settings: { 15 | 'x-component-props': { 16 | accordion: 'Accordion Mode', 17 | }, 18 | }, 19 | }, 20 | } 21 | 22 | export const FormCollapsePanel = { 23 | 'zh-CN': { 24 | title: '面板', 25 | settings: { 26 | 'x-component-props': { 27 | title: '标题', 28 | disabled: '禁用', 29 | }, 30 | }, 31 | }, 32 | 'en-US': { 33 | title: 'Panel', 34 | settings: { 35 | 'x-component-props': { 36 | title: '标题', 37 | disabled: '禁用', 38 | }, 39 | }, 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/effects/useSnapshot.tsx: -------------------------------------------------------------------------------- 1 | import { Operation } from '@designable/core' 2 | import { onFieldInputValueChange } from '@formily/core' 3 | import { Ref } from 'vue-demi' 4 | let timeRequest = null 5 | 6 | export const useSnapshot = (operation: Operation, keyup: Ref) => { 7 | // TODO::usesnapshot is causing problem but dont know what this is 8 | // the elementui's input-number emit('input') event by immediate watcher 9 | // also CreateForm effect changes schema by locales which cause label goes to null 10 | // workaround listen to keyup event, if keyup event is fired then snapshot, otherwise no snapshots 11 | onFieldInputValueChange('*', () => { 12 | if (!keyup.value) return 13 | clearTimeout(timeRequest) 14 | timeRequest = setTimeout(() => { 15 | operation.snapshot('update:node:props') 16 | keyup.value = false 17 | }, 1000) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "allowJs": true, 14 | "lib": [ 15 | "esnext", 16 | "dom" 17 | ], 18 | "skipLibCheck": true, 19 | "paths": { 20 | "@": [ 21 | "./src" 22 | ], 23 | "@form-designer": [ 24 | "./src/formDesigner" 25 | ], 26 | "@/*": [ 27 | "./src/*" 28 | ] 29 | } 30 | }, 31 | "include": [ 32 | "src/**/*.ts", 33 | "src/**/*.d.ts", 34 | "src/**/*.tsx", 35 | "src/**/*.vue" 36 | ], 37 | "references": [ 38 | { 39 | "path": "./tsconfig.node.json" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Component.ts: -------------------------------------------------------------------------------- 1 | export const Component = { 2 | 'zh-CN': { 3 | settings: { 4 | style: { 5 | width: '宽度', 6 | height: '高度', 7 | display: '展示', 8 | background: '背景', 9 | boxShadow: '阴影', 10 | font: '字体', 11 | margin: '外边距', 12 | padding: '内边距', 13 | borderRadius: '圆角', 14 | border: '边框', 15 | opacity: '透明度', 16 | }, 17 | }, 18 | }, 19 | 'en-US': { 20 | settings: { 21 | style: { 22 | width: 'Width', 23 | height: 'Height', 24 | display: 'Display', 25 | background: 'Background', 26 | boxShadow: 'Box Shadow', 27 | font: 'Font', 28 | margin: 'Margin', 29 | padding: 'Padding', 30 | borderRadius: 'Radius', 31 | border: 'Border', 32 | opacity: 'Opacity', 33 | }, 34 | }, 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/shift.tsx: -------------------------------------------------------------------------------- 1 | export const Shift = ( 2 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/useWorkspace.ts: -------------------------------------------------------------------------------- 1 | import { useDesigner } from './useDesigner' 2 | import { WorkspaceSymbol, useContext } from '../context' 3 | import { Workspace } from '@designable/core' 4 | import { ref, computed, Ref } from 'vue-demi' 5 | import { computed as reactiveComputed } from '../shared' 6 | 7 | export const useWorkspace = (id?: string): Ref => { 8 | const designer = useDesigner() 9 | const workspaceRef = ref() 10 | 11 | const WorkspaceSymbolRef = useContext(WorkspaceSymbol) 12 | 13 | if (window['__DESINGER_WORKSPACE__']) { 14 | workspaceRef.value = window['__DESINGER_WORKSPACE__'] 15 | return workspaceRef 16 | } 17 | 18 | return reactiveComputed(() => { 19 | const workspaceId = id || WorkspaceSymbolRef?.value.id 20 | if (workspaceId) { 21 | return designer.value.workbench.findWorkspaceById(workspaceId) 22 | } 23 | return designer.value.workbench.currentWorkspace 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/upload.tsx: -------------------------------------------------------------------------------- 1 | export const CloudUpload = ( 2 | 3 | 4 | 5 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/ResponsiveSimulator/handle.tsx: -------------------------------------------------------------------------------- 1 | import { usePrefix } from '../../hooks' 2 | import cls from 'classnames' 3 | import { defineComponent } from '@vue/runtime-core' 4 | export enum ResizeHandleType { 5 | Resize = 'RESIZE', 6 | ResizeWidth = 'RESIZE_WIDTH', 7 | ResizeHeight = 'RESIZE_HEIGHT', 8 | } 9 | 10 | export interface IResizeHandleProps { 11 | type?: ResizeHandleType 12 | } 13 | 14 | export const ResizeHandle = defineComponent({ 15 | props: ['type'], 16 | setup(props, { slots, attrs }) { 17 | const prefixRef = usePrefix('resize-handle') 18 | return () => { 19 | return ( 20 |
27 | {slots.default?.()} 28 |
29 | ) 30 | } 31 | }, 32 | }) 33 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__tests__/reset.spec.ts: -------------------------------------------------------------------------------- 1 | import { Reset } from '../reset' 2 | import { render } from '@testing-library/vue' 3 | import { defineComponent } from 'vue' 4 | import { FormProvider, Field } from '@formily/vue' 5 | import { createForm } from '@formily/core' 6 | 7 | test('render Reset', () => { 8 | const form = createForm() 9 | render( 10 | defineComponent({ 11 | name: 'TestReset', 12 | components: { 13 | FormProvider, 14 | Field, 15 | }, 16 | setup() { 17 | return { 18 | form, 19 | Reset, 20 | } 21 | }, 22 | template: ` 23 | 24 | 29 | 30 | `, 31 | }) 32 | ) 33 | expect(form.mounted).toBeTruthy() 34 | expect(form.query('aa').take().mounted).toBeTruthy() 35 | }) 36 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/PolyInput/styles.less: -------------------------------------------------------------------------------- 1 | // @import '~antd/lib/style/themes/default.less'; 2 | @import '../../styles.less'; 3 | 4 | .dn-poly-input { 5 | display: flex; 6 | width: 100%; 7 | align-items: center; 8 | 9 | .dn-poly-input-content { 10 | flex-grow: 2; 11 | margin-right: 2px; 12 | display: flex; 13 | 14 | .@{antdv-prefix}-button { 15 | flex: 1; 16 | } 17 | 18 | .@{antdv-prefix}-select { 19 | width: 100%; 20 | } 21 | 22 | .@{antdv-prefix}-input-number { 23 | width: 100%; 24 | 25 | .el-input__inner { 26 | padding: 0 11px; 27 | text-align: left; 28 | } 29 | } 30 | } 31 | 32 | .dn-poly-input-controller { 33 | border: 1px solid @border-color-base; 34 | border-radius: 2px; 35 | cursor: pointer; 36 | padding: 8px 8px; 37 | display: flex; 38 | align-items: center; 39 | justify-content: center; 40 | flex-grow: 0; 41 | } 42 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/all.ts: -------------------------------------------------------------------------------- 1 | export * from './Component' 2 | export * from './Field' 3 | export * from './Input' 4 | export * from './Select' 5 | export * from './TextArea' 6 | export * from './TreeSelect' 7 | export * from './Cascader' 8 | export * from './Radio' 9 | export * from './Checkbox' 10 | export * from './Slider' 11 | export * from './Rate' 12 | export * from './DatePicker' 13 | export * from './TimePicker' 14 | export * from './NumberPicker' 15 | export * from './Password' 16 | export * from './Transfer' 17 | export * from './Upload' 18 | export * from './Switch' 19 | export * from './Object' 20 | export * from './Form' 21 | export * from './FormLayout' 22 | export * from './Text' 23 | export * from './Card' 24 | export * from './ArrayBase' 25 | export * from './ArrayCards' 26 | export * from './ArrayTable' 27 | export * from './Void' 28 | export * from './Space' 29 | export * from './FormTab' 30 | export * from './FormCollapse' 31 | export * from './FormGrid' 32 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/hooks/useDropTemplate.ts: -------------------------------------------------------------------------------- 1 | import { AppendNodeEvent, TreeNode } from '@designable/core' 2 | import { useDesigner } from '../../prototypes' 3 | import { matchComponent, matchChildComponent } from '../shared' 4 | 5 | export const useDropTemplate = ( 6 | name: string, 7 | getChildren: (source: TreeNode[]) => TreeNode[] 8 | ) => { 9 | return useDesigner((designer) => { 10 | return designer.subscribeTo(AppendNodeEvent, (event) => { 11 | const { source, target } = event.data 12 | if (Array.isArray(target)) return 13 | if (!Array.isArray(source)) return 14 | if ( 15 | matchComponent( 16 | target, 17 | (key) => 18 | key === name && 19 | source.every((child) => !matchChildComponent(child, name)) 20 | ) && 21 | target.children.length === 0 22 | ) { 23 | target.setChildren(...getChildren(source)) 24 | return false 25 | } 26 | }) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-base/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | @array-base-prefix-cls: ~'@{formily-prefix}-array-base'; 4 | 5 | .@{array-base-prefix-cls}-remove { 6 | transition: all 0.25s ease-in-out; 7 | color: @text-color; 8 | font-size: 16px; 9 | &:hover { 10 | color: @primary-5; 11 | } 12 | } 13 | 14 | .@{array-base-prefix-cls}-sort-handle { 15 | cursor: move; 16 | color: #888 !important; 17 | } 18 | 19 | .@{array-base-prefix-cls}-addition { 20 | transition: all 0.25s ease-in-out; 21 | } 22 | 23 | .@{array-base-prefix-cls}-move-down { 24 | transition: all 0.25s ease-in-out; 25 | color: @text-color; 26 | font-size: 16px; 27 | margin-left: 6px; 28 | 29 | &:hover { 30 | color: @primary-5; 31 | } 32 | } 33 | 34 | .@{array-base-prefix-cls}-move-up { 35 | transition: all 0.25s ease-in-out; 36 | color: @text-color; 37 | font-size: 16px; 38 | margin-left: 6px; 39 | 40 | &:hover { 41 | color: @primary-5; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/context.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode, Engine } from '@designable/core' 2 | import { InjectionKey, Ref } from 'vue' 3 | import { 4 | IDesignerLayoutContext, 5 | IWorkspaceContext, 6 | IDesignerComponents, 7 | } from './types' 8 | import { inject, ref } from 'vue-demi' 9 | export * from './types' 10 | 11 | export const DesignerComponentsSymbol: InjectionKey> = 12 | Symbol('DesignerComponentsSymbol') 13 | 14 | export const DesignerLayoutSymbol: InjectionKey> = 15 | Symbol('DesignerLayoutSymbol') 16 | 17 | export const DesignerEngineSymbol: InjectionKey> = Symbol( 18 | 'DesignerEngineSymbol' 19 | ) 20 | 21 | export const TreeNodeSymbol: InjectionKey> = 22 | Symbol('TreeNodeSymbol') 23 | 24 | export const WorkspaceSymbol: InjectionKey> = 25 | Symbol('WorkspaceSymbol') 26 | 27 | export function useContext(key: InjectionKey>) { 28 | return inject(key, ref()) 29 | } 30 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Radio.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const Radio: ISchema & { Group?: ISchema } = { 4 | type: 'object', 5 | properties: { 6 | autoFocus: { 7 | type: 'boolean', 8 | 'x-decorator': 'FormItem', 9 | 'x-component': 'Switch', 10 | }, 11 | }, 12 | } 13 | 14 | Radio.Group = { 15 | type: 'object', 16 | properties: { 17 | optionType: { 18 | type: 'string', 19 | enum: ['default', 'button'], 20 | 'x-decorator': 'FormItem', 21 | 'x-component': 'Radio.Group', 22 | 'x-component-props': { 23 | defaultValue: 'default', 24 | optionType: 'button', 25 | }, 26 | }, 27 | buttonStyle: { 28 | type: 'string', 29 | enum: ['outline', 'solid'], 30 | 'x-decorator': 'FormItem', 31 | 'x-component': 'Radio.Group', 32 | 'x-component-props': { 33 | defaultValue: 'outline', 34 | optionType: 'button', 35 | }, 36 | }, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/types.ts: -------------------------------------------------------------------------------- 1 | import { Engine, IResource, IBehavior } from '@designable/core' 2 | import { DefineComponent } from 'vue' 3 | // import Vue from 'vue' 4 | 5 | 6 | 7 | export interface IDesignerLayoutProps { 8 | prefixCls?: string 9 | theme?: 'dark' | 'light' | (string & {}) 10 | } 11 | export interface IDesignerProps extends IDesignerLayoutProps { 12 | engine: Engine 13 | } 14 | 15 | export interface IDesignerComponents { 16 | [key: string]: DnFC 17 | } 18 | 19 | export interface IDesignerLayoutContext { 20 | theme?: 'dark' | 'light' | (string & {}) 21 | prefixCls: string 22 | } 23 | 24 | export interface IWorkspaceContext { 25 | id: string 26 | title?: string 27 | description?: string 28 | } 29 | 30 | export type DnFC

= DefineComponent & { 31 | Resource?: IResource[] 32 | Behavior?: IBehavior[] 33 | } 34 | 35 | export type DnComponent

= DefineComponent & { 36 | Resource?: IResource[] 37 | Behavior?: IBehavior[] 38 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/components/input/index.ts: -------------------------------------------------------------------------------- 1 | import { composeExport, transformComponent } from '../__builtins__/shared' 2 | import { connect, mapProps, mapReadPretty } from '@formily/vue' 3 | import { PreviewText } from '../preview-text' 4 | import { Input as AntInput } from 'ant-design-vue' 5 | // import type { Input as AntInputProps } from 'ant-design-vue/types/input/input' 6 | import type { InputProps as AntInputProps } from 'ant-design-vue' 7 | 8 | const TransformElInput = transformComponent(AntInput, { 9 | change: 'input', 10 | }) 11 | 12 | const InnerInput = connect( 13 | TransformElInput, 14 | mapProps({ readOnly: 'read-only' }), 15 | mapReadPretty(PreviewText.Input) 16 | ) 17 | 18 | const TextArea = connect( 19 | InnerInput, 20 | mapProps((props) => { 21 | return { 22 | ...props, 23 | type: 'textarea', 24 | } 25 | }), 26 | mapReadPretty(PreviewText.Input) 27 | ) 28 | 29 | export const Input = composeExport(InnerInput, { 30 | TextArea, 31 | }) 32 | 33 | export default Input 34 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/focus.tsx: -------------------------------------------------------------------------------- 1 | export const Focus = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/DesignerToolsWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-designer-tools { 4 | display: flex; 5 | align-items: center; 6 | 7 | .ant-input-number { 8 | font-size: 12px !important; 9 | background: var(--dn-toolbar-input-bg-color) !important; 10 | border-color: var(--dn-toolbar-input-border-color) !important; 11 | color: var(--dn-toolbar-input-color) !important; 12 | 13 | .ant-input-number-handler-wrap, 14 | .ant-input-number-handler { 15 | background: var(--dn-toolbar-input-handler-bg-color) !important; 16 | border-color: var(--dn-toolbar-input-border-color) !important; 17 | color: var(--dn-toolbar-input-color) !important; 18 | } 19 | 20 | .ant-input-number-handler-down-inner, 21 | .ant-input-number-handler-up-inner { 22 | color: var(--dn-toolbar-input-color) !important; 23 | } 24 | 25 | &:hover { 26 | border-color: var(--dn-toolbar-input-hover-border-color) !important; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formily-antdv3", 3 | "private": true, 4 | "version": "1.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vue-tsc --noEmit && vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "@codemirror/lang-javascript": "^0.20.1", 12 | "@designable/core": "^1.0.0-beta.45", 13 | "@designable/formily-transformer": "^1.0.0-beta.45", 14 | "@formily/antdv-x3": "^1.0.0-alpha.5", 15 | "@formily/grid": "^2.1.4", 16 | "@formily/reactive-vue": "^2.1.4", 17 | "@formily/vue": "^2.1.4", 18 | "@types/node": "^17.0.38", 19 | "@vitejs/plugin-vue-jsx": "^1.3.10", 20 | "ant-design-vue": "^3.2.5", 21 | "classnames": "^2.3.1", 22 | "less": "^4.1.2", 23 | "moment": "^2.29.3", 24 | "vue": "^3.2.25", 25 | "vue-codemirror": "^5.0.1", 26 | "vue-slicksort": "^1.2.0" 27 | }, 28 | "devDependencies": { 29 | "@vitejs/plugin-vue": "^2.3.3", 30 | "typescript": "^4.5.4", 31 | "vite": "^2.9.9", 32 | "vue-tsc": "^0.34.7" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/BorderRadiusStyleSetter/index.tsx: -------------------------------------------------------------------------------- 1 | import { IconWidget } from '../../../prototypes' 2 | import { defineComponent } from 'vue-demi' 3 | import { BoxStyleSetter } from '../BoxStyleSetter' 4 | export interface IBorderRadiusStyleSetterProps { 5 | value?: string 6 | onChange?: (value: string) => void 7 | } 8 | 9 | export const BorderRadiusStyleSetter = 10 | defineComponent({ 11 | props: { value: String }, 12 | setup(props, { emit }) { 13 | return () => { 14 | return ( 15 | emit('change', value)} 18 | labels={[ 19 | , 20 | , 21 | , 22 | , 23 | ]} 24 | /> 25 | ) 26 | } 27 | }, 28 | }) 29 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/shared/loadScript.ts: -------------------------------------------------------------------------------- 1 | export interface ILoadScriptProps { 2 | package: string 3 | entry: string 4 | root: string 5 | base?: string 6 | } 7 | 8 | export const loadScript = async (props: ILoadScriptProps) => { 9 | const options: ILoadScriptProps = { 10 | base: '//cdn.jsdelivr.net/npm', 11 | ...props, 12 | } 13 | if (window[props.root]) return window[options.root] 14 | const path = `${options.base}/${options.package}/${options.entry}` 15 | return new Promise((resolve, reject) => { 16 | const script = document.createElement('script') 17 | script.type = 'text/javascript' 18 | script.async = false 19 | script.src = path 20 | script.onload = () => { 21 | const module = window[options.root] 22 | window['define'] = define 23 | resolve(module) 24 | script.remove() 25 | } 26 | script.onerror = (err) => { 27 | reject(err) 28 | } 29 | const define = window['define'] 30 | window['define'] = undefined 31 | document.body.appendChild(script) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/code.tsx: -------------------------------------------------------------------------------- 1 | export const Code = ( 2 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/locales/operations.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'zh-CN': { 3 | operations: { 4 | default_state: '缺省态', 5 | append_node: '追加节点', 6 | prepend_node: '头部追加', 7 | clone_node: '复制节点', 8 | update_node_props: '属性更改', 9 | insert_after: '后置插入', 10 | insert_before: '前置插入', 11 | insert_children: '插入子节点', 12 | update_children: '覆盖子节点', 13 | remove_node: '删除节点', 14 | wrap_node: '包装节点', 15 | from_node: '子树更新', 16 | }, 17 | }, 18 | 'en-US': { 19 | operations: { 20 | default_state: 'Default State', 21 | append_node: 'Append Node', 22 | prepend_node: 'Prepend Node', 23 | clone_node: 'Clone Node', 24 | update_node_props: 'Update Node Props', 25 | insert_after: 'Insert Node After', 26 | insert_before: 'Insert Node Before', 27 | insert_children: 'Insert Node Children', 28 | update_children: 'Update Children', 29 | remove_node: 'Remove Node', 30 | wrap_node: 'Wrap Node', 31 | from_node: 'Update Child Tree', 32 | }, 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Form/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../styles.less'; 2 | 3 | .dn-designable-form { 4 | .@{antdv-prefix}-input, 5 | .@{antdv-prefix}-input-number, 6 | .@{antdv-prefix}-input-affix-wrapper, 7 | .@{antdv-prefix}-cascader-picker, 8 | .@{antdv-prefix}-picker-input, 9 | .@{antdv-prefix}-picker, 10 | .@{antdv-prefix}-cascader-picker-label, 11 | .@{antdv-prefix}-slider, 12 | .@{antdv-prefix}-checkbox, 13 | .@{antdv-prefix}-cascader, 14 | .@{antdv-prefix}-textarea, 15 | .@{antdv-prefix}-rate, 16 | .@{antdv-prefix}-switch, 17 | .@{antdv-prefix}-radio, 18 | .@{antdv-prefix}-radio-wrapper, 19 | .@{antdv-prefix}-checkbox-group, 20 | .@{antdv-prefix}-checkbox-wrapper, 21 | .@{antdv-prefix}-radio-group, 22 | .@{antdv-prefix}-upload, 23 | .@{antdv-prefix}-transfer, 24 | .@{antdv-prefix}-select, 25 | .@{antdv-prefix}-select-selector { 26 | pointer-events: none !important; 27 | 28 | input { 29 | pointer-events: none !important; 30 | } 31 | } 32 | 33 | .elementicon svg { 34 | pointer-events: none; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/boolean.tsx: -------------------------------------------------------------------------------- 1 | export const Boolean = ( 2 | 3 | 4 | 5 | ) 6 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Rate.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const Rate: ISchema = { 4 | type: 'object', 5 | properties: { 6 | allowClear: { 7 | type: 'boolean', 8 | 'x-decorator': 'FormItem', 9 | 'x-component': 'Switch', 10 | 'x-component-props': { 11 | // defaultChecked: true, 12 | 'v-model:checked':true, 13 | }, 14 | }, 15 | count: { 16 | type: 'number', 17 | 'x-decorator': 'FormItem', 18 | 'x-component': 'InputNumber', 19 | 'x-component-props': { 20 | defaultValue: 5, 21 | }, 22 | }, 23 | allowHalf: { 24 | type: 'boolean', 25 | 'x-decorator': 'FormItem', 26 | 'x-component': 'Switch', 27 | }, 28 | tooltips: { 29 | 'x-decorator': 'FormItem', 30 | 'x-component': 'ValueInput', 31 | 'x-component-props': { 32 | include: ['EXPRESSION'], 33 | }, 34 | }, 35 | autoFocus: { 36 | type: 'boolean', 37 | 'x-decorator': 'FormItem', 38 | 'x-component': 'Switch', 39 | }, 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/color-picker/lib/draggable.ts: -------------------------------------------------------------------------------- 1 | let isDragging = false 2 | 3 | export declare interface IOptions { 4 | drag?: (event: Event) => void 5 | start?: (event: Event) => void 6 | end?: (event: Event) => void 7 | } 8 | 9 | export default function (ele: HTMLElement, options: IOptions) { 10 | const moveFun = function (event: Event) { 11 | options?.drag?.(event) 12 | } 13 | 14 | const upFun = function (event: Event) { 15 | document.removeEventListener('mousemove', moveFun) 16 | document.removeEventListener('mouseup', upFun) 17 | document.onselectstart = null 18 | document.ondragstart = null 19 | 20 | isDragging = false 21 | 22 | options?.end?.(event) 23 | } 24 | 25 | ele.addEventListener('mousedown', function (event: Event) { 26 | if (isDragging) return 27 | document.onselectstart = () => false 28 | document.ondragstart = () => false 29 | document.addEventListener('mousemove', moveFun) 30 | document.addEventListener('mouseup', upFun) 31 | 32 | isDragging = true 33 | 34 | options?.start?.(event) 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Object/preview.tsx: -------------------------------------------------------------------------------- 1 | import { createBehavior, createResource } from '@designable/core' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import { DnFC } from '../../../prototypes' 4 | import { createFieldSchema } from '../Field' 5 | import { Container } from '../../common/Container' 6 | import { AllLocales } from '../../locales' 7 | import { VNode } from 'vue' 8 | 9 | export const ObjectContainer: DnFC = 10 | composeExport(Container, { 11 | Behavior: createBehavior({ 12 | name: 'Object', 13 | extends: ['Field'], 14 | selector: (node) => node.props?.type === 'object', 15 | designerProps: { 16 | droppable: true, 17 | propsSchema: createFieldSchema(), 18 | }, 19 | designerLocales: AllLocales.ObjectLocale, 20 | }), 21 | Resource: createResource({ 22 | icon: 'ObjectSource', 23 | elements: [ 24 | { 25 | componentName: 'Field', 26 | props: { 27 | type: 'object', 28 | }, 29 | }, 30 | ], 31 | }), 32 | }) 33 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/AuxToolWidget/Delete.tsx: -------------------------------------------------------------------------------- 1 | import { IconWidget } from '../IconWidget' 2 | import { useOperation, usePrefix } from '../../hooks' 3 | import { Button as Button } from 'ant-design-vue' 4 | import { composeExport } from '../../../components/__builtins__' 5 | import { defineComponent } from 'vue-demi' 6 | 7 | // export interface IDeleteProps { 8 | // node: TreeNode 9 | // style?: React.CSSProperties 10 | // } 11 | 12 | const DeleteComponent = defineComponent({ 13 | props: ['node'], 14 | setup(props) { 15 | const operationRef = useOperation() 16 | const prefixRef = usePrefix('aux-copy') 17 | return () => { 18 | if (props.node === props.node.root) return null 19 | return ( 20 | 28 | ) 29 | } 30 | }, 31 | }) 32 | export const Delete = composeExport(DeleteComponent, { displayName: 'Delete' }) 33 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/portal.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent, onBeforeUnmount } from 'vue' 2 | import { h, Fragment } from '@formily/vue' 3 | export interface IPortalProps { 4 | id?: string | symbol 5 | } 6 | 7 | const PortalMap = new Map() 8 | 9 | export const createPortalProvider = (id: string | symbol) => { 10 | const Portal = defineComponent({ 11 | name: 'ProtalProvider', 12 | props: { 13 | id: { 14 | type: [String, Symbol], 15 | default: id, 16 | }, 17 | }, 18 | 19 | setup(props) { 20 | onBeforeUnmount(() => { 21 | const { id } = props 22 | if (id && PortalMap.has(id)) { 23 | PortalMap.delete(id) 24 | } 25 | }) 26 | }, 27 | 28 | render() { 29 | const { id } = this 30 | if (id && !PortalMap.has(id)) { 31 | PortalMap.set(id, this) 32 | } 33 | 34 | return h(Fragment, {}, this.$scopedSlots) 35 | }, 36 | }) 37 | 38 | return Portal 39 | } 40 | 41 | export function getProtalContext(id: string | symbol) { 42 | return PortalMap.get(id) 43 | } 44 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/SchemaField.tsx: -------------------------------------------------------------------------------- 1 | import { createSchemaField } from '@formily/vue' 2 | import { 3 | ColorInput, 4 | CollapseItem, 5 | SizeInput, 6 | DisplayStyleSetter, 7 | BackgroundStyleSetter, 8 | BoxShadowStyleSetter, 9 | FontStyleSetter, 10 | BoxStyleSetter, 11 | BorderRadiusStyleSetter, 12 | BorderStyleSetter, 13 | ValueInput, 14 | DrawerSetter, 15 | } from './components' 16 | import * as Antdv from '../components'; 17 | 18 | import { Slider } from '../renderer/components/Slider/preview'; 19 | import { FormItemSwitcher } from '../renderer/common/FormItemSwitcher' 20 | 21 | 22 | const SchemaFields = createSchemaField({ 23 | components: { 24 | ...Antdv, 25 | CollapseItem, 26 | ColorInput, 27 | SizeInput, 28 | DisplayStyleSetter, 29 | BackgroundStyleSetter, 30 | BoxShadowStyleSetter, 31 | FontStyleSetter, 32 | DrawerSetter, 33 | BoxStyleSetter, 34 | BorderRadiusStyleSetter, 35 | BorderStyleSetter, 36 | ValueInput, 37 | Slider, 38 | FormItemSwitcher 39 | }, 40 | }) 41 | 42 | export const SchemaField = SchemaFields.SchemaField 43 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Checkbox.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const Checkbox: ISchema & { Group?: ISchema } = { 4 | type: 'object', 5 | properties: { 6 | autoFocus: { 7 | type: 'boolean', 8 | 'x-decorator': 'FormItem', 9 | 'x-component': 'Switch', 10 | }, 11 | }, 12 | } 13 | 14 | Checkbox.Group = { 15 | type: 'object', 16 | properties: { 17 | optionType: { 18 | type: 'string', 19 | enum: ['default', 'button'], 20 | 'x-decorator': 'FormItem', 21 | 'x-component': 'Radio.Group', 22 | 'x-component-props': { 23 | 24 | optionType: 'button', 25 | }, 26 | }, 27 | size: { 28 | default: 'default', 29 | type: 'string', 30 | enum: ['large', 'default', 'small', null], 31 | 'x-decorator': 'FormItem', 32 | 'x-component': 'Select', 33 | 'x-component-props': { 34 | 35 | }, 36 | 'x-reactions': (field) => { 37 | field.visible = 38 | field.form?.values?.['x-component-props']?.optionType === 'button' 39 | }, 40 | }, 41 | }, 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 kelvin0926 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 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/Space.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const Space: ISchema = { 4 | type: 'object', 5 | properties: { 6 | align: { 7 | type: 'string', 8 | enum: ['start', 'end', 'center', 'baseline'], 9 | 'x-decorator': 'FormItem', 10 | 'x-component': 'Select', 11 | }, 12 | direction: { 13 | type: 'string', 14 | enum: ['vertical', 'horizontal'], 15 | 'x-decorator': 'FormItem', 16 | 'x-component': 'Radio.Group', 17 | 'x-component-props': { 18 | defaultValue: 'horizontal', 19 | optionType: 'button', 20 | }, 21 | }, 22 | size: { 23 | type: 'number', 24 | 'x-decorator': 'FormItem', 25 | 'x-component': 'InputNumber', 26 | 'x-component-props': { 27 | defaultValue: 8, 28 | }, 29 | }, 30 | split: { 31 | 'x-visible': false, 32 | type: 'string', 33 | 'x-decorator': 'FormItem', 34 | 'x-component': 'Input', 35 | }, 36 | wrap: { 37 | type: 'boolean', 38 | 'x-decorator': 'FormItem', 39 | 'x-component': 'Switch', 40 | }, 41 | }, 42 | } 43 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Transfer.ts: -------------------------------------------------------------------------------- 1 | export const Transfer = { 2 | 'zh-CN': { 3 | title: '穿梭框', 4 | settings: { 5 | 'x-component-props': { 6 | 'filter-placeholder': '搜索框占位符', 7 | 'filter-method': '自定义搜索方法', 8 | 'target-order': { 9 | title: '排序策略', 10 | tooltip: 11 | '右侧列表元素的排序策略:若为 original,则保持与数据源相同的顺序;若为 push,则新加入的元素排在最后;若为 unshift,则新加入的元素排在最前', 12 | }, 13 | titles: '标题', 14 | 'button-texts': '按钮文案', 15 | 'render-content': '自定义数据项渲染函数', 16 | format: '列表顶部勾选状态文案', 17 | props: '数据源的字段别名', 18 | 'left-default-checked': '初始状态下左侧列表的已勾选项的 key 数组', 19 | 'right-default-checked': '初始状态下右侧列表的已勾选项的 key 数组', 20 | }, 21 | }, 22 | }, 23 | 'en-US': { 24 | title: 'Transfer', 25 | settings: { 26 | 'x-component-props': { 27 | oneWay: 'One Way', 28 | operations: { title: 'Operations', tooltip: 'Format:string[]' }, 29 | titles: { title: 'Titles', tooltip: 'Format:string[]' }, 30 | showSearchAll: 'Show Search All', 31 | filterOption: 'Filter Option', 32 | }, 33 | }, 34 | }, 35 | } 36 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/CollapseItem/styles.less: -------------------------------------------------------------------------------- 1 | .dn-collapse-item { 2 | flex-wrap: wrap; 3 | 4 | &-header { 5 | display: flex; 6 | align-items: center; 7 | padding: 5px 20px; 8 | margin: -1px -20px 0 -20px; 9 | color: var(--dn-collapse-header-color); 10 | border-top: 1px solid var(--dn-panel-border-color); 11 | border-bottom: 1px solid var(--dn-panel-border-color); 12 | background-color: var(--dn-panel-active-bg-color); 13 | cursor: pointer; 14 | transition: all 0.25s ease-in-out; 15 | font-size: 13px; 16 | 17 | &-expand { 18 | margin-left: -13px; 19 | transform: rotate(-90deg); 20 | font-size: 12px; 21 | transition: all 0.15s ease-in-out; 22 | margin-right: 3px; 23 | } 24 | } 25 | 26 | &-content { 27 | display: none; 28 | width: 100%; 29 | padding-top: 4px; 30 | 31 | & > div:last-child { 32 | border-bottom: none !important; 33 | } 34 | } 35 | 36 | &.expand { 37 | .dn-collapse-item-content { 38 | display: block; 39 | } 40 | 41 | .dn-collapse-item-header-expand { 42 | transform: rotate(0); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/moment.ts: -------------------------------------------------------------------------------- 1 | import { isArr, isFn } from '@formily/shared' 2 | import moment from 'moment' 3 | 4 | export const momentable = (value: any, format?: string) => { 5 | return Array.isArray(value) 6 | ? value.map((val) => moment(val, format)) 7 | : value 8 | ? moment(value, format) 9 | : value 10 | } 11 | 12 | export const formatMomentValue = ( 13 | value: any, 14 | format: any, 15 | placeholder?: string 16 | ): string | string[] => { 17 | const formatDate = (date: any, format: any, i = 0) => { 18 | if (!date) return placeholder 19 | if (isArr(format)) { 20 | const _format = format[i] 21 | if (isFn(_format)) { 22 | return _format(date) 23 | } 24 | return date?.format ? date.format(_format) : date 25 | } else { 26 | if (isFn(format)) { 27 | return format(date) 28 | } 29 | return date?.format ? date.format(format) : date 30 | } 31 | } 32 | if (isArr(value)) { 33 | return value.map((val, index) => { 34 | return formatDate(val, format, index) 35 | }) 36 | } else { 37 | return value ? formatDate(value, format) : value || placeholder 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 35 | 36 | 53 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/common/LoadTemplate/index.tsx: -------------------------------------------------------------------------------- 1 | import { NodeActionsWidget } from '../../../prototypes' 2 | import type { VNode, CSSProperties } from '@vue/runtime-dom' 3 | import type { VueComponent } from '@formily/vue' 4 | import { defineComponent } from 'vue-demi' 5 | import { PropType } from 'vue' 6 | 7 | export interface ITemplateAction { 8 | title: VNode 9 | tooltip?: VNode 10 | icon?: string | VNode 11 | onClick: () => void 12 | } 13 | 14 | export interface ILoadTemplateProps { 15 | className?: string 16 | style?: CSSProperties 17 | actions?: ITemplateAction[] 18 | } 19 | //设计器中某个组件下面的操作按钮 20 | export const LoadTemplate = defineComponent({ 21 | props: { actions: Array as PropType> }, 22 | setup(props, { attrs, slots }) { 23 | return () => { 24 | return ( 25 | 26 | {props.actions?.map((action, key) => { 27 | return ( 28 | 33 | ) 34 | })} 35 | 36 | ) 37 | } 38 | }, 39 | }) 40 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/DrawerSetter/styles.less: -------------------------------------------------------------------------------- 1 | // @import '~antd/lib/style/themes/default.less'; 2 | 3 | .dn-drawer-setter { 4 | position: absolute; 5 | top: 0; 6 | left: 0; 7 | width: 100%; 8 | bottom: 0; 9 | background: var(--dn-composite-panel-tabs-content-bg-color); 10 | z-index: 10; 11 | display: flex; 12 | flex-direction: column; 13 | 14 | &-header { 15 | display: flex; 16 | align-items: center; 17 | flex-shrink: 0; 18 | flex-grow: 0; 19 | padding: 5px 10px; 20 | // color: @text-color; 21 | // border-bottom: 1px solid @border-color-split; 22 | cursor: pointer; 23 | } 24 | 25 | &-header-text { 26 | margin-left: 4px; 27 | } 28 | 29 | &-body { 30 | padding: 10px 20px; 31 | overflow: overlay; 32 | overflow-x: hidden; 33 | flex-grow: 2; 34 | } 35 | } 36 | 37 | .dn-drawer-wrapper { 38 | transition: all 0.16s ease-in-out; 39 | 40 | &-enter { 41 | transform: translateX(100%); 42 | } 43 | 44 | &-enter-active { 45 | transform: translateX(0); 46 | } 47 | 48 | &-exit { 49 | transform: translateX(0); 50 | } 51 | 52 | &-exit-active { 53 | transform: translateX(100%); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/hooks/observer.ts: -------------------------------------------------------------------------------- 1 | export class LayoutObserver { 2 | private resizeObserver: ResizeObserver 3 | 4 | private performanceObserver: PerformanceObserver 5 | 6 | private mutationObserver: MutationObserver 7 | 8 | private connected = false 9 | 10 | constructor(observer: () => void = () => {}) { 11 | this.resizeObserver = new ResizeObserver(() => observer()) 12 | this.performanceObserver = new PerformanceObserver(() => { 13 | observer() 14 | }) 15 | this.mutationObserver = new MutationObserver(() => observer()) 16 | } 17 | 18 | observe = (target: HTMLElement | Element) => { 19 | this.resizeObserver.observe(target) 20 | this.performanceObserver.observe({ 21 | entryTypes: ['paint', 'element', 'layout-shift', 'event'], 22 | }) 23 | this.mutationObserver.observe(target, { 24 | attributeFilter: ['style'], 25 | attributes: true, 26 | }) 27 | this.connected = true 28 | } 29 | 30 | disconnect = () => { 31 | if (this.connected) { 32 | this.resizeObserver.disconnect() 33 | this.performanceObserver.disconnect() 34 | this.mutationObserver.disconnect() 35 | } 36 | this.connected = false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/AuxToolWidget/Copy.tsx: -------------------------------------------------------------------------------- 1 | import { useOperation, usePrefix } from '../../hooks' 2 | import { IconWidget } from '../IconWidget' 3 | import { Button } from 'ant-design-vue' 4 | import { defineComponent } from 'vue-demi' 5 | import { useStyle } from '../../../prototypes' 6 | import { composeExport } from '../../../components/__builtins__' 7 | 8 | // export interface ICopyProps { 9 | // node: TreeNode 10 | // style?: React.CSSProperties 11 | // } 12 | 13 | const CopyComponent = defineComponent({ 14 | name: 'CopyComponent', 15 | props: ['node'], 16 | setup(props) { 17 | const operationRef = useOperation() 18 | const prefixRef = usePrefix('aux-copy') 19 | const style = useStyle() 20 | return () => { 21 | if (props.node === props.node.root) return null 22 | return ( 23 | 32 | ) 33 | } 34 | }, 35 | }) 36 | 37 | export const Copy = composeExport(CopyComponent, { displayName: 'Copy' }) 38 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/FoldItem/styles.less: -------------------------------------------------------------------------------- 1 | // @import '~antd/lib/style/themes/default.less'; 2 | @import '../../styles.less'; 3 | 4 | .dn-fold-item { 5 | // .@{ant-prefix}-formily-item-label-content { 6 | // overflow: visible; 7 | // } 8 | .@{formily-antdv-prefix}-form-item-label-content { 9 | overflow: visible; 10 | } 11 | // .formily-antdv-form-item-label-content { 12 | // overflow: visible; 13 | // } 14 | &-base { 15 | cursor: pointer; 16 | } 17 | 18 | &-title { 19 | display: flex; 20 | align-items: center; 21 | margin-left: -10px; 22 | cursor: pointer; 23 | .dn-icon { 24 | transform: translateX(-3px); 25 | 26 | svg { 27 | transition: all 0.15s ease-in-out; 28 | transform: rotate(-90deg); 29 | } 30 | } 31 | 32 | &.expand { 33 | .dn-icon { 34 | svg { 35 | transform: rotate(0deg); 36 | } 37 | } 38 | } 39 | } 40 | 41 | &-extra { 42 | margin-top: -10px; 43 | margin-left: -10px; 44 | margin-right: -10px; 45 | margin-bottom: 10px; 46 | padding: 10px 10px 0 10px; 47 | background-color: var(--dn-composite-panel-highlight-bg-color); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/containers/Layout.tsx: -------------------------------------------------------------------------------- 1 | import { defineComponent, provide, ref } from 'vue' 2 | import { IDesignerLayoutProps } from '../types' 3 | 4 | import { 5 | DesignerLayoutSymbol, 6 | IDesignerLayoutContext, 7 | useContext, 8 | } from '../context' 9 | 10 | export const Layout = defineComponent({ 11 | name: 'Layout', 12 | props: { 13 | theme: { type: String, default: 'light' }, 14 | prefixCls: { type: String, default: 'dn-' }, 15 | }, 16 | setup(props: IDesignerLayoutProps, { slots }) { 17 | const layoutRef = useContext(DesignerLayoutSymbol) 18 | 19 | if (layoutRef.value) { 20 | return () => { 21 | return slots.default?.() 22 | } 23 | } 24 | 25 | provide( 26 | DesignerLayoutSymbol, 27 | ref({ 28 | theme: props.theme, 29 | prefixCls: props.prefixCls, 30 | } as IDesignerLayoutProps) 31 | ) 32 | 33 | return () => { 34 | return ( 35 |

40 | {slots.default?.()} 41 |
42 | ) 43 | } 44 | }, 45 | }) 46 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Select/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Select as FormilySelect } from '../../../components' 2 | import { createBehavior, createResource } from '@designable/core' 3 | import { DnFC } from '../../../prototypes' 4 | import { createFieldSchema } from '../Field' 5 | import { AllSchemas } from '../../schemas' 6 | import { AllLocales } from '../../locales' 7 | import { composeExport } from '../../../components/__builtins__' 8 | import { VNode } from 'vue' 9 | 10 | export const Select: DnFC = 11 | composeExport(FormilySelect, { 12 | Behavior: createBehavior({ 13 | name: 'Select', 14 | extends: ['Field'], 15 | selector: (node) => node.props?.['x-component'] === 'Select', 16 | designerProps: { 17 | propsSchema: createFieldSchema(AllSchemas.Select), 18 | }, 19 | designerLocales: AllLocales.Select, 20 | }), 21 | Resource: createResource({ 22 | icon: 'SelectSource', 23 | elements: [ 24 | { 25 | componentName: 'Field', 26 | props: { 27 | title: 'Select', 28 | 'x-decorator': 'FormItem', 29 | 'x-component': 'Select', 30 | }, 31 | }, 32 | ], 33 | }), 34 | }) 35 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Input.ts: -------------------------------------------------------------------------------- 1 | export const Input = { 2 | 'zh-CN': { 3 | title: '输入框', 4 | settings: { 5 | 'x-component-props': { 6 | maxlength: '最大输入长度', 7 | minlength: '最小输入长度', 8 | 'show-word-limit': '显示输入字数', 9 | placeholder: '占位提示', 10 | clearable: '可清空', 11 | 'prefix-icon': '输入框头部图标', 12 | 'suffix-icon': '输入框尾部图标', 13 | autofocus: '获取焦点', 14 | size: '尺寸', 15 | rows: '行数', 16 | autoSize: { 17 | title: '自适应高度', 18 | tooltip: '可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }', 19 | }, 20 | }, 21 | }, 22 | }, 23 | 'en-US': { 24 | title: 'Input', 25 | settings: { 26 | 'x-component-props': { 27 | maxlength: '最大输入长度', 28 | minlength: '最小输入长度', 29 | 'show-word-limit': '显示输入字数', 30 | placeholder: '占位提示', 31 | clearable: '可清空', 32 | 'prefix-icon': '输入框头部图标', 33 | 'suffix-icon': '输入框尾部图标', 34 | autofocus: '获取焦点', 35 | size: '尺寸', 36 | autoSize: { 37 | title: '自适应高度', 38 | tooltip: '可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }', 39 | }, 40 | }, 41 | }, 42 | }, 43 | } -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/play.tsx: -------------------------------------------------------------------------------- 1 | export const Play = ( 2 | 6 | ) 7 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/utils.ts: -------------------------------------------------------------------------------- 1 | export function isValidElement(element) { 2 | return ( 3 | isVueOptions(element) || 4 | (element && 5 | typeof element === 'object' && 6 | 'componentOptions' in element && 7 | 'context' in element && 8 | element.tag !== undefined) 9 | ) // remove text node 10 | } 11 | 12 | export function isVnode(element: any): boolean { 13 | return ( 14 | element && 15 | typeof element === 'object' && 16 | 'componentOptions' in element && 17 | 'context' in element && 18 | element.tag !== undefined 19 | ) 20 | } 21 | 22 | export function isVueOptions(options) { 23 | return ( 24 | options && 25 | (typeof options.template === 'string' || 26 | typeof options.render === 'function') 27 | ) 28 | } 29 | 30 | // eslint-disable-next-line @typescript-eslint/ban-types 31 | export function composeExport( 32 | s0: T0, 33 | s1: T1 34 | ): T0 & T1 { 35 | return Object.assign(s0, s1) 36 | } 37 | 38 | export function isEmptyElement(c) { 39 | return !(c.tag || (c.text && c.text.trim() !== '')) 40 | } 41 | 42 | export function filterEmpty(children = []) { 43 | return children.filter((c) => !isEmptyElement(c)) 44 | } 45 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/dragmove.tsx: -------------------------------------------------------------------------------- 1 | export const DragMove = ( 2 | 3 | 7 | 8 | ) 9 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Cascader/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Cascader as FormilyCascader } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import { createBehavior, createResource } from '@designable/core' 4 | import { DnFC } from '../../../prototypes' 5 | import { createFieldSchema } from '../Field' 6 | import { AllSchemas } from '../../schemas' 7 | import { AllLocales } from '../../locales' 8 | import { VNode } from 'vue' 9 | 10 | export const Cascader: DnFC = 11 | composeExport(FormilyCascader, { 12 | Behavior: createBehavior({ 13 | name: 'Cascader', 14 | extends: ['Field'], 15 | selector: (node) => node.props?.['x-component'] === 'Cascader', 16 | designerProps: { 17 | propsSchema: createFieldSchema(AllSchemas.Cascader), 18 | }, 19 | designerLocales: AllLocales.Cascader, 20 | }), 21 | Resource: createResource({ 22 | icon: 'CascaderSource', 23 | elements: [ 24 | { 25 | componentName: 'Field', 26 | props: { 27 | title: 'Cascader', 28 | 'x-decorator': 'FormItem', 29 | 'x-component': 'Cascader', 30 | }, 31 | }, 32 | ], 33 | }), 34 | }) 35 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/editable/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | @editable-prefix-cls: ~'@{formily-prefix}-editable'; 4 | 5 | .@{editable-prefix-cls} { 6 | cursor: pointer; 7 | display: inline-block !important; 8 | 9 | .@{formily-prefix}-form-text { 10 | .@{formily-prefix}-tag { 11 | transition: none !important; 12 | } 13 | 14 | .@{formily-prefix}-tag:last-child { 15 | margin-right: 0 !important; 16 | } 17 | } 18 | 19 | &-content { 20 | display: flex; 21 | align-items: center; 22 | 23 | > * { 24 | margin-right: 3px; 25 | &:last-child { 26 | margin-right: 0; 27 | } 28 | } 29 | } 30 | 31 | .@{editable-prefix-cls}-edit-btn, 32 | .@{editable-prefix-cls}-close-btn { 33 | transition: all 0.25s ease-in-out; 34 | color: #aaa; 35 | font-size: 12px; 36 | 37 | &:hover { 38 | color: @primary-5; 39 | } 40 | } 41 | 42 | .@{formily-prefix}-form-text { 43 | display: flex; 44 | align-items: center; 45 | } 46 | 47 | .@{editable-prefix-cls}-preview { 48 | white-space: nowrap; 49 | text-overflow: ellipsis; 50 | overflow: hidden; 51 | word-break: break-all; 52 | max-width: 100px; 53 | display: block; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/delete.tsx: -------------------------------------------------------------------------------- 1 | export const Delete = ( 2 | 3 | 7 | 11 | 15 | 16 | ) 17 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/eyes.tsx: -------------------------------------------------------------------------------- 1 | export const Eye = ( 2 | 3 | 4 | 5 | 6 | ) 7 | 8 | export const EyeClose = ( 9 | 10 | 11 | 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/simulators/ResponsiveSimulator/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .@{prefix-cls}-responsive-simulator { 4 | background-color: var(--dn-responsive-simulator-bg-color); 5 | } 6 | 7 | .@{prefix-cls}-resize-handle { 8 | position: absolute; 9 | transition: 0.2s all ease-in-out; 10 | box-sizing: border-box; 11 | user-select: none; 12 | bottom: 0; 13 | z-index: 10; 14 | background: var(--dn-resize-handle-bg-color); 15 | color: var(--dn-resize-handle-color); 16 | display: flex; 17 | justify-content: center; 18 | align-items: center; 19 | 20 | &-RESIZE_WIDTH { 21 | top: 0; 22 | bottom: 15px; 23 | cursor: ew-resize; 24 | 25 | svg { 26 | transform-origin: center; 27 | transform: rotate(-90deg); 28 | } 29 | } 30 | 31 | &-RESIZE_HEIGHT { 32 | left: 0; 33 | right: 15px; 34 | cursor: ns-resize; 35 | } 36 | 37 | &-RESIZE { 38 | cursor: nwse-resize; 39 | } 40 | 41 | &-RESIZE_HEIGHT, 42 | &-RESIZE { 43 | height: 15px; 44 | } 45 | 46 | &-RESIZE_WIDTH, 47 | &-RESIZE { 48 | right: 0; 49 | width: 15px; 50 | } 51 | 52 | &:hover { 53 | background: var(--dn-resize-handle-hover-bg-color); 54 | color: var(--dn-resize-handle-hover-color); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/TreeSelect/preview.tsx: -------------------------------------------------------------------------------- 1 | import { TreeSelect as FTreeSelect } from '../../../components' 2 | import { createBehavior, createResource } from '@designable/core' 3 | import { DnFC } from '../../../prototypes' 4 | import { createFieldSchema } from '../Field' 5 | import { AllSchemas } from '../../schemas' 6 | import { AllLocales } from '../../locales' 7 | import { composeExport } from '../../../components/__builtins__' 8 | import { DefineComponent } from 'vue' 9 | 10 | export const TreeSelect: DnFC> = 11 | composeExport(FTreeSelect, { 12 | Behavior: createBehavior({ 13 | name: 'TreeSelect', 14 | extends: ['Field'], 15 | selector: (node) => node.props?.['x-component'] === 'TreeSelect', 16 | designerProps: { 17 | propsSchema: createFieldSchema(AllSchemas.TreeSelect), 18 | }, 19 | designerLocales: AllLocales.TreeSelect, 20 | }), 21 | Resource: createResource({ 22 | icon: 'TreeSelectSource', 23 | elements: [ 24 | { 25 | componentName: 'Field', 26 | props: { 27 | title: 'TreeSelect', 28 | 'x-decorator': 'FormItem', 29 | 'x-component': 'TreeSelect', 30 | }, 31 | }, 32 | ], 33 | }), 34 | }) 35 | -------------------------------------------------------------------------------- /src/formDesigner/widgets/schema-editor-widget.tsx: -------------------------------------------------------------------------------- 1 | //json编辑器 2 | 3 | import { defineComponent, computed } from 'vue' 4 | import { 5 | transformToSchema, 6 | transformToTreeNode, 7 | } from '@designable/formily-transformer' 8 | import _ from 'lodash' 9 | import { Codemirror } from 'vue-codemirror' 10 | import { javascript } from '@codemirror/lang-javascript' 11 | 12 | export default defineComponent({ 13 | name: 'SchemaEditorWidget', 14 | props: ['tree'], 15 | setup(props, { emit }) { 16 | const code = computed(() => { 17 | return JSON.stringify(transformToSchema(props.tree), null, 2) 18 | }) 19 | 20 | const handleEmitChanges = _.debounce((value) => { 21 | emit('change', transformToTreeNode(JSON.parse(value))) 22 | }, 1000) 23 | 24 | return () => { 25 | return ( 26 | 38 | ) 39 | } 40 | }, 41 | }) 42 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Transfer/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Transfer as FormilyTransfer } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | export const Transfer: DnFC = 12 | composeExport(FormilyTransfer, { 13 | Resource: createResource({ 14 | icon: 'TransferSource', 15 | elements: [ 16 | { 17 | componentName: 'Field', 18 | props: { 19 | title: 'Transfer', 20 | 'x-decorator': 'FormItem', 21 | 'x-component': 'Transfer', 22 | }, 23 | }, 24 | ], 25 | }), 26 | Behavior: createBehavior({ 27 | name: 'Transfer', 28 | extends: ['Field'], 29 | selector: (node) => node.props?.['x-component'] === 'Transfer', 30 | designerProps: { 31 | propsSchema: createFieldSchema(AllSchemas.Transfer), 32 | }, 33 | designerLocales: AllLocales.Transfer, 34 | }), 35 | }) 36 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/index.ts: -------------------------------------------------------------------------------- 1 | // import './style' 2 | // export * from './form' 3 | // export * from './form-item' 4 | // export * from './form-layout' 5 | // export * from './form-grid' 6 | // export * from './form-button-group' 7 | // export * from './form-step' 8 | // export * from './form-tab' 9 | // export * from './form-collapse' 10 | // export * from './form-dialog' 11 | // export * from './form-drawer' 12 | // export * from './preview-text' 13 | // export * from './space' 14 | // export * from './reset' 15 | // export * from './submit' 16 | // export * from './input' 17 | // export * from './input-number' 18 | // export * from './select' 19 | // export * from './switch' 20 | // export * from './radio' 21 | // export * from './password' 22 | // export * from './checkbox' 23 | // export * from './cascader' 24 | // export * from './transfer' 25 | // export * from './tree-select' 26 | // export * from './time-picker' 27 | // export * from './date-picker' 28 | // export * from './editable' 29 | // export * from './upload' 30 | // export * from './array-tabs' 31 | // export * from './array-base' 32 | // export * from './array-cards' 33 | // export * from './array-items' 34 | // export * from './array-table' 35 | // export * from './array-collapse' 36 | export * from './color-picker' 37 | 38 | export * from '@formily/antdv-x3' 39 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Switch/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Switch as FormilySwitch } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | export const Switch: DnFC = composeExport( 12 | FormilySwitch, 13 | { 14 | Behavior: createBehavior({ 15 | name: 'Switch', 16 | extends: ['Field'], 17 | selector: (node) => node.props?.['x-component'] === 'Switch', 18 | designerProps: { 19 | propsSchema: createFieldSchema(AllSchemas.Switch), 20 | }, 21 | designerLocales: AllLocales.Switch, 22 | }), 23 | Resource: createResource({ 24 | icon: 'SwitchSource', 25 | elements: [ 26 | { 27 | componentName: 'Field', 28 | props: { 29 | type: 'boolean', 30 | title: 'Switch', 31 | 'x-decorator': 'FormItem', 32 | 'x-component': 'Switch', 33 | }, 34 | }, 35 | ], 36 | }), 37 | } 38 | ) 39 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/FormLayout/preview.ts: -------------------------------------------------------------------------------- 1 | import { FormLayout as FormilyFormLayout } from '../../../components' 2 | import { VueComponent } from '@formily/vue' 3 | import { createBehavior, createResource } from '@designable/core' 4 | // import { DnFC } from '../../prototypes' 5 | import { withContainer } from '../../common/Container' 6 | import { createVoidFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { composeExport } from '../../../components/__builtins__' 10 | 11 | export const FormLayout = 12 | composeExport(withContainer(FormilyFormLayout), { 13 | Behavior: createBehavior({ 14 | name: 'FormLayout', 15 | extends: ['Field'], 16 | selector: (node) => node.props?.['x-component'] === 'FormLayout', 17 | designerProps: { 18 | droppable: true, 19 | propsSchema: createVoidFieldSchema(AllSchemas.FormLayout), 20 | }, 21 | designerLocales: AllLocales.FormLayout, 22 | }), 23 | Resource: createResource({ 24 | icon: 'FormLayoutSource', 25 | elements: [ 26 | { 27 | componentName: 'Field', 28 | props: { 29 | type: 'void', 30 | 'x-component': 'FormLayout', 31 | }, 32 | }, 33 | ], 34 | }), 35 | }) 36 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/panels/WorkspacePanel.tsx: -------------------------------------------------------------------------------- 1 | import { defineComponent } from '@vue/runtime-core' 2 | import { usePrefix } from '../hooks' 3 | import { useStyle } from '../shared' 4 | import { composeExport } from '../../components/__builtins__' 5 | 6 | export interface IWorkspaceItemProps { 7 | style?: any 8 | flexable?: boolean 9 | } 10 | 11 | const WorkspacePanelComponent = defineComponent({ 12 | name: 'DnWorkspacePanel', 13 | setup(props, { slots }) { 14 | const prefix = usePrefix('workspace-panel') 15 | return () =>
{slots.default?.()}
16 | }, 17 | }) 18 | 19 | const WorkspacePanelItem = defineComponent({ 20 | name: 'DnWorkspacePanelItem', 21 | props: ['flexable'], 22 | setup(props, { slots }) { 23 | const prefix = usePrefix('workspace-panel-item') 24 | return () => { 25 | const style = useStyle() 26 | return ( 27 |
35 | {slots.default?.()} 36 |
37 | ) 38 | } 39 | }, 40 | }) 41 | 42 | export const WorkspacePanel = composeExport(WorkspacePanelComponent, { 43 | Item: WorkspacePanelItem, 44 | }) 45 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/DatePicker/preview.tsx: -------------------------------------------------------------------------------- 1 | import { DatePicker as FormilyDatePicker } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | export const DatePicker: DnFC = 12 | composeExport(FormilyDatePicker, { 13 | Behavior: createBehavior({ 14 | name: 'DatePicker', 15 | extends: ['Field'], 16 | selector: (node) => node.props?.['x-component'] === 'DatePicker', 17 | designerProps: { 18 | propsSchema: createFieldSchema(AllSchemas.DatePicker), 19 | }, 20 | designerLocales: AllLocales.DatePicker, 21 | }), 22 | Resource: createResource({ 23 | icon: 'DatePickerSource', 24 | elements: [ 25 | { 26 | componentName: 'Field', 27 | props: { 28 | type: 'string', 29 | title: 'DatePicker', 30 | 'x-decorator': 'FormItem', 31 | 'x-component': 'DatePicker', 32 | }, 33 | }, 34 | ], 35 | }), 36 | }) 37 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/TimePicker/preview.tsx: -------------------------------------------------------------------------------- 1 | import { TimePicker as FormilyTimePicker } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | export const TimePicker: DnFC = 12 | composeExport(FormilyTimePicker, { 13 | Behavior: createBehavior({ 14 | name: 'TimePicker', 15 | extends: ['Field'], 16 | selector: (node) => node.props?.['x-component'] === 'TimePicker', 17 | designerProps: { 18 | propsSchema: createFieldSchema(AllSchemas.TimePicker), 19 | }, 20 | designerLocales: AllLocales.TimePicker, 21 | }), 22 | Resource: createResource({ 23 | icon: 'TimePickerSource', 24 | elements: [ 25 | { 26 | componentName: 'Field', 27 | props: { 28 | type: 'string', 29 | title: 'TimePicker', 30 | 'x-decorator': 'FormItem', 31 | 'x-component': 'TimePicker', 32 | }, 33 | }, 34 | ], 35 | }), 36 | }) 37 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/array-table/style.less: -------------------------------------------------------------------------------- 1 | @import '../__builtins__/styles/common.less'; 2 | 3 | @array-table-prefix-cls: ~'@{formily-prefix}-array-table'; 4 | 5 | .@{array-table-prefix-cls} { 6 | .@{array-table-prefix-cls}-pagination { 7 | display: flex; 8 | justify-content: center; 9 | 10 | .@{array-table-prefix-cls}-status-select.has-error { 11 | .@{ant-prefix}-select-selector { 12 | border-color: @error-color !important; 13 | } 14 | } 15 | } 16 | 17 | .@{ant-prefix}-table { 18 | td { 19 | visibility: visible; 20 | 21 | .@{formily-prefix}-form-item:not(.@{formily-prefix}-form-item-feedback-layout-popover) { 22 | margin-bottom: 0 !important; 23 | 24 | .@{formily-prefix}-form-item-help { 25 | position: absolute; 26 | font-size: 12px; 27 | top: 100%; 28 | background: #fff; 29 | width: 100%; 30 | margin-top: 3px; 31 | padding: 3px; 32 | z-index: 1; 33 | border-radius: 3px; 34 | box-shadow: 0 0 10px #eee; 35 | animation: none; 36 | transform: translateY(0); 37 | opacity: 1; 38 | } 39 | } 40 | } 41 | } 42 | 43 | .@{array-table-prefix-cls}-sort-helper { 44 | background: #fff; 45 | border: 1px solid #eee; 46 | z-index: 10; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/component.tsx: -------------------------------------------------------------------------------- 1 | export const Component = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Upload/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Upload as FormilyUpload } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import { createBehavior, createResource } from '@designable/core' 4 | import { DnFC } from '../../../prototypes' 5 | import { createFieldSchema } from '../Field' 6 | import { AllSchemas } from '../../schemas' 7 | import { AllLocales } from '../../locales' 8 | import { VNode } from 'vue' 9 | 10 | export const Upload: DnFC = composeExport( 11 | FormilyUpload, 12 | { 13 | Behavior: createBehavior({ 14 | name: 'Upload', 15 | extends: ['Field'], 16 | selector: (node) => node.props?.['x-component'] === 'Upload', 17 | designerProps: { 18 | propsSchema: createFieldSchema(AllSchemas.Upload), 19 | }, 20 | designerLocales: AllLocales.Upload, 21 | }), 22 | 23 | Resource: createResource({ 24 | icon: 'UploadSource', 25 | elements: [ 26 | { 27 | componentName: 'Field', 28 | props: { 29 | type: 'Array', 30 | title: '上传', 31 | 'x-decorator': 'FormItem', 32 | 'x-component': 'Upload', 33 | 'x-component-props': { 34 | textContent: '上传', 35 | }, 36 | }, 37 | }, 38 | ], 39 | }), 40 | } 41 | ) 42 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/AuxToolWidget/DragHandler.tsx: -------------------------------------------------------------------------------- 1 | import { TreeNode } from '@designable/core' 2 | import { observer } from '@formily/reactive-vue' 3 | import { IconWidget } from '../IconWidget' 4 | import { useDesigner, usePrefix, } from '../../hooks' 5 | import { useStyle } from '../../shared' 6 | import { defineComponent } from 'vue' 7 | import { PropType } from 'vue' 8 | 9 | export interface IDragHandlerProps { 10 | node: TreeNode 11 | } 12 | 13 | export const DragHandler = observer( 14 | defineComponent({ 15 | name: 'DragHandler', 16 | props: { node: { type: Object as PropType } }, 17 | setup(props) { 18 | const designerRef = useDesigner() 19 | const style = useStyle() 20 | const prefixRef = usePrefix('aux-drag-handler') 21 | 22 | return () => { 23 | const prefix = prefixRef.value 24 | const designer = designerRef.value 25 | const node = props.node! 26 | if (node === node.root || !node.allowDrag()) return null 27 | const handlerProps = { 28 | [designer.props.nodeDragHandlerAttrName!]: 'true', 29 | } 30 | return ( 31 | 34 | ) 35 | } 36 | } 37 | }) 38 | 39 | ) 40 | 41 | DragHandler.displayName = 'DragHandler' 42 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Space/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Space as FormilySpace } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createVoidFieldSchema } from '../Field' 7 | import { withContainer } from '../../common/Container' 8 | import { AllSchemas } from '../../schemas' 9 | import { AllLocales } from '../../locales' 10 | import { VNode } from 'vue' 11 | 12 | export const Space: DnFC = composeExport( 13 | withContainer(FormilySpace), 14 | { 15 | Behavior: createBehavior({ 16 | name: 'Space', 17 | extends: ['Field'], 18 | selector: (node) => node.props?.['x-component'] === 'Space', 19 | designerProps: { 20 | droppable: true, 21 | inlineChildrenLayout: true, 22 | propsSchema: createVoidFieldSchema(AllSchemas.Space), 23 | }, 24 | designerLocales: AllLocales.Space, 25 | }), 26 | Resource: createResource({ 27 | icon: 'SpaceSource', 28 | elements: [ 29 | { 30 | componentName: 'Field', 31 | props: { 32 | type: 'void', 33 | 'x-component': 'Space', 34 | }, 35 | }, 36 | ], 37 | }), 38 | } 39 | ) 40 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/schemas/CSSStyle.ts: -------------------------------------------------------------------------------- 1 | import { ISchema } from '@formily/vue' 2 | 3 | export const CSSStyle: ISchema = { 4 | type: 'void', 5 | properties: { 6 | 'style.width': { 7 | type: 'string', 8 | 'x-decorator': 'FormItem', 9 | 'x-component': 'SizeInput', 10 | }, 11 | 'style.height': { 12 | type: 'string', 13 | 'x-decorator': 'FormItem', 14 | 'x-component': 'SizeInput', 15 | }, 16 | 'style.display': { 17 | 'x-component': 'DisplayStyleSetter', 18 | }, 19 | 'style.background': { 20 | 'x-component': 'BackgroundStyleSetter', 21 | }, 22 | 'style.boxShadow': { 23 | 'x-component': 'BoxShadowStyleSetter', 24 | }, 25 | 'style.font': { 26 | 'x-component': 'FontStyleSetter', 27 | }, 28 | 'style.margin': { 29 | 'x-component': 'BoxStyleSetter', 30 | }, 31 | 'style.padding': { 32 | 'x-component': 'BoxStyleSetter', 33 | }, 34 | 'style.borderRadius': { 35 | 'x-component': 'BorderRadiusStyleSetter', 36 | }, 37 | 'style.border': { 38 | 'x-component': 'BorderStyleSetter', 39 | }, 40 | 'style.opacity': { 41 | default: 1, 42 | 'x-decorator': 'FormItem', 43 | 'x-component': 'Slider', 44 | 'x-component-props': { 45 | min: 0, 46 | max: 1, 47 | step: 0.01, 48 | }, 49 | }, 50 | }, 51 | } 52 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Rate/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Rate as ARate } from 'ant-design-vue' 2 | import { composeExport, transformComponent } from '../../../components/__builtins__' 3 | import { connect, mapProps, VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | const RateInner = connect(transformComponent(ARate, { 12 | change: 'onUpdate:modelValue' 13 | }), mapProps({ value: 'modelValue' })) 14 | 15 | export const Rate: DnFC = composeExport(RateInner, { 16 | Behavior: createBehavior({ 17 | name: 'Rate', 18 | extends: ['Field'], 19 | selector: (node) => node.props?.['x-component'] === 'Rate', 20 | designerProps: { 21 | propsSchema: createFieldSchema(AllSchemas.Rate), 22 | }, 23 | designerLocales: AllLocales.Rate, 24 | }), 25 | Resource: createResource({ 26 | icon: 'RateSource', 27 | elements: [ 28 | { 29 | componentName: 'Field', 30 | props: { 31 | type: 'number', 32 | title: 'Rate', 33 | 'x-decorator': 'FormItem', 34 | 'x-component': 'Rate', 35 | }, 36 | }, 37 | ], 38 | }), 39 | }) 40 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Cascader.ts: -------------------------------------------------------------------------------- 1 | export const Cascader = { 2 | 'zh-CN': { 3 | title: '联级选择', 4 | settings: { 5 | 'x-component-props': { 6 | props: '属性', 7 | size: { title: '尺寸', dataSource: ['大', '小', '迷你', '继承'] }, 8 | 'show-all-levels': { 9 | title: '路径', 10 | tooltip: '输入框中是否显示选中值的完整路径', 11 | }, 12 | 'collapse-tags': { 13 | title: '折叠标签', 14 | tooltip: '多选模式下是否折叠Tag', 15 | }, 16 | separator: '选项分隔符', 17 | debounce: '去抖延迟', 18 | 'before-filter': '筛选之前钩子', 19 | 'popper-class': '自定义浮层类名', 20 | 'filter-method': '过滤钩子', 21 | }, 22 | }, 23 | }, 24 | 'en-US': { 25 | title: 'Cascader', 26 | settings: { 27 | 'x-component-props': { 28 | changeOnSelect: { 29 | title: 'Change On Select', 30 | tooltip: 'Click on each level of menu option value will change', 31 | }, 32 | displayRender: { 33 | title: 'Display Render', 34 | tooltip: 35 | 'The rendering function displayed after selection, the default is label => label.join("/") ', 36 | }, 37 | fieldNames: { 38 | title: 'Field Names', 39 | tooltip: 40 | 'Defaults:{ label: "label", value: "value", children: "children" }', 41 | }, 42 | }, 43 | }, 44 | }, 45 | } 46 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/containers/Simulator.tsx: -------------------------------------------------------------------------------- 1 | import { ScreenType } from '@designable/core' 2 | import { observer } from '@formily/reactive-vue' 3 | import { useScreen } from '../hooks' 4 | import { 5 | MobileSimulator, 6 | PCSimulator, 7 | ResponsiveSimulator, 8 | } from '../simulators' 9 | import { defineComponent } from 'vue-demi' 10 | 11 | export type ISimulatorProps = HTMLDivElement & any 12 | 13 | const SimulatorComponent = defineComponent({ 14 | setup(props, { attrs, slots }) { 15 | const screenRef = useScreen() 16 | return () => { 17 | if (screenRef.value.type === ScreenType.PC) 18 | return ( 19 | 20 | {slots.default?.()} 21 | 22 | ) 23 | if (screenRef.value.type === ScreenType.Mobile) 24 | return ( 25 | 26 | {slots.default?.()} 27 | 28 | ) 29 | if (screenRef.value.type === ScreenType.Responsive) 30 | return ( 31 | 32 | {slots.default?.()} 33 | 34 | ) 35 | return ( 36 | 37 | {slots.default?.()} 38 | 39 | ) 40 | } 41 | }, 42 | }) 43 | 44 | export const Simulator = observer(SimulatorComponent) 45 | -------------------------------------------------------------------------------- /src/formDesigner/playground/components/__builtins__/shared/create-context.ts: -------------------------------------------------------------------------------- 1 | import type { Component } from 'vue' 2 | import type { InjectionKey, Ref } from 'vue' 3 | import { 4 | defineComponent, 5 | provide, 6 | inject, 7 | readonly, 8 | ref, 9 | toRef, 10 | } from 'vue' 11 | 12 | export type CreateContext = { 13 | Provider: Component 14 | Consumer: Component 15 | injectKey: InjectionKey> 16 | } 17 | 18 | export const createContext = (defaultValue?: T): CreateContext => { 19 | const injectKey: InjectionKey> = Symbol() 20 | 21 | return { 22 | Provider: defineComponent({ 23 | name: 'ContextProvider', 24 | props: { 25 | value: { 26 | type: null, 27 | default() { 28 | return defaultValue ?? null 29 | }, 30 | }, 31 | }, 32 | setup(props, { slots }) { 33 | const value = toRef(props, 'value') 34 | provide(injectKey, readonly(value)) 35 | 36 | return () => slots?.default?.() 37 | }, 38 | }), 39 | 40 | Consumer: defineComponent({ 41 | name: 'ContextConsumer', 42 | setup(_props, { slots }) { 43 | const value = inject(injectKey) 44 | 45 | return () => slots?.default?.(value) 46 | }, 47 | }), 48 | injectKey, 49 | } 50 | } 51 | 52 | export const useContext = (context: CreateContext) => { 53 | const key = context.injectKey 54 | 55 | return inject(key, ref(null)) 56 | } 57 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/ColorInput/index.tsx: -------------------------------------------------------------------------------- 1 | import { Input, 2 | //ColorPicker 3 | } from 'ant-design-vue' 4 | import { ColorPicker } from '../../../components'; 5 | import { usePrefix } from '../../../prototypes' 6 | import './styles.less' 7 | import { defineComponent } from 'vue-demi' 8 | 9 | export interface IColorInputProps { 10 | value?: string 11 | onChange?: (color: string) => void 12 | } 13 | 14 | export const ColorInput = defineComponent({ 15 | props: ['value'], 16 | emits: ['change'], 17 | setup(props, { emit }) { 18 | const prefixRef = usePrefix('color-input') 19 | return () => { 20 | return ( 21 |
22 | { 27 | emit('change', e) 28 | } 29 | }} 30 | v-slots={{ 31 | suffix: () => { 32 | return ( 33 | { 37 | emit('change', e) 38 | } 39 | }} 40 | /> 41 | ) 42 | } 43 | }} 44 | /> 45 |
46 | ) 47 | } 48 | }, 49 | }) 50 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/NodeActionsWidget/styles.less: -------------------------------------------------------------------------------- 1 | @import '../../variables.less'; 2 | 3 | .dn-node-actions { 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | width: 100%; 8 | overflow: hidden; 9 | padding-top: 8px; 10 | padding-bottom: 8px; 11 | &-content { 12 | position: relative; 13 | padding: 0 20px; 14 | display: flex; 15 | align-items: center; 16 | line-height: 1; 17 | &::before { 18 | position: absolute; 19 | content: ''; 20 | display: block; 21 | height: 0; 22 | width: 300%; 23 | top: 50%; 24 | border-bottom: 1px dashed @border-color-split; 25 | right: 100%; 26 | } 27 | &::after { 28 | position: absolute; 29 | content: ''; 30 | display: block; 31 | height: 0; 32 | width: 300%; 33 | top: 50%; 34 | border-bottom: 1px dashed @border-color-split; 35 | left: 100%; 36 | } 37 | // a { 38 | // color: @text-color-secondary; 39 | // &:hover { 40 | // color: @primary-color; 41 | // } 42 | // } 43 | button { 44 | color: @text-color-secondary; 45 | &:hover { 46 | color: @primary-color; 47 | } 48 | } 49 | } 50 | &-item { 51 | &-text { 52 | font-size: 10px; 53 | display: flex; 54 | align-items: center; 55 | line-height: 1; 56 | .dn-icon { 57 | margin-right: 6px; 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/Slider.ts: -------------------------------------------------------------------------------- 1 | export const Slider = { 2 | 'zh-CN': { 3 | title: '滑动条', 4 | settings: { 5 | 'x-component-props': { 6 | dots: '刻度固定', 7 | range: '双滑块', 8 | reverse: '反向坐标系', 9 | vertical: '垂直布局', 10 | tooltipPlacement: { 11 | title: '提示位置', 12 | tooltip: '设置 提示 展示位置。参考 Tooltip', 13 | }, 14 | tooltipVisible: { 15 | title: '提示显示', 16 | tooltip: 17 | '开启时,提示 将会始终显示;否则始终不显示,哪怕在拖拽及移入时', 18 | }, 19 | max: '最大值', 20 | min: '最小值', 21 | step: '步长', 22 | marks: '刻度标签', 23 | }, 24 | }, 25 | }, 26 | 'en-US': { 27 | title: 'Slider', 28 | settings: { 29 | 'x-component-props': { 30 | dots: 'Fixed Scale', 31 | range: 'Double Slider', 32 | reverse: 'Reverse Coordinate System', 33 | vertical: 'Vertical', 34 | tooltipPlacement: { 35 | title: 'Tooltip Placement', 36 | tooltip: 'Set up prompt placement. Reference Tooltip', 37 | }, 38 | tooltipVisible: { 39 | title: 'Tooltip Visible', 40 | tooltip: 41 | 'When turned on, the prompt will always be displayed; otherwise, it will always not be displayed, even when dragging and moving in', 42 | }, 43 | max: 'Max', 44 | min: 'Min', 45 | step: 'Step', 46 | marks: 'Marks', 47 | }, 48 | }, 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/page.tsx: -------------------------------------------------------------------------------- 1 | export const Page = ( 2 | 3 | 4 | 5 | 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/ArrayBase.ts: -------------------------------------------------------------------------------- 1 | import { GlobalRegistry } from '@designable/core' 2 | 3 | GlobalRegistry.registerDesignerLocales({ 4 | 'zh-CN': { 5 | Previews: { 6 | droppable: '可以拖入组件', 7 | addTabPane: '添加选项卡', 8 | addCollapsePanel: '添加手风琴卡片', 9 | addTableColumn: '添加表格列', 10 | addTableSortHandle: '添加排序', 11 | addIndex: '添加索引', 12 | addOperation: '添加操作', 13 | }, 14 | }, 15 | }) 16 | 17 | export const ArrayAddition = { 18 | 'zh-CN': { 19 | title: '添加按钮', 20 | settings: { 21 | 'x-component-props': { 22 | method: '方法', 23 | defaultValue: '默认值', 24 | }, 25 | }, 26 | }, 27 | 'en-US': { 28 | title: 'Addition', 29 | }, 30 | } 31 | 32 | export const ArrayRemove = { 33 | 'zh-CN': { 34 | title: '删除按钮', 35 | }, 36 | 'en-US': { 37 | title: 'Remove', 38 | }, 39 | } 40 | 41 | export const ArrayMoveUp = { 42 | 'zh-CN': { 43 | title: '上移按钮', 44 | }, 45 | 'en-US': { 46 | title: 'Move Up', 47 | }, 48 | } 49 | 50 | export const ArrayMoveDown = { 51 | 'zh-CN': { 52 | title: '下移按钮', 53 | }, 54 | 'en-US': { 55 | title: 'Move Down', 56 | }, 57 | } 58 | 59 | export const ArrayIndex = { 60 | 'zh-CN': { 61 | title: '索引标识', 62 | }, 63 | 'en-US': { 64 | title: 'Index', 65 | }, 66 | } 67 | 68 | export const ArraySortHandle = { 69 | 'zh-CN': { 70 | title: '排序标识', 71 | }, 72 | 'en-US': { 73 | title: 'Sort Handle', 74 | }, 75 | } 76 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/locales/FormGrid.ts: -------------------------------------------------------------------------------- 1 | export const FormGrid = { 2 | 'zh-CN': { 3 | title: '网格布局', 4 | addGridColumn: '添加网格列', 5 | settings: { 6 | 'x-component-props': { 7 | minWidth: '最小宽度', 8 | minColumns: '最小列数', 9 | maxWidth: '最大宽度', 10 | maxColumns: '最大列数', 11 | breakpoints: '响应式断点', 12 | columnGap: '列间距', 13 | rowGap: '行间距', 14 | colWrap: '自动换行', 15 | strictAutoFit: 16 | 'GridItem 宽度是否严格受限于 maxWidth,不受限的话会自动占满容器', 17 | }, 18 | }, 19 | }, 20 | 'en-US': { 21 | title: 'Grid', 22 | addGridColumn: 'Add Grid Column', 23 | settings: { 24 | 'x-component-props': { 25 | minWidth: 'Min Width', 26 | minColumns: 'Min Columns', 27 | maxWidth: 'Max Width', 28 | maxColumns: 'Max Columns', 29 | breakpoints: 'Breakpoints', 30 | columnGap: 'Column Gap', 31 | rowGap: 'Row Gap', 32 | colWrap: 'Col Wrap', 33 | strictAutoFit: 34 | 'GridItem 宽度是否严格受限于 maxWidth,不受限的话会自动占满容器', 35 | }, 36 | }, 37 | }, 38 | } 39 | 40 | export const FormGridColumn = { 41 | 'zh-CN': { 42 | title: '网格列', 43 | settings: { 44 | 'x-component-props': { 45 | gridSpan: '跨列栏数', 46 | }, 47 | }, 48 | }, 49 | 'en-US': { 50 | title: 'Grid Column', 51 | settings: { 52 | 'x-component-props': { 53 | gridSpan: 'Grid Span', 54 | }, 55 | }, 56 | }, 57 | } 58 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/containers/Workspace.tsx: -------------------------------------------------------------------------------- 1 | import { useDesigner } from '../hooks' 2 | import { WorkspaceSymbol } from '../context' 3 | import { defineComponent, provide, ref, unref, computed } from 'vue-demi' 4 | import { 5 | FragmentComponent, 6 | h as CreateElment, 7 | VueComponent, 8 | } from '@formily/vue' 9 | export interface IWorkspaceProps { 10 | id?: string 11 | title?: string 12 | description?: string 13 | } 14 | 15 | export const Workspace = defineComponent({ 16 | name: 'Workspace', 17 | props: { 18 | id: String, 19 | title: String, 20 | description: String, 21 | }, 22 | setup(props, { slots }) { 23 | const oldId = ref() 24 | const designerRef = useDesigner() 25 | // memo [id, designer] 26 | const workspace = computed(() => { 27 | const designer = unref(designerRef) 28 | if (!designer) return 29 | if (oldId.value && oldId.value !== props.id) { 30 | const old = designer.workbench.findWorkspaceById(oldId.value) 31 | if (old) old.viewport.detachEvents() 32 | } 33 | const workspace = { 34 | id: props.id || 'index', 35 | title: props.title, 36 | description: props.description, 37 | } 38 | designer.workbench.ensureWorkspace(workspace) 39 | oldId.value = workspace.id 40 | return workspace 41 | }) 42 | 43 | provide(WorkspaceSymbol, workspace) 44 | 45 | return () => { 46 | return slots.default?.() 47 | } 48 | }, 49 | }) 50 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Radio/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Radio as FormilyRadio } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | export const Radio: DnFC = composeExport( 12 | FormilyRadio, 13 | { 14 | Behavior: createBehavior({ 15 | name: 'Radio.Group', 16 | extends: ['Field'], 17 | selector: (node) => node.props?.['x-component'] === 'Radio.Group', 18 | designerProps: { 19 | propsSchema: createFieldSchema(AllSchemas.Checkbox.Group), 20 | }, 21 | designerLocales: AllLocales.CheckboxGroup, 22 | }), 23 | Resource: createResource({ 24 | icon: 'RadioGroupSource', 25 | elements: [ 26 | { 27 | componentName: 'Field', 28 | props: { 29 | type: 'string | number', 30 | title: 'Radio Group', 31 | 'x-decorator': 'FormItem', 32 | 'x-component': 'Radio.Group', 33 | enum: [ 34 | { label: '选项1', value: 1 }, 35 | { label: '选项2', value: 2 }, 36 | ], 37 | }, 38 | }, 39 | ], 40 | }), 41 | } 42 | ) 43 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/widgets/AuxToolWidget/DragFocus.tsx: -------------------------------------------------------------------------------- 1 | import { observer } from '@formily/reactive-vue' 2 | import { IconWidget } from '../IconWidget' 3 | import { useOperation, usePrefix } from '../../hooks' 4 | import { Button as Button } from 'ant-design-vue' 5 | import { composeExport } from '../../components/__builtins__' 6 | import { defineComponent } from 'vue-demi' 7 | 8 | // export interface IDragFocusProps { 9 | // node: TreeNode 10 | // style?: React.CSSProperties 11 | // } 12 | 13 | const DragFocusComponent = observer( 14 | defineComponent({ 15 | name: 'DragFocus', 16 | props: ['node'], 17 | setup(props) { 18 | const operationRef = useOperation() 19 | const prefixRef = usePrefix('aux-focus') 20 | return () => { 21 | if (props.node === props.node.root) return null 22 | return ( 23 | 39 | ) 40 | } 41 | }, 42 | }) 43 | ) 44 | 45 | export const DragFocus = composeExport(DragFocusComponent, { 46 | displayName: 'DragFocus', 47 | }) 48 | -------------------------------------------------------------------------------- /src/formDesigner/playground/settings-form/components/CornerInput/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | import { usePrefix } from '@designable/react' 3 | import cls from 'classnames' 4 | import './styles.less' 5 | 6 | export interface ICornerInputProps { 7 | className?: string 8 | style?: React.CSSProperties 9 | value?: string 10 | onChange?: (value: string) => void 11 | } 12 | 13 | export const CornerInput: React.FC = (props) => { 14 | const prefix = usePrefix('corner-input') 15 | const [current, setCurrent] = useState(props.value) 16 | useEffect(() => { 17 | if (!props.value) { 18 | setCurrent('all') 19 | } 20 | }, [props.value]) 21 | const createCellProps = (type: string) => ({ 22 | className: cls(prefix + '-cell', { active: current === type }), 23 | onClick() { 24 | setCurrent(type) 25 | props.onChange?.(type) 26 | }, 27 | }) 28 | return ( 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/NumberPicker/preview.ts: -------------------------------------------------------------------------------- 1 | import { InputNumber as FormilyInputNumber } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | const NumberPicker: DnFC = 12 | composeExport(FormilyInputNumber, { 13 | Behavior: createBehavior({ 14 | name: 'InputNumber', 15 | extends: ['Field'], 16 | selector: (node) => node.props?.['x-component'] === 'InputNumber', 17 | designerProps: { 18 | propsSchema: createFieldSchema(AllSchemas.InputNumber), 19 | }, 20 | designerLocales: AllLocales.InputNumber, 21 | }), 22 | Resource: createResource({ 23 | icon: 'NumberPickerSource', 24 | elements: [ 25 | { 26 | componentName: 'Field', 27 | props: { 28 | type: 'number', 29 | title: 'InputNumber', 30 | 'x-decorator': 'FormItem', 31 | 'x-component': 'InputNumber', 32 | 'x-component-props': { 33 | 'controls-position': 'right', 34 | }, 35 | }, 36 | }, 37 | ], 38 | }), 39 | }) 40 | 41 | export const InputNumber = NumberPicker 42 | -------------------------------------------------------------------------------- /src/formDesigner/playground/prototypes/icons/recover.tsx: -------------------------------------------------------------------------------- 1 | export const Recover = ( 2 | 3 | ) 4 | -------------------------------------------------------------------------------- /src/formDesigner/playground/renderer/components/Checkbox/preview.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox as FormilyCheckbox } from '../../../components' 2 | import { composeExport } from '../../../components/__builtins__' 3 | import type { VueComponent } from '@formily/vue' 4 | import { createBehavior, createResource } from '@designable/core' 5 | import { DnFC } from '../../../prototypes' 6 | import { createFieldSchema } from '../Field' 7 | import { AllSchemas } from '../../schemas' 8 | import { AllLocales } from '../../locales' 9 | import { VNode } from 'vue' 10 | 11 | export const Checkbox: DnFC = 12 | composeExport(FormilyCheckbox, { 13 | Behavior: createBehavior({ 14 | name: 'Checkbox.Group', 15 | extends: ['Field'], 16 | selector: (node) => node.props?.['x-component'] === 'Checkbox.Group', 17 | designerProps: { 18 | propsSchema: createFieldSchema(AllSchemas.Checkbox.Group), 19 | }, 20 | designerLocales: AllLocales.CheckboxGroup, 21 | }), 22 | Resource: createResource({ 23 | icon: 'CheckboxGroupSource', 24 | elements: [ 25 | { 26 | componentName: 'Field', 27 | props: { 28 | type: 'array' || 'Array', 29 | title: 'Checkbox Group', 30 | 'x-decorator': 'FormItem', 31 | 'x-component': 'Checkbox.Group', 32 | enum: [ 33 | { label: '选项1', value: 1 }, 34 | { label: '选项2', value: 2 }, 35 | ], 36 | }, 37 | }, 38 | ], 39 | }), 40 | }) 41 | --------------------------------------------------------------------------------