diff --git a/examples/form-designer-react/src/App.tsx b/examples/form-designer-react/src/App.tsx index 1ad9d4a..4aa9802 100644 --- a/examples/form-designer-react/src/App.tsx +++ b/examples/form-designer-react/src/App.tsx @@ -11,7 +11,7 @@ import { ViewportPanel, WorkspacePanel } from "@trionesdev/form-designer-react"; -import {Form, Input, Select} from "./components"; +import {Form, Input, Password, Select} from "./components"; import {AntdSettingsPanel} from "./AntdSettingsPanel"; import * as icons from "./Icons"; @@ -26,7 +26,7 @@ function App() { const value = { "x-id": "td_tXAABwaZAE", "type": "object", - "x-component-name":"Form", + "x-component-name": "Form", "properties": { "td_rszikvOzVh": { "type": "string", @@ -36,7 +36,7 @@ function App() { "x-component": "Input.TextArea", "x-id": "td_rszikvOzVh", "x-index": 0, - "x-component-name":"Field", + "x-component-name": "Field", }, "td_AaMFjiFfps": { "title": "性别", @@ -44,7 +44,7 @@ function App() { "x-component": "Select", "x-id": "td_AaMFjiFfps", "x-index": 1, - "x-component-name":"Field", + "x-component-name": "Field", } } } @@ -54,13 +54,12 @@ function App() { - + -
ssss
- - + +
diff --git a/examples/form-designer-react/src/Icons.tsx b/examples/form-designer-react/src/Icons.tsx index 52d10fc..6632d03 100644 --- a/examples/form-designer-react/src/Icons.tsx +++ b/examples/form-designer-react/src/Icons.tsx @@ -1,15 +1,74 @@ import React from "react"; -export const InputIcon = ( - - - - - - - - - -) \ No newline at end of file +export const InputIcon = ( + + + + +) + +export const TextAreaIcon = ( + + + + + +) + +export const SelectIcon = ( + + + + + +) + +export const PasswordIcon = ( + + + + + + + + + + +) \ No newline at end of file diff --git a/examples/form-designer-react/src/components/Input.tsx b/examples/form-designer-react/src/components/Input.tsx index a0ea418..f90a4ef 100644 --- a/examples/form-designer-react/src/components/Input.tsx +++ b/examples/form-designer-react/src/components/Input.tsx @@ -41,7 +41,7 @@ Input.Resource = createResource([ }, { name: 'Input.TextArea', - icon: 'InputIcon', + icon: 'TextAreaIcon', title: '多行输入框', componentName: 'Field', schema: { diff --git a/examples/form-designer-react/src/components/Password.tsx b/examples/form-designer-react/src/components/Password.tsx new file mode 100644 index 0000000..57b6504 --- /dev/null +++ b/examples/form-designer-react/src/components/Password.tsx @@ -0,0 +1,40 @@ +import {DesignerCore, TdFC} from "@trionesdev/form-designer-react"; +import {Password as FormilyPassword} from '@formily/antd-v5' +import createResource = DesignerCore.createResource; +import React from "react"; + +export const Password: TdFC> = + FormilyPassword + +Password.Resource = createResource([ + { + name: 'Password', + icon: 'PasswordIcon', + title: '密码输入', + componentName: 'Field', + schema: { + title: '密码输入', + 'x-decorator': 'FormItem', + 'x-component': 'Password', + }, + designerProps: { + propsSchema: { + type: 'object', + properties: { + title: { + type: 'string', + title: '标题', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + required: { + type: 'string', + title: '是否必填', + 'x-decorator': 'FormItem', + 'x-component': 'Switch', + }, + } + } + } + } +]) \ No newline at end of file diff --git a/examples/form-designer-react/src/components/Select.tsx b/examples/form-designer-react/src/components/Select.tsx index abf9eda..b144e67 100644 --- a/examples/form-designer-react/src/components/Select.tsx +++ b/examples/form-designer-react/src/components/Select.tsx @@ -8,10 +8,11 @@ export const Select: TdFC> = FormilyS Select.Resource = createResource([ { name: 'Select', - title: '选择', + icon:'SelectIcon', + title: '选择框', componentName: 'Field', schema: { - title: '性别', + title: '选择', 'x-decorator': 'FormItem', 'x-component': 'Select', }, @@ -19,12 +20,6 @@ Select.Resource = createResource([ propsSchema: { type: 'object', properties: { - name: { - type: 'string', - title: '字段标识', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, title: { type: 'string', title: '标题', diff --git a/examples/form-designer-react/src/components/index.ts b/examples/form-designer-react/src/components/index.ts index 62328af..3f89ea2 100644 --- a/examples/form-designer-react/src/components/index.ts +++ b/examples/form-designer-react/src/components/index.ts @@ -1,3 +1,4 @@ export * from "./Input" export * from "./Form" -export * from "./Select" \ No newline at end of file +export * from "./Select" +export * from "./Password" \ No newline at end of file diff --git a/packages/form-designer-react/src/Icon.tsx b/packages/form-designer-react/src/Icon.tsx index bcf0a8d..fcbc560 100644 --- a/packages/form-designer-react/src/Icon.tsx +++ b/packages/form-designer-react/src/Icon.tsx @@ -1,6 +1,24 @@ import React from "react"; +export const Up = ( + + + +) + +export const Down = ( + + + +) + export const MoveIcon: React.JSX.Element = ( diff --git a/packages/form-designer-react/src/container/Simulator.tsx b/packages/form-designer-react/src/container/Simulator.tsx index d62e96d..1be0d93 100644 --- a/packages/form-designer-react/src/container/Simulator.tsx +++ b/packages/form-designer-react/src/container/Simulator.tsx @@ -1,13 +1,19 @@ import React, {FC} from "react"; -import {PCSimulator} from "../simulator"; +import {MobileSimulator, PCSimulator} from "../simulator"; import {observer} from "@formily/react"; import {requestIdle} from "../request-idle"; +import {useFormDesigner} from "../hooks"; type SimulatorProps = { children: React.ReactNode; } export const Simulator: FC = observer(({children}) => { - return {children} + const {type} = useFormDesigner() + if (type == 'PC'){ + return {children} + }else if (type == 'MOBILE'){ + return {children} + } }, { scheduler: requestIdle }) \ No newline at end of file diff --git a/packages/form-designer-react/src/coordinate.ts b/packages/form-designer-react/src/coordinate.ts index a688af0..07775ef 100644 --- a/packages/form-designer-react/src/coordinate.ts +++ b/packages/form-designer-react/src/coordinate.ts @@ -146,12 +146,22 @@ export const transformToTreeNode = (data: any) => { children: [] } const schema = new Schema(data) + + const cleanProps = (props: any) => { + if (props['name'] === props['x-id']) { + delete props.name + } + delete props['version'] + delete props['_isJSONSchemaObject'] + return props + } + const appendTreeNode = (parent: ITreeNode, schema: Schema) => { if (!schema) return const current = { id: schema['x-id'], componentName: schema['x-component-name'], - schema: schema.toJSON(false), + schema: cleanProps(schema.toJSON(false)), //一定要cleanProps,否则无法修改属性 children: [], } parent.children.push(current) diff --git a/packages/form-designer-react/src/effect/dragDropEffect.tsx b/packages/form-designer-react/src/effect/dragDropEffect.tsx index 6d68b38..58bf2f2 100644 --- a/packages/form-designer-react/src/effect/dragDropEffect.tsx +++ b/packages/form-designer-react/src/effect/dragDropEffect.tsx @@ -49,6 +49,7 @@ export const dragMoveEffect = (e, operation: Operation) => { topClientY: e.clientY, } operation.cursor.setPosition() + operation.dragMove(position) const engine = operation.engine const target = e.target as HTMLElement const el = target?.closest(` @@ -58,7 +59,7 @@ export const dragMoveEffect = (e, operation: Operation) => { operation.cleanDraggingHover() return } - operation.dragMove(position) + operation.calcClosestPosition(new Point(e.clientX, e.clientX)) const nodeId = el.getAttribute(engine.nodeIdAttrName) if (nodeId) { @@ -73,13 +74,9 @@ export const dragEndEffect = (e: React.MouseEvent, operation: Operation) => { const closestNode = operation.closestNode const closestPosition = operation.closestPosition - console.log("dragEndEffect operation", operation, operation.draggingNode) + if (operation.draggingNode) { - console.log("dragEndEffect operation draggingNode", operation.draggingNode) - console.log("dragEndEffect operation closestNode", closestNode) - console.log("dragEndEffect operation closestPosition", closestPosition) - console.log("dragEndEffect operation draggingHoverNode", operation.draggingHoverNode) if (ClosestPosition.INNER === closestPosition) { closestNode.append(operation.draggingNode) } else if (ClosestPosition.BEFORE === closestPosition || ClosestPosition.UPPER === closestPosition) { diff --git a/packages/form-designer-react/src/event/event.tsx b/packages/form-designer-react/src/event/event.tsx index d080113..66106ca 100644 --- a/packages/form-designer-react/src/event/event.tsx +++ b/packages/form-designer-react/src/event/event.tsx @@ -60,7 +60,6 @@ export class EventManager { } onViewportScroll(e: React.UIEvent) { - console.log("onViewportScroll",e) ViewportEffect.viewportScrollEffect(e, this.operation) } diff --git a/packages/form-designer-react/src/hooks/useValidNodeOffsetRect.tsx b/packages/form-designer-react/src/hooks/useValidNodeOffsetRect.tsx index ad3fb5d..8ee84d0 100644 --- a/packages/form-designer-react/src/hooks/useValidNodeOffsetRect.tsx +++ b/packages/form-designer-react/src/hooks/useValidNodeOffsetRect.tsx @@ -21,7 +21,6 @@ export const useValidNodeOffsetRect = (node: TreeNode) => { }, [viewport, node]) useEffect(() => { - console.log("useValidNodeOffsetRect ", node,element) const layoutObserver = new LayoutObserver(compute) if (element) layoutObserver.observe(element) return () => { diff --git a/packages/form-designer-react/src/model/Operation.ts b/packages/form-designer-react/src/model/Operation.ts index c86bb39..3d9093a 100644 --- a/packages/form-designer-react/src/model/Operation.ts +++ b/packages/form-designer-react/src/model/Operation.ts @@ -1,6 +1,6 @@ import {TreeNode} from "./TreeNode"; import {FormDesignerEngine} from "./FormDesignerEngine"; -import {action, autorun, define, observable, observe} from "@formily/reactive"; +import {action, define, observable} from "@formily/reactive"; import {EventManager} from "../event/event"; import {Cursor, CursorStatus, ICursorPosition} from "./Cursor"; import {requestIdle} from "../request-idle"; @@ -75,14 +75,9 @@ export class Operation { onChange:action }) - autorun(() => { - console.log("[TreeInfo]", "sssssssssss") - }) - } onChange = (msg) => { - console.log("[TreeInfo]", "tree change sssse",msg, this.tree) this.engine.onChange?.(transformToSchema(this.tree)) } diff --git a/packages/form-designer-react/src/model/TreeNode.ts b/packages/form-designer-react/src/model/TreeNode.ts index 1753658..c069931 100644 --- a/packages/form-designer-react/src/model/TreeNode.ts +++ b/packages/form-designer-react/src/model/TreeNode.ts @@ -74,32 +74,9 @@ export class TreeNode { this.operation.onChange(`${this.id} children changed`) } }) - // - // reaction(() => { - // return JSON.stringify(this.schema) - // }, () => { - // console.log("treenode change", this.schema, this.children) - // }) - - observe(this.schema, (change) => { - if (!this.isSourceNode) { - this.operation.onChange(`${this.id} schema changed`) - } - }) - - // autorun(() => { - // console.log("[TreeInfo]", "tree changed") - // if (!this.isSourceNode){ - // this.operation.onChange() - // console.log("[TreeInfo] autorun", this.schema) - // } - // }) } - // get sourceComponent() { - // return this.operation?.engine?.findSourceComponent(_.get(this.schema, 'x-component', this.componentName)) - // } from(node?: ITreeNode) { if (!node) return diff --git a/packages/form-designer-react/src/model/Viewport.ts b/packages/form-designer-react/src/model/Viewport.ts index 092436c..3e5c74b 100644 --- a/packages/form-designer-react/src/model/Viewport.ts +++ b/packages/form-designer-react/src/model/Viewport.ts @@ -1,4 +1,4 @@ -import {define, observable} from "@formily/reactive"; +import {action, define, observable} from "@formily/reactive"; import {FormDesignerEngine} from "./FormDesignerEngine"; import {TreeNode} from "./TreeNode"; import _ from "lodash" @@ -8,6 +8,13 @@ interface IViewport { viewportElement: HTMLElement } +export interface IViewportData { + scrollX?: number + scrollY?: number + width?: number + height?: number +} + export class Viewport { engine: FormDesignerEngine; viewportElement: HTMLElement @@ -19,13 +26,18 @@ export class Viewport { constructor(args: IViewport) { this.engine = args.engine this.viewportElement = args.viewportElement - + this.digestViewport() this.makeObservable() } makeObservable() { define(this, { viewportElement: observable.ref, + scrollX: observable.ref, + scrollY: observable.ref, + width: observable.ref, + height: observable.ref, + digestViewport: action }) } @@ -48,19 +60,6 @@ export class Viewport { return new DOMRect(0, 0, rect?.width, rect?.height); } - // viewportNodeRect(nodeHtml: Element) { - // if (!nodeHtml) { - // return null - // } - // const viewportRect = this.viewportElement.getBoundingClientRect(); - // const nodeRect = nodeHtml.getBoundingClientRect() - // return new DOMRect( - // nodeRect.left - viewportRect.left, - // nodeRect.top - viewportRect.top, - // nodeRect.width, - // nodeRect.height - // ) - // } findElementById(id: string) { if (!id) { @@ -90,20 +89,17 @@ export class Viewport { const viewportRect = this.viewportElement.getBoundingClientRect(); const nodeRect = nodeHtml.getBoundingClientRect() - console.log(" Viewport viewportRect", viewportRect) - console.log("Viewport nodeRect", nodeRect) - console.log("Viewport vietport", this) if (this.isInPosition(nodeRect)) { return new DOMRect( - nodeRect.left - viewportRect.left + this.scrollX, - nodeRect.top - viewportRect.top + this.scrollY, + nodeRect.left - viewportRect.left + this.viewportElement.scrollLeft, + nodeRect.top - viewportRect.top + this.viewportElement.scrollTop, nodeRect.width, nodeRect.height ) } else { return new DOMRect( - nodeRect.left - viewportRect.left + this.scrollX, - nodeRect.top - viewportRect.top + this.scrollY, + nodeRect.left - viewportRect.left + this.viewportElement.scrollLeft, + nodeRect.top - viewportRect.top + this.viewportElement.scrollTop, nodeRect.width, nodeRect.height ) @@ -127,7 +123,8 @@ export class Viewport { if (!node) { return } - return this.getElementOffsetRectById(node.id) + const rect =this.getElementOffsetRectById(node.id) + return rect; } /** @@ -135,7 +132,7 @@ export class Viewport { */ digestViewport() { if (this.viewportElement) { - const data = { + const data:IViewportData = { scrollX: this.viewportElement.scrollLeft, scrollY: this.viewportElement.scrollTop, width: this.viewportElement.clientWidth, diff --git a/packages/form-designer-react/src/panel/SettingsPanel.tsx b/packages/form-designer-react/src/panel/SettingsPanel.tsx index db3091f..bcff8e6 100644 --- a/packages/form-designer-react/src/panel/SettingsPanel.tsx +++ b/packages/form-designer-react/src/panel/SettingsPanel.tsx @@ -50,7 +50,6 @@ export const SettingsPanel: React.FC = observer(({ const {selectionNode} = operation const form = useMemo(() => { - console.log("SettingsPanel selectionNode", selectionNode) return createForm({ initialValues: selectionNode?.designerProps?.defaultProps, values: selectionNode?.schema, diff --git a/packages/form-designer-react/src/panel/StudioPanel.tsx b/packages/form-designer-react/src/panel/StudioPanel.tsx index bdf00cf..f8b3b1f 100644 --- a/packages/form-designer-react/src/panel/StudioPanel.tsx +++ b/packages/form-designer-react/src/panel/StudioPanel.tsx @@ -1,4 +1,4 @@ -import React, {FC} from "react"; +import React, {CSSProperties, FC} from "react"; import styled from "@emotion/styled"; import {useOperation} from "../hooks"; import {css, Global} from "@emotion/react"; @@ -27,6 +27,7 @@ export const StudioPanel: FC = ({ }) => { const {eventManager} = useOperation() + return eventManager.onMouseDown(e)} diff --git a/packages/form-designer-react/src/panel/ViewPanel.tsx b/packages/form-designer-react/src/panel/ViewPanel.tsx index 7efced1..0643bc1 100644 --- a/packages/form-designer-react/src/panel/ViewPanel.tsx +++ b/packages/form-designer-react/src/panel/ViewPanel.tsx @@ -1,8 +1,8 @@ -import React, {FC, useEffect, useLayoutEffect, useMemo, useRef} from "react" -import {useFormDesigner, useOperation} from "../hooks"; +import React, {CSSProperties, FC, useEffect, useLayoutEffect, useMemo, useRef} from "react" +import {useCursor, useFormDesigner, useOperation} from "../hooks"; import styled from "@emotion/styled"; import {ViewportContext} from "../context"; -import {DesignerType, Viewport} from "../model"; +import {CursorStatus, DesignerType, Viewport} from "../model"; import {AuxToolsWidget} from "../widget"; import {MobileAuxToolsWidget} from "../widget/MobileAuxToolsWidget"; import {observer} from "@formily/react"; @@ -23,6 +23,16 @@ export const ViewPanel: FC = observer(({children, type}) => { const ref = useRef() const engine = useFormDesigner() const {eventManager} = useOperation() + const cursor = useCursor() + const handleStudioPanelStyles = (): CSSProperties => { + const baseStyle: CSSProperties = {} + if (cursor.status === CursorStatus.DRAGGING) { + baseStyle.cursor = 'move' + } else { + baseStyle.cursor = 'default' + } + return baseStyle + } const viewport = useMemo(() => { return new Viewport({ @@ -50,7 +60,7 @@ export const ViewPanel: FC = observer(({children, type}) => { return - eventManager.onMouseClick(e)} onScroll={(e) => eventManager.onViewportScroll(e)} onResize={(e) => eventManager.onViewportResize(e)} diff --git a/packages/form-designer-react/src/panel/ViewportPanel.tsx b/packages/form-designer-react/src/panel/ViewportPanel.tsx index 7dcf219..4fbde6c 100644 --- a/packages/form-designer-react/src/panel/ViewportPanel.tsx +++ b/packages/form-designer-react/src/panel/ViewportPanel.tsx @@ -1,7 +1,6 @@ import React, {FC} from "react" import styled from "@emotion/styled"; import {Simulator} from "../container"; -import {MobileSimulator} from "../simulator"; type ViewportPanelProps = { children?: React.ReactNode; @@ -24,7 +23,6 @@ const ViewportPanelStyled = styled('div')({ export const ViewportPanel: FC = ({children}) => { return - {/*{children}*/} - {children} + {children} } \ No newline at end of file diff --git a/packages/form-designer-react/src/simulator/MobileSimulator.tsx b/packages/form-designer-react/src/simulator/MobileSimulator.tsx index 0a2d224..ec63734 100644 --- a/packages/form-designer-react/src/simulator/MobileSimulator.tsx +++ b/packages/form-designer-react/src/simulator/MobileSimulator.tsx @@ -26,7 +26,8 @@ const MobileSimulatorStyled = styled('div')({ // backgroundColor:'#f2f4f5', '&-wrapper':{ border: '1px solid #f2f4f5', - height:'100%' + height:'100%', + borderRadius: '24px', } } } diff --git a/packages/form-designer-react/src/store.tsx b/packages/form-designer-react/src/store.tsx index f49c8e9..b703d68 100644 --- a/packages/form-designer-react/src/store.tsx +++ b/packages/form-designer-react/src/store.tsx @@ -20,14 +20,8 @@ export namespace GlobalStore { //endregion export function registerDesignerResources(components: Record>) { - // const resources = _.reduce(components, (result, component, ) => { - // result[key] = component - // return result - // }, {}) - // Object.assign(DESIGNER_RESOURCES_STORE, components) const componentArr = _.values(components) - console.log("Store componentArr", componentArr) const resources = _.reduce(componentArr, (result: any, item: TdFC) => { return _.concat(result, item.Resource) }, []) @@ -37,9 +31,7 @@ export namespace GlobalStore { }) }, {}) - console.log("Store ", resourcesMap) _.assign(DESIGNER_RESOURCES_STORE, resourcesMap) - console.log("Store DESIGNER_RESOURCES_STORE.value", DESIGNER_RESOURCES_STORE) } export function getDesignerResource(componentName: string) { diff --git a/packages/form-designer-react/src/widget/AuxToolsWidget/Insertion.tsx b/packages/form-designer-react/src/widget/AuxToolsWidget/Insertion.tsx index ba9ebc6..51f3cd1 100644 --- a/packages/form-designer-react/src/widget/AuxToolsWidget/Insertion.tsx +++ b/packages/form-designer-react/src/widget/AuxToolsWidget/Insertion.tsx @@ -1,12 +1,8 @@ import styled from "@emotion/styled"; -import React, {FC, useEffect, useRef} from "react"; +import React, {FC, useRef} from "react"; import {observer} from "@formily/react"; import {useOperation} from "../../hooks"; -import {useFormDesigner} from "../../hooks"; import {ClosestPosition} from "../../model"; -import _ from "lodash"; -import {TreeNode} from "../../model"; -import {useViewport} from "../../hooks"; const InsertionStyled = styled('div')({ position: 'absolute', @@ -18,122 +14,11 @@ type InsertionProps = {} export const Insertion: FC = observer(({}) => { const ref = useRef() - const {nodeIdAttrName} = useFormDesigner() const operation = useOperation() - const {dragging, draggingHoverNode, mouseEvent,closestNode,closestPosition,closestNodeRect} = operation - const viewport = useViewport() + const {dragging, draggingHoverNode, mouseEvent, closestNode, closestPosition, closestNodeRect} = operation - //计算鼠标与元素的距离 - // const handleComputePointDistance = (rect: DOMRect) => { - // if (mouseEvent.clientX <= rect.left && mouseEvent.clientY <= rect.top) { //鼠标在元素左上角 - // return Math.sqrt(Math.pow(rect.left - mouseEvent.clientX, 2) + Math.pow(rect.top - mouseEvent.clientY, 2)); - // } else if (mouseEvent.clientX <= rect.left && mouseEvent.clientY >= rect.bottom) { //鼠标在元素左下角 - // return Math.sqrt(Math.pow(rect.left - mouseEvent.clientX, 2) + Math.pow(mouseEvent.clientY - rect.bottom, 2)); - // } else if (mouseEvent.clientX >= rect.right && mouseEvent.clientY <= rect.top) {//鼠标在元素右上角 - // return Math.sqrt(Math.pow(mouseEvent.clientX - rect.right, 2) + Math.pow(rect.top - mouseEvent.clientY, 2)); - // } else if (mouseEvent.clientX >= rect.right && mouseEvent.clientY >= rect.bottom) {//鼠标在元素右上角 - // return Math.sqrt(Math.pow(mouseEvent.clientX - rect.right, 2) + Math.pow(mouseEvent.clientY - rect.bottom, 2)); - // } else if ((mouseEvent.clientX >= rect.left && mouseEvent.clientX <= rect.right) && mouseEvent.clientY <= rect.top) { //上方 - // return rect.top - mouseEvent.clientY; - // } else if ((mouseEvent.clientX >= rect.left && mouseEvent.clientX <= rect.right) && mouseEvent.clientY >= rect.bottom) { //下方 - // return mouseEvent.clientY - rect.bottom; - // } else if (mouseEvent.clientX <= rect.left && (mouseEvent.clientY >= rect.top && mouseEvent.clientY <= rect.bottom)) { //左边 - // return rect.left - mouseEvent.clientX; - // } else if (mouseEvent.clientX >= rect.right && (mouseEvent.clientY >= rect.top && mouseEvent.clientY <= rect.bottom)) { //右边 - // return mouseEvent.clientX - rect.right; - // } else { - // return 0; - // } - // } - // - // const handleClosestNode = () => { - // - // if (draggingHoverNode?.droppable) { //当前是可拖入节点 - // if (_.isEmpty(draggingHoverNode.children)) { - // return draggingHoverNode; - // } else { - // let minDistance = Number.MAX_VALUE; - // let closestElement = draggingHoverNode; - // _.forEach(draggingHoverNode.children, (node: TreeNode) => { - // const rect = viewport.getValidNodeOffsetRect(node) - // const distance = handleComputePointDistance(rect) - // - // if (distance < minDistance) { - // minDistance = distance - // closestElement = node - // } - // }) - // return closestElement - // } - // } else { - // return draggingHoverNode; - // } - // } - // - // const handleClosestPosition = (closestNode: TreeNode) => { - // if (closestNode?.droppable) { - // return ClosestPosition.INNER - // } - // const closestRect = viewport.getValidNodeOffsetRect(closestNode) - // const point = { - // x: mouseEvent.clientX, - // y: mouseEvent.clientY - // } - // console.log("Insertion",closestRect) - // console.log("Insertion",point) - // const rectCenter = { - // x: closestRect.left + closestRect.width / 2, - // y: closestRect.top + closestRect.height / 2, - // } - // if (closestNode.layout == 'vertical') { - // if (point.y <= rectCenter.y) { - // return ClosestPosition.BEFORE - // } else { - // return ClosestPosition.AFTER - // } - // } else { - // { - // if (point.x <= rectCenter.x) { - // return ClosestPosition.BEFORE - // } else { - // return ClosestPosition.AFTER - // } - // } - // } - // } - // - // useEffect(() => { - // if (!dragging || !draggingHoverNode || !ref.current) { - // return - // } - // - // let closestNode = handleClosestNode() - // console.log("closestNode", closestNode) - // if (closestNode) { - // operation.closestNode = closestNode - // let closestPosition = handleClosestPosition(closestNode) - // operation.closestPosition = closestPosition - // const closestRect = viewport.getValidNodeOffsetRect(closestNode) - // if (closestPosition == ClosestPosition.BEFORE) { - // ref.current.style.height = `2px` - // ref.current.style.width = `${closestRect.width}px` - // ref.current.style.backgroundColor = `#1890FF` - // ref.current.style.transform = `perspective(1px) translate3d(0px, ${closestRect.top}px, 0px)` - // } else if (closestPosition == ClosestPosition.AFTER) { - // ref.current.style.height = `2px` - // ref.current.style.width = `${closestRect.width}px` - // ref.current.style.backgroundColor = `#1890FF` - // ref.current.style.transform = `perspective(1px) translate3d(0px, ${closestRect.top + closestRect.height}px, 0px)` - // } - // } - // }, [dragging, draggingHoverNode, mouseEvent]); - - const handleInsertionStyles = ():React.CSSProperties => { - const baseStyle: React.CSSProperties = { - } - console.log("Insertion closestNode", closestNode) - console.log("Insertion closestNodeRect", closestNodeRect) - console.log("Insertion closestPosition", closestPosition) + const handleInsertionStyles = (): React.CSSProperties => { + const baseStyle: React.CSSProperties = {} if (closestNode) { diff --git a/packages/form-designer-react/src/widget/AuxToolsWidget/Selection.tsx b/packages/form-designer-react/src/widget/AuxToolsWidget/Selection.tsx index bffb33c..b11135d 100644 --- a/packages/form-designer-react/src/widget/AuxToolsWidget/Selection.tsx +++ b/packages/form-designer-react/src/widget/AuxToolsWidget/Selection.tsx @@ -1,7 +1,7 @@ -import React, {CSSProperties, FC, useEffect} from "react" +import React, {CSSProperties, FC} from "react" import styled from "@emotion/styled"; import {DragHandler} from "./DragHandler"; -import {useFormDesigner, useOperation, useValidNodeOffsetRect, useViewport} from "../../hooks"; +import {useOperation, useValidNodeOffsetRect} from "../../hooks"; import {observer} from "@formily/react"; import {DeleteIcon} from "../../Icon"; import {CursorStatus, TreeNode} from "../../model"; @@ -43,15 +43,10 @@ type SelectionBoxProps = { export const SelectionBox: FC = ({ node }) => { - const {nodeIdAttrName} = useFormDesigner() const operation = useOperation() const {dragging, selectionNode} = operation - console.log("mouseClickEffect operation SelectionBox selectionNode box", selectionNode) - const viewport = useViewport() - // const selectionNodeEl = document.querySelector(`*[${nodeIdAttrName}=${node?.id}]`) - // console.log("mouseClickEffect operation SelectionBox selectionNodeEl", selectionNodeEl) + const rect = useValidNodeOffsetRect(selectionNode) - console.log("mouseClickEffect operation SelectionBox rect", rect) const handleBoxStyles = () => { const boxStyles: CSSProperties = { @@ -109,10 +104,8 @@ export const SelectionBox: FC = ({ export const Selection = observer(() => { const operation = useOperation() const {selectionNode, tree, cursor} = operation - console.log("mouseClickEffect operation Selection selectionNode", selectionNode) - console.log("mouseClickEffect operation Selection cursor.status", cursor.status) - if (cursor.status != CursorStatus.NORMAL) { + if (cursor.status != CursorStatus.NORMAL) { //如果拖拽状态未释放,则不进行渲染 return null } diff --git a/packages/form-designer-react/src/widget/ComponentsWidget/TreeNodeWidget.tsx b/packages/form-designer-react/src/widget/ComponentsWidget/TreeNodeWidget.tsx index 08c9ada..87dd095 100644 --- a/packages/form-designer-react/src/widget/ComponentsWidget/TreeNodeWidget.tsx +++ b/packages/form-designer-react/src/widget/ComponentsWidget/TreeNodeWidget.tsx @@ -1,10 +1,9 @@ -import React, {FC, useEffect} from "react" +import React, {FC} from "react" import {observer} from "@formily/react"; import {TreeNode} from "../../model"; import {useFormDesigner} from "../../hooks"; import {TreeNodeContext} from "../../context"; import {useComponents} from "../../hooks"; -import {autorun, reaction} from "@formily/reactive"; type ComponentWidgetProps = { treeNode: TreeNode; @@ -43,21 +42,5 @@ export const TreeNodeWidget: FC = observer(({treeNode}) => } - useEffect(() => { - autorun(() => { - console.log("[Reactive listiner]") - }) - }, []); - - reaction(() => { - return [treeNode.schema,treeNode.children] - }, ()=>{ - console.log("[Reactive listiner reaction]") - }) - - useEffect(() => { - console.log("[Reactive listiner useEffect]") - }, [treeNode.schema,treeNode.children]); - return {handleRender()} }) \ No newline at end of file diff --git a/packages/form-designer-react/src/widget/ComponentsWidget/index.tsx b/packages/form-designer-react/src/widget/ComponentsWidget/index.tsx index 54db0e3..5de13af 100644 --- a/packages/form-designer-react/src/widget/ComponentsWidget/index.tsx +++ b/packages/form-designer-react/src/widget/ComponentsWidget/index.tsx @@ -2,8 +2,7 @@ import React, {FC, useEffect} from "react" import {TreeNodeWidget} from "./TreeNodeWidget"; import {observer} from "@formily/react"; import {IComponents} from "../../types"; -import {useFormDesigner} from "../../hooks"; -import {useTree} from "../../hooks"; +import {useFormDesigner, useTree} from "../../hooks"; import _ from "lodash"; import {Field} from "../Field"; import {GlobalStore} from "../../store"; @@ -27,9 +26,6 @@ export const ComponentsWidget: FC = observer(({children, dataId[nodeIdAttrName] = tree.id } - useEffect(() => { - console.log("treeNode {}", tree) - }, [tree]) const componentsMap = _.assign({Field}, components) useEffect(() => { diff --git a/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Insertion.tsx b/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Insertion.tsx index a9da976..0537ea9 100644 --- a/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Insertion.tsx +++ b/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Insertion.tsx @@ -22,9 +22,6 @@ export const Insertion: FC = observer(({}) => { const handleInsertionStyles = (): React.CSSProperties => { const baseStyle: React.CSSProperties = {} - console.log("Insertion closestNode", closestNode) - console.log("Insertion closestNodeRect", closestNodeRect) - console.log("Insertion closestPosition", closestPosition) if (closestNode) { diff --git a/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Selection.tsx b/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Selection.tsx index 154be41..21cdc2d 100644 --- a/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Selection.tsx +++ b/packages/form-designer-react/src/widget/MobileAuxToolsWidget/Selection.tsx @@ -42,9 +42,8 @@ export const SelectionBox: FC = ({ node }) => { const operation = useOperation() - const {dragging, selectionNode} = operation + const {dragging, selectionNode,viewport} = operation const rect = useValidNodeOffsetRect(selectionNode) - const handleBoxStyles = () => { const boxStyles: CSSProperties = { borderLeft: `2px solid #1890FF`, diff --git a/packages/form-designer-react/src/widget/ResourceWidget/SourceWidget.tsx b/packages/form-designer-react/src/widget/ResourceWidget/SourceWidget.tsx index d2e67c1..19c4ce1 100644 --- a/packages/form-designer-react/src/widget/ResourceWidget/SourceWidget.tsx +++ b/packages/form-designer-react/src/widget/ResourceWidget/SourceWidget.tsx @@ -10,7 +10,7 @@ import {DesignerComponent} from "../../types"; const SourceItemStyled = styled('div')({ gridColumnStart: 'span 1', userSelect: 'none', - cursor: 'move', + cursor: 'grab', padding: '6px 16px', display: 'flex', alignItems: 'center', diff --git a/packages/form-designer-react/src/widget/ResourceWidget/index.tsx b/packages/form-designer-react/src/widget/ResourceWidget/index.tsx index 15c15f2..259b46c 100644 --- a/packages/form-designer-react/src/widget/ResourceWidget/index.tsx +++ b/packages/form-designer-react/src/widget/ResourceWidget/index.tsx @@ -1,38 +1,70 @@ -import React, {FC} from "react"; +import React, {FC, useState} from "react"; import _ from "lodash"; import styled from "@emotion/styled"; import {DesignerComponent} from "../../types"; import {SourceWidget} from "./SourceWidget"; import {Row, Col} from "../Row"; +import {Down, Up} from "../../Icon"; +import classNames from "classnames"; const ResourceWidgetStyled = styled('div')({ + '.td-resource-header': { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '8px', + '.action': { + cursor: 'pointer', + '.icon': { + width: '1em', + height: '1em', + } + } + }, '.td-resource-content': { padding: '4px', + visibility: 'hidden', '&-inner': { display: 'grid', gridTemplateColumns: 'repeat(2, 50%)', gap: '4px', + }, + '&.open': { + visibility: 'visible' } - } + }, + }) type ResourceWidgetProps = { + title?: React.ReactNode, sources?: DesignerComponent[] } -export const ResourceWidget: FC = ({sources}) => { +export const ResourceWidget: FC = ({ + title, + sources + }) => { + const [open, setOpen] = useState(true) const scopeSources = _.reduce(sources, (result: any, source: any) => { return _.concat(result, source.Resource) }, []) return -
+
+
{title}
+
setOpen(!open)}> + {React.cloneElement(open ? Down : Up)} +
+
+
{ - scopeSources.map((source: any) => ) + scopeSources.map((source: any) => ) }
diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..bc5e92d --- /dev/null +++ b/readme.md @@ -0,0 +1,12 @@ +### 表单设计器 + +Triones from designer 是一款表单设计器,支持PC端和移动端。当前有react版本,后续会开发vue版本 + +### 说明 +项目设计思路,大量借鉴了 [designable](https://github.com/alibaba/designable) ,另外由于designable已经不再维护, +我们提供了支持antd v5的designable修复版本 [triones-designable](https://github.com/trionesdev/triones-designable) + +### 特性 +- 基于formilyjs 表单解决方案 [formilyjs](https://formilyjs.org/zh-CN) +- 支持基于formilyjs 封装的各种组件库 +