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;
|
||||
},
|
||||
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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 (
|
||||
<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?.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)
|
||||
|
||||
### 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() {
|
||||
<div data-port-id="condition-if-0" data-port-type="output"></div>
|
||||
<div data-port-id="condition-if-1" data-port-type="output"></div>
|
||||
{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>
|
||||
)
|
||||
|
||||
@ -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 (
|
||||
<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 生成
|
||||
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` 传递颜色 props 来自定义端口颜色:
|
||||
|
||||
- `primaryColor` - 激活状态颜色(linked/hovered)
|
||||
- `secondaryColor` - 默认状态颜色
|
||||
- `errorColor` - 错误状态颜色
|
||||
- `backgroundColor` - 背景颜色
|
||||
|
||||
```tsx pure
|
||||
|
||||
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-1" data-port-type="output"></div>
|
||||
{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>
|
||||
)
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -19,6 +19,14 @@ export interface WorkflowNodeProps {
|
||||
port: WorkflowPortEntity,
|
||||
e: React.MouseEvent<HTMLDivElement> | React.MouseEventHandler<HTMLDivElement>
|
||||
) => void;
|
||||
/** 端口激活状态颜色 (linked/hovered) */
|
||||
portPrimaryColor?: string;
|
||||
/** 端口默认状态颜色 */
|
||||
portSecondaryColor?: string;
|
||||
/** 端口错误状态颜色 */
|
||||
portErrorColor?: string;
|
||||
/** 端口背景颜色 */
|
||||
portBackgroundColor?: string;
|
||||
}
|
||||
|
||||
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}
|
||||
className={props.portClassName}
|
||||
style={props.portStyle}
|
||||
primaryColor={props.portPrimaryColor}
|
||||
secondaryColor={props.portSecondaryColor}
|
||||
errorColor={props.portErrorColor}
|
||||
backgroundColor={props.portBackgroundColor}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
|
||||
@ -19,6 +19,14 @@ export interface WorkflowPortRenderProps {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||
/** 激活状态颜色 (linked/hovered) */
|
||||
primaryColor?: string;
|
||||
/** 默认状态颜色 */
|
||||
secondaryColor?: string;
|
||||
/** 错误状态颜色 */
|
||||
errorColor?: string;
|
||||
/** 背景颜色 */
|
||||
backgroundColor?: string;
|
||||
}
|
||||
|
||||
export const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =
|
||||
@ -79,10 +87,30 @@ export const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =
|
||||
// 有线条链接的时候深蓝色小圆点
|
||||
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 = (
|
||||
<WorkflowPointStyle
|
||||
className={className}
|
||||
style={targetElement ? props.style : { ...props.style, left: posX, top: posY }}
|
||||
style={combinedStyle}
|
||||
onClick={onClick}
|
||||
data-port-entity-id={entity.id}
|
||||
data-port-entity-type={entity.portType}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user