mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
feat: add customizable port colors to WorkflowPortRender (#360)
* feat(workflow-port): add customizable port colors * fix(workflow-colors): unify CSS variable naming to --g-workflow-* format - Update LineColors enum and demo configuration - Add CSS variable definitions - Ensure consistent naming across all workflow-related variables --------- Co-authored-by: husky-dot <xiaozhi@xiaozhideMacBook-Pro.local> Co-authored-by: husky-dot <xiaozhi@172-0-8-36.lightspeed.rcsntx.sbcglobal.net>
This commit is contained in:
parent
f994881b22
commit
a6d61d347e
@ -77,12 +77,12 @@ export function useEditorProps(
|
|||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
lineColor: {
|
lineColor: {
|
||||||
hidden: 'var(--g-line-color-hidden,transparent)',
|
hidden: 'var(--g-workflow-line-color-hidden,transparent)',
|
||||||
default: 'var(--g-line-color-default,#4d53e8)',
|
default: 'var(--g-workflow-line-color-default,#4d53e8)',
|
||||||
drawing: 'var(--g-line-color-drawing, #5DD6E3)',
|
drawing: 'var(--g-workflow-line-color-drawing, #5DD6E3)',
|
||||||
hovered: 'var(--g-line-color-hover,#37d0ff)',
|
hovered: 'var(--g-workflow-line-color-hover,#37d0ff)',
|
||||||
selected: 'var(--g-line-color-selected,#37d0ff)',
|
selected: 'var(--g-workflow-line-color-selected,#37d0ff)',
|
||||||
error: 'var(--g-line-color-hover,red)',
|
error: 'var(--g-workflow-line-color-error,red)',
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
* Check whether the line can be added
|
* Check whether the line can be added
|
||||||
|
|||||||
@ -1,8 +1,17 @@
|
|||||||
:root {
|
:root {
|
||||||
|
/* Port colors */
|
||||||
--g-workflow-port-color-primary: #4d53e8;
|
--g-workflow-port-color-primary: #4d53e8;
|
||||||
--g-workflow-port-color-secondary: #9197f1;
|
--g-workflow-port-color-secondary: #9197f1;
|
||||||
--g-workflow-port-color-error: #ff0000;
|
--g-workflow-port-color-error: #ff0000;
|
||||||
--g-workflow-port-color-background: #ffffff;
|
--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 {
|
.gedit-selector-bounds-background {
|
||||||
|
|||||||
@ -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
|
* https://github.com/bytedance/flowgram.ai/blob/main/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx
|
||||||
*/
|
*/
|
||||||
return (
|
return (
|
||||||
<WorkflowNodeRenderer className="demo-free-node" node={props.node}>
|
<WorkflowNodeRenderer
|
||||||
|
className="demo-free-node"
|
||||||
|
node={props.node}
|
||||||
|
// Optional port color customization
|
||||||
|
portPrimaryColor="#4d53e8" // Active state color (linked/hovered)
|
||||||
|
portSecondaryColor="#9197f1" // Default state color
|
||||||
|
portErrorColor="#ff4444" // Error state color
|
||||||
|
portBackgroundColor="#ffffff" // Background color
|
||||||
|
>
|
||||||
{
|
{
|
||||||
// Form rendering through formMeta generation
|
// Form rendering through formMeta generation
|
||||||
form?.render()
|
form?.render()
|
||||||
|
|||||||
@ -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)
|
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
|
```tsx pure
|
||||||
|
|
||||||
import { WorkflowPortRender, useNodeRender } from '@flowgram.ai/free-layout-editor';
|
import { WorkflowPortRender, useNodeRender } from '@flowgram.ai/free-layout-editor';
|
||||||
@ -67,7 +76,17 @@ function BaseNode() {
|
|||||||
<div data-port-id="condition-if-0" data-port-type="output"></div>
|
<div data-port-id="condition-if-0" data-port-type="output"></div>
|
||||||
<div data-port-id="condition-if-1" data-port-type="output"></div>
|
<div data-port-id="condition-if-1" data-port-type="output"></div>
|
||||||
{ports.map((p) => (
|
{ports.map((p) => (
|
||||||
<WorkflowPortRender key={p.id} entity={p} className="xxx" style={{ /* custom style */}}/>
|
<WorkflowPortRender
|
||||||
|
key={p.id}
|
||||||
|
entity={p}
|
||||||
|
className="xxx"
|
||||||
|
style={{ /* custom style */}}
|
||||||
|
// Custom port colors
|
||||||
|
primaryColor="#4d53e8" // Active state color (linked/hovered)
|
||||||
|
secondaryColor="#9197f1" // Default state color
|
||||||
|
errorColor="#ff4444" // Error state color
|
||||||
|
backgroundColor="#ffffff" // Background color
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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
|
* https://github.com/bytedance/flowgram.ai/blob/main/packages/client/free-layout-editor/src/components/workflow-node-renderer.tsx
|
||||||
*/
|
*/
|
||||||
return (
|
return (
|
||||||
<WorkflowNodeRenderer className="demo-free-node" node={props.node}>
|
<WorkflowNodeRenderer
|
||||||
|
className="demo-free-node"
|
||||||
|
node={props.node}
|
||||||
|
// 可选的端口颜色自定义
|
||||||
|
portPrimaryColor="#4d53e8" // 激活状态颜色 (linked/hovered)
|
||||||
|
portSecondaryColor="#9197f1" // 默认状态颜色
|
||||||
|
portErrorColor="#ff4444" // 错误状态颜色
|
||||||
|
portBackgroundColor="#ffffff" // 背景颜色
|
||||||
|
>
|
||||||
{
|
{
|
||||||
// 表单渲染通过 formMeta 生成
|
// 表单渲染通过 formMeta 生成
|
||||||
form?.render()
|
form?.render()
|
||||||
|
|||||||
@ -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` 组件渲染,支持自定义 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
|
```tsx pure
|
||||||
|
|
||||||
import { WorkflowPortRender, useNodeRender } from '@flowgram.ai/free-layout-editor';
|
import { WorkflowPortRender, useNodeRender } from '@flowgram.ai/free-layout-editor';
|
||||||
@ -67,7 +76,17 @@ function BaseNode() {
|
|||||||
<div data-port-id="condition-if-0" data-port-type="output"></div>
|
<div data-port-id="condition-if-0" data-port-type="output"></div>
|
||||||
<div data-port-id="condition-if-1" data-port-type="output"></div>
|
<div data-port-id="condition-if-1" data-port-type="output"></div>
|
||||||
{ports.map((p) => (
|
{ports.map((p) => (
|
||||||
<WorkflowPortRender key={p.id} entity={p} className="xxx" style={{ /* custom style */}}/>
|
<WorkflowPortRender
|
||||||
|
key={p.id}
|
||||||
|
entity={p}
|
||||||
|
className="xxx"
|
||||||
|
style={{ /* custom style */}}
|
||||||
|
// 自定义端口颜色
|
||||||
|
primaryColor="#4d53e8" // 激活状态颜色(linked/hovered)
|
||||||
|
secondaryColor="#9197f1" // 默认状态颜色
|
||||||
|
errorColor="#ff4444" // 错误状态颜色
|
||||||
|
backgroundColor="#ffffff" // 背景颜色
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -24,12 +24,12 @@ export interface LineColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum LineColors {
|
export enum LineColors {
|
||||||
HIDDEN = 'var(--g-line-color-hidden,transparent)', // 隐藏线条
|
HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条
|
||||||
DEFUALT = 'var(--g-line-color-default,#4d53e8)',
|
DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',
|
||||||
DRAWING = 'var(--g-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',
|
DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',
|
||||||
HOVER = 'var(--g-line-color-hover,#37d0ff)',
|
HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',
|
||||||
SELECTED = 'var(--g-line-color-selected,#37d0ff)',
|
SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',
|
||||||
ERROR = 'var(--g-line-color-error,red)',
|
ERROR = 'var(--g-workflow-line-color-error,red)',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkflowLineRenderContribution {
|
export interface WorkflowLineRenderContribution {
|
||||||
|
|||||||
@ -19,6 +19,14 @@ export interface WorkflowNodeProps {
|
|||||||
port: WorkflowPortEntity,
|
port: WorkflowPortEntity,
|
||||||
e: React.MouseEvent<HTMLDivElement> | React.MouseEventHandler<HTMLDivElement>
|
e: React.MouseEvent<HTMLDivElement> | React.MouseEventHandler<HTMLDivElement>
|
||||||
) => void;
|
) => void;
|
||||||
|
/** 端口激活状态颜色 (linked/hovered) */
|
||||||
|
portPrimaryColor?: string;
|
||||||
|
/** 端口默认状态颜色 */
|
||||||
|
portSecondaryColor?: string;
|
||||||
|
/** 端口错误状态颜色 */
|
||||||
|
portErrorColor?: string;
|
||||||
|
/** 端口背景颜色 */
|
||||||
|
portBackgroundColor?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WorkflowNodeRenderer: React.FC<WorkflowNodeProps> = (props) => {
|
export const WorkflowNodeRenderer: React.FC<WorkflowNodeProps> = (props) => {
|
||||||
@ -50,6 +58,10 @@ export const WorkflowNodeRenderer: React.FC<WorkflowNodeProps> = (props) => {
|
|||||||
onClick={props.onPortClick ? (e) => props.onPortClick!(p, e) : undefined}
|
onClick={props.onPortClick ? (e) => props.onPortClick!(p, e) : undefined}
|
||||||
className={props.portClassName}
|
className={props.portClassName}
|
||||||
style={props.portStyle}
|
style={props.portStyle}
|
||||||
|
primaryColor={props.portPrimaryColor}
|
||||||
|
secondaryColor={props.portSecondaryColor}
|
||||||
|
errorColor={props.portErrorColor}
|
||||||
|
backgroundColor={props.portBackgroundColor}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -19,6 +19,14 @@ export interface WorkflowPortRenderProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
/** 激活状态颜色 (linked/hovered) */
|
||||||
|
primaryColor?: string;
|
||||||
|
/** 默认状态颜色 */
|
||||||
|
secondaryColor?: string;
|
||||||
|
/** 错误状态颜色 */
|
||||||
|
errorColor?: string;
|
||||||
|
/** 背景颜色 */
|
||||||
|
backgroundColor?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =
|
export const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =
|
||||||
@ -79,10 +87,30 @@ export const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =
|
|||||||
// 有线条链接的时候深蓝色小圆点
|
// 有线条链接的时候深蓝色小圆点
|
||||||
linked,
|
linked,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 构建 CSS 自定义属性用于颜色覆盖
|
||||||
|
const colorStyles: Record<string, string> = {};
|
||||||
|
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 = (
|
const content = (
|
||||||
<WorkflowPointStyle
|
<WorkflowPointStyle
|
||||||
className={className}
|
className={className}
|
||||||
style={targetElement ? props.style : { ...props.style, left: posX, top: posY }}
|
style={combinedStyle}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
data-port-entity-id={entity.id}
|
data-port-entity-id={entity.id}
|
||||||
data-port-entity-type={entity.portType}
|
data-port-entity-type={entity.portType}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user