Skip to content

Commit fd061f5

Browse files
authored
improvement(deps): harden dependency graph (#7343)
* improvement(deps): harden dependency graph * chore(deps): simplify dependency upkeep * fix(sidebar): preserve cookie whitespace matching * fix(deps): address review edge cases
1 parent b4bc9b9 commit fd061f5

185 files changed

Lines changed: 3925 additions & 1814 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

NOTICE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Sim Studio
22
Copyright 2026 Sim Studio
33

4-
This product includes software developed for the Sim project.
4+
This product includes software developed for the Sim project.

apps/desktop/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@
5050
"@sim/tsconfig": "workspace:*",
5151
"@types/micromatch": "4.0.10",
5252
"@types/node": "24.2.1",
53-
"electron": "43.5.0",
53+
"electron": "43.4.1",
5454
"electron-builder": "26.15.3",
5555
"esbuild": "0.28.1",
56+
"jsdom": "^26.0.0",
5657
"typescript": "^7.0.2",
5758
"vitest": "^4.1.0"
5859
}

apps/docs/app/global.css

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ body {
5454
nominally references; loading a webfont here would make docs the odd one out, not the
5555
aligned one. If the app ever wires that font up for real, add the var back in both
5656
places at once. */
57-
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
58-
"Courier New", monospace;
57+
--font-mono:
58+
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
59+
monospace;
5960
}
6061

6162
/* Pure white light mode background */
@@ -243,14 +244,16 @@ body {
243244

244245
/* Font family utilities */
245246
.font-sans {
246-
font-family: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
247-
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
247+
font-family:
248+
var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
249+
Roboto, "Helvetica Neue", Arial, sans-serif;
248250
}
249251

250252
/* Platform UI font — Season Sans, used by the chip chrome to match the main app */
251253
.font-season {
252-
font-family: var(--font-season), system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial,
253-
"Noto Sans", sans-serif;
254+
font-family:
255+
var(--font-season), system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans",
256+
sans-serif;
254257
}
255258

256259
:root {
@@ -445,8 +448,9 @@ html #nd-sidebar button:not([aria-label*="ollapse"]):not([aria-label*="xpand"])
445448
padding: 5px 0.5rem !important; /* 30px tall overall — the app's chip pill, at its px-2 */
446449
font-weight: 400 !important;
447450
border-radius: 0.5rem !important; /* platform rounded-lg */
448-
font-family: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
449-
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
451+
font-family:
452+
var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
453+
Roboto, "Helvetica Neue", Arial, sans-serif !important;
450454
}
451455

452456
/* Sidebar text — platform --text-body */
@@ -904,8 +908,9 @@ video {
904908
#nd-page:has(.api-page-header) div:not(.font-mono),
905909
#nd-page:has(.api-page-header) label:not(.font-mono),
906910
#nd-page:has(.api-page-header) button:not(.font-mono) {
907-
font-family: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
908-
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
911+
font-family:
912+
var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
913+
Roboto, "Helvetica Neue", Arial, sans-serif;
909914
}
910915

911916
/* Method badge pills — shared background colors (page + sidebar) */

apps/docs/components/workflow-preview/block-preview.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
'use client'
22

33
import { useMemo } from 'react'
4+
import { type NodeTypes, ReactFlow, ReactFlowProvider } from '@xyflow/react'
45
import { domAnimation, LazyMotion } from 'framer-motion'
5-
import ReactFlow, { type NodeTypes, ReactFlowProvider } from 'reactflow'
6-
import 'reactflow/dist/style.css'
6+
import '@xyflow/react/dist/style.css'
77
import { BLOCK_DISPLAY_WORKFLOWS } from '@/components/workflow-preview/block-display-workflows'
88
import { DocsBlockNode } from '@/components/workflow-preview/docs-block-node'
99
import { toReactFlowElements } from '@/components/workflow-preview/workflow-data'
1010

1111
/** The hero mounts the same node type the canvas uses, so it can never drift. */
12-
const NODE_TYPES: NodeTypes = { previewBlock: DocsBlockNode }
12+
const NODE_TYPES = { previewBlock: DocsBlockNode } satisfies NodeTypes
1313
const PRO_OPTIONS = { hideAttribution: true }
1414
/** `maxZoom` mirrors the previous hand-rolled hero's 1.3 scale. */
1515
const FIT_VIEW_OPTIONS = { padding: 0.2, maxZoom: 1.3 } as const

apps/docs/components/workflow-preview/docs-block-node.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import { type ComponentType, memo } from 'react'
44
import { SubBlockRowView, WorkflowBlockView } from '@sim/workflow-renderer'
5+
import type { Node, NodeProps } from '@xyflow/react'
56
import { m } from 'framer-motion'
6-
import type { NodeProps } from 'reactflow'
77
import { resolveIcon } from '@/components/workflow-preview/block-icons'
88
import {
99
BLOCK_STAGGER,
@@ -16,7 +16,7 @@ const EMPTY_ICON: ComponentType<{ className?: string }> = () => null
1616

1717
const RING_STYLES = 'ring-[1.75px] ring-[var(--brand-secondary)]'
1818

19-
interface DocsBlockData {
19+
export interface DocsBlockData extends Record<string, unknown> {
2020
name: string
2121
blockType: string
2222
bgColor: string
@@ -30,6 +30,8 @@ interface DocsBlockData {
3030
isDimmed?: boolean
3131
}
3232

33+
export type DocsBlockNodeType = Node<DocsBlockData, 'previewBlock'>
34+
3335
/**
3436
* Docs adapter for workflow block nodes: maps the static preview data to the
3537
* shared {@link WorkflowBlockView}'s props. Carries no stores, hooks, or
@@ -38,7 +40,10 @@ interface DocsBlockData {
3840
* `WorkflowPreview` provides the `LazyMotion` feature set). The block's ring is
3941
* driven by `hasRing`/`ringStyles` inside the View.
4042
*/
41-
export const DocsBlockNode = memo(function DocsBlockNode({ id, data }: NodeProps<DocsBlockData>) {
43+
export const DocsBlockNode = memo(function DocsBlockNode({
44+
id,
45+
data,
46+
}: NodeProps<DocsBlockNodeType>) {
4247
const {
4348
name,
4449
blockType,

apps/docs/components/workflow-preview/docs-container-node.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22

33
import { memo } from 'react'
44
import { type SubflowNodeData, SubflowNodeView } from '@sim/workflow-renderer'
5-
import type { NodeProps } from 'reactflow'
5+
import type { Node, NodeProps } from '@xyflow/react'
66

7-
interface DocsContainerData {
7+
export interface DocsContainerData extends Record<string, unknown> {
88
name: string
99
blockType: string
1010
size?: { width: number; height: number }
1111
parentId?: string
1212
}
1313

14+
export type DocsContainerNodeType = Node<DocsContainerData, 'previewContainer'>
15+
1416
/**
1517
* Docs adapter for loop/parallel container blocks: maps the static preview data
1618
* to {@link SubflowNodeView}'s read-only `isPreview` shape. Carries no stores,
@@ -19,7 +21,7 @@ interface DocsContainerData {
1921
export const DocsContainerNode = memo(function DocsContainerNode({
2022
id,
2123
data,
22-
}: NodeProps<DocsContainerData>) {
24+
}: NodeProps<DocsContainerNodeType>) {
2325
const subflowData: SubflowNodeData = {
2426
kind: data.blockType === 'parallel' ? 'parallel' : 'loop',
2527
name: data.name,

apps/docs/components/workflow-preview/workflow-data.ts

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ import {
44
getEdgeZIndex,
55
getEdgeZIndexForTarget,
66
} from '@sim/workflow-renderer'
7-
import { type Edge, type Node, Position } from 'reactflow'
7+
import { type Edge, Position } from '@xyflow/react'
8+
import type {
9+
DocsBlockData,
10+
DocsBlockNodeType,
11+
} from '@/components/workflow-preview/docs-block-node'
12+
import type {
13+
DocsContainerData,
14+
DocsContainerNodeType,
15+
} from '@/components/workflow-preview/docs-container-node'
816

917
/**
1018
* Tool entry displayed as a chip on a block (e.g. an Agent's attached tools).
@@ -51,6 +59,15 @@ export interface PreviewWorkflow {
5159
edges: Array<{ id: string; source: string; target: string; sourceHandle?: string }>
5260
}
5361

62+
export type PreviewNode = DocsBlockNodeType | DocsContainerNodeType
63+
64+
export interface PreviewEdgeData extends Record<string, unknown> {
65+
animate: boolean
66+
delay: number
67+
}
68+
69+
export type PreviewFlowEdge = Edge<PreviewEdgeData, 'previewEdge'>
70+
5471
export const BLOCK_STAGGER = 0.12
5572
export const EASE_OUT: [number, number, number, number] = [0.16, 1, 0.3, 1]
5673

@@ -96,14 +113,14 @@ export function toReactFlowElements(
96113
workflow: PreviewWorkflow,
97114
animate = false,
98115
highlight: HighlightOptions = {}
99-
): { nodes: Node[]; edges: Edge[] } {
116+
): { nodes: PreviewNode[]; edges: PreviewFlowEdge[] } {
100117
const { highlightBlock, highlightEdge, selectedBlock } = highlight
101118
const hasHighlight = Boolean(highlightBlock || highlightEdge)
102119
const blockIndexMap = new Map(workflow.blocks.map((b, i) => [b.id, i]))
103120

104121
const blocksById = new Map(workflow.blocks.map((b) => [b.id, b]))
105122

106-
const nodes: Node[] = workflow.blocks.map((block, index) => {
123+
const nodes: PreviewNode[] = workflow.blocks.map((block, index) => {
107124
const isContainer = Boolean(block.size)
108125
const nestingDepth = getNestingDepth(block, blocksById)
109126
// Nested blocks are authored relative to their container; render them at
@@ -113,13 +130,20 @@ export function toReactFlowElements(
113130
const position = parent
114131
? { x: parent.position.x + block.position.x, y: parent.position.y + block.position.y }
115132
: block.position
116-
return {
133+
const commonNode = {
117134
id: block.id,
118-
type: isContainer ? 'previewContainer' : 'previewBlock',
119135
position,
120136
zIndex: isContainer ? nestingDepth : block.parentId ? CONTAINER_CHILD_Z_BASE : BLOCK_Z_BASE,
121137
...(block.size ? { style: { width: block.size.width, height: block.size.height } } : {}),
122-
data: {
138+
draggable: true,
139+
selectable: false,
140+
connectable: false,
141+
sourcePosition: Position.Right,
142+
targetPosition: Position.Left,
143+
}
144+
145+
if (isContainer) {
146+
const data: DocsContainerData = {
123147
name: block.name,
124148
blockType: block.type,
125149
bgColor: block.bgColor,
@@ -133,16 +157,37 @@ export function toReactFlowElements(
133157
animate,
134158
isHighlighted: highlightBlock === block.id || selectedBlock === block.id,
135159
isDimmed: hasHighlight && highlightBlock !== block.id,
136-
},
137-
draggable: true,
138-
selectable: false,
139-
connectable: false,
140-
sourcePosition: Position.Right,
141-
targetPosition: Position.Left,
160+
}
161+
return {
162+
...commonNode,
163+
type: 'previewContainer',
164+
data,
165+
}
166+
}
167+
168+
const data: DocsBlockData = {
169+
name: block.name,
170+
blockType: block.type,
171+
bgColor: block.bgColor,
172+
rows: block.rows,
173+
branches: block.branches,
174+
tools: block.tools,
175+
hideTargetHandle: block.hideTargetHandle,
176+
size: block.size,
177+
parentId: block.parentId,
178+
index,
179+
animate,
180+
isHighlighted: highlightBlock === block.id || selectedBlock === block.id,
181+
isDimmed: hasHighlight && highlightBlock !== block.id,
182+
}
183+
return {
184+
...commonNode,
185+
type: 'previewBlock',
186+
data,
142187
}
143188
})
144189

145-
const edges: Edge[] = workflow.edges.map((e) => {
190+
const edges: PreviewFlowEdge[] = workflow.edges.map((e) => {
146191
const sourceIndex = blockIndexMap.get(e.source) ?? 0
147192
const isEdgeHighlight = highlightEdge === e.id
148193
const dimmed = hasHighlight && !isEdgeHighlight

apps/docs/components/workflow-preview/workflow-preview.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,29 @@
22

33
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import { Expand, X } from '@sim/emcn/icons'
5-
import { domAnimation, LazyMotion, m } from 'framer-motion'
6-
import ReactFlow, {
5+
import {
76
applyEdgeChanges,
87
applyNodeChanges,
9-
type Edge,
108
type EdgeProps,
119
type EdgeTypes,
1210
getSmoothStepPath,
13-
type Node,
1411
type NodeTypes,
1512
type OnEdgesChange,
1613
type OnNodesChange,
14+
ReactFlow,
1715
ReactFlowProvider,
18-
} from 'reactflow'
19-
import 'reactflow/dist/style.css'
16+
} from '@xyflow/react'
17+
import { domAnimation, LazyMotion, m } from 'framer-motion'
18+
import '@xyflow/react/dist/style.css'
2019
import { BLOCK_DISPLAY_WORKFLOWS } from '@/components/workflow-preview/block-display-workflows'
2120
import { BlockInspector } from '@/components/workflow-preview/block-inspector'
2221
import { DocsBlockNode } from '@/components/workflow-preview/docs-block-node'
2322
import { DocsContainerNode } from '@/components/workflow-preview/docs-container-node'
2423
import {
2524
EASE_OUT,
2625
type PreviewBlock,
26+
type PreviewFlowEdge,
27+
type PreviewNode,
2728
type PreviewWorkflow,
2829
toReactFlowElements,
2930
} from '@/components/workflow-preview/workflow-data'
@@ -50,7 +51,7 @@ function PreviewEdge({
5051
targetPosition,
5152
style,
5253
data,
53-
}: EdgeProps) {
54+
}: EdgeProps<PreviewFlowEdge>) {
5455
const [edgePath] = getSmoothStepPath({
5556
sourceX,
5657
sourceY,
@@ -89,11 +90,11 @@ function PreviewEdge({
8990
)
9091
}
9192

92-
const NODE_TYPES: NodeTypes = {
93+
const NODE_TYPES = {
9394
previewBlock: DocsBlockNode,
9495
previewContainer: DocsContainerNode,
95-
}
96-
const EDGE_TYPES: EdgeTypes = { previewEdge: PreviewEdge }
96+
} satisfies NodeTypes
97+
const EDGE_TYPES = { previewEdge: PreviewEdge } satisfies EdgeTypes
9798
const PRO_OPTIONS = { hideAttribution: true }
9899
const FIT_VIEW_OPTIONS = { padding: 0.25, maxZoom: 1 } as const
99100
const LIGHTBOX_FIT_VIEW_OPTIONS = { padding: 0.3, maxZoom: 1.4 } as const
@@ -176,8 +177,8 @@ function PreviewFlow({
176177
[workflow, animate, highlightBlock, highlightEdge, selectedBlock]
177178
)
178179

179-
const [nodes, setNodes] = useState<Node[]>(initialNodes)
180-
const [edges, setEdges] = useState<Edge[]>(initialEdges)
180+
const [nodes, setNodes] = useState<PreviewNode[]>(initialNodes)
181+
const [edges, setEdges] = useState<PreviewFlowEdge[]>(initialEdges)
181182

182183
/**
183184
* Apply data changes (highlight/selection) without discarding positions the
@@ -194,17 +195,17 @@ function PreviewFlow({
194195
setEdges(initialEdges)
195196
}, [initialNodes, initialEdges])
196197

197-
const onNodesChange: OnNodesChange = useCallback(
198+
const onNodesChange: OnNodesChange<PreviewNode> = useCallback(
198199
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
199200
[]
200201
)
201-
const onEdgesChange: OnEdgesChange = useCallback(
202+
const onEdgesChange: OnEdgesChange<PreviewFlowEdge> = useCallback(
202203
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
203204
[]
204205
)
205206

206207
return (
207-
<ReactFlow
208+
<ReactFlow<PreviewNode, PreviewFlowEdge>
208209
nodes={nodes}
209210
edges={edges}
210211
onNodesChange={onNodesChange}

apps/docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@sim/db": "workspace:*",
2222
"@sim/emcn": "workspace:*",
2323
"@sim/workflow-renderer": "workspace:*",
24+
"@xyflow/react": "12.11.3",
2425
"class-variance-authority": "^0.7.1",
2526
"clsx": "^2.1.1",
2627
"drizzle-orm": "^0.45.2",
@@ -35,7 +36,6 @@
3536
"remark-breaks": "^4.0.0",
3637
"shiki": "4.3.1",
3738
"tailwind-merge": "^3.0.2",
38-
"reactflow": "^11.11.4",
3939
"framer-motion": "^12.5.0",
4040
"zod": "4.3.6"
4141
},

0 commit comments

Comments
 (0)