ai-design-system 0.1.37 → 0.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/blocks/WorkflowCanvas/WorkflowCanvas.tsx +2 -10
- package/components/blocks/WorkflowCanvas/index.ts +1 -0
- package/components/blocks/WorkflowCanvas/layout-engine.ts +59 -0
- package/components/blocks/index.ts +1 -1
- package/components/composites/TriggerNode/TriggerNode.tsx +62 -0
- package/components/composites/TriggerNode/index.ts +2 -0
- package/components/composites/index.ts +4 -0
- package/components/index.ts +1 -0
- package/dist/index.cjs +85 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +29 -0
- package/dist/index.d.ts +42 -30
- package/dist/index.js +86 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -2,17 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ConnectionMode,
|
|
5
|
-
MiniMap,
|
|
6
5
|
ReactFlowProvider,
|
|
7
|
-
type Node,
|
|
8
|
-
type NodeChange,
|
|
9
|
-
type EdgeChange,
|
|
10
6
|
type Connection,
|
|
11
|
-
type OnConnectStartParams,
|
|
12
7
|
useReactFlow,
|
|
13
8
|
} from "@xyflow/react";
|
|
14
9
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
15
|
-
import type { ReactNode } from "react";
|
|
16
10
|
import { Canvas } from "@/components/ai-elements/canvas";
|
|
17
11
|
import { Connection as ConnectionLine } from "@/components/ai-elements/connection";
|
|
18
12
|
import { Controls } from "@/components/ai-elements/controls";
|
|
@@ -20,6 +14,7 @@ import { Edge } from "@/components/ai-elements/edge";
|
|
|
20
14
|
import { Panel } from "@/components/ai-elements/panel";
|
|
21
15
|
import { StateNode } from "@/components/composites/StateNode";
|
|
22
16
|
import { TransitionNode } from "@/components/composites/TransitionNode";
|
|
17
|
+
import { TriggerNode } from "@/components/composites/TriggerNode";
|
|
23
18
|
import type { WorkflowCanvasProps, WorkflowEdge } from "./interfaces";
|
|
24
19
|
import "@xyflow/react/dist/style.css";
|
|
25
20
|
|
|
@@ -32,6 +27,7 @@ const edgeTypes = {
|
|
|
32
27
|
const nodeTypes = {
|
|
33
28
|
state: StateNode,
|
|
34
29
|
transition: TransitionNode,
|
|
30
|
+
trigger: TriggerNode,
|
|
35
31
|
};
|
|
36
32
|
|
|
37
33
|
function WorkflowCanvasInner({
|
|
@@ -45,7 +41,6 @@ function WorkflowCanvasInner({
|
|
|
45
41
|
onPaneClick,
|
|
46
42
|
onNodeClick,
|
|
47
43
|
onEdgeClick,
|
|
48
|
-
showMinimap = false,
|
|
49
44
|
interactive = false,
|
|
50
45
|
topLeft,
|
|
51
46
|
topRight,
|
|
@@ -139,9 +134,6 @@ function WorkflowCanvasInner({
|
|
|
139
134
|
>
|
|
140
135
|
<Controls />
|
|
141
136
|
</Panel>
|
|
142
|
-
{showMinimap && (
|
|
143
|
-
<MiniMap bgColor="var(--sidebar)" nodeStrokeColor="var(--border)" />
|
|
144
|
-
)}
|
|
145
137
|
</Canvas>
|
|
146
138
|
</div>
|
|
147
139
|
);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import ELK from 'elkjs';
|
|
2
|
+
import type { WorkflowNode, WorkflowEdge } from './interfaces';
|
|
3
|
+
|
|
4
|
+
const NODE_WIDTH = 180;
|
|
5
|
+
const NODE_HEIGHT = 52;
|
|
6
|
+
|
|
7
|
+
const elk = new ELK();
|
|
8
|
+
|
|
9
|
+
export async function getLayoutedElements(
|
|
10
|
+
nodes: WorkflowNode[],
|
|
11
|
+
edges: WorkflowEdge[],
|
|
12
|
+
): Promise<{ nodes: WorkflowNode[]; edges: WorkflowEdge[] }> {
|
|
13
|
+
const graph = {
|
|
14
|
+
id: 'root',
|
|
15
|
+
layoutOptions: {
|
|
16
|
+
'elk.algorithm': 'layered',
|
|
17
|
+
'elk.direction': 'DOWN',
|
|
18
|
+
'elk.layered.spacing.nodeNodeBetweenLayers': '60',
|
|
19
|
+
'elk.spacing.nodeNode': '40',
|
|
20
|
+
'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',
|
|
21
|
+
'elk.layered.nodePlacement.bk.fixedAlignment': 'BALANCED',
|
|
22
|
+
'elk.layered.considerModelOrder': 'true',
|
|
23
|
+
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
|
24
|
+
},
|
|
25
|
+
children: nodes.map((n) => ({
|
|
26
|
+
id: n.id,
|
|
27
|
+
width: NODE_WIDTH,
|
|
28
|
+
height: NODE_HEIGHT,
|
|
29
|
+
})),
|
|
30
|
+
edges: edges.map((e) => {
|
|
31
|
+
return {
|
|
32
|
+
id: e.id,
|
|
33
|
+
sources: [e.source],
|
|
34
|
+
targets: [e.target],
|
|
35
|
+
};
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
+
const layout = await elk.layout(graph as any);
|
|
41
|
+
|
|
42
|
+
const layoutedNodes: WorkflowNode[] = nodes.map((n) => {
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
const elkNode = (layout.children ?? []).find((c: any) => c.id === n.id);
|
|
45
|
+
if (!elkNode || elkNode.x == null || elkNode.y == null) return n;
|
|
46
|
+
return {
|
|
47
|
+
...n,
|
|
48
|
+
position: { x: elkNode.x, y: elkNode.y },
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const layoutedEdges: WorkflowEdge[] = edges.map((e) => ({
|
|
53
|
+
...e,
|
|
54
|
+
sourceHandle: 'source-bottom',
|
|
55
|
+
targetHandle: 'target-top',
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
return { nodes: layoutedNodes, edges: layoutedEdges };
|
|
59
|
+
}
|
|
@@ -15,7 +15,7 @@ export * from './LayoutProvider'
|
|
|
15
15
|
export * from './SectionLayout'
|
|
16
16
|
export type { LayoutProviderProps } from './LayoutProvider'
|
|
17
17
|
|
|
18
|
-
export { WorkflowCanvas } from './WorkflowCanvas'
|
|
18
|
+
export { WorkflowCanvas, getLayoutedElements } from './WorkflowCanvas'
|
|
19
19
|
export type { WorkflowCanvasProps, WorkflowNode, WorkflowEdge, WorkflowNodeData } from './WorkflowCanvas'
|
|
20
20
|
|
|
21
21
|
export { DashboardHeader } from './DashboardHeader'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { NodeProps } from "@xyflow/react";
|
|
4
|
+
import { Play } from "lucide-react";
|
|
5
|
+
import { memo } from "react";
|
|
6
|
+
import {
|
|
7
|
+
Node,
|
|
8
|
+
NodeDescription,
|
|
9
|
+
NodeTitle,
|
|
10
|
+
} from "@/components/ai-elements/node";
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
|
|
13
|
+
export type TriggerNodeData = {
|
|
14
|
+
label: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
type: "trigger";
|
|
17
|
+
status?: "idle" | "running" | "success" | "error";
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type TriggerNodeProps = NodeProps & {
|
|
22
|
+
data?: TriggerNodeData;
|
|
23
|
+
id: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const TriggerNode = memo(({ data, selected, id }: TriggerNodeProps) => {
|
|
27
|
+
if (!data) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const displayTitle = data.label || "Trigger";
|
|
32
|
+
const displayDescription = data.description;
|
|
33
|
+
const status = data.status;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Node
|
|
37
|
+
className={cn(
|
|
38
|
+
"relative flex flex-col items-center justify-center bg-purple-50 dark:bg-purple-950/30 border border-purple-200 dark:border-purple-800 shadow-none transition-all duration-150 ease-out",
|
|
39
|
+
selected && "border-primary border-2"
|
|
40
|
+
)}
|
|
41
|
+
data-testid={`trigger-node-${id}`}
|
|
42
|
+
handles={{ target: false, source: true }}
|
|
43
|
+
status={status}
|
|
44
|
+
>
|
|
45
|
+
<div className="flex h-full w-full items-center justify-center gap-1.5 px-3 py-2">
|
|
46
|
+
<Play className="size-3 shrink-0 text-purple-600 dark:text-purple-400" strokeWidth={1.5} />
|
|
47
|
+
<div className="min-w-0 flex-1 text-center">
|
|
48
|
+
<NodeTitle className="line-clamp-2 text-center text-xs font-medium leading-tight" title={displayTitle}>
|
|
49
|
+
{displayTitle}
|
|
50
|
+
</NodeTitle>
|
|
51
|
+
{displayDescription && (
|
|
52
|
+
<NodeDescription className="mt-0.5 line-clamp-2 text-center text-[10px] leading-tight" title={displayDescription}>
|
|
53
|
+
{displayDescription}
|
|
54
|
+
</NodeDescription>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</Node>
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
TriggerNode.displayName = "TriggerNode";
|
|
@@ -130,6 +130,10 @@ export type { StateNodeData } from './StateNode'
|
|
|
130
130
|
export { TransitionNode } from './TransitionNode'
|
|
131
131
|
export type { TransitionNodeData } from './TransitionNode'
|
|
132
132
|
|
|
133
|
+
// TriggerNode Composite
|
|
134
|
+
export { TriggerNode } from './TriggerNode'
|
|
135
|
+
export type { TriggerNodeData } from './TriggerNode'
|
|
136
|
+
|
|
133
137
|
// WorkflowToolbar Composite
|
|
134
138
|
export { WorkflowToolbar, WorkflowToolbarActions } from './WorkflowToolbar'
|
|
135
139
|
export type { WorkflowToolbarProps, WorkflowToolbarActionsProps, WorkflowVersion, ToolbarAction } from './WorkflowToolbar'
|
package/components/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type * from './features';
|
|
|
9
9
|
|
|
10
10
|
// Composites (value exports not covered by export type *)
|
|
11
11
|
export { ModeSwitcher } from './composites';
|
|
12
|
+
export { getLayoutedElements } from './blocks';
|
|
12
13
|
|
|
13
14
|
// External library re-exports
|
|
14
15
|
export { ReactFlowProvider, applyNodeChanges, applyEdgeChanges, addEdge } from '@xyflow/react';
|
package/dist/index.cjs
CHANGED
|
@@ -48,6 +48,7 @@ var zod = require('zod');
|
|
|
48
48
|
var uiSchemaContracts = require('ui-schema-contracts');
|
|
49
49
|
var react = require('@xyflow/react');
|
|
50
50
|
require('@xyflow/react/dist/style.css');
|
|
51
|
+
var ELK = require('elkjs');
|
|
51
52
|
var form = require('design-schema/schemas/form');
|
|
52
53
|
|
|
53
54
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -92,6 +93,7 @@ var ProgressPrimitive__namespace = /*#__PURE__*/_interopNamespace(ProgressPrimit
|
|
|
92
93
|
var ToggleGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(ToggleGroupPrimitive);
|
|
93
94
|
var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
|
|
94
95
|
var Highlight__default = /*#__PURE__*/_interopDefault(Highlight);
|
|
96
|
+
var ELK__default = /*#__PURE__*/_interopDefault(ELK);
|
|
95
97
|
|
|
96
98
|
var __defProp = Object.defineProperty;
|
|
97
99
|
var __defProps = Object.defineProperties;
|
|
@@ -8370,6 +8372,34 @@ var TransitionNode = React3.memo(
|
|
|
8370
8372
|
}
|
|
8371
8373
|
);
|
|
8372
8374
|
TransitionNode.displayName = "TransitionNode";
|
|
8375
|
+
var TriggerNode = React3.memo(({ data, selected, id }) => {
|
|
8376
|
+
if (!data) {
|
|
8377
|
+
return null;
|
|
8378
|
+
}
|
|
8379
|
+
const displayTitle = data.label || "Trigger";
|
|
8380
|
+
const displayDescription = data.description;
|
|
8381
|
+
const status = data.status;
|
|
8382
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8383
|
+
Node2,
|
|
8384
|
+
{
|
|
8385
|
+
className: cn(
|
|
8386
|
+
"relative flex flex-col items-center justify-center bg-purple-50 dark:bg-purple-950/30 border border-purple-200 dark:border-purple-800 shadow-none transition-all duration-150 ease-out",
|
|
8387
|
+
selected && "border-primary border-2"
|
|
8388
|
+
),
|
|
8389
|
+
"data-testid": `trigger-node-${id}`,
|
|
8390
|
+
handles: { target: false, source: true },
|
|
8391
|
+
status,
|
|
8392
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full items-center justify-center gap-1.5 px-3 py-2", children: [
|
|
8393
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "size-3 shrink-0 text-purple-600 dark:text-purple-400", strokeWidth: 1.5 }),
|
|
8394
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 text-center", children: [
|
|
8395
|
+
/* @__PURE__ */ jsxRuntime.jsx(NodeTitle, { className: "line-clamp-2 text-center text-xs font-medium leading-tight", title: displayTitle, children: displayTitle }),
|
|
8396
|
+
displayDescription && /* @__PURE__ */ jsxRuntime.jsx(NodeDescription, { className: "mt-0.5 line-clamp-2 text-center text-[10px] leading-tight", title: displayDescription, children: displayDescription })
|
|
8397
|
+
] })
|
|
8398
|
+
] })
|
|
8399
|
+
}
|
|
8400
|
+
);
|
|
8401
|
+
});
|
|
8402
|
+
TriggerNode.displayName = "TriggerNode";
|
|
8373
8403
|
function WorkflowToolbarActions({
|
|
8374
8404
|
actionGroups = [],
|
|
8375
8405
|
className
|
|
@@ -9341,7 +9371,8 @@ var edgeTypes = {
|
|
|
9341
9371
|
};
|
|
9342
9372
|
var nodeTypes = {
|
|
9343
9373
|
state: StateNode,
|
|
9344
|
-
transition: TransitionNode
|
|
9374
|
+
transition: TransitionNode,
|
|
9375
|
+
trigger: TriggerNode
|
|
9345
9376
|
};
|
|
9346
9377
|
function WorkflowCanvasInner({
|
|
9347
9378
|
nodes,
|
|
@@ -9354,7 +9385,6 @@ function WorkflowCanvasInner({
|
|
|
9354
9385
|
onPaneClick,
|
|
9355
9386
|
onNodeClick,
|
|
9356
9387
|
onEdgeClick,
|
|
9357
|
-
showMinimap = false,
|
|
9358
9388
|
interactive = false,
|
|
9359
9389
|
topLeft,
|
|
9360
9390
|
topRight,
|
|
@@ -9447,8 +9477,7 @@ function WorkflowCanvasInner({
|
|
|
9447
9477
|
position: "bottom-left",
|
|
9448
9478
|
children: /* @__PURE__ */ jsxRuntime.jsx(Controls, {})
|
|
9449
9479
|
}
|
|
9450
|
-
)
|
|
9451
|
-
showMinimap && /* @__PURE__ */ jsxRuntime.jsx(react.MiniMap, { bgColor: "var(--sidebar)", nodeStrokeColor: "var(--border)" })
|
|
9480
|
+
)
|
|
9452
9481
|
]
|
|
9453
9482
|
}
|
|
9454
9483
|
)
|
|
@@ -9458,6 +9487,50 @@ function WorkflowCanvasInner({
|
|
|
9458
9487
|
function WorkflowCanvas(props) {
|
|
9459
9488
|
return /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowCanvasInner, __spreadValues({}, props)) });
|
|
9460
9489
|
}
|
|
9490
|
+
var NODE_WIDTH = 180;
|
|
9491
|
+
var NODE_HEIGHT = 52;
|
|
9492
|
+
var elk = new ELK__default.default();
|
|
9493
|
+
async function getLayoutedElements(nodes, edges) {
|
|
9494
|
+
const graph = {
|
|
9495
|
+
id: "root",
|
|
9496
|
+
layoutOptions: {
|
|
9497
|
+
"elk.algorithm": "layered",
|
|
9498
|
+
"elk.direction": "DOWN",
|
|
9499
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "60",
|
|
9500
|
+
"elk.spacing.nodeNode": "40",
|
|
9501
|
+
"elk.layered.nodePlacement.strategy": "BRANDES_KOEPF",
|
|
9502
|
+
"elk.layered.nodePlacement.bk.fixedAlignment": "BALANCED",
|
|
9503
|
+
"elk.layered.considerModelOrder": "true",
|
|
9504
|
+
"elk.hierarchyHandling": "INCLUDE_CHILDREN"
|
|
9505
|
+
},
|
|
9506
|
+
children: nodes.map((n) => ({
|
|
9507
|
+
id: n.id,
|
|
9508
|
+
width: NODE_WIDTH,
|
|
9509
|
+
height: NODE_HEIGHT
|
|
9510
|
+
})),
|
|
9511
|
+
edges: edges.map((e) => {
|
|
9512
|
+
return {
|
|
9513
|
+
id: e.id,
|
|
9514
|
+
sources: [e.source],
|
|
9515
|
+
targets: [e.target]
|
|
9516
|
+
};
|
|
9517
|
+
})
|
|
9518
|
+
};
|
|
9519
|
+
const layout = await elk.layout(graph);
|
|
9520
|
+
const layoutedNodes = nodes.map((n) => {
|
|
9521
|
+
var _a;
|
|
9522
|
+
const elkNode = ((_a = layout.children) != null ? _a : []).find((c) => c.id === n.id);
|
|
9523
|
+
if (!elkNode || elkNode.x == null || elkNode.y == null) return n;
|
|
9524
|
+
return __spreadProps(__spreadValues({}, n), {
|
|
9525
|
+
position: { x: elkNode.x, y: elkNode.y }
|
|
9526
|
+
});
|
|
9527
|
+
});
|
|
9528
|
+
const layoutedEdges = edges.map((e) => __spreadProps(__spreadValues({}, e), {
|
|
9529
|
+
sourceHandle: "source-bottom",
|
|
9530
|
+
targetHandle: "target-top"
|
|
9531
|
+
}));
|
|
9532
|
+
return { nodes: layoutedNodes, edges: layoutedEdges };
|
|
9533
|
+
}
|
|
9461
9534
|
function WorkflowBuilder({
|
|
9462
9535
|
workflowName,
|
|
9463
9536
|
versions,
|
|
@@ -10472,6 +10545,13 @@ var selectedWorkflowRunMock = {
|
|
|
10472
10545
|
suspensionReason: "-"
|
|
10473
10546
|
})
|
|
10474
10547
|
});
|
|
10548
|
+
var DashboardHeader = React3__namespace.memo(({ ctaLabel = "Quick Create" }) => {
|
|
10549
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10550
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button2, { variant: "outline", size: "sm", className: "hidden sm:flex", children: ctaLabel }),
|
|
10551
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: "GitHub" })
|
|
10552
|
+
] });
|
|
10553
|
+
});
|
|
10554
|
+
DashboardHeader.displayName = "DashboardHeader";
|
|
10475
10555
|
|
|
10476
10556
|
Object.defineProperty(exports, "ReactFlowProvider", {
|
|
10477
10557
|
enumerable: true,
|
|
@@ -10499,5 +10579,6 @@ exports.SpecNavigator = SpecNavigator;
|
|
|
10499
10579
|
exports.WorkflowBuilder = WorkflowBuilder;
|
|
10500
10580
|
exports.WorkflowObservabilityFeature = WorkflowObservabilityFeature;
|
|
10501
10581
|
exports.cn = cn;
|
|
10582
|
+
exports.getLayoutedElements = getLayoutedElements;
|
|
10502
10583
|
//# sourceMappingURL=index.cjs.map
|
|
10503
10584
|
//# sourceMappingURL=index.cjs.map
|