@cyoda/workflow-viewer 0.1.0
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/LICENSE +201 -0
- package/README.md +26 -0
- package/dist/index.cjs +941 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +57 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +913 -0
- package/dist/index.js.map +1 -0
- package/dist/theme/index.cjs +213 -0
- package/dist/theme/index.cjs.map +1 -0
- package/dist/theme/index.d.cts +176 -0
- package/dist/theme/index.d.ts +176 -0
- package/dist/theme/index.js +178 -0
- package/dist/theme/index.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/WorkflowViewer.tsx","../src/theme/tokens.ts","../src/layout.ts","../src/hooks/usePanZoom.ts","../src/theme/lane.ts","../src/components/EdgePath.tsx","../src/components/Defs.tsx","../src/components/StartMarker.tsx","../src/theme/role-label.ts","../src/theme/node-palette.ts","../src/theme/badges.ts","../src/components/StateNode.tsx","../src/components/EdgeLabel.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport type {\n GraphDocument,\n GraphEdge,\n GraphNode,\n StateNode,\n TransitionEdge,\n} from \"@cyoda/workflow-graph\";\nimport { simpleLayout, type LayoutResult, type NodePosition } from \"../layout.js\";\nimport { usePanZoom } from \"../hooks/usePanZoom.js\";\nimport { Defs } from \"./Defs.js\";\nimport { StartMarker } from \"./StartMarker.js\";\nimport { StateNodeView } from \"./StateNode.js\";\nimport { EdgePath, computeEdgeGeometry } from \"./EdgePath.js\";\nimport { EdgeLabel } from \"./EdgeLabel.js\";\nimport { workflowPalette } from \"../theme/tokens.js\";\n\nexport interface WorkflowViewerProps {\n graph: GraphDocument;\n /** Optional pre-computed layout (e.g. from @cyoda/workflow-layout). */\n layout?: LayoutResult;\n width?: number | string;\n height?: number | string;\n selectedId?: string;\n onSelectionChange?: (id: string | null) => void;\n className?: string;\n}\n\n/**\n * Slim read-only SVG renderer. Renders workflow state nodes, transitions,\n * and edge-label chips using the theme tokens. No editing affordances.\n */\nexport function WorkflowViewer({\n graph,\n layout,\n width = \"100%\",\n height = \"100%\",\n selectedId,\n onSelectionChange,\n className,\n}: WorkflowViewerProps) {\n const effectiveLayout = useMemo(\n () => layout ?? simpleLayout(graph),\n [graph, layout],\n );\n const pan = usePanZoom();\n const [internalSelection, setInternalSelection] = useState<string | null>(null);\n const [hovered, setHovered] = useState<string | null>(null);\n const selection = selectedId ?? internalSelection;\n\n const stateNodes = useMemo(\n () => graph.nodes.filter((n): n is StateNode => n.kind === \"state\"),\n [graph.nodes],\n );\n const stateById = useMemo(() => {\n const m = new Map<string, StateNode>();\n for (const n of stateNodes) m.set(n.id, n);\n return m;\n }, [stateNodes]);\n\n const transitionEdges = useMemo(\n () => graph.edges.filter((e): e is TransitionEdge => e.kind === \"transition\"),\n [graph.edges],\n );\n\n const highlightSet = useMemo(\n () => computeHighlightSet(hovered ?? selection, graph.nodes, graph.edges),\n [hovered, selection, graph.nodes, graph.edges],\n );\n\n const anythingFocused = highlightSet !== null;\n\n const handleSelect = (id: string) => {\n setInternalSelection(id);\n onSelectionChange?.(id);\n };\n\n const handleBackgroundClick = () => {\n setInternalSelection(null);\n onSelectionChange?.(null);\n };\n\n return (\n <svg\n width={width}\n height={height}\n viewBox={`0 0 ${effectiveLayout.width} ${effectiveLayout.height}`}\n preserveAspectRatio=\"xMidYMid meet\"\n onClick={handleBackgroundClick}\n onWheel={pan.onWheel}\n onMouseDown={pan.onMouseDown}\n onMouseMove={pan.onMouseMove}\n onMouseUp={pan.onMouseUp}\n onMouseLeave={pan.onMouseUp}\n className={className}\n style={{\n background: workflowPalette.neutrals.white,\n fontFamily: \"inherit\",\n userSelect: \"none\",\n }}\n data-testid=\"workflow-viewer\"\n >\n <Defs />\n <g\n transform={`translate(${pan.transform.x}, ${pan.transform.y}) scale(${pan.transform.scale})`}\n >\n {/* Edges first so they render behind nodes. */}\n {transitionEdges.map((edge) => {\n const source = effectiveLayout.positions.get(edge.sourceId);\n const target = effectiveLayout.positions.get(edge.targetId);\n if (!source || !target) return null;\n const targetNode = stateById.get(edge.targetId);\n const route = effectiveLayout.edges?.get(edge.id);\n const isEdgeSelected = selection === edge.id;\n const isHighlighted = highlightSet?.has(edge.id) ?? false;\n const isDimmed = anythingFocused && !isHighlighted;\n return (\n <EdgePath\n key={edge.id}\n edge={edge}\n source={source}\n target={target}\n route={route}\n targetIsTerminal={\n targetNode?.role === \"terminal\" ||\n targetNode?.role === \"initial-terminal\"\n }\n highlighted={isHighlighted}\n dimmed={isDimmed}\n selected={isEdgeSelected}\n onSelect={handleSelect}\n onHoverEnter={setHovered}\n onHoverLeave={() => setHovered(null)}\n />\n );\n })}\n\n {/* Edge labels on top of edges. */}\n {transitionEdges.map((edge) => {\n const source = effectiveLayout.positions.get(edge.sourceId);\n const target = effectiveLayout.positions.get(edge.targetId);\n if (!source || !target) return null;\n const route = effectiveLayout.edges?.get(edge.id);\n const labelPos = route\n ? { midX: route.labelX, midY: route.labelY }\n : computeEdgeGeometry(edge, source, target);\n const isHighlighted = highlightSet?.has(edge.id) ?? false;\n const isDimmed = anythingFocused && !isHighlighted;\n return (\n <EdgeLabel\n key={`label-${edge.id}`}\n edge={edge}\n x={labelPos.midX}\n y={labelPos.midY}\n width={route?.labelWidth}\n height={route?.labelHeight}\n dimmed={isDimmed}\n />\n );\n })}\n\n {/* Nodes on top. */}\n {graph.nodes.map((node) => renderNode(node, effectiveLayout, {\n selection,\n highlightSet,\n anythingFocused,\n onSelect: handleSelect,\n onHoverEnter: setHovered,\n onHoverLeave: () => setHovered(null),\n }))}\n </g>\n </svg>\n );\n}\n\ninterface RenderCtx {\n selection: string | null;\n highlightSet: Set<string> | null;\n anythingFocused: boolean;\n onSelect: (id: string) => void;\n onHoverEnter: (id: string) => void;\n onHoverLeave: () => void;\n}\n\nfunction renderNode(\n node: GraphNode,\n layout: LayoutResult,\n ctx: RenderCtx,\n) {\n const pos = layout.positions.get(node.id);\n if (!pos) return null;\n if (node.kind === \"startMarker\") {\n return <StartMarker key={node.id} position={smallPositionForMarker(pos)} />;\n }\n const isHighlighted = ctx.highlightSet?.has(node.id) ?? false;\n const isDimmed = ctx.anythingFocused && !isHighlighted;\n return (\n <StateNodeView\n key={node.id}\n node={node}\n position={pos}\n selected={ctx.selection === node.id}\n highlighted={isHighlighted}\n dimmed={isDimmed}\n onSelect={ctx.onSelect}\n onHoverEnter={ctx.onHoverEnter}\n onHoverLeave={ctx.onHoverLeave}\n />\n );\n}\n\nfunction smallPositionForMarker(pos: NodePosition): NodePosition {\n // Shrink the marker to a small badge centred at the node slot.\n const size = 16;\n return {\n id: pos.id,\n x: pos.x + pos.width / 2 - size / 2,\n y: pos.y + pos.height / 2 - size / 2,\n width: size,\n height: size,\n };\n}\n\n/**\n * Compute the set of node/edge IDs to highlight when `focusedId` is hovered\n * or selected. Returns `null` when nothing is focused (all nodes+edges shown\n * at full opacity).\n */\nfunction computeHighlightSet(\n focusedId: string | null,\n nodes: GraphNode[],\n edges: GraphEdge[],\n): Set<string> | null {\n if (!focusedId) return null;\n\n const set = new Set<string>();\n set.add(focusedId);\n\n const node = nodes.find((n) => n.id === focusedId);\n if (node) {\n for (const e of edges) {\n if (e.kind !== \"transition\") continue;\n if (e.sourceId === focusedId || e.targetId === focusedId) {\n set.add(e.id);\n set.add(e.sourceId);\n set.add(e.targetId);\n }\n }\n return set;\n }\n\n const edge = edges.find((e) => e.id === focusedId);\n if (edge && edge.kind === \"transition\") {\n set.add(edge.sourceId);\n set.add(edge.targetId);\n }\n return set;\n}\n","/**\n * Design tokens for the Cyoda workflow viewer.\n *\n * Palette values match the existing Cyoda Launchpad workflow diagram at\n * `cyoda-launchpad/src/lib/workflow-diagram/cyoda/CyodaWorkflowDiagram.tsx`.\n * Changes here should be coordinated with that renderer so the website and\n * editor remain visually identical.\n */\n\nexport interface RolePaletteEntry {\n fill: string;\n border: string;\n meta: string;\n title: string;\n}\n\nexport interface TerminalPaletteEntry extends RolePaletteEntry {\n innerRing: string;\n}\n\nexport interface NodePalette {\n default: RolePaletteEntry;\n initial: RolePaletteEntry;\n terminal: TerminalPaletteEntry;\n manualReview: RolePaletteEntry;\n processing: RolePaletteEntry;\n}\n\nexport interface EdgePalette {\n automated: string;\n manual: string;\n conditional: string;\n processing: string;\n terminal: string;\n loop: string;\n disabled: string;\n arrowhead: string;\n}\n\nexport interface BadgePaletteEntry {\n fill: string;\n border: string;\n}\n\nexport interface BadgePalette {\n manual: BadgePaletteEntry;\n processor: BadgePaletteEntry;\n criterion: BadgePaletteEntry;\n disabled: BadgePaletteEntry;\n text: string;\n}\n\nexport interface EdgeLabelPalette {\n fill: string;\n border: string;\n text: string;\n}\n\nexport interface NeutralPalette {\n white: string;\n white95: string;\n white75: string;\n slate200: string;\n slate300: string;\n slate500: string;\n slate600: string;\n slate900: string;\n}\n\nexport interface WorkflowPalette {\n neutrals: NeutralPalette;\n node: NodePalette;\n edge: EdgePalette;\n edgeLabel: EdgeLabelPalette;\n badge: BadgePalette;\n}\n\nexport const workflowPalette: WorkflowPalette = {\n neutrals: {\n white: \"#FFFFFF\",\n white95: \"#FFFFFFF2\",\n white75: \"#FFFFFFBF\",\n slate200: \"#E2E8F0\",\n slate300: \"#CBD5E1\",\n slate500: \"#64748B\",\n slate600: \"#475569\",\n slate900: \"#0F172A\",\n },\n node: {\n default: {\n fill: \"#F0FDFA\",\n border: \"#2DD4BF\",\n meta: \"#0F766E\",\n title: \"#0F172A\",\n },\n initial: {\n fill: \"#D1FAE5\",\n border: \"#059669\",\n meta: \"#047857\",\n title: \"#022C22\",\n },\n terminal: {\n fill: \"#FFF1F2\",\n border: \"#FDA4AF\",\n meta: \"#BE123C\",\n title: \"#4C0519\",\n innerRing: \"#FFFFFFBF\",\n },\n manualReview: {\n fill: \"#F5F3FF\",\n border: \"#C4B5FD\",\n meta: \"#6D28D9\",\n title: \"#2E1065\",\n },\n processing: {\n fill: \"#F0F9FF\",\n border: \"#7DD3FC\",\n meta: \"#0369A1\",\n title: \"#082F49\",\n },\n },\n edge: {\n automated: \"#64748B\",\n manual: \"#8B5CF6\",\n conditional: \"#F59E0B\",\n processing: \"#0EA5E9\",\n terminal: \"#FB7185\",\n loop: \"#14B8A6\",\n disabled: \"#CBD5E1\",\n arrowhead: \"#64748B\",\n },\n edgeLabel: {\n fill: \"#FFFFFFF2\",\n border: \"#E2E8F0\",\n text: \"#475569\",\n },\n badge: {\n manual: { fill: \"#F5F3FF\", border: \"#DDD6FE\" },\n processor: { fill: \"#F0F9FF\", border: \"#BAE6FD\" },\n criterion: { fill: \"#FFFBEB\", border: \"#FDE68A\" },\n disabled: { fill: \"#F8FAFC\", border: \"#E2E8F0\" },\n text: \"#475569\",\n },\n};\n\nexport const typography = {\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Inter\", system-ui, sans-serif',\n monoFamily: 'ui-monospace, \"SF Mono\", \"Cascadia Code\", Menlo, monospace',\n stateCategory: { size: 10, weight: 700, tracking: \"0.12em\" },\n stateTitle: { size: 14, weight: 700, tracking: \"0.01em\" },\n edgeLabel: { size: 9, weight: 700, tracking: \"0.04em\" },\n badge: { size: 8, weight: 600, tracking: \"0.04em\" },\n};\n\nexport const geometry = {\n node: {\n width: 144,\n height: 72,\n radius: 8,\n strokeWidth: 1.5,\n terminalInset: 3,\n terminalInnerRadius: 6,\n },\n edge: {\n strokeWidth: 1.8,\n loopStrokeWidth: 1.6,\n arrowheadSize: 6,\n },\n labelPill: {\n paddingX: 6,\n paddingY: 3,\n radius: 6,\n shadowOpacity: 0.08,\n },\n};\n","import type { GraphDocument, GraphNode } from \"@cyoda/workflow-graph\";\nimport { geometry } from \"./theme/tokens.js\";\n\nexport interface NodePosition {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface EdgeWaypoint {\n x: number;\n y: number;\n}\n\nexport interface EdgeRoute {\n id: string;\n /** Full polyline from source attach point to target attach point. */\n points: EdgeWaypoint[];\n labelX: number;\n labelY: number;\n labelWidth?: number;\n labelHeight?: number;\n}\n\nexport interface LayoutResult {\n positions: Map<string, NodePosition>;\n /** Optional pre-computed polyline routes (e.g. from ELK). */\n edges?: Map<string, EdgeRoute>;\n width: number;\n height: number;\n}\n\n/**\n * Simple deterministic fallback layout used by the viewer when no ELK-computed\n * layout is provided. Groups nodes by workflow and arranges each workflow's\n * states in a BFS-layered top-to-bottom flow.\n *\n * The editor and the website both prefer ELK output (Phase 4). This layout is\n * a dependency-free default so the viewer package can render in isolation.\n */\nexport function simpleLayout(graph: GraphDocument): LayoutResult {\n const { width: nodeW, height: nodeH } = geometry.node;\n const hGap = 48;\n const vGap = 48;\n\n const positions = new Map<string, NodePosition>();\n const nodesByWorkflow = groupByWorkflow(graph.nodes);\n\n let yCursor = 24;\n let maxWidth = 0;\n\n for (const wfNodes of nodesByWorkflow.values()) {\n const layers = layerByBFS(wfNodes, graph);\n let y = yCursor;\n for (const layer of layers) {\n const layerWidth = layer.length * nodeW + (layer.length - 1) * hGap;\n maxWidth = Math.max(maxWidth, layerWidth + 48);\n let x = Math.max(24, (maxWidth - layerWidth) / 2);\n for (const node of layer) {\n positions.set(node.id, { id: node.id, x, y, width: nodeW, height: nodeH });\n x += nodeW + hGap;\n }\n y += nodeH + vGap;\n }\n yCursor = y + vGap;\n }\n\n return { positions, width: maxWidth + 24, height: yCursor };\n}\n\nfunction groupByWorkflow(nodes: GraphNode[]): Map<string, GraphNode[]> {\n const out = new Map<string, GraphNode[]>();\n for (const n of nodes) {\n const wf = \"workflow\" in n ? n.workflow : \"\";\n const list = out.get(wf) ?? [];\n list.push(n);\n out.set(wf, list);\n }\n return out;\n}\n\nfunction layerByBFS(nodes: GraphNode[], graph: GraphDocument): GraphNode[][] {\n const stateNodes: GraphNode[] = nodes.filter((n) => n.kind === \"state\");\n const markers: GraphNode[] = nodes.filter((n) => n.kind === \"startMarker\");\n if (stateNodes.length === 0) return markers.length > 0 ? [markers] : [];\n\n // Build adjacency from transition edges (skip loopbacks for layering).\n const adj = new Map<string, Set<string>>();\n const indeg = new Map<string, number>();\n for (const n of stateNodes) {\n adj.set(n.id, new Set());\n indeg.set(n.id, 0);\n }\n for (const e of graph.edges) {\n if (e.kind !== \"transition\" || e.isLoopback) continue;\n if (!adj.has(e.sourceId) || !adj.has(e.targetId)) continue;\n const set = adj.get(e.sourceId)!;\n if (!set.has(e.targetId)) {\n set.add(e.targetId);\n indeg.set(e.targetId, (indeg.get(e.targetId) ?? 0) + 1);\n }\n }\n\n const layers: GraphNode[][] = [];\n if (markers.length > 0) layers.push(markers);\n\n // Topological layering: sources first, then successors.\n const byId = new Map(stateNodes.map((n) => [n.id, n] as const));\n let frontier = stateNodes.filter((n) => (indeg.get(n.id) ?? 0) === 0);\n const placed = new Set<string>();\n while (frontier.length > 0) {\n layers.push(frontier);\n const next: GraphNode[] = [];\n for (const n of frontier) {\n placed.add(n.id);\n for (const succ of adj.get(n.id) ?? []) {\n const remaining = (indeg.get(succ) ?? 0) - 1;\n indeg.set(succ, remaining);\n if (remaining === 0 && !placed.has(succ)) {\n const node = byId.get(succ);\n if (node) next.push(node);\n }\n }\n }\n frontier = next;\n }\n\n // Any unplaced (cycle participants not reachable via in-degree-0) — drop\n // into a trailing layer so they still render.\n const remaining = stateNodes.filter((n) => !placed.has(n.id));\n if (remaining.length > 0) layers.push(remaining);\n return layers;\n}\n","import { useCallback, useRef, useState } from \"react\";\n\nexport interface ViewportTransform {\n x: number;\n y: number;\n scale: number;\n}\n\nexport interface PanZoomHandlers {\n transform: ViewportTransform;\n onWheel: (e: React.WheelEvent<SVGSVGElement>) => void;\n onMouseDown: (e: React.MouseEvent<SVGSVGElement>) => void;\n onMouseMove: (e: React.MouseEvent<SVGSVGElement>) => void;\n onMouseUp: (e: React.MouseEvent<SVGSVGElement>) => void;\n reset: () => void;\n setTransform: (t: ViewportTransform) => void;\n}\n\nconst MIN_SCALE = 0.25;\nconst MAX_SCALE = 4;\nconst ZOOM_STEP = 1.1;\n\n/**\n * Minimal pan + zoom state for a single SVG `<g>` transform. No inertia, no\n * trackpad-gesture normalisation — deferred to when we adopt react-zoom-pan\n * or a similar library.\n */\nexport function usePanZoom(initial?: Partial<ViewportTransform>): PanZoomHandlers {\n const [transform, setTransform] = useState<ViewportTransform>({\n x: initial?.x ?? 0,\n y: initial?.y ?? 0,\n scale: initial?.scale ?? 1,\n });\n const dragStart = useRef<{ x: number; y: number; vx: number; vy: number } | null>(null);\n\n const onWheel = useCallback((e: React.WheelEvent<SVGSVGElement>) => {\n if (!e.ctrlKey && !e.metaKey) return;\n e.preventDefault();\n const delta = e.deltaY > 0 ? 1 / ZOOM_STEP : ZOOM_STEP;\n setTransform((t) => {\n const nextScale = clamp(t.scale * delta, MIN_SCALE, MAX_SCALE);\n const ratio = nextScale / t.scale;\n const rect = (e.currentTarget as SVGSVGElement).getBoundingClientRect();\n const px = e.clientX - rect.left;\n const py = e.clientY - rect.top;\n return {\n scale: nextScale,\n x: px - (px - t.x) * ratio,\n y: py - (py - t.y) * ratio,\n };\n });\n }, []);\n\n const onMouseDown = useCallback((e: React.MouseEvent<SVGSVGElement>) => {\n if (e.button !== 0) return;\n dragStart.current = { x: e.clientX, y: e.clientY, vx: transform.x, vy: transform.y };\n }, [transform.x, transform.y]);\n\n const onMouseMove = useCallback((e: React.MouseEvent<SVGSVGElement>) => {\n if (!dragStart.current) return;\n const dx = e.clientX - dragStart.current.x;\n const dy = e.clientY - dragStart.current.y;\n setTransform((t) => ({ ...t, x: dragStart.current!.vx + dx, y: dragStart.current!.vy + dy }));\n }, []);\n\n const onMouseUp = useCallback(() => {\n dragStart.current = null;\n }, []);\n\n const reset = useCallback(() => {\n setTransform({ x: 0, y: 0, scale: 1 });\n }, []);\n\n return { transform, onWheel, onMouseDown, onMouseMove, onMouseUp, reset, setTransform };\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, n));\n}\n","import type { TransitionEdge } from \"@cyoda/workflow-graph\";\nimport { workflowPalette } from \"./tokens.js\";\n\n/**\n * Select the edge stroke color (\"lane\") for a transition edge.\n *\n * Order of precedence (mirrors the Launchpad renderer):\n * 1. Disabled transitions → disabled lane.\n * 2. Loopback (self or back-edge) → loop lane.\n * 3. Target is a terminal state → terminal lane (set by caller via\n * `targetIsTerminal` since the edge itself doesn't know).\n * 4. Processor-bearing transition → processing lane.\n * 5. Manual transition → manual lane.\n * 6. Has a criterion (non-group) → conditional lane.\n * 7. Default → automated lane.\n */\nexport function laneColor(\n edge: TransitionEdge,\n opts: { targetIsTerminal: boolean },\n): string {\n const e = workflowPalette.edge;\n if (edge.disabled) return e.disabled;\n if (edge.isLoopback) return e.loop;\n if (opts.targetIsTerminal) return e.terminal;\n if (edge.summary.processor && edge.summary.processor.kind !== \"none\") {\n return e.processing;\n }\n if (edge.manual) return e.manual;\n if (edge.summary.criterion) return e.conditional;\n return e.automated;\n}\n\n/**\n * Whether the stroke should be rendered dashed (spec §24: dashed-vs-solid\n * carries meaning, colour alone never does).\n */\nexport function laneIsDashed(edge: TransitionEdge): boolean {\n return edge.disabled || edge.isLoopback;\n}\n\n/**\n * SVG `strokeDasharray` value for an edge.\n * - Disabled: tight \"3 2\" — visually reads as \"greyed out / inactive\".\n * - Loopback (non-disabled): \"6 4\" — looser, still dashed.\n * - Otherwise: undefined (solid).\n */\nexport function laneDashArray(edge: TransitionEdge): string | undefined {\n if (edge.disabled) return \"3 2\";\n if (edge.isLoopback) return \"6 4\";\n return undefined;\n}\n","import type { TransitionEdge } from \"@cyoda/workflow-graph\";\nimport { laneColor, laneDashArray } from \"../theme/lane.js\";\nimport { geometry, workflowPalette } from \"../theme/tokens.js\";\nimport type { EdgeRoute, NodePosition } from \"../layout.js\";\n\ninterface Props {\n edge: TransitionEdge;\n source: NodePosition;\n target: NodePosition;\n /** Pre-computed polyline from the layout engine (ELK). Overrides center-to-center heuristic. */\n route?: EdgeRoute;\n targetIsTerminal: boolean;\n highlighted: boolean;\n dimmed: boolean;\n selected: boolean;\n onSelect: (id: string) => void;\n onHoverEnter: (id: string) => void;\n onHoverLeave: () => void;\n}\n\nexport interface EdgeGeometry {\n d: string;\n midX: number;\n midY: number;\n}\n\n/**\n * Convert a polyline to an SVG path `d` string.\n */\nexport function polylineToPath(points: { x: number; y: number }[]): string {\n if (points.length === 0) return \"\";\n const [first, ...rest] = points;\n let d = `M ${first!.x} ${first!.y}`;\n for (const p of rest) d += ` L ${p.x} ${p.y}`;\n return d;\n}\n\n/**\n * Compute a simple orthogonal-ish path between two node centres. Self-loops\n * are rendered as a right-side arc; parallel siblings are offset laterally\n * based on parallelIndex to avoid overlap.\n */\nexport function computeEdgeGeometry(\n edge: TransitionEdge,\n source: NodePosition,\n target: NodePosition,\n): EdgeGeometry {\n const sx = source.x + source.width / 2;\n const sy = source.y + source.height / 2;\n const tx = target.x + target.width / 2;\n const ty = target.y + target.height / 2;\n\n if (edge.isSelf) {\n const rightX = source.x + source.width;\n const topY = source.y + source.height / 3;\n const bottomY = source.y + (source.height * 2) / 3;\n const loopX = rightX + 28;\n const d = `M ${rightX} ${topY} C ${loopX} ${topY}, ${loopX} ${bottomY}, ${rightX} ${bottomY}`;\n return { d, midX: loopX, midY: (topY + bottomY) / 2 };\n }\n\n // Lateral offset for parallel edges: stagger by parallelIndex around the\n // midpoint. 0 → centred, 1 → +offset, 2 → -offset, etc.\n const offsetStep = 18;\n const half = Math.floor(edge.parallelGroupSize / 2);\n const signed = edge.parallelIndex - half;\n const offset = signed * offsetStep;\n\n const mx = (sx + tx) / 2 + offset;\n const my = (sy + ty) / 2;\n\n // Simple cubic curve so parallel siblings don't overlap.\n const d = `M ${sx} ${sy} Q ${mx} ${my}, ${tx} ${ty}`;\n return { d, midX: mx, midY: my };\n}\n\nexport function EdgePath({\n edge,\n source,\n target,\n route,\n targetIsTerminal,\n highlighted,\n dimmed,\n selected,\n onSelect,\n onHoverEnter,\n onHoverLeave,\n}: Props) {\n const color = laneColor(edge, { targetIsTerminal });\n const dash = laneDashArray(edge);\n const d =\n route && route.points.length >= 2\n ? polylineToPath(route.points)\n : computeEdgeGeometry(edge, source, target).d;\n\n const strokeWidth =\n selected || highlighted\n ? geometry.edge.strokeWidth + 0.8\n : edge.isLoopback\n ? geometry.edge.loopStrokeWidth\n : geometry.edge.strokeWidth;\n const opacity = dimmed ? 0.25 : 1;\n // Manual transitions get a thin ghost stroke on top of the main stroke —\n // strengthens the manual-vs-auto visual cue without changing semantics.\n const isManualSolid = edge.manual && !edge.disabled && !edge.isLoopback;\n\n return (\n <g\n opacity={opacity}\n onClick={(e) => {\n e.stopPropagation();\n onSelect(edge.id);\n }}\n onMouseEnter={() => onHoverEnter(edge.id)}\n onMouseLeave={onHoverLeave}\n style={{ cursor: \"pointer\" }}\n data-testid={`edge-${edge.id}`}\n >\n {/* Transparent fat stroke to widen the hit-area. */}\n <path d={d} fill=\"none\" stroke=\"transparent\" strokeWidth={12} />\n <path\n d={d}\n fill=\"none\"\n stroke={color}\n strokeWidth={strokeWidth}\n strokeDasharray={dash}\n markerEnd={`url(#wf-arrow-${colorKey(color)})`}\n />\n {isManualSolid && (\n <path\n d={d}\n fill=\"none\"\n stroke={workflowPalette.neutrals.white}\n strokeWidth={0.6}\n pointerEvents=\"none\"\n />\n )}\n </g>\n );\n}\n\n/**\n * Lane colours keyed so we can reuse one marker per lane. Must be a valid\n * fragment identifier.\n */\nexport function colorKey(color: string): string {\n return color.replace(\"#\", \"\").toLowerCase();\n}\n\n/**\n * The set of lane colours we need arrowhead markers for. Emitted once per\n * SVG instance from `WorkflowViewer`.\n */\nexport const laneColorSet: string[] = Object.values(workflowPalette.edge);\n","import { geometry, workflowPalette } from \"../theme/tokens.js\";\nimport { colorKey, laneColorSet } from \"./EdgePath.js\";\n\n/**\n * Shared SVG `<defs>` — arrowhead markers (one per lane colour) and the two\n * drop-shadow filters used by nodes and label chips.\n */\nexport function Defs() {\n const size = geometry.edge.arrowheadSize;\n // Sharper 2:1 triangle: width (tip-to-base) = 2*size, base thickness = size,\n // so the base runs vertically from (0, size/2) to (0, 3*size/2) and the tip\n // sits at (2*size, size). refX is pushed close to the tip so the arrow kisses\n // the node edge, not floats away from it.\n const unique = Array.from(new Set(laneColorSet));\n return (\n <defs>\n {unique.map((color) => (\n <marker\n key={color}\n id={`wf-arrow-${colorKey(color)}`}\n viewBox={`0 0 ${size * 2} ${size * 2}`}\n refX={size * 1.85}\n refY={size}\n markerWidth={size}\n markerHeight={size}\n orient=\"auto-start-reverse\"\n >\n <path\n d={`M 0 ${size / 2} L ${size * 2} ${size} L 0 ${size * 1.5} z`}\n fill={color}\n />\n </marker>\n ))}\n <filter id=\"wf-node-shadow\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"140%\">\n <feDropShadow\n dx={0}\n dy={2}\n stdDeviation={2}\n floodColor={workflowPalette.neutrals.slate900}\n floodOpacity={0.08}\n />\n </filter>\n <filter\n id=\"wf-node-shadow-strong\"\n x=\"-10%\"\n y=\"-10%\"\n width=\"120%\"\n height=\"140%\"\n >\n <feDropShadow\n dx={0}\n dy={3}\n stdDeviation={3}\n floodColor={workflowPalette.neutrals.slate900}\n floodOpacity={0.18}\n />\n </filter>\n <filter id=\"wf-label-shadow\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"140%\">\n <feDropShadow\n dx={0}\n dy={1}\n stdDeviation={1.2}\n floodColor={workflowPalette.neutrals.slate900}\n floodOpacity={geometry.labelPill.shadowOpacity}\n />\n </filter>\n </defs>\n );\n}\n","import { workflowPalette } from \"../theme/tokens.js\";\nimport type { NodePosition } from \"../layout.js\";\n\ninterface Props {\n position: NodePosition;\n}\n\n/**\n * Non-interactive start marker node (spec §10.5). Rendered as a small filled\n * circle above the initial state.\n */\nexport function StartMarker({ position }: Props) {\n const cx = position.x + position.width / 2;\n const cy = position.y + position.height / 2;\n const r = Math.min(position.width, position.height) / 3;\n return (\n <g aria-hidden=\"true\">\n <circle\n cx={cx}\n cy={cy}\n r={r}\n fill={workflowPalette.node.initial.border}\n stroke={workflowPalette.node.initial.meta}\n strokeWidth={1.5}\n />\n </g>\n );\n}\n","import type { StateNode } from \"@cyoda/workflow-graph\";\n\n/**\n * Category label shown in the small uppercase header line above the state\n * title. Derived from projection data (role + visual category).\n *\n * Reused by the editor shell so the website viewer and editor canvas display\n * identical headers.\n */\nexport function roleCategoryLabel(node: StateNode): string {\n if (node.role === \"initial\" || node.role === \"initial-terminal\") return \"INITIAL\";\n if (node.role === \"terminal\") return \"TERMINAL\";\n if (node.category === \"MANUAL_REVIEW\") return \"MANUAL REVIEW\";\n if (node.category === \"PROCESSING_STATE\") return \"PROCESSING STATE\";\n return \"STATE\";\n}\n","import type { StateNode } from \"@cyoda/workflow-graph\";\nimport { workflowPalette, type RolePaletteEntry, type TerminalPaletteEntry } from \"./tokens.js\";\n\n/**\n * Select the palette entry for a state node.\n * initial-terminal prefers terminal styling (with initial accent applied\n * separately by the renderer — e.g. a secondary border ring).\n */\nexport function paletteFor(\n node: StateNode,\n): RolePaletteEntry | TerminalPaletteEntry {\n const p = workflowPalette.node;\n if (node.role === \"terminal\" || node.role === \"initial-terminal\") return p.terminal;\n if (node.role === \"initial\") return p.initial;\n if (node.category === \"MANUAL_REVIEW\") return p.manualReview;\n if (node.category === \"PROCESSING_STATE\") return p.processing;\n return p.default;\n}\n","import type { TransitionSummary } from \"@cyoda/workflow-graph\";\n\nexport interface BadgeDescriptor {\n key: \"manual\" | \"processor\" | \"criterion\" | \"disabled\" | \"execution\";\n label: string;\n}\n\n/**\n * Translate a transition summary + flags into the ordered list of badges the\n * edge chip should render. Mirrors §10 chip summaries + the visual design\n * section of the implementation plan.\n */\nexport function badgesFor(\n summary: TransitionSummary,\n flags: { manual: boolean; disabled: boolean },\n): BadgeDescriptor[] {\n const out: BadgeDescriptor[] = [];\n\n if (flags.manual) out.push({ key: \"manual\", label: \"Manual\" });\n\n if (summary.processor) {\n if (summary.processor.kind === \"single\") {\n out.push({ key: \"processor\", label: summary.processor.name });\n } else if (summary.processor.kind === \"multiple\") {\n out.push({ key: \"processor\", label: `${summary.processor.count} processors` });\n }\n }\n\n if (summary.criterion) {\n const c = summary.criterion;\n if (c.kind === \"group\") {\n out.push({ key: \"criterion\", label: `${c.operator} · ${c.count}` });\n } else {\n out.push({ key: \"criterion\", label: \"Criterion\" });\n }\n }\n\n if (summary.execution?.kind === \"sync\") {\n out.push({ key: \"execution\", label: \"SYNC\" });\n } else if (summary.execution?.kind === \"asyncSameTx\") {\n out.push({ key: \"execution\", label: \"ASYNC_SAME_TX\" });\n }\n\n if (flags.disabled) out.push({ key: \"disabled\", label: \"Disabled\" });\n\n return out;\n}\n","import type { StateNode as StateNodeData } from \"@cyoda/workflow-graph\";\nimport { paletteFor, roleCategoryLabel } from \"../theme/index.js\";\nimport { geometry, typography, workflowPalette } from \"../theme/tokens.js\";\nimport type { NodePosition } from \"../layout.js\";\n\ninterface Props {\n node: StateNodeData;\n position: NodePosition;\n selected: boolean;\n highlighted: boolean;\n dimmed: boolean;\n onSelect: (id: string) => void;\n onHoverEnter: (id: string) => void;\n onHoverLeave: () => void;\n}\n\nexport function StateNodeView({\n node,\n position,\n selected,\n highlighted,\n dimmed,\n onSelect,\n onHoverEnter,\n onHoverLeave,\n}: Props) {\n const palette = paletteFor(node);\n const { radius, strokeWidth, terminalInset, terminalInnerRadius } = geometry.node;\n const { width, height } = position;\n const isTerminal = node.role === \"terminal\" || node.role === \"initial-terminal\";\n const isInitialTerminal = node.role === \"initial-terminal\";\n const category = roleCategoryLabel(node);\n\n const opacity = dimmed ? 0.35 : 1;\n const outerStroke = selected\n ? workflowPalette.neutrals.slate900\n : palette.border;\n const outerStrokeWidth = selected ? strokeWidth + 1 : strokeWidth;\n\n return (\n <g\n transform={`translate(${position.x}, ${position.y})`}\n opacity={opacity}\n onClick={(e) => {\n e.stopPropagation();\n onSelect(node.id);\n }}\n onMouseEnter={() => onHoverEnter(node.id)}\n onMouseLeave={onHoverLeave}\n style={{ cursor: \"pointer\" }}\n data-testid={`state-node-${node.stateCode}`}\n aria-label={`${category} ${node.stateCode}`}\n role=\"button\"\n tabIndex={0}\n >\n <rect\n x={0}\n y={0}\n width={width}\n height={height}\n rx={radius}\n ry={radius}\n fill={palette.fill}\n stroke={outerStroke}\n strokeWidth={outerStrokeWidth}\n filter={highlighted || selected ? \"url(#wf-node-shadow-strong)\" : \"url(#wf-node-shadow)\"}\n />\n {isTerminal && (\n <rect\n x={terminalInset}\n y={terminalInset}\n width={width - terminalInset * 2}\n height={height - terminalInset * 2}\n rx={terminalInnerRadius}\n ry={terminalInnerRadius}\n fill=\"none\"\n stroke={\n \"innerRing\" in palette\n ? palette.innerRing\n : workflowPalette.neutrals.white75\n }\n strokeWidth={1}\n />\n )}\n {isInitialTerminal && (\n <rect\n x={terminalInset}\n y={terminalInset}\n width={width - terminalInset * 2}\n height={height - terminalInset * 2}\n rx={terminalInnerRadius}\n ry={terminalInnerRadius}\n fill=\"none\"\n stroke={workflowPalette.node.initial.border}\n strokeWidth={1}\n strokeDasharray=\"3 3\"\n />\n )}\n <text\n x={width / 2}\n y={height / 2 - 8}\n textAnchor=\"middle\"\n fill={palette.meta}\n fontFamily={typography.fontFamily}\n fontSize={typography.stateCategory.size}\n fontWeight={typography.stateCategory.weight}\n letterSpacing={typography.stateCategory.tracking}\n >\n {category}\n </text>\n <text\n x={width / 2}\n y={height / 2 + 12}\n textAnchor=\"middle\"\n fill={palette.title}\n fontFamily={typography.monoFamily}\n fontSize={typography.stateTitle.size}\n fontWeight={typography.stateTitle.weight}\n letterSpacing={typography.stateTitle.tracking}\n >\n {truncate(node.stateCode, 18)}\n </text>\n </g>\n );\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n","import type { TransitionEdge } from \"@cyoda/workflow-graph\";\nimport { badgesFor, type BadgeDescriptor } from \"../theme/badges.js\";\nimport { geometry, typography, workflowPalette } from \"../theme/tokens.js\";\n\ninterface Props {\n edge: TransitionEdge;\n x: number;\n y: number;\n width?: number;\n height?: number;\n dimmed: boolean;\n}\n\nconst BADGE_HEIGHT = 14;\nconst BADGE_GAP = 4;\nconst LABEL_PADDING_X = geometry.labelPill.paddingX;\nconst LABEL_PADDING_Y = geometry.labelPill.paddingY;\nconst BADGE_TEXT_PADDING_X = 6;\n\n/**\n * Estimate label width in SVG units. Rough heuristic: avg glyph width ≈\n * fontSize * 0.58 for the sans/mono stack at these sizes. Good enough until\n * we measure via getBBox.\n */\nfunction estimateWidth(text: string, fontSize: number): number {\n return Math.ceil(text.length * fontSize * 0.58);\n}\n\nexport function EdgeLabel({ edge, x, y, width, height, dimmed }: Props) {\n const title = edge.summary.display;\n const badges = badgesFor(edge.summary, {\n manual: edge.manual,\n disabled: edge.disabled,\n });\n\n const titleW = estimateWidth(title, typography.edgeLabel.size);\n\n const badgeWidths = badges.map(\n (b) => estimateWidth(b.label, typography.badge.size) + BADGE_TEXT_PADDING_X * 2,\n );\n const badgesTotalW =\n badgeWidths.reduce((a, b) => a + b, 0) +\n Math.max(0, badges.length - 1) * BADGE_GAP;\n\n const pillW = width ?? Math.max(titleW, badgesTotalW) + LABEL_PADDING_X * 2;\n const hasBadges = badges.length > 0;\n const pillH = height ??\n typography.edgeLabel.size +\n LABEL_PADDING_Y * 2 +\n (hasBadges ? BADGE_HEIGHT + BADGE_GAP : 0);\n\n const pillX = x - pillW / 2;\n const pillY = y - pillH / 2;\n const titleY = pillY + LABEL_PADDING_Y + typography.edgeLabel.size - 2;\n const badgeY = titleY + BADGE_GAP + 2;\n\n const opacity = dimmed ? 0.4 : 1;\n\n return (\n <g opacity={opacity} pointerEvents=\"none\">\n <rect\n x={pillX}\n y={pillY}\n width={pillW}\n height={pillH}\n rx={geometry.labelPill.radius}\n ry={geometry.labelPill.radius}\n fill={workflowPalette.edgeLabel.fill}\n stroke={workflowPalette.edgeLabel.border}\n strokeWidth={1}\n filter=\"url(#wf-label-shadow)\"\n />\n <text\n x={x}\n y={titleY}\n textAnchor=\"middle\"\n fill={workflowPalette.edgeLabel.text}\n fontFamily={typography.fontFamily}\n fontSize={typography.edgeLabel.size}\n fontWeight={typography.edgeLabel.weight}\n letterSpacing={typography.edgeLabel.tracking}\n >\n {title}\n </text>\n {hasBadges && renderBadges(badges, badgeWidths, pillX, pillW, badgeY)}\n </g>\n );\n}\n\nfunction renderBadges(\n badges: BadgeDescriptor[],\n widths: number[],\n pillX: number,\n pillW: number,\n y: number,\n) {\n const totalW =\n widths.reduce((a, b) => a + b, 0) +\n Math.max(0, badges.length - 1) * BADGE_GAP;\n let cursor = pillX + (pillW - totalW) / 2;\n return (\n <g>\n {badges.map((b, i) => {\n const w = widths[i]!;\n const slot = pickBadgePalette(b.key);\n const node = (\n <g key={`${b.key}-${i}`}>\n <rect\n x={cursor}\n y={y}\n width={w}\n height={BADGE_HEIGHT}\n rx={BADGE_HEIGHT / 2}\n ry={BADGE_HEIGHT / 2}\n fill={slot.fill}\n stroke={slot.border}\n strokeWidth={1}\n />\n <text\n x={cursor + w / 2}\n y={y + BADGE_HEIGHT - 4}\n textAnchor=\"middle\"\n fill={workflowPalette.badge.text}\n fontFamily={typography.fontFamily}\n fontSize={typography.badge.size}\n fontWeight={typography.badge.weight}\n letterSpacing={typography.badge.tracking}\n >\n {b.label}\n </text>\n </g>\n );\n cursor += w + BADGE_GAP;\n return node;\n })}\n </g>\n );\n}\n\nfunction pickBadgePalette(key: BadgeDescriptor[\"key\"]) {\n switch (key) {\n case \"manual\":\n return workflowPalette.badge.manual;\n case \"processor\":\n return workflowPalette.badge.processor;\n case \"criterion\":\n return workflowPalette.badge.criterion;\n case \"execution\":\n return workflowPalette.badge.processor;\n case \"disabled\":\n return workflowPalette.badge.disabled;\n }\n}\n"],"mappings":"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","names":["useState","remaining","d","jsx","jsxs","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState"]}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/theme/index.ts
|
|
21
|
+
var theme_exports = {};
|
|
22
|
+
__export(theme_exports, {
|
|
23
|
+
badgesFor: () => badgesFor,
|
|
24
|
+
geometry: () => geometry,
|
|
25
|
+
laneColor: () => laneColor,
|
|
26
|
+
laneDashArray: () => laneDashArray,
|
|
27
|
+
laneIsDashed: () => laneIsDashed,
|
|
28
|
+
paletteFor: () => paletteFor,
|
|
29
|
+
roleCategoryLabel: () => roleCategoryLabel,
|
|
30
|
+
typography: () => typography,
|
|
31
|
+
workflowPalette: () => workflowPalette
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(theme_exports);
|
|
34
|
+
|
|
35
|
+
// src/theme/tokens.ts
|
|
36
|
+
var workflowPalette = {
|
|
37
|
+
neutrals: {
|
|
38
|
+
white: "#FFFFFF",
|
|
39
|
+
white95: "#FFFFFFF2",
|
|
40
|
+
white75: "#FFFFFFBF",
|
|
41
|
+
slate200: "#E2E8F0",
|
|
42
|
+
slate300: "#CBD5E1",
|
|
43
|
+
slate500: "#64748B",
|
|
44
|
+
slate600: "#475569",
|
|
45
|
+
slate900: "#0F172A"
|
|
46
|
+
},
|
|
47
|
+
node: {
|
|
48
|
+
default: {
|
|
49
|
+
fill: "#F0FDFA",
|
|
50
|
+
border: "#2DD4BF",
|
|
51
|
+
meta: "#0F766E",
|
|
52
|
+
title: "#0F172A"
|
|
53
|
+
},
|
|
54
|
+
initial: {
|
|
55
|
+
fill: "#D1FAE5",
|
|
56
|
+
border: "#059669",
|
|
57
|
+
meta: "#047857",
|
|
58
|
+
title: "#022C22"
|
|
59
|
+
},
|
|
60
|
+
terminal: {
|
|
61
|
+
fill: "#FFF1F2",
|
|
62
|
+
border: "#FDA4AF",
|
|
63
|
+
meta: "#BE123C",
|
|
64
|
+
title: "#4C0519",
|
|
65
|
+
innerRing: "#FFFFFFBF"
|
|
66
|
+
},
|
|
67
|
+
manualReview: {
|
|
68
|
+
fill: "#F5F3FF",
|
|
69
|
+
border: "#C4B5FD",
|
|
70
|
+
meta: "#6D28D9",
|
|
71
|
+
title: "#2E1065"
|
|
72
|
+
},
|
|
73
|
+
processing: {
|
|
74
|
+
fill: "#F0F9FF",
|
|
75
|
+
border: "#7DD3FC",
|
|
76
|
+
meta: "#0369A1",
|
|
77
|
+
title: "#082F49"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
edge: {
|
|
81
|
+
automated: "#64748B",
|
|
82
|
+
manual: "#8B5CF6",
|
|
83
|
+
conditional: "#F59E0B",
|
|
84
|
+
processing: "#0EA5E9",
|
|
85
|
+
terminal: "#FB7185",
|
|
86
|
+
loop: "#14B8A6",
|
|
87
|
+
disabled: "#CBD5E1",
|
|
88
|
+
arrowhead: "#64748B"
|
|
89
|
+
},
|
|
90
|
+
edgeLabel: {
|
|
91
|
+
fill: "#FFFFFFF2",
|
|
92
|
+
border: "#E2E8F0",
|
|
93
|
+
text: "#475569"
|
|
94
|
+
},
|
|
95
|
+
badge: {
|
|
96
|
+
manual: { fill: "#F5F3FF", border: "#DDD6FE" },
|
|
97
|
+
processor: { fill: "#F0F9FF", border: "#BAE6FD" },
|
|
98
|
+
criterion: { fill: "#FFFBEB", border: "#FDE68A" },
|
|
99
|
+
disabled: { fill: "#F8FAFC", border: "#E2E8F0" },
|
|
100
|
+
text: "#475569"
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var typography = {
|
|
104
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", system-ui, sans-serif',
|
|
105
|
+
monoFamily: 'ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace',
|
|
106
|
+
stateCategory: { size: 10, weight: 700, tracking: "0.12em" },
|
|
107
|
+
stateTitle: { size: 14, weight: 700, tracking: "0.01em" },
|
|
108
|
+
edgeLabel: { size: 9, weight: 700, tracking: "0.04em" },
|
|
109
|
+
badge: { size: 8, weight: 600, tracking: "0.04em" }
|
|
110
|
+
};
|
|
111
|
+
var geometry = {
|
|
112
|
+
node: {
|
|
113
|
+
width: 144,
|
|
114
|
+
height: 72,
|
|
115
|
+
radius: 8,
|
|
116
|
+
strokeWidth: 1.5,
|
|
117
|
+
terminalInset: 3,
|
|
118
|
+
terminalInnerRadius: 6
|
|
119
|
+
},
|
|
120
|
+
edge: {
|
|
121
|
+
strokeWidth: 1.8,
|
|
122
|
+
loopStrokeWidth: 1.6,
|
|
123
|
+
arrowheadSize: 6
|
|
124
|
+
},
|
|
125
|
+
labelPill: {
|
|
126
|
+
paddingX: 6,
|
|
127
|
+
paddingY: 3,
|
|
128
|
+
radius: 6,
|
|
129
|
+
shadowOpacity: 0.08
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/theme/role-label.ts
|
|
134
|
+
function roleCategoryLabel(node) {
|
|
135
|
+
if (node.role === "initial" || node.role === "initial-terminal") return "INITIAL";
|
|
136
|
+
if (node.role === "terminal") return "TERMINAL";
|
|
137
|
+
if (node.category === "MANUAL_REVIEW") return "MANUAL REVIEW";
|
|
138
|
+
if (node.category === "PROCESSING_STATE") return "PROCESSING STATE";
|
|
139
|
+
return "STATE";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/theme/lane.ts
|
|
143
|
+
function laneColor(edge, opts) {
|
|
144
|
+
const e = workflowPalette.edge;
|
|
145
|
+
if (edge.disabled) return e.disabled;
|
|
146
|
+
if (edge.isLoopback) return e.loop;
|
|
147
|
+
if (opts.targetIsTerminal) return e.terminal;
|
|
148
|
+
if (edge.summary.processor && edge.summary.processor.kind !== "none") {
|
|
149
|
+
return e.processing;
|
|
150
|
+
}
|
|
151
|
+
if (edge.manual) return e.manual;
|
|
152
|
+
if (edge.summary.criterion) return e.conditional;
|
|
153
|
+
return e.automated;
|
|
154
|
+
}
|
|
155
|
+
function laneIsDashed(edge) {
|
|
156
|
+
return edge.disabled || edge.isLoopback;
|
|
157
|
+
}
|
|
158
|
+
function laneDashArray(edge) {
|
|
159
|
+
if (edge.disabled) return "3 2";
|
|
160
|
+
if (edge.isLoopback) return "6 4";
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/theme/node-palette.ts
|
|
165
|
+
function paletteFor(node) {
|
|
166
|
+
const p = workflowPalette.node;
|
|
167
|
+
if (node.role === "terminal" || node.role === "initial-terminal") return p.terminal;
|
|
168
|
+
if (node.role === "initial") return p.initial;
|
|
169
|
+
if (node.category === "MANUAL_REVIEW") return p.manualReview;
|
|
170
|
+
if (node.category === "PROCESSING_STATE") return p.processing;
|
|
171
|
+
return p.default;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/theme/badges.ts
|
|
175
|
+
function badgesFor(summary, flags) {
|
|
176
|
+
const out = [];
|
|
177
|
+
if (flags.manual) out.push({ key: "manual", label: "Manual" });
|
|
178
|
+
if (summary.processor) {
|
|
179
|
+
if (summary.processor.kind === "single") {
|
|
180
|
+
out.push({ key: "processor", label: summary.processor.name });
|
|
181
|
+
} else if (summary.processor.kind === "multiple") {
|
|
182
|
+
out.push({ key: "processor", label: `${summary.processor.count} processors` });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (summary.criterion) {
|
|
186
|
+
const c = summary.criterion;
|
|
187
|
+
if (c.kind === "group") {
|
|
188
|
+
out.push({ key: "criterion", label: `${c.operator} \xB7 ${c.count}` });
|
|
189
|
+
} else {
|
|
190
|
+
out.push({ key: "criterion", label: "Criterion" });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (summary.execution?.kind === "sync") {
|
|
194
|
+
out.push({ key: "execution", label: "SYNC" });
|
|
195
|
+
} else if (summary.execution?.kind === "asyncSameTx") {
|
|
196
|
+
out.push({ key: "execution", label: "ASYNC_SAME_TX" });
|
|
197
|
+
}
|
|
198
|
+
if (flags.disabled) out.push({ key: "disabled", label: "Disabled" });
|
|
199
|
+
return out;
|
|
200
|
+
}
|
|
201
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
202
|
+
0 && (module.exports = {
|
|
203
|
+
badgesFor,
|
|
204
|
+
geometry,
|
|
205
|
+
laneColor,
|
|
206
|
+
laneDashArray,
|
|
207
|
+
laneIsDashed,
|
|
208
|
+
paletteFor,
|
|
209
|
+
roleCategoryLabel,
|
|
210
|
+
typography,
|
|
211
|
+
workflowPalette
|
|
212
|
+
});
|
|
213
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/theme/index.ts","../../src/theme/tokens.ts","../../src/theme/role-label.ts","../../src/theme/lane.ts","../../src/theme/node-palette.ts","../../src/theme/badges.ts"],"sourcesContent":["export {\n workflowPalette,\n typography,\n geometry,\n} from \"./tokens.js\";\nexport type {\n BadgePalette,\n BadgePaletteEntry,\n EdgeLabelPalette,\n EdgePalette,\n NeutralPalette,\n NodePalette,\n RolePaletteEntry,\n TerminalPaletteEntry,\n WorkflowPalette,\n} from \"./tokens.js\";\nexport { roleCategoryLabel } from \"./role-label.js\";\nexport { laneColor, laneIsDashed, laneDashArray } from \"./lane.js\";\nexport { paletteFor } from \"./node-palette.js\";\nexport { badgesFor } from \"./badges.js\";\nexport type { BadgeDescriptor } from \"./badges.js\";\n","/**\n * Design tokens for the Cyoda workflow viewer.\n *\n * Palette values match the existing Cyoda Launchpad workflow diagram at\n * `cyoda-launchpad/src/lib/workflow-diagram/cyoda/CyodaWorkflowDiagram.tsx`.\n * Changes here should be coordinated with that renderer so the website and\n * editor remain visually identical.\n */\n\nexport interface RolePaletteEntry {\n fill: string;\n border: string;\n meta: string;\n title: string;\n}\n\nexport interface TerminalPaletteEntry extends RolePaletteEntry {\n innerRing: string;\n}\n\nexport interface NodePalette {\n default: RolePaletteEntry;\n initial: RolePaletteEntry;\n terminal: TerminalPaletteEntry;\n manualReview: RolePaletteEntry;\n processing: RolePaletteEntry;\n}\n\nexport interface EdgePalette {\n automated: string;\n manual: string;\n conditional: string;\n processing: string;\n terminal: string;\n loop: string;\n disabled: string;\n arrowhead: string;\n}\n\nexport interface BadgePaletteEntry {\n fill: string;\n border: string;\n}\n\nexport interface BadgePalette {\n manual: BadgePaletteEntry;\n processor: BadgePaletteEntry;\n criterion: BadgePaletteEntry;\n disabled: BadgePaletteEntry;\n text: string;\n}\n\nexport interface EdgeLabelPalette {\n fill: string;\n border: string;\n text: string;\n}\n\nexport interface NeutralPalette {\n white: string;\n white95: string;\n white75: string;\n slate200: string;\n slate300: string;\n slate500: string;\n slate600: string;\n slate900: string;\n}\n\nexport interface WorkflowPalette {\n neutrals: NeutralPalette;\n node: NodePalette;\n edge: EdgePalette;\n edgeLabel: EdgeLabelPalette;\n badge: BadgePalette;\n}\n\nexport const workflowPalette: WorkflowPalette = {\n neutrals: {\n white: \"#FFFFFF\",\n white95: \"#FFFFFFF2\",\n white75: \"#FFFFFFBF\",\n slate200: \"#E2E8F0\",\n slate300: \"#CBD5E1\",\n slate500: \"#64748B\",\n slate600: \"#475569\",\n slate900: \"#0F172A\",\n },\n node: {\n default: {\n fill: \"#F0FDFA\",\n border: \"#2DD4BF\",\n meta: \"#0F766E\",\n title: \"#0F172A\",\n },\n initial: {\n fill: \"#D1FAE5\",\n border: \"#059669\",\n meta: \"#047857\",\n title: \"#022C22\",\n },\n terminal: {\n fill: \"#FFF1F2\",\n border: \"#FDA4AF\",\n meta: \"#BE123C\",\n title: \"#4C0519\",\n innerRing: \"#FFFFFFBF\",\n },\n manualReview: {\n fill: \"#F5F3FF\",\n border: \"#C4B5FD\",\n meta: \"#6D28D9\",\n title: \"#2E1065\",\n },\n processing: {\n fill: \"#F0F9FF\",\n border: \"#7DD3FC\",\n meta: \"#0369A1\",\n title: \"#082F49\",\n },\n },\n edge: {\n automated: \"#64748B\",\n manual: \"#8B5CF6\",\n conditional: \"#F59E0B\",\n processing: \"#0EA5E9\",\n terminal: \"#FB7185\",\n loop: \"#14B8A6\",\n disabled: \"#CBD5E1\",\n arrowhead: \"#64748B\",\n },\n edgeLabel: {\n fill: \"#FFFFFFF2\",\n border: \"#E2E8F0\",\n text: \"#475569\",\n },\n badge: {\n manual: { fill: \"#F5F3FF\", border: \"#DDD6FE\" },\n processor: { fill: \"#F0F9FF\", border: \"#BAE6FD\" },\n criterion: { fill: \"#FFFBEB\", border: \"#FDE68A\" },\n disabled: { fill: \"#F8FAFC\", border: \"#E2E8F0\" },\n text: \"#475569\",\n },\n};\n\nexport const typography = {\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Inter\", system-ui, sans-serif',\n monoFamily: 'ui-monospace, \"SF Mono\", \"Cascadia Code\", Menlo, monospace',\n stateCategory: { size: 10, weight: 700, tracking: \"0.12em\" },\n stateTitle: { size: 14, weight: 700, tracking: \"0.01em\" },\n edgeLabel: { size: 9, weight: 700, tracking: \"0.04em\" },\n badge: { size: 8, weight: 600, tracking: \"0.04em\" },\n};\n\nexport const geometry = {\n node: {\n width: 144,\n height: 72,\n radius: 8,\n strokeWidth: 1.5,\n terminalInset: 3,\n terminalInnerRadius: 6,\n },\n edge: {\n strokeWidth: 1.8,\n loopStrokeWidth: 1.6,\n arrowheadSize: 6,\n },\n labelPill: {\n paddingX: 6,\n paddingY: 3,\n radius: 6,\n shadowOpacity: 0.08,\n },\n};\n","import type { StateNode } from \"@cyoda/workflow-graph\";\n\n/**\n * Category label shown in the small uppercase header line above the state\n * title. Derived from projection data (role + visual category).\n *\n * Reused by the editor shell so the website viewer and editor canvas display\n * identical headers.\n */\nexport function roleCategoryLabel(node: StateNode): string {\n if (node.role === \"initial\" || node.role === \"initial-terminal\") return \"INITIAL\";\n if (node.role === \"terminal\") return \"TERMINAL\";\n if (node.category === \"MANUAL_REVIEW\") return \"MANUAL REVIEW\";\n if (node.category === \"PROCESSING_STATE\") return \"PROCESSING STATE\";\n return \"STATE\";\n}\n","import type { TransitionEdge } from \"@cyoda/workflow-graph\";\nimport { workflowPalette } from \"./tokens.js\";\n\n/**\n * Select the edge stroke color (\"lane\") for a transition edge.\n *\n * Order of precedence (mirrors the Launchpad renderer):\n * 1. Disabled transitions → disabled lane.\n * 2. Loopback (self or back-edge) → loop lane.\n * 3. Target is a terminal state → terminal lane (set by caller via\n * `targetIsTerminal` since the edge itself doesn't know).\n * 4. Processor-bearing transition → processing lane.\n * 5. Manual transition → manual lane.\n * 6. Has a criterion (non-group) → conditional lane.\n * 7. Default → automated lane.\n */\nexport function laneColor(\n edge: TransitionEdge,\n opts: { targetIsTerminal: boolean },\n): string {\n const e = workflowPalette.edge;\n if (edge.disabled) return e.disabled;\n if (edge.isLoopback) return e.loop;\n if (opts.targetIsTerminal) return e.terminal;\n if (edge.summary.processor && edge.summary.processor.kind !== \"none\") {\n return e.processing;\n }\n if (edge.manual) return e.manual;\n if (edge.summary.criterion) return e.conditional;\n return e.automated;\n}\n\n/**\n * Whether the stroke should be rendered dashed (spec §24: dashed-vs-solid\n * carries meaning, colour alone never does).\n */\nexport function laneIsDashed(edge: TransitionEdge): boolean {\n return edge.disabled || edge.isLoopback;\n}\n\n/**\n * SVG `strokeDasharray` value for an edge.\n * - Disabled: tight \"3 2\" — visually reads as \"greyed out / inactive\".\n * - Loopback (non-disabled): \"6 4\" — looser, still dashed.\n * - Otherwise: undefined (solid).\n */\nexport function laneDashArray(edge: TransitionEdge): string | undefined {\n if (edge.disabled) return \"3 2\";\n if (edge.isLoopback) return \"6 4\";\n return undefined;\n}\n","import type { StateNode } from \"@cyoda/workflow-graph\";\nimport { workflowPalette, type RolePaletteEntry, type TerminalPaletteEntry } from \"./tokens.js\";\n\n/**\n * Select the palette entry for a state node.\n * initial-terminal prefers terminal styling (with initial accent applied\n * separately by the renderer — e.g. a secondary border ring).\n */\nexport function paletteFor(\n node: StateNode,\n): RolePaletteEntry | TerminalPaletteEntry {\n const p = workflowPalette.node;\n if (node.role === \"terminal\" || node.role === \"initial-terminal\") return p.terminal;\n if (node.role === \"initial\") return p.initial;\n if (node.category === \"MANUAL_REVIEW\") return p.manualReview;\n if (node.category === \"PROCESSING_STATE\") return p.processing;\n return p.default;\n}\n","import type { TransitionSummary } from \"@cyoda/workflow-graph\";\n\nexport interface BadgeDescriptor {\n key: \"manual\" | \"processor\" | \"criterion\" | \"disabled\" | \"execution\";\n label: string;\n}\n\n/**\n * Translate a transition summary + flags into the ordered list of badges the\n * edge chip should render. Mirrors §10 chip summaries + the visual design\n * section of the implementation plan.\n */\nexport function badgesFor(\n summary: TransitionSummary,\n flags: { manual: boolean; disabled: boolean },\n): BadgeDescriptor[] {\n const out: BadgeDescriptor[] = [];\n\n if (flags.manual) out.push({ key: \"manual\", label: \"Manual\" });\n\n if (summary.processor) {\n if (summary.processor.kind === \"single\") {\n out.push({ key: \"processor\", label: summary.processor.name });\n } else if (summary.processor.kind === \"multiple\") {\n out.push({ key: \"processor\", label: `${summary.processor.count} processors` });\n }\n }\n\n if (summary.criterion) {\n const c = summary.criterion;\n if (c.kind === \"group\") {\n out.push({ key: \"criterion\", label: `${c.operator} · ${c.count}` });\n } else {\n out.push({ key: \"criterion\", label: \"Criterion\" });\n }\n }\n\n if (summary.execution?.kind === \"sync\") {\n out.push({ key: \"execution\", label: \"SYNC\" });\n } else if (summary.execution?.kind === \"asyncSameTx\") {\n out.push({ key: \"execution\", label: \"ASYNC_SAME_TX\" });\n }\n\n if (flags.disabled) out.push({ key: \"disabled\", label: \"Disabled\" });\n\n return out;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { StateNode, TransitionEdge, TransitionSummary } from '@cyoda/workflow-graph';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Design tokens for the Cyoda workflow viewer.
|
|
5
|
+
*
|
|
6
|
+
* Palette values match the existing Cyoda Launchpad workflow diagram at
|
|
7
|
+
* `cyoda-launchpad/src/lib/workflow-diagram/cyoda/CyodaWorkflowDiagram.tsx`.
|
|
8
|
+
* Changes here should be coordinated with that renderer so the website and
|
|
9
|
+
* editor remain visually identical.
|
|
10
|
+
*/
|
|
11
|
+
interface RolePaletteEntry {
|
|
12
|
+
fill: string;
|
|
13
|
+
border: string;
|
|
14
|
+
meta: string;
|
|
15
|
+
title: string;
|
|
16
|
+
}
|
|
17
|
+
interface TerminalPaletteEntry extends RolePaletteEntry {
|
|
18
|
+
innerRing: string;
|
|
19
|
+
}
|
|
20
|
+
interface NodePalette {
|
|
21
|
+
default: RolePaletteEntry;
|
|
22
|
+
initial: RolePaletteEntry;
|
|
23
|
+
terminal: TerminalPaletteEntry;
|
|
24
|
+
manualReview: RolePaletteEntry;
|
|
25
|
+
processing: RolePaletteEntry;
|
|
26
|
+
}
|
|
27
|
+
interface EdgePalette {
|
|
28
|
+
automated: string;
|
|
29
|
+
manual: string;
|
|
30
|
+
conditional: string;
|
|
31
|
+
processing: string;
|
|
32
|
+
terminal: string;
|
|
33
|
+
loop: string;
|
|
34
|
+
disabled: string;
|
|
35
|
+
arrowhead: string;
|
|
36
|
+
}
|
|
37
|
+
interface BadgePaletteEntry {
|
|
38
|
+
fill: string;
|
|
39
|
+
border: string;
|
|
40
|
+
}
|
|
41
|
+
interface BadgePalette {
|
|
42
|
+
manual: BadgePaletteEntry;
|
|
43
|
+
processor: BadgePaletteEntry;
|
|
44
|
+
criterion: BadgePaletteEntry;
|
|
45
|
+
disabled: BadgePaletteEntry;
|
|
46
|
+
text: string;
|
|
47
|
+
}
|
|
48
|
+
interface EdgeLabelPalette {
|
|
49
|
+
fill: string;
|
|
50
|
+
border: string;
|
|
51
|
+
text: string;
|
|
52
|
+
}
|
|
53
|
+
interface NeutralPalette {
|
|
54
|
+
white: string;
|
|
55
|
+
white95: string;
|
|
56
|
+
white75: string;
|
|
57
|
+
slate200: string;
|
|
58
|
+
slate300: string;
|
|
59
|
+
slate500: string;
|
|
60
|
+
slate600: string;
|
|
61
|
+
slate900: string;
|
|
62
|
+
}
|
|
63
|
+
interface WorkflowPalette {
|
|
64
|
+
neutrals: NeutralPalette;
|
|
65
|
+
node: NodePalette;
|
|
66
|
+
edge: EdgePalette;
|
|
67
|
+
edgeLabel: EdgeLabelPalette;
|
|
68
|
+
badge: BadgePalette;
|
|
69
|
+
}
|
|
70
|
+
declare const workflowPalette: WorkflowPalette;
|
|
71
|
+
declare const typography: {
|
|
72
|
+
fontFamily: string;
|
|
73
|
+
monoFamily: string;
|
|
74
|
+
stateCategory: {
|
|
75
|
+
size: number;
|
|
76
|
+
weight: number;
|
|
77
|
+
tracking: string;
|
|
78
|
+
};
|
|
79
|
+
stateTitle: {
|
|
80
|
+
size: number;
|
|
81
|
+
weight: number;
|
|
82
|
+
tracking: string;
|
|
83
|
+
};
|
|
84
|
+
edgeLabel: {
|
|
85
|
+
size: number;
|
|
86
|
+
weight: number;
|
|
87
|
+
tracking: string;
|
|
88
|
+
};
|
|
89
|
+
badge: {
|
|
90
|
+
size: number;
|
|
91
|
+
weight: number;
|
|
92
|
+
tracking: string;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
declare const geometry: {
|
|
96
|
+
node: {
|
|
97
|
+
width: number;
|
|
98
|
+
height: number;
|
|
99
|
+
radius: number;
|
|
100
|
+
strokeWidth: number;
|
|
101
|
+
terminalInset: number;
|
|
102
|
+
terminalInnerRadius: number;
|
|
103
|
+
};
|
|
104
|
+
edge: {
|
|
105
|
+
strokeWidth: number;
|
|
106
|
+
loopStrokeWidth: number;
|
|
107
|
+
arrowheadSize: number;
|
|
108
|
+
};
|
|
109
|
+
labelPill: {
|
|
110
|
+
paddingX: number;
|
|
111
|
+
paddingY: number;
|
|
112
|
+
radius: number;
|
|
113
|
+
shadowOpacity: number;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Category label shown in the small uppercase header line above the state
|
|
119
|
+
* title. Derived from projection data (role + visual category).
|
|
120
|
+
*
|
|
121
|
+
* Reused by the editor shell so the website viewer and editor canvas display
|
|
122
|
+
* identical headers.
|
|
123
|
+
*/
|
|
124
|
+
declare function roleCategoryLabel(node: StateNode): string;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Select the edge stroke color ("lane") for a transition edge.
|
|
128
|
+
*
|
|
129
|
+
* Order of precedence (mirrors the Launchpad renderer):
|
|
130
|
+
* 1. Disabled transitions → disabled lane.
|
|
131
|
+
* 2. Loopback (self or back-edge) → loop lane.
|
|
132
|
+
* 3. Target is a terminal state → terminal lane (set by caller via
|
|
133
|
+
* `targetIsTerminal` since the edge itself doesn't know).
|
|
134
|
+
* 4. Processor-bearing transition → processing lane.
|
|
135
|
+
* 5. Manual transition → manual lane.
|
|
136
|
+
* 6. Has a criterion (non-group) → conditional lane.
|
|
137
|
+
* 7. Default → automated lane.
|
|
138
|
+
*/
|
|
139
|
+
declare function laneColor(edge: TransitionEdge, opts: {
|
|
140
|
+
targetIsTerminal: boolean;
|
|
141
|
+
}): string;
|
|
142
|
+
/**
|
|
143
|
+
* Whether the stroke should be rendered dashed (spec §24: dashed-vs-solid
|
|
144
|
+
* carries meaning, colour alone never does).
|
|
145
|
+
*/
|
|
146
|
+
declare function laneIsDashed(edge: TransitionEdge): boolean;
|
|
147
|
+
/**
|
|
148
|
+
* SVG `strokeDasharray` value for an edge.
|
|
149
|
+
* - Disabled: tight "3 2" — visually reads as "greyed out / inactive".
|
|
150
|
+
* - Loopback (non-disabled): "6 4" — looser, still dashed.
|
|
151
|
+
* - Otherwise: undefined (solid).
|
|
152
|
+
*/
|
|
153
|
+
declare function laneDashArray(edge: TransitionEdge): string | undefined;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Select the palette entry for a state node.
|
|
157
|
+
* initial-terminal prefers terminal styling (with initial accent applied
|
|
158
|
+
* separately by the renderer — e.g. a secondary border ring).
|
|
159
|
+
*/
|
|
160
|
+
declare function paletteFor(node: StateNode): RolePaletteEntry | TerminalPaletteEntry;
|
|
161
|
+
|
|
162
|
+
interface BadgeDescriptor {
|
|
163
|
+
key: "manual" | "processor" | "criterion" | "disabled" | "execution";
|
|
164
|
+
label: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Translate a transition summary + flags into the ordered list of badges the
|
|
168
|
+
* edge chip should render. Mirrors §10 chip summaries + the visual design
|
|
169
|
+
* section of the implementation plan.
|
|
170
|
+
*/
|
|
171
|
+
declare function badgesFor(summary: TransitionSummary, flags: {
|
|
172
|
+
manual: boolean;
|
|
173
|
+
disabled: boolean;
|
|
174
|
+
}): BadgeDescriptor[];
|
|
175
|
+
|
|
176
|
+
export { type BadgeDescriptor, type BadgePalette, type BadgePaletteEntry, type EdgeLabelPalette, type EdgePalette, type NeutralPalette, type NodePalette, type RolePaletteEntry, type TerminalPaletteEntry, type WorkflowPalette, badgesFor, geometry, laneColor, laneDashArray, laneIsDashed, paletteFor, roleCategoryLabel, typography, workflowPalette };
|