diff --git a/apps/demo-free-layout/src/hooks/use-editor-props.tsx b/apps/demo-free-layout/src/hooks/use-editor-props.tsx index 9e322eab..79a4d02f 100644 --- a/apps/demo-free-layout/src/hooks/use-editor-props.tsx +++ b/apps/demo-free-layout/src/hooks/use-editor-props.tsx @@ -77,12 +77,12 @@ export function useEditorProps( return json; }, lineColor: { - hidden: 'var(--g-line-color-hidden,transparent)', - default: 'var(--g-line-color-default,#4d53e8)', - drawing: 'var(--g-line-color-drawing, #5DD6E3)', - hovered: 'var(--g-line-color-hover,#37d0ff)', - selected: 'var(--g-line-color-selected,#37d0ff)', - error: 'var(--g-line-color-hover,red)', + hidden: 'var(--g-workflow-line-color-hidden,transparent)', + default: 'var(--g-workflow-line-color-default,#4d53e8)', + drawing: 'var(--g-workflow-line-color-drawing, #5DD6E3)', + hovered: 'var(--g-workflow-line-color-hover,#37d0ff)', + selected: 'var(--g-workflow-line-color-selected,#37d0ff)', + error: 'var(--g-workflow-line-color-error,red)', }, /* * Check whether the line can be added diff --git a/apps/demo-free-layout/src/styles/index.css b/apps/demo-free-layout/src/styles/index.css index b5459edd..6f88e2ba 100644 --- a/apps/demo-free-layout/src/styles/index.css +++ b/apps/demo-free-layout/src/styles/index.css @@ -1,71 +1,80 @@ :root { - --g-workflow-port-color-primary: #4d53e8; - --g-workflow-port-color-secondary: #9197f1; - --g-workflow-port-color-error: #ff0000; - --g-workflow-port-color-background: #ffffff; + /* Port colors */ + --g-workflow-port-color-primary: #4d53e8; + --g-workflow-port-color-secondary: #9197f1; + --g-workflow-port-color-error: #ff0000; + --g-workflow-port-color-background: #ffffff; + + /* Line colors */ + --g-workflow-line-color-hidden: transparent; + --g-workflow-line-color-default: #4d53e8; + --g-workflow-line-color-drawing: #5dd6e3; + --g-workflow-line-color-hover: #37d0ff; + --g-workflow-line-color-selected: #37d0ff; + --g-workflow-line-color-error: red; } .gedit-selector-bounds-background { - cursor: move; - display: none !important; + cursor: move; + display: none !important; } .gedit-selector-bounds-foreground { - cursor: move; - position: absolute; - left: 0; - top: 0; - width: 0; - height: 0; - outline: 1px solid var(--g-playground-selectBox-outline); - z-index: 33; - background-color: var(--g-playground-selectBox-background); + cursor: move; + position: absolute; + left: 0; + top: 0; + width: 0; + height: 0; + outline: 1px solid var(--g-playground-selectBox-outline); + z-index: 33; + background-color: var(--g-playground-selectBox-background); } @keyframes blink { - 0% { - opacity: 1; - } - 50% { - opacity: 0; - } - 100% { - opacity: 1; - } + 0% { + opacity: 1; + } + 50% { + opacity: 0; + } + 100% { + opacity: 1; + } } .node-running { - border: 1px dashed rgb(78, 64, 229) !important; - border-radius: 8px; + border: 1px dashed rgb(78, 64, 229) !important; + border-radius: 8px; } .demo-editor { - flex-grow: 1; - position: relative; - height: 100%; + flex-grow: 1; + position: relative; + height: 100%; } .demo-container { - position: absolute; - left: 0px; - top: 0px; - display: flex; - width: 100%; - height: 100%; - flex-direction: column; + position: absolute; + left: 0px; + top: 0px; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; } .demo-tools { - padding: 10px; - display: flex; - justify-content: space-between; + padding: 10px; + display: flex; + justify-content: space-between; } .demo-tools-group > * { - margin-right: 8px; + margin-right: 8px; } .mouse-pad-option-icon { - display: flex; - justify-content: center; - align-items: center; + display: flex; + justify-content: center; + align-items: center; } diff --git a/apps/docs/src/en/api/components/workflow-node-renderer.mdx b/apps/docs/src/en/api/components/workflow-node-renderer.mdx index f07373de..7bc69010 100644 --- a/apps/docs/src/en/api/components/workflow-node-renderer.mdx +++ b/apps/docs/src/en/api/components/workflow-node-renderer.mdx @@ -17,7 +17,15 @@ export const BaseNode = () => { * https://github.com/bytedance/flowgram.ai/blob/main/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx */ return ( - + { // Form rendering through formMeta generation form?.render() diff --git a/apps/docs/src/en/guide/advanced/free-layout/port.mdx b/apps/docs/src/en/guide/advanced/free-layout/port.mdx index 488f4543..4887e38d 100644 --- a/apps/docs/src/en/guide/advanced/free-layout/port.mdx +++ b/apps/docs/src/en/guide/advanced/free-layout/port.mdx @@ -56,6 +56,15 @@ function BaseNode() { Ports are ultimately rendered through the `WorkflowPortRender` component, supporting custom styles, or businesses can reimplement this component based on the source code, see [Free Layout Best Practices - Node Rendering](https://github.com/bytedance/flowgram.ai/blob/main/apps/demo-free-layout/src/components/base-node/node-wrapper.tsx) +### Custom Port Colors + +You can customize port colors by passing color props to `WorkflowPortRender`: + +- `primaryColor` - Active state color (when linked or hovered) +- `secondaryColor` - Default state color +- `errorColor` - Error state color +- `backgroundColor` - Background color + ```tsx pure import { WorkflowPortRender, useNodeRender } from '@flowgram.ai/free-layout-editor'; @@ -67,7 +76,17 @@ function BaseNode() {
{ports.map((p) => ( - + ))} ) diff --git a/apps/docs/src/zh/api/components/workflow-node-renderer.mdx b/apps/docs/src/zh/api/components/workflow-node-renderer.mdx index 863ea96f..ebde029b 100644 --- a/apps/docs/src/zh/api/components/workflow-node-renderer.mdx +++ b/apps/docs/src/zh/api/components/workflow-node-renderer.mdx @@ -17,7 +17,15 @@ export const BaseNode = () => { * https://github.com/bytedance/flowgram.ai/blob/main/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx */ return ( - + { // 表单渲染通过 formMeta 生成 form?.render() diff --git a/apps/docs/src/zh/guide/advanced/free-layout/port.mdx b/apps/docs/src/zh/guide/advanced/free-layout/port.mdx index eb43ded2..e063a4f4 100644 --- a/apps/docs/src/zh/guide/advanced/free-layout/port.mdx +++ b/apps/docs/src/zh/guide/advanced/free-layout/port.mdx @@ -56,6 +56,15 @@ function BaseNode() { 端口最终通过 `WorkflowPortRender` 组件渲染,支持自定义 style, 或者业务基于源码重新实现该组件, 参考 [自由布局最佳实践 - 节点渲染](https://github.com/bytedance/flowgram.ai/blob/main/apps/demo-free-layout/src/components/base-node/node-wrapper.tsx) +### 自定义端口颜色 + +可以通过向 `WorkflowPortRender` 传递颜色 props 来自定义端口颜色: + +- `primaryColor` - 激活状态颜色(linked/hovered) +- `secondaryColor` - 默认状态颜色 +- `errorColor` - 错误状态颜色 +- `backgroundColor` - 背景颜色 + ```tsx pure import { WorkflowPortRender, useNodeRender } from '@flowgram.ai/free-layout-editor'; @@ -67,7 +76,17 @@ function BaseNode() {
{ports.map((p) => ( - + ))} ) diff --git a/packages/canvas-engine/free-layout-core/src/typings/workflow-line.ts b/packages/canvas-engine/free-layout-core/src/typings/workflow-line.ts index e784a2d3..092bf28e 100644 --- a/packages/canvas-engine/free-layout-core/src/typings/workflow-line.ts +++ b/packages/canvas-engine/free-layout-core/src/typings/workflow-line.ts @@ -24,12 +24,12 @@ export interface LineColor { } export enum LineColors { - HIDDEN = 'var(--g-line-color-hidden,transparent)', // 隐藏线条 - DEFUALT = 'var(--g-line-color-default,#4d53e8)', - DRAWING = 'var(--g-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1', - HOVER = 'var(--g-line-color-hover,#37d0ff)', - SELECTED = 'var(--g-line-color-selected,#37d0ff)', - ERROR = 'var(--g-line-color-error,red)', + HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条 + DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)', + DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1', + HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)', + SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)', + ERROR = 'var(--g-workflow-line-color-error,red)', } export interface WorkflowLineRenderContribution { diff --git a/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx b/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx index 454b9f8a..89c43444 100644 --- a/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx +++ b/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx @@ -19,6 +19,14 @@ export interface WorkflowNodeProps { port: WorkflowPortEntity, e: React.MouseEvent | React.MouseEventHandler ) => void; + /** 端口激活状态颜色 (linked/hovered) */ + portPrimaryColor?: string; + /** 端口默认状态颜色 */ + portSecondaryColor?: string; + /** 端口错误状态颜色 */ + portErrorColor?: string; + /** 端口背景颜色 */ + portBackgroundColor?: string; } export const WorkflowNodeRenderer: React.FC = (props) => { @@ -50,6 +58,10 @@ export const WorkflowNodeRenderer: React.FC = (props) => { onClick={props.onPortClick ? (e) => props.onPortClick!(p, e) : undefined} className={props.portClassName} style={props.portStyle} + primaryColor={props.portPrimaryColor} + secondaryColor={props.portSecondaryColor} + errorColor={props.portErrorColor} + backgroundColor={props.portBackgroundColor} /> ))} diff --git a/packages/plugins/free-lines-plugin/src/components/workflow-port-render/index.tsx b/packages/plugins/free-lines-plugin/src/components/workflow-port-render/index.tsx index c8f4ec49..933713ff 100644 --- a/packages/plugins/free-lines-plugin/src/components/workflow-port-render/index.tsx +++ b/packages/plugins/free-lines-plugin/src/components/workflow-port-render/index.tsx @@ -19,6 +19,14 @@ export interface WorkflowPortRenderProps { className?: string; style?: React.CSSProperties; onClick?: React.MouseEventHandler; + /** 激活状态颜色 (linked/hovered) */ + primaryColor?: string; + /** 默认状态颜色 */ + secondaryColor?: string; + /** 错误状态颜色 */ + errorColor?: string; + /** 背景颜色 */ + backgroundColor?: string; } export const WorkflowPortRender: React.FC = @@ -79,10 +87,30 @@ export const WorkflowPortRender: React.FC = // 有线条链接的时候深蓝色小圆点 linked, }); + + // 构建 CSS 自定义属性用于颜色覆盖 + const colorStyles: Record = {}; + if (props.primaryColor) { + colorStyles['--g-workflow-port-color-primary'] = props.primaryColor; + } + if (props.secondaryColor) { + colorStyles['--g-workflow-port-color-secondary'] = props.secondaryColor; + } + if (props.errorColor) { + colorStyles['--g-workflow-port-color-error'] = props.errorColor; + } + if (props.backgroundColor) { + colorStyles['--g-workflow-port-color-background'] = props.backgroundColor; + } + + const combinedStyle = targetElement + ? { ...props.style, ...colorStyles } + : { ...props.style, ...colorStyles, left: posX, top: posY }; + const content = (