@glyphlab/diagram-react 0.0.0-stage → 0.1.1
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 +21 -0
- package/README.md +28 -2
- package/diagram.css +892 -0
- package/index.d.ts +192 -0
- package/index.js +1727 -0
- package/index.js.map +1 -0
- package/package.json +46 -4
- package/theme.css +102 -0
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/actions.ts","../src/colors.ts","../src/ArrowHeads.tsx","../src/beginConnect.ts","../src/ColorControl.tsx","../src/context.ts","../src/DiagramProvider.tsx","../src/DiagramCanvas.tsx","../src/EdgeEditor.tsx","../src/GroupEditor.tsx","../src/ConnectHandles.tsx","../src/CanvasMenu.tsx","../src/ResizeHandles.tsx","../src/beginEdit.ts","../src/DiagramEdge.tsx","../src/hooks.ts","../src/DiagramGroup.tsx","../src/DiagramNode.tsx","../src/LinkBadge.tsx","../src/NodeEditor.tsx","../src/EdgeLabel.tsx","../src/DiagramLayers.tsx","../src/EdgeStyleControl.tsx","../src/SwimlaneControls.tsx","../src/DiagramToolbar.tsx","../src/ZoomControls.tsx","../src/DiagramViewer.tsx","../src/ui.ts","../src/instance.ts"],"sourcesContent":["import type { DiagramController } from '@glyphlab/diagram-core'\n\n// What a person does on the canvas, as changes to the diagram: each is one `apply`, with source 'user', so it is one undoable change in\n// whatever history the host keeps, and a proposal an agent wrote before it goes stale.\n\nconst NEW_NODE = { w: 280, h: 150 }\nconst NEW_GROUP = { w: 360, h: 240 }\n\n// Adds a node centred on a point, and returns its id.\nexport function addNodeAt(controller: DiagramController, x: number, y: number, laneId?: string, onError?: (message: string) => void): string | undefined {\n const before = new Set(controller.getSnapshot().nodes.map((n) => n.id))\n const result = controller.apply({\n ops: [{ op: 'createNode', node: { title: 'New node', body: '', x: Math.round(x - NEW_NODE.w / 2), y: Math.round(y - NEW_NODE.h / 2), ...(laneId && { laneId }) } }],\n summary: 'Add node',\n source: 'user',\n })\n if (!result.ok) {\n onError?.(result.message)\n return undefined\n }\n return controller.getSnapshot().nodes.find((n) => !before.has(n.id))?.id\n}\n\n// Adds an empty group (a labelled box) centred on a point, and returns its id.\nexport function addGroupAt(controller: DiagramController, x: number, y: number): string | undefined {\n const before = new Set(controller.getSnapshot().groups.map((g) => g.id))\n const result = controller.apply({\n ops: [{ op: 'createGroup', group: { title: 'New group', nodeIds: [], x: Math.round(x - NEW_GROUP.w / 2), y: Math.round(y - NEW_GROUP.h / 2), w: NEW_GROUP.w, h: NEW_GROUP.h } }],\n summary: 'Add group',\n source: 'user',\n })\n if (!result.ok) return undefined\n return controller.getSnapshot().groups.find((g) => !before.has(g.id))?.id\n}\n\n// A node takes its edges with it.\nexport function deleteNode(controller: DiagramController, id: string) {\n const title = controller.stores.nodes.getState().byId[id]?.title ?? id\n controller.apply({ ops: [{ op: 'deleteNode', id }], summary: `Delete node “${title}”`, source: 'user' })\n}\n\n// Only the box goes; the nodes it was drawn around stay.\nexport function deleteGroup(controller: DiagramController, id: string) {\n const title = controller.stores.groups.getState().byId[id]?.title ?? id\n controller.apply({ ops: [{ op: 'deleteGroup', id }], summary: `Delete group “${title}”`, source: 'user' })\n}\n\nexport function deleteEdge(controller: DiagramController, id: string) {\n const label = controller.stores.edges.getState().byId[id]?.label\n controller.apply({ ops: [{ op: 'deleteEdge', id }], summary: `Delete edge${label ? ` “${label}”` : ''}`, source: 'user' })\n}\n","import type { CSSProperties } from 'react'\nimport { arrowId, colorCss, colorKey, colorLabel, COLOR_PRESETS, isPreset } from '@glyphlab/diagram-core'\n\nexport { arrowId, colorCss, colorKey, colorLabel, COLOR_PRESETS, isPreset }\n\n// A node or group takes its colour from --layer, so a chosen colour replaces the default one.\nexport function layerStyle(color: string | undefined): CSSProperties {\n const css = colorCss(color)\n return css ? ({ '--layer': css } as CSSProperties) : {}\n}\n\n// A line takes its colour from --edge-color (the 'colored' class puts it on the stroke).\nexport const edgeColor = colorCss\nexport function edgeStyle(color: string | undefined): CSSProperties | undefined {\n const css = colorCss(color)\n return css ? ({ '--edge-color': css } as CSSProperties) : undefined\n}\n\n// The id the arrow heads of one diagram's lines start from.\nexport const arrowBase = (uid: string) => `${uid}-arrow`\n","import { arrowId, colorCss } from './colors'\n\n// The arrow heads for a set of lines: the usual one with `id`, and one per colour the lines use.\nexport function ArrowHeads({ id, colors }: { id: string; colors: (string | undefined)[] }) {\n const used = [...new Set(colors.filter((c): c is string => c !== undefined && colorCss(c) !== undefined))]\n return (\n <>\n <marker id={id} viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\n <path d=\"M 0 1 L 9 5 L 0 9 z\" className=\"arrow-head\" />\n </marker>\n {used.map((color) => (\n <marker key={color} id={arrowId(id, color)} viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\n <path d=\"M 0 1 L 9 5 L 0 9 z\" className=\"arrow-head\" style={{ fill: colorCss(color) }} />\n </marker>\n ))}\n </>\n )\n}\n","import type { PointerEvent as ReactPointerEvent } from 'react'\nimport type { DiagramInstance } from './instance'\n\ntype Side = 'n' | 'e' | 's' | 'w'\n\nexport function sidePoint(node: { x: number; y: number; w: number; h: number }, side: Side) {\n if (side === 'n') return { x: node.x + node.w / 2, y: node.y }\n if (side === 's') return { x: node.x + node.w / 2, y: node.y + node.h }\n if (side === 'w') return { x: node.x, y: node.y + node.h / 2 }\n return { x: node.x + node.w, y: node.y + node.h / 2 }\n}\n\n// A pointer position on the screen as a position on the diagram.\nexport function toDiagram(instance: DiagramInstance, clientX: number, clientY: number) {\n const canvas = instance.surface.el?.getBoundingClientRect()\n const { x, y, scale } = instance.ui.viewport.getState()\n return { x: (clientX - (canvas?.left ?? 0) - x) / scale, y: (clientY - (canvas?.top ?? 0) - y) / scale }\n}\n\nconst nodeUnder = (instance: DiagramInstance, clientX: number, clientY: number, not: string) => {\n const found = document.elementFromPoint(clientX, clientY)?.closest<HTMLElement>('[data-node-id]')\n // A node of another canvas on the same page is not a place to connect to.\n if (!found || (instance.surface.el && !instance.surface.el.contains(found))) return null\n const id = found.dataset.nodeId\n return id && id !== not ? id : null\n}\n\n// Drags an edge out of a node. Dropping it on another node connects them, as one undoable change;\n// dropping anywhere else, or pressing Escape, does nothing.\nexport function beginConnect(instance: DiagramInstance, e: ReactPointerEvent, source: string, side: Side) {\n if (e.button !== 0) return\n // Without this the press would start a canvas pan.\n e.stopPropagation()\n e.preventDefault()\n const from = instance.controller.stores.nodes.getState().byId[source]\n if (!from) return\n\n const connect = instance.ui.connect\n connect.getState().start(source, side, toDiagram(instance, e.clientX, e.clientY))\n\n const onMove = (ev: PointerEvent) => connect.getState().move(toDiagram(instance, ev.clientX, ev.clientY), nodeUnder(instance, ev.clientX, ev.clientY, source))\n\n const stop = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n window.removeEventListener('pointercancel', onCancel)\n window.removeEventListener('keydown', onKey, true)\n connect.getState().end()\n }\n\n const onUp = (ev: PointerEvent) => {\n const target = nodeUnder(instance, ev.clientX, ev.clientY, source)\n stop()\n if (target) connectNodes(instance, source, target)\n }\n\n const onCancel = () => stop()\n\n const onKey = (ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return\n ev.stopPropagation()\n stop()\n }\n\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n window.addEventListener('pointercancel', onCancel)\n window.addEventListener('keydown', onKey, true)\n}\n\n// Adds an unlabelled edge, or selects the one that is already there.\nexport function connectNodes(instance: DiagramInstance, from: string, to: string) {\n const { controller, ui } = instance\n const nodes = controller.stores.nodes.getState().byId\n const find = () => controller.getSnapshot().edges.find((edge) => edge.from === from && edge.to === to && edge.label === '')\n const found = find()\n if (found) {\n ui.selection.getState().select({ kind: 'edge', id: found.id })\n return\n }\n const result = controller.apply({\n ops: [{ op: 'createEdge', edge: { from, to, label: '' } }],\n summary: `Connect “${nodes[from]?.title ?? from}” → “${nodes[to]?.title ?? to}”`,\n source: 'user',\n })\n if (!result.ok) return\n const id = find()?.id\n if (id) ui.selection.getState().select({ kind: 'edge', id })\n}\n","import { useEffect, useRef } from 'react'\nimport type { DiagramOp } from '@glyphlab/diagram-core'\nimport { useDiagram, useEdges, useGroups, useNodes, useSelection } from './context'\nimport { COLOR_PRESETS, colorCss, colorLabel, isPreset } from './colors'\n\nconst KIND_LABEL = { node: 'node', group: 'group', edge: 'edge' } as const\n\n// Chooses the colour of the selected node, group or edge: a preset (which follows the light or dark theme), a colour of\n// your own, or none. Each choice is one undoable change.\nexport function ColorControl() {\n const { controller } = useDiagram()\n const selection = useSelection((s) => s.selection)\n const item = useNodes((s) => (selection?.kind === 'node' ? s.byId[selection.id] : undefined))\n const group = useGroups((s) => (selection?.kind === 'group' ? s.byId[selection.id] : undefined))\n const edge = useEdges((s) => (selection?.kind === 'edge' ? s.byId[selection.id] : undefined))\n const custom = useRef<HTMLInputElement>(null)\n const current = (item ?? group ?? edge)?.color\n const name = item?.title ?? group?.title ?? edge?.label ?? 'edge'\n\n const choose = (color: string | null) => {\n if (!selection || color === (current ?? null)) return\n const { id } = selection\n const op: DiagramOp = selection.kind === 'node' ? { op: 'updateNode', id, patch: { color } } : selection.kind === 'group' ? { op: 'updateGroup', id, patch: { color } } : { op: 'updateEdge', id, patch: { color } }\n controller.apply({ ops: [op], summary: `${color === null ? 'Remove the color of' : 'Color'} ${KIND_LABEL[selection.kind]} “${name}”`, source: 'user' })\n }\n\n // The picker reports every step while it is dragged; only the colour it settles on is a change.\n const latest = useRef(choose)\n useEffect(() => {\n latest.current = choose\n })\n useEffect(() => {\n const input = custom.current\n if (!input) return\n const onChange = () => latest.current(input.value.toLowerCase())\n input.addEventListener('change', onChange)\n return () => input.removeEventListener('change', onChange)\n }, [selection])\n\n // The picker shows the colour of your own that the selection has, if it has one.\n useEffect(() => {\n if (custom.current && current && !isPreset(current)) custom.current.value = current\n }, [current, selection])\n\n if (!selection || !(item ?? group ?? edge)) return null\n const isOwn = current !== undefined && !isPreset(current)\n\n return (\n <div\n className=\"color-control\"\n role=\"group\"\n aria-label={`Color of the selected ${KIND_LABEL[selection.kind]}`}\n onPointerDown={(e) => e.stopPropagation()}\n onContextMenu={(e) => e.stopPropagation()}\n >\n <button type=\"button\" className=\"color-swatch none\" aria-label=\"Default color\" aria-pressed={current === undefined} title=\"Default color\" onClick={() => choose(null)}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M5.6 5.6l12.8 12.8\" />\n </svg>\n </button>\n {COLOR_PRESETS.map((preset) => (\n <button\n key={preset}\n type=\"button\"\n className=\"color-swatch\"\n style={{ background: colorCss(preset) }}\n aria-label={colorLabel(preset)}\n aria-pressed={current === preset}\n title={colorLabel(preset)}\n onClick={() => choose(preset)}\n />\n ))}\n <label className={`color-swatch custom${isOwn ? ' on' : ''}`} title=\"Choose another color\">\n <input ref={custom} type=\"color\" aria-label=\"Custom color\" defaultValue=\"#3b82f6\" />\n </label>\n </div>\n )\n}\n","import { createContext, useContext } from 'react'\nimport type { ReactNode } from 'react'\nimport { useStore } from 'zustand'\nimport type { StoreApi } from 'zustand/vanilla'\nimport type { EdgeState, GroupState, MetaState, NodeState } from '@glyphlab/diagram-core'\nimport type { DiagramInstance } from './instance'\nimport type { NodeLinkState } from './LinkBadge'\nimport type { ConnectState, EditState, HighlightState, SelectionState, ViewportState } from './ui'\n\n// What a host supplies that the canvas does not know how to do itself.\nexport interface DiagramSlots {\n // Draws a node's content (the node's body is Markdown). Without it the text is shown as it is.\n renderMarkdown?: (source: string) => ReactNode\n openNodeContent?: (id: string, section?: 'decisions' | 'code') => void\n // A hook giving a node's staleness (from the link check), or undefined when it has not been checked. Only a node that is not ok gets an icon.\n useLinkState?: (id: string) => NodeLinkState | undefined\n}\n\nexport interface DiagramContextValue {\n instance: DiagramInstance\n slots: DiagramSlots\n}\n\nexport const DiagramContext = createContext<DiagramContextValue | null>(null)\n\nconst useContextValue = () => {\n const value = useContext(DiagramContext)\n if (!value) throw new Error('This component must be inside a DiagramProvider.')\n return value\n}\n\nexport const useDiagram = (): DiagramInstance => useContextValue().instance\nexport const useSlots = (): DiagramSlots => useContextValue().slots\n\n// Reads one thing from one of the diagram's stores (or the canvas's), so a component re-renders only when that changes.\nfunction useSelected<S, T>(api: StoreApi<S>, selector: (state: S) => T): T {\n return useStore(api, selector)\n}\n\nexport const useNodes = <T,>(selector: (state: NodeState) => T) => useSelected(useDiagram().controller.stores.nodes, selector)\nexport const useEdges = <T,>(selector: (state: EdgeState) => T) => useSelected(useDiagram().controller.stores.edges, selector)\nexport const useGroups = <T,>(selector: (state: GroupState) => T) => useSelected(useDiagram().controller.stores.groups, selector)\nexport const useMeta = <T,>(selector: (state: MetaState) => T) => useSelected(useDiagram().controller.stores.meta, selector)\nexport const useViewport = <T,>(selector: (state: ViewportState) => T) => useSelected(useDiagram().ui.viewport, selector)\nexport const useSelection = <T,>(selector: (state: SelectionState) => T) => useSelected(useDiagram().ui.selection, selector)\nexport const useEditing = <T,>(selector: (state: EditState) => T) => useSelected(useDiagram().ui.edit, selector)\nexport const useConnecting = <T,>(selector: (state: ConnectState) => T) => useSelected(useDiagram().ui.connect, selector)\nexport const useHighlights = <T,>(selector: (state: HighlightState) => T) => useSelected(useDiagram().ui.highlight, selector)\n\n// A store made elsewhere, used like the ones zustand's `create` makes: a hook with the store's own getState, setState and subscribe on it.\n// For a host that has global code written against such hooks.\nexport function bindStore<S>(api: StoreApi<S>) {\n function useBound(): S\n function useBound<T>(selector: (state: S) => T): T\n function useBound<T>(selector?: (state: S) => T) {\n return useStore(api, selector as (state: S) => T)\n }\n return Object.assign(useBound, api)\n}\n","import type { ReactNode } from 'react'\nimport { DiagramContext } from './context'\nimport type { DiagramSlots } from './context'\nimport type { DiagramInstance } from './instance'\n\n// Gives the canvas components below it a diagram to show: an instance (a controller and the canvas state for it) and what the host supplies.\nexport function DiagramProvider({ instance, slots = {}, children }: { instance: DiagramInstance; slots?: DiagramSlots; children: ReactNode }) {\n return <DiagramContext.Provider value={{ instance, slots }}>{children}</DiagramContext.Provider>\n}\n","import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { diagramBounds } from '@glyphlab/diagram-core'\nimport { deleteEdge, deleteGroup, deleteNode } from './actions'\nimport { useDiagram, useGroups, useHighlights, useNodes, useViewport } from './context'\nimport { EdgeEditor } from './EdgeEditor'\nimport { GroupEditor } from './GroupEditor'\nimport { ConnectHandles, ConnectPreview } from './ConnectHandles'\nimport { CanvasMenu } from './CanvasMenu'\nimport type { CanvasMenuState } from './CanvasMenu'\nimport { toDiagram } from './beginConnect'\nimport { ResizeHandles } from './ResizeHandles'\nimport { EdgeLabelLayer, EdgeLayer, GroupLayer, NodeLayer } from './DiagramLayers'\nimport { DiagramToolbar } from './DiagramToolbar'\nimport { ZoomControls } from './ZoomControls'\n\nconst GRID = 24\n// Pointer travel under this many pixels counts as a click, not a pan.\nconst CLICK_SLOP = 3\n\ninterface DragState {\n px: number\n py: number\n vx: number\n vy: number\n moved: boolean\n}\n\n// `designKey` changes when a different diagram is shown, so the view is fitted to it again. `empty` is what the canvas says when there is\n// nothing on it at all (no nodes and no groups).\nexport function DiagramCanvas({ title, designKey, empty: emptyMessage }: { title: string; designKey?: string | number; empty?: ReactNode }) {\n const instance = useDiagram()\n const { controller, ui } = instance\n const ref = useRef<HTMLElement>(null)\n const drag = useRef<DragState | null>(null)\n const [menu, setMenu] = useState<CanvasMenuState | null>(null)\n\n const x = useViewport((s) => s.x)\n const y = useViewport((s) => s.y)\n const scale = useViewport((s) => s.scale)\n const panning = useViewport((s) => s.panning)\n\n const groupsById = useGroups((s) => s.byId)\n const dimmed = useHighlights((s) => s.dimmed)\n // Empty means nothing at all: a diagram of only groups is not empty.\n const noNodes = useNodes((s) => s.ids.length === 0)\n const noGroups = useGroups((s) => s.ids.length === 0)\n const empty = noNodes && noGroups\n const nodesById = useNodes((s) => s.byId)\n const bounds = useMemo(() => diagramBounds(Object.values(groupsById), Object.values(nodesById)), [groupsById, nodesById])\n\n const size = useCallback(() => {\n const el = ref.current\n return { width: el?.clientWidth ?? 0, height: el?.clientHeight ?? 0 }\n }, [])\n\n const fit = useCallback(() => ui.viewport.getState().fit(size(), bounds), [ui, size, bounds])\n\n const zoomCenter = useCallback(\n (factor: number) => {\n const { width, height } = size()\n ui.viewport.getState().zoomAround(factor, width / 2, height / 2)\n },\n [ui, size],\n )\n\n useLayoutEffect(() => {\n // The first layout, and each time another diagram is shown; other bounds changes (the assistant\n // adding a node) must not reset the user's view.\n ui.viewport.getState().reset(size(), bounds)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [designKey])\n\n // Native listener so preventDefault works: pinch / ctrl+wheel zooms, plain wheel pans.\n useEffect(() => {\n const el = ref.current\n if (!el) return\n instance.surface.el = el\n const onWheel = (e: WheelEvent) => {\n // A text box being edited scrolls itself.\n if ((e.target as HTMLElement | null)?.closest?.('textarea')) return\n e.preventDefault()\n const viewport = ui.viewport.getState()\n if (e.ctrlKey || e.metaKey) {\n const rect = el.getBoundingClientRect()\n viewport.zoomAround(Math.exp(-e.deltaY * 0.01), e.clientX - rect.left, e.clientY - rect.top)\n } else {\n viewport.panBy(-e.deltaX, -e.deltaY)\n }\n }\n el.addEventListener('wheel', onWheel, { passive: false })\n return () => {\n el.removeEventListener('wheel', onWheel)\n if (instance.surface.el === el) instance.surface.el = null\n }\n }, [instance, ui])\n\n useEffect(() => {\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') ui.selection.getState().clearSelection()\n if (e.key !== 'Delete' && e.key !== 'Backspace') return\n if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey || e.defaultPrevented) return\n if ((e.target as HTMLElement | null)?.closest?.('input, textarea, select, [contenteditable]')) return\n // Only when nothing else has the keyboard: not a text field, and not a list that has its own Delete.\n const target = e.target as HTMLElement | null\n if (target && target !== document.body && !ref.current?.contains(target)) return\n const { selection } = ui.selection.getState()\n if (!selection) return\n e.preventDefault()\n if (selection.kind === 'node') deleteNode(controller, selection.id)\n else if (selection.kind === 'group') deleteGroup(controller, selection.id)\n else deleteEdge(controller, selection.id)\n }\n window.addEventListener('keydown', onKeyDown)\n return () => window.removeEventListener('keydown', onKeyDown)\n }, [controller, ui])\n\n // Right-click on empty canvas opens the add menu. On a node, group or edge nothing special happens (but the browser's\n // own menu is not shown over the diagram), and in a text box being edited the browser's menu (copy, paste) is left alone.\n const onContextMenu = (e: React.MouseEvent) => {\n const target = e.target as HTMLElement\n if (target.closest('input, textarea, [contenteditable]')) return\n e.preventDefault()\n if (target.closest('.node, .group-bar, .group-edge, .edge-hit, .resize-handle, .connect-handle, .canvas-head, .zoom, .canvas-empty')) {\n setMenu(null)\n return\n }\n setMenu({ screen: { x: e.clientX, y: e.clientY }, at: toDiagram(instance, e.clientX, e.clientY) })\n }\n\n const onPointerDown = (e: React.PointerEvent) => {\n if (e.button !== 0) return\n e.currentTarget.setPointerCapture(e.pointerId)\n const { x: vx, y: vy, setPanning } = ui.viewport.getState()\n drag.current = { px: e.clientX, py: e.clientY, vx, vy, moved: false }\n setPanning(true)\n }\n\n const onPointerMove = (e: React.PointerEvent) => {\n const d = drag.current\n if (!d) return\n const dx = e.clientX - d.px\n const dy = e.clientY - d.py\n if (Math.abs(dx) > CLICK_SLOP || Math.abs(dy) > CLICK_SLOP) d.moved = true\n ui.viewport.getState().setPosition(d.vx + dx, d.vy + dy)\n }\n\n const endDrag = () => {\n const d = drag.current\n drag.current = null\n ui.viewport.getState().setPanning(false)\n // A click on empty canvas clears the selection.\n if (d && !d.moved) ui.selection.getState().clearSelection()\n }\n\n return (\n <section\n ref={ref}\n className={panning ? 'canvas dragging' : 'canvas'}\n style={{\n backgroundSize: `${GRID * scale}px ${GRID * scale}px`,\n backgroundPosition: `${x}px ${y}px`,\n }}\n onPointerDown={onPointerDown}\n onContextMenu={onContextMenu}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n >\n <DiagramToolbar title={title} />\n {menu && <CanvasMenu menu={menu} onClose={() => setMenu(null)} />}\n\n <div\n className={dimmed ? 'world focus' : 'world'}\n style={{ transform: `translate(${x}px, ${y}px) scale(${scale})` }}\n >\n <GroupLayer />\n <EdgeLayer bounds={bounds} />\n <NodeLayer />\n <EdgeLabelLayer bounds={bounds} />\n <ResizeHandles />\n <ConnectHandles />\n <ConnectPreview />\n <EdgeEditor />\n <GroupEditor />\n </div>\n\n {empty && (\n <div className=\"canvas-empty\" role=\"note\">\n {emptyMessage ?? <strong>This diagram is empty</strong>}\n </div>\n )}\n\n <ZoomControls config={{ onZoom: zoomCenter, onFit: fit }} />\n </section>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { LIMITS, edgeGeometry } from '@glyphlab/diagram-core'\nimport { useDiagram, useEdges, useEditing, useNodes } from './context'\n\n// Edits an edge's label on the edge. Enter or clicking away saves (one undoable change); Escape discards.\nexport function EdgeEditor() {\n const id = useEditing((s) => s.edge)\n const edge = useEdges((s) => (id ? s.byId[id] : undefined))\n const from = useNodes((s) => (edge ? s.byId[edge.from] : undefined))\n const to = useNodes((s) => (edge ? s.byId[edge.to] : undefined))\n if (!id || !edge || !from || !to) return null\n const { lx, ly } = edgeGeometry(from, to)\n return <LabelInput key={id} id={id} label={edge.label} at={{ x: lx, y: ly }} />\n}\n\nfunction LabelInput({ id, label, at }: { id: string; label: string; at: { x: number; y: number } }) {\n const { controller, ui } = useDiagram()\n const [value, setValue] = useState(label)\n const ref = useRef<HTMLInputElement>(null)\n const done = useRef(false)\n\n useEffect(() => {\n ref.current?.focus()\n ref.current?.select()\n }, [])\n\n const finish = (save: boolean) => {\n if (done.current) return\n done.current = true\n if (save && value !== label) {\n controller.apply({ ops: [{ op: 'updateEdge', id, patch: { label: value.trim() } }], summary: 'Edit edge label', source: 'user' })\n }\n ui.edit.getState().end()\n }\n\n return (\n <input\n ref={ref}\n className=\"edge-edit\"\n aria-label=\"Edge label\"\n value={value}\n maxLength={LIMITS.label}\n placeholder=\"Label\"\n style={{ left: at.x, top: at.y, width: Math.max(120, value.length * 7 + 28) }}\n onChange={(e) => setValue(e.target.value)}\n onPointerDown={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n onBlur={() => finish(true)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n finish(true)\n } else if (e.key === 'Escape') {\n e.stopPropagation()\n finish(false)\n }\n }}\n />\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { LIMITS } from '@glyphlab/diagram-core'\nimport { useDiagram, useEditing, useGroups } from './context'\n\n// Renames a group where its title is. Enter or clicking away saves (one undoable change); Escape discards.\nexport function GroupEditor() {\n const id = useEditing((s) => s.group)\n const group = useGroups((s) => (id ? s.byId[id] : undefined))\n if (!id || !group) return null\n if (group.lane) return <LaneInput key={id} id={id} title={group.title} body={group.lane.body} x={group.x} y={group.y} width={group.w} />\n return <TitleInput key={id} id={id} title={group.title} at={{ x: group.x + 14, y: group.y + 8 }} width={Math.max(140, group.w - 28)} />\n}\n\nfunction LaneInput({ id, title, body, x, y, width }: { id: string; title: string; body: string; x: number; y: number; width: number }) {\n const { controller, ui } = useDiagram()\n const [name, setName] = useState(title)\n const [description, setDescription] = useState(body)\n const [error, setError] = useState('')\n const ref = useRef<HTMLInputElement>(null)\n useEffect(() => { ref.current?.focus(); ref.current?.select() }, [])\n const save = () => {\n const result = controller.apply({ source: 'user', summary: `Edit swimlane \"${title}\"`, ops: [{ op: 'updateLane', id, patch: { title: name.trim(), body: description } }] })\n if (!result.ok) { setError(result.message); return }\n ui.edit.getState().end()\n }\n return (\n <form className=\"lane-edit\" aria-label=\"Edit swimlane\" style={{ left: x + 8, top: y + 8, width: Math.max(240, width - 16) }}\n onPointerDown={(e) => e.stopPropagation()} onDoubleClick={(e) => e.stopPropagation()}\n onSubmit={(e) => { e.preventDefault(); save() }}\n onKeyDown={(e) => { if (e.key === 'Escape') { e.stopPropagation(); ui.edit.getState().end() } }}>\n <label>Title<input ref={ref} aria-label=\"Lane title\" value={name} required maxLength={LIMITS.title} onChange={(e) => setName(e.target.value)} /></label>\n <label>Description<textarea aria-label=\"Lane description\" value={description} maxLength={LIMITS.body} onChange={(e) => setDescription(e.target.value)} /></label>\n {error && <p role=\"alert\">{error}</p>}\n <div><button className=\"dg-btn\" type=\"button\" onClick={() => ui.edit.getState().end()}>Cancel</button> <button className=\"dg-btn\" type=\"submit\">Save lane</button></div>\n </form>\n )\n}\n\nfunction TitleInput({ id, title, at, width }: { id: string; title: string; at: { x: number; y: number }; width: number }) {\n const { controller, ui } = useDiagram()\n const [value, setValue] = useState(title)\n const ref = useRef<HTMLInputElement>(null)\n const done = useRef(false)\n\n useEffect(() => {\n ref.current?.focus()\n ref.current?.select()\n }, [])\n\n const finish = (save: boolean) => {\n if (done.current) return\n done.current = true\n const next = value.trim()\n // An empty name is refused: the group keeps the one it had.\n if (save && next !== '' && next !== title) {\n controller.apply({ ops: [{ op: 'updateGroup', id, patch: { title: next } }], summary: `Rename group “${title}”`, source: 'user' })\n }\n ui.edit.getState().end()\n }\n\n return (\n <input\n ref={ref}\n className=\"group-edit\"\n aria-label=\"Group name\"\n value={value}\n maxLength={LIMITS.title}\n style={{ left: at.x, top: at.y, width }}\n onChange={(e) => setValue(e.target.value)}\n onPointerDown={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n onBlur={() => finish(true)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n finish(true)\n } else if (e.key === 'Escape') {\n e.stopPropagation()\n finish(false)\n }\n }}\n />\n )\n}\n","import { beginConnect, sidePoint } from './beginConnect'\nimport { arrowBase } from './colors'\nimport { useConnecting, useDiagram, useEditing, useNodes } from './context'\n\nconst SIDES = ['n', 'e', 's', 'w'] as const\nconst LABEL = { n: 'top', e: 'right', s: 'bottom', w: 'left' } as const\n\n// The dots that appear when the pointer is over a node: drag one onto another node to connect them.\n// They sit outside the node, which clips its contents.\nexport function ConnectHandles() {\n const instance = useDiagram()\n const hovered = useConnecting((s) => s.hovered)\n const dragging = useConnecting((s) => s.source !== null)\n const node = useNodes((s) => (hovered ? s.byId[hovered] : undefined))\n const editing = useEditing((s) => s.node?.id === hovered)\n if (!hovered || !node || dragging || editing) return null\n\n return (\n <div className=\"connect-box\" style={{ left: node.x, top: node.y, width: node.w, height: node.h }}>\n {SIDES.map((side) => (\n <span\n key={side}\n className={`connect-handle connect-${side}`}\n role=\"presentation\"\n data-connect={side}\n title={`Drag onto another node to connect (${LABEL[side]})`}\n onPointerEnter={() => instance.ui.connect.getState().hover(hovered)}\n onPointerLeave={() => instance.ui.connect.getState().leave()}\n onPointerDown={(e) => beginConnect(instance, e, hovered, side)}\n />\n ))}\n </div>\n )\n}\n\n// The line being dragged out, from the handle to the pointer.\nexport function ConnectPreview() {\n const { uid } = useDiagram()\n const source = useConnecting((s) => s.source)\n const side = useConnecting((s) => s.side)\n const cursor = useConnecting((s) => s.cursor)\n const target = useConnecting((s) => s.target)\n const from = useNodes((s) => (source ? s.byId[source] : undefined))\n if (!source || !from || !cursor) return null\n const a = sidePoint(from, side)\n return (\n <svg className=\"connect-preview\" width={1} height={1} aria-hidden=\"true\">\n <path d={`M ${a.x} ${a.y} L ${cursor.x} ${cursor.y}`} className={target ? 'connect-line ready' : 'connect-line'} markerEnd={`url(#${arrowBase(uid)})`} />\n </svg>\n )\n}\n","import { useEffect, useRef } from 'react'\nimport { addGroupAt, addNodeAt } from './actions'\nimport { useDiagram } from './context'\n\nconst icon = { width: 14, height: 14, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true } as const\n\nexport interface CanvasMenuState {\n // Where it was opened, on screen (to place the menu) and on the diagram (where the new thing goes).\n screen: { x: number; y: number }\n at: { x: number; y: number }\n}\n\n// The menu that opens when the empty canvas is right-clicked: add a node or a group at that point.\nexport function CanvasMenu({ menu, onClose }: { menu: CanvasMenuState; onClose: () => void }) {\n const { controller, ui } = useDiagram()\n const ref = useRef<HTMLDivElement>(null)\n\n // Opened with the first item ready for the keyboard; closed by Escape, a click elsewhere, or the window changing.\n useEffect(() => {\n ref.current?.querySelector<HTMLElement>('[role=\"menuitem\"]')?.focus()\n const close = () => onClose()\n const onPointer = (e: PointerEvent) => {\n if (!ref.current?.contains(e.target as Node)) onClose()\n }\n window.addEventListener('pointerdown', onPointer, true)\n window.addEventListener('blur', close)\n window.addEventListener('resize', close)\n window.addEventListener('wheel', close, { passive: true })\n return () => {\n window.removeEventListener('pointerdown', onPointer, true)\n window.removeEventListener('blur', close)\n window.removeEventListener('resize', close)\n window.removeEventListener('wheel', close)\n }\n }, [onClose])\n\n const add = (kind: 'node' | 'group') => {\n onClose()\n const id = kind === 'node' ? addNodeAt(controller, menu.at.x, menu.at.y) : addGroupAt(controller, menu.at.x, menu.at.y)\n if (!id) return\n // Straight into naming it.\n if (kind === 'node') {\n ui.selection.getState().select({ kind: 'node', id })\n ui.edit.getState().editNode(id, 'title')\n } else {\n ui.selection.getState().select({ kind: 'group', id })\n ui.edit.getState().editGroup(id)\n }\n }\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n const items = Array.from(ref.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? [])\n const index = items.indexOf(document.activeElement as HTMLElement)\n if (e.key === 'Escape') {\n e.stopPropagation()\n onClose()\n } else if (e.key === 'ArrowDown') items[(index + 1) % items.length]?.focus()\n else if (e.key === 'ArrowUp') items[(index - 1 + items.length) % items.length]?.focus()\n else if (e.key === 'Home') items[0]?.focus()\n else if (e.key === 'End') items[items.length - 1]?.focus()\n else return\n e.preventDefault()\n }\n\n // Kept on screen when opened near an edge.\n const left = Math.min(menu.screen.x, window.innerWidth - 200)\n const top = Math.min(menu.screen.y, window.innerHeight - 100)\n\n return (\n <div ref={ref} className=\"canvas-menu\" role=\"menu\" aria-label=\"Canvas\" style={{ left, top }} onKeyDown={onKeyDown}\n // The canvas pans on a press; a press on the menu must reach its buttons instead.\n onPointerDown={(e) => e.stopPropagation()}\n onContextMenu={(e) => e.preventDefault()}\n >\n <button type=\"button\" role=\"menuitem\" onClick={() => add('node')}>\n <svg {...icon}><path d=\"M21 8 12 3 3 8v8l9 5 9-5z\" /><path d=\"m3.3 7.5 8.7 5 8.7-5M12 22V12.5\" /></svg> Add node\n </button>\n <button type=\"button\" role=\"menuitem\" onClick={() => add('group')}>\n <svg {...icon}><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" strokeDasharray=\"3 3\" /><rect x=\"7\" y=\"7\" width=\"6\" height=\"5\" rx=\"1\" /><rect x=\"12\" y=\"13\" width=\"5\" height=\"4\" rx=\"1\" /></svg> Add group\n </button>\n </div>\n )\n}\n","import { HANDLES } from '@glyphlab/diagram-core'\nimport { beginEdit } from './beginEdit'\nimport { useDiagram, useGroups, useNodes, useSelection, useViewport } from './context'\n\nconst LABELS: Record<string, string> = {\n n: 'top', s: 'bottom', e: 'right', w: 'left', ne: 'top right', nw: 'top left', se: 'bottom right', sw: 'bottom left',\n}\n\n// Handles on the selected node or group. They live outside the node, which clips its contents.\nexport function ResizeHandles() {\n const instance = useDiagram()\n const selection = useSelection((s) => s.selection)\n const rect = useNodes((s) => (selection?.kind === 'node' ? s.byId[selection.id] : undefined))\n const groupRect = useGroups((s) => (selection?.kind === 'group' ? s.byId[selection.id] : undefined))\n const scale = useViewport((s) => s.scale)\n const target = rect ?? groupRect\n if (!selection || !target || (selection.kind !== 'node' && selection.kind !== 'group')) return null\n\n // Keeps the handles a steady size on screen at any zoom.\n const inverse = Math.min(3, Math.max(0.75, 1 / scale))\n return (\n <div\n className=\"resize-box\"\n style={{ left: target.x, top: target.y, width: target.w, height: target.h, ['--inv' as string]: inverse }}\n >\n {HANDLES.map((handle) => (\n <span\n key={handle}\n className={`resize-handle resize-${handle}`}\n role=\"presentation\"\n data-handle={handle}\n title={`Resize ${LABELS[handle]}`}\n onPointerDown={(e) => beginEdit(instance, e, selection.kind as 'node' | 'group', selection.id, handle)}\n />\n ))}\n </div>\n )\n}\n","import type { PointerEvent as ReactPointerEvent } from 'react'\nimport { membersOf } from '@glyphlab/diagram-core'\nimport type { DiagramInstance } from './instance'\nimport { dragRect, minSize, rectPatch } from '@glyphlab/diagram-core'\nimport type { EditKind, EditMode, Rect } from '@glyphlab/diagram-core'\n\n// Below this many screen pixels a press is a click, not a drag.\nconst CLICK_SLOP = 3\n\nconst read = ({ controller }: DiagramInstance, kind: EditKind, id: string): (Rect & { title: string }) | undefined =>\n kind === 'node' ? controller.stores.nodes.getState().byId[id] : controller.stores.groups.getState().byId[id]\n\nfunction write({ controller }: DiagramInstance, kind: EditKind, id: string, rect: Rect) {\n if (kind === 'node') controller.stores.nodes.getState().updateNode(id, rect)\n else controller.stores.groups.getState().updateGroup(id, rect)\n}\n\n// What goes along when a group moves: the nodes and groups inside it (the planner applies the same rule).\nfunction carriedBy({ controller }: DiagramInstance, kind: EditKind, id: string, mode: EditMode) {\n if (kind !== 'group' || mode !== 'move') return { nodes: [], groups: [] }\n const snapshot = controller.getSnapshot()\n const group = snapshot.groups.find((g) => g.id === id)\n return group ? membersOf(group, snapshot.nodes, snapshot.groups) : { nodes: [], groups: [] }\n}\n\n// Starts moving or resizing a node or group. The drag previews live in the stores; when it ends the\n// preview is rolled back and the result goes through the controller as ONE change, so it can be\n// undone, moves the revision, and makes a proposal written before it stale. Escape cancels.\nexport function beginEdit(instance: DiagramInstance, e: ReactPointerEvent, kind: EditKind, id: string, mode: EditMode) {\n const { controller, ui } = instance\n if (e.button !== 0) return\n // Without this the press would start a canvas pan.\n e.stopPropagation()\n ui.selection.getState().select({ kind, id })\n\n const found = read(instance, kind, id)\n if (!found) return\n const { title } = found\n const start: Rect = { x: found.x, y: found.y, w: found.w, h: found.h }\n const scale = ui.viewport.getState().scale\n const origin = { x: e.clientX, y: e.clientY }\n let moved = false\n let latest = start\n const carried = carriedBy(instance, kind, id, mode)\n const carriedCount = carried.nodes.length + carried.groups.length\n\n const preview = (dx: number, dy: number) => {\n for (const n of carried.nodes) controller.stores.nodes.getState().updateNode(n.id, { x: n.x + dx, y: n.y + dy })\n for (const g of carried.groups) controller.stores.groups.getState().updateGroup(g.id, { x: g.x + dx, y: g.y + dy })\n }\n\n const onMove = (ev: PointerEvent) => {\n const dx = ev.clientX - origin.x\n const dy = ev.clientY - origin.y\n if (!moved && Math.hypot(dx, dy) < CLICK_SLOP) return\n moved = true\n latest = dragRect(start, mode, dx / scale, dy / scale, minSize(kind))\n write(instance, kind, id, latest)\n preview(latest.x - start.x, latest.y - start.y)\n }\n\n const stop = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n window.removeEventListener('pointercancel', onCancel)\n window.removeEventListener('keydown', onKey, true)\n }\n\n const onUp = () => {\n stop()\n const patch = rectPatch(start, latest)\n write(instance, kind, id, start)\n preview(0, 0)\n if (!moved || Object.keys(patch).length === 0) return\n const what = mode === 'move' ? 'Move' : 'Resize'\n controller.apply({\n ops: [kind === 'node' ? { op: 'updateNode', id, patch } : { op: 'updateGroup', id, patch }],\n summary: `${what} ${kind} “${title}”${carriedCount > 0 ? ` with what is inside it` : ''}`,\n source: 'user',\n })\n }\n\n const onCancel = () => {\n stop()\n write(instance, kind, id, start)\n preview(0, 0)\n }\n\n const onKey = (ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return\n ev.stopPropagation()\n onCancel()\n }\n\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n window.addEventListener('pointercancel', onCancel)\n window.addEventListener('keydown', onKey, true)\n}\n","import { memo } from 'react'\nimport { useDiagram, useHighlights } from './context'\nimport { arrowBase, arrowId, edgeColor, edgeStyle } from './colors'\nimport { useEdgeGeometry, useIsSelected } from './hooks'\n\nexport const DiagramEdge = memo(function DiagramEdge({ id }: { id: string }) {\n const instance = useDiagram()\n const { edge, geometry } = useEdgeGeometry(id)\n const selected = useIsSelected('edge', id)\n const highlight = useHighlights((s) => s.edges[id])\n if (!edge || !geometry) return null\n\n const className = [\n 'edge',\n edge.dashed ? 'dashed' : '',\n edge.optional ? 'optional' : '',\n edgeColor(edge.color) ? 'colored' : '',\n selected ? 'selected' : '',\n highlight ? `hl-${highlight}` : '',\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <g>\n <path d={geometry.d} className={className} style={edgeStyle(edge.color)} markerEnd={`url(#${arrowId(arrowBase(instance.uid), edge.color)})`} />\n {/* Wide invisible stroke so thin lines are easy to click. */}\n <path\n d={geometry.d}\n className=\"edge-hit\"\n onPointerDown={(e) => {\n e.stopPropagation()\n instance.ui.selection.getState().select({ kind: 'edge', id })\n }}\n onDoubleClick={(e) => {\n e.stopPropagation()\n instance.ui.edit.getState().editEdge(id)\n }}\n />\n </g>\n )\n})\n","import { useMemo } from 'react'\nimport { edgeGeometry } from '@glyphlab/diagram-core'\nimport type { SelectionKind } from '@glyphlab/diagram-core'\nimport { useEdges, useNodes, useSelection } from './context'\n\nexport function useIsSelected(kind: SelectionKind, id: string) {\n return useSelection((s) => s.selection?.kind === kind && s.selection.id === id)\n}\n\n// An edge's path depends only on its two end nodes, so only edges attached to a moved node recompute.\nexport function useEdgeGeometry(id: string) {\n const edge = useEdges((s) => s.byId[id])\n const from = useNodes((s) => (edge ? s.byId[edge.from] : undefined))\n const to = useNodes((s) => (edge ? s.byId[edge.to] : undefined))\n const geometry = useMemo(() => (from && to ? edgeGeometry(from, to) : null), [from, to])\n return { edge, geometry }\n}\n","import { memo, useState } from 'react'\nimport { useDiagram, useGroups } from './context'\nimport { beginEdit } from './beginEdit'\nimport { layerStyle } from './colors'\nimport { useIsSelected } from './hooks'\nimport { addNodeAt } from './actions'\nimport { toDiagram } from './beginConnect'\n\n// Only the title bar and the border take the pointer, so dragging across the inside of a group still pans the canvas.\nexport const DiagramGroup = memo(function DiagramGroup({ id }: { id: string }) {\n const instance = useDiagram()\n const group = useGroups((s) => s.byId[id])\n const selected = useIsSelected('group', id)\n const [error, setError] = useState('')\n if (!group) return null\n\n const grab = (e: React.PointerEvent) => beginEdit(instance, e, 'group', id, 'move')\n const add = (x: number, y: number) => {\n setError('')\n const nodeId = addNodeAt(instance.controller, x, y, id, setError)\n if (nodeId) {\n instance.ui.selection.getState().select({ kind: 'node', id: nodeId })\n instance.ui.edit.getState().editNode(nodeId, 'title')\n }\n }\n\n return (\n <div\n className={`group${group.lane ? ' swimlane' : ''}${selected ? ' selected' : ''}`}\n data-lane-id={group.lane ? id : undefined}\n style={{ left: group.x, top: group.y, width: group.w, height: group.h, ...layerStyle(group.color) }}\n >\n <div\n className=\"group-bar\"\n onPointerDown={grab}\n // Double-click the title to rename the group.\n onDoubleClick={(e) => {\n e.stopPropagation()\n instance.ui.edit.getState().editGroup(id)\n }}\n >\n <span className=\"group-title\">{group.title}</span>\n {group.lane && <span className=\"lane-description\">{group.lane.body || 'Double-click to edit lane title and description'}</span>}\n </div>\n {group.lane && (\n <div\n className=\"lane-content\"\n role=\"button\"\n tabIndex={0}\n aria-label={`Add node to ${group.title}`}\n title=\"Double-click to add a node\"\n onPointerDown={(e) => {\n e.stopPropagation()\n instance.ui.selection.getState().select({ kind: 'group', id })\n }}\n onDoubleClick={(e) => {\n e.stopPropagation()\n const at = toDiagram(instance, e.clientX, e.clientY)\n add(at.x, at.y)\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n add(group.x + group.w / 2, group.y + 180)\n }\n }}\n />\n )}\n {error && <span className=\"lane-error\" role=\"alert\">{error}</span>}\n <span className=\"group-edge group-edge-s\" onPointerDown={grab} />\n <span className=\"group-edge group-edge-w\" onPointerDown={grab} />\n <span className=\"group-edge group-edge-e\" onPointerDown={grab} />\n </div>\n )\n})\n","import { memo } from 'react'\nimport { useConnecting, useDiagram, useEditing, useHighlights, useNodes, useSlots } from './context'\nimport { beginEdit } from './beginEdit'\nimport { layerStyle } from './colors'\nimport { useIsSelected } from './hooks'\nimport { LinkBadge } from './LinkBadge'\nimport { NodeEditor } from './NodeEditor'\n\nexport const DiagramNode = memo(function DiagramNode({ id }: { id: string }) {\n const instance = useDiagram()\n const { renderMarkdown, openNodeContent, useLinkState } = useSlots()\n // The slot is fixed for the life of the provider, so this hook is called on every render or on none.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const linkState = useLinkState?.(id)\n const node = useNodes((s) => s.byId[id])\n const selected = useIsSelected('node', id)\n const editing = useEditing((s) => (s.node?.id === id ? s.node : null))\n const isTarget = useConnecting((s) => s.target === id)\n const highlight = useHighlights((s) => s.nodes[id])\n if (!node) return null\n\n return (\n <article\n data-node-id={id}\n className={`node${selected ? ' selected' : ''}${editing ? ' editing' : ''}${isTarget ? ' connect-target' : ''}${highlight ? ` hl-${highlight}` : ''}`}\n style={{ left: node.x, top: node.y, width: node.w, height: node.h, ...layerStyle(node.color) }}\n // Pressing a node selects it and, if dragged, moves it (beginEdit also keeps the canvas from panning).\n onPointerDown={(e) => {\n if (editing || (e.target instanceof Element && e.target.closest('a, button'))) e.stopPropagation()\n else beginEdit(instance, e, 'node', id, 'move')\n }}\n onDoubleClick={(e) => {\n e.stopPropagation()\n if (e.target instanceof Element && e.target.closest('a, button')) return\n const onTitle = (e.target as HTMLElement).closest('h2') !== null\n instance.ui.edit.getState().editNode(id, onTitle ? 'title' : 'body')\n }}\n onPointerEnter={() => instance.ui.connect.getState().hover(id)}\n onPointerLeave={() => instance.ui.connect.getState().leave()}\n >\n {editing ? (\n <NodeEditor node={node} field={editing.field} />\n ) : (\n <>\n <h2>{node.title}</h2>\n {openNodeContent && (\n <LinkBadge\n title={node.title}\n state={linkState}\n onOpen={() => {\n instance.ui.selection.getState().select({ kind: 'node', id })\n openNodeContent(id, 'code')\n }}\n />\n )}\n {openNodeContent && (\n <button\n className=\"node-expand\"\n type=\"button\"\n aria-label={`Open full content for ${node.title}`}\n title=\"View and edit full content\"\n onPointerDown={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n onClick={(e) => {\n e.stopPropagation()\n instance.ui.selection.getState().select({ kind: 'node', id })\n openNodeContent(id)\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden=\"true\">\n <path d=\"M8 3H3v5m13-5h5v5M3 16v5h5m13-5v5h-5M3 3l6 6m12-6-6 6M3 21l6-6m12 6-6-6\" />\n </svg>\n </button>\n )}\n {openNodeContent && node.decisions?.trim() && (\n <button\n className=\"node-decisions\"\n type=\"button\"\n aria-label={`Open the decision log for ${node.title}`}\n title=\"Decisions recorded: why this was chosen and what else was considered\"\n onPointerDown={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n onClick={(e) => {\n e.stopPropagation()\n instance.ui.selection.getState().select({ kind: 'node', id })\n openNodeContent(id, 'decisions')\n }}\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M16 3h5v5M8 3H3v5M12 22v-8.3a4 4 0 0 0-1.17-2.87L3 3M15 9l6-6\" />\n </svg>\n Decisions\n </button>\n )}\n {renderMarkdown ? renderMarkdown(node.body) : <div className=\"dg-plain\">{node.body}</div>}\n </>\n )}\n </article>\n )\n})\n","import type { ReactNode } from 'react'\nimport type { LinkStatus } from '@glyphlab/diagram-core'\n\n// What a node shows about the code it links to. Nothing is drawn when everything is fine (or nothing was checked), so a quiet node is a\n// good node; only the states that need a look get an icon. Each has its own shape, so it reads without colour.\nexport interface NodeLinkState {\n status: LinkStatus\n // For the tooltip: which link, and what happened.\n detail?: string\n // Problems on this node, when more than one.\n count?: number\n}\n\nconst LABEL: Record<Exclude<LinkStatus, 'ok'>, string> = {\n missing: 'Linked code is missing',\n changed: 'Possibly stale: linked code changed',\n moved: 'Linked code moved',\n unchecked: 'Links not checked',\n}\n\nconst SHAPE: Record<Exclude<LinkStatus, 'ok'>, ReactNode> = {\n changed: <><circle cx=\"12\" cy=\"12\" r=\"9\" /><path d=\"M12 7v5l3 2\" /></>,\n missing: <><circle cx=\"12\" cy=\"12\" r=\"9\" /><path d=\"M12 7v6M12 16.5v.5\" /></>,\n moved: <><circle cx=\"12\" cy=\"12\" r=\"9\" /><path d=\"M7.5 12h8M12.5 8.5 16 12l-3.5 3.5\" /></>,\n unchecked: <circle cx=\"12\" cy=\"12\" r=\"6\" />,\n}\n\nexport function LinkBadge({ title, state, onOpen }: { title: string; state: NodeLinkState | undefined; onOpen?: () => void }) {\n if (!state || state.status === 'ok') return null\n const status = state.status\n const label = `${LABEL[status]}${state.detail ? `: ${state.detail}` : ''}`\n return (\n <button\n type=\"button\"\n className={`node-link-badge link-${status}`}\n aria-label={`${label} (${title}). Open its code links.`}\n title={label}\n onPointerDown={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n onClick={(e) => {\n e.stopPropagation()\n onOpen?.()\n }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n {SHAPE[status]}\n </svg>\n {state.count && state.count > 1 ? <span className=\"node-link-count\">{state.count}</span> : null}\n </button>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { LIMITS } from '@glyphlab/diagram-core'\nimport type { NodeDef } from '@glyphlab/diagram-core'\nimport { useDiagram } from './context'\n\n// Edits a node's title and Markdown content where they are. Click away or Cmd/Ctrl+Enter saves\n// (one undoable change); Escape discards.\nexport function NodeEditor({ node, field }: { node: NodeDef; field: 'title' | 'body' }) {\n const { controller, ui } = useDiagram()\n const [title, setTitle] = useState(node.title)\n const [body, setBody] = useState(node.body)\n const titleRef = useRef<HTMLInputElement>(null)\n const bodyRef = useRef<HTMLTextAreaElement>(null)\n const done = useRef(false)\n\n useEffect(() => {\n const el = field === 'title' ? titleRef.current : bodyRef.current\n el?.focus()\n el?.select()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const finish = (save: boolean) => {\n if (done.current) return\n done.current = true\n const trimmed = title.trim()\n if (save && trimmed !== '') {\n const patch: { title?: string; body?: string } = {}\n if (trimmed !== node.title) patch.title = trimmed\n if (body !== node.body) patch.body = body\n if (Object.keys(patch).length > 0) {\n controller.apply({ ops: [{ op: 'updateNode', id: node.id, patch }], summary: `Edit node “${node.title}”`, source: 'user' })\n }\n }\n ui.edit.getState().end()\n }\n\n return (\n <div\n className=\"node-editor\"\n // Pressing inside must not drag the node or pan the canvas.\n onPointerDown={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) finish(true)\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n finish(false)\n } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n finish(true)\n }\n }}\n >\n <input\n ref={titleRef}\n className=\"node-edit-title\"\n aria-label=\"Node title\"\n value={title}\n maxLength={LIMITS.title}\n onChange={(e) => setTitle(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.metaKey && !e.ctrlKey) {\n e.preventDefault()\n bodyRef.current?.focus()\n }\n }}\n />\n <textarea\n ref={bodyRef}\n className=\"node-edit-body\"\n aria-label=\"Node content (Markdown)\"\n value={body}\n maxLength={LIMITS.body}\n spellCheck={false}\n onChange={(e) => setBody(e.target.value)}\n />\n </div>\n )\n}\n","import { memo } from 'react'\nimport { labelWidth } from '@glyphlab/diagram-core'\nimport { useHighlights } from './context'\nimport { useEdgeGeometry, useIsSelected } from './hooks'\n\nexport const EdgeLabel = memo(function EdgeLabel({ id }: { id: string }) {\n const { edge, geometry } = useEdgeGeometry(id)\n const selected = useIsSelected('edge', id)\n const highlight = useHighlights((s) => s.edges[id])\n if (!edge || !geometry || !edge.label) return null\n\n const width = labelWidth(edge)\n const className = ['edge-label', selected ? 'selected' : '', highlight ? `hl-${highlight}` : '']\n .filter(Boolean)\n .join(' ')\n\n return (\n <g className={className} transform={`translate(${geometry.lx}, ${geometry.ly})`}>\n <rect x={-width / 2} y={-9} width={width} height={18} rx={4} className=\"label-bg\" />\n <text textAnchor=\"middle\" dy=\"3.5\" className=\"label-text\">\n {edge.label}\n </text>\n </g>\n )\n})\n","import type { Bounds } from '@glyphlab/diagram-core'\nimport { useDiagram, useEdges, useGroups, useNodes } from './context'\nimport { ArrowHeads } from './ArrowHeads'\nimport { arrowBase } from './colors'\nimport { DiagramEdge } from './DiagramEdge'\nimport { DiagramGroup } from './DiagramGroup'\nimport { DiagramNode } from './DiagramNode'\nimport { EdgeLabel } from './EdgeLabel'\n\nexport function GroupLayer() {\n const ids = useGroups((s) => s.ids)\n return ids.map((id) => <DiagramGroup key={id} id={id} />)\n}\n\nexport function EdgeLayer({ bounds }: { bounds: Bounds }) {\n const { uid } = useDiagram()\n const ids = useEdges((s) => s.ids)\n const byId = useEdges((s) => s.byId)\n return (\n <svg className=\"edges\" width={bounds.w} height={bounds.h} aria-hidden=\"true\">\n <defs>\n <ArrowHeads id={arrowBase(uid)} colors={ids.map((id) => byId[id].color)} />\n </defs>\n {ids.map((id) => (\n <DiagramEdge key={id} id={id} />\n ))}\n </svg>\n )\n}\n\nexport function NodeLayer() {\n const ids = useNodes((s) => s.ids)\n return ids.map((id) => <DiagramNode key={id} id={id} />)\n}\n\n// Drawn above the nodes so labels are never hidden behind them.\nexport function EdgeLabelLayer({ bounds }: { bounds: Bounds }) {\n const ids = useEdges((s) => s.ids)\n return (\n <svg className=\"labels\" width={bounds.w} height={bounds.h} aria-hidden=\"true\">\n {ids.map((id) => (\n <EdgeLabel key={id} id={id} />\n ))}\n </svg>\n )\n}\n","import { useDiagram, useEdges, useSelection } from './context'\n\n// For a selected edge: a solid line or a dashed one. One undoable change each.\nexport function EdgeStyleControl() {\n const { controller } = useDiagram()\n const selection = useSelection((s) => s.selection)\n const edge = useEdges((s) => (selection?.kind === 'edge' ? s.byId[selection.id] : undefined))\n if (!selection || selection.kind !== 'edge' || !edge) return null\n const dashed = edge.dashed === true\n\n const choose = (next: boolean) => {\n if (next === dashed) return\n controller.apply({\n ops: [{ op: 'updateEdge', id: edge.id, patch: { dashed: next } }],\n summary: `Make the edge ${edge.label ? `“${edge.label}” ` : ''}${next ? 'dashed' : 'solid'}`,\n source: 'user',\n })\n }\n\n return (\n <div className=\"edge-style-control\" role=\"group\" aria-label=\"Line style of the selected edge\" onPointerDown={(e) => e.stopPropagation()} onContextMenu={(e) => e.stopPropagation()}>\n <button type=\"button\" className=\"edge-style-btn\" aria-pressed={!dashed} title=\"Solid line\" aria-label=\"Solid line\" onClick={() => choose(false)}>\n <svg width=\"28\" height=\"10\" viewBox=\"0 0 28 10\" aria-hidden=\"true\">\n <path d=\"M2 5h24\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n <button type=\"button\" className=\"edge-style-btn\" aria-pressed={dashed} title=\"Dashed line\" aria-label=\"Dashed line\" onClick={() => choose(true)}>\n <svg width=\"28\" height=\"10\" viewBox=\"0 0 28 10\" aria-hidden=\"true\">\n <path d=\"M2 5h24\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeDasharray=\"5 4\" />\n </svg>\n </button>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { DiagramOp, LaneOrientation } from '@glyphlab/diagram-core'\nimport { useDiagram, useGroups, useMeta, useSelection } from './context'\n\nexport function SwimlaneControls() {\n const { controller, ui } = useDiagram()\n const type = useMeta((s) => s.type)\n const groups = useGroups((s) => s.byId)\n const selection = useSelection((s) => s.selection)\n const [error, setError] = useState('')\n const lanes = Object.values(groups).filter((g) => g.lane).sort((a, b) => a.lane?.orientation === 'vertical' ? a.x - b.x : a.y - b.y)\n if (type !== 'swimlane' && lanes.length === 0) return null\n const selected = selection?.kind === 'group' ? lanes.find((g) => g.id === selection.id) : undefined\n const orientation = lanes[0]?.lane?.orientation ?? 'horizontal'\n const apply = (ops: DiagramOp[], summary: string) => {\n const result = controller.apply({ ops, summary, source: 'user' })\n setError(result.ok ? '' : result.message)\n return result.ok\n }\n const reorder = (direction: number) => {\n if (!selected) return\n const ids = lanes.map((g) => g.id)\n const index = ids.indexOf(selected.id)\n const other = index + direction\n if (other < 0 || other >= ids.length) return\n ;[ids[index], ids[other]] = [ids[other], ids[index]]\n apply([{ op: 'arrangeLanes', orientation, laneIds: ids }], 'Reorder swimlanes')\n }\n return (\n <div className=\"swimlane-controls\" onPointerDown={(e) => e.stopPropagation()}>\n <button className=\"dg-btn\" type=\"button\" onClick={() => {\n const before = new Set(lanes.map((g) => g.id))\n if (!apply([{ op: 'createLane', lane: { title: `Lane ${lanes.length + 1}`, body: '', orientation } }], 'Add swimlane')) return\n const lane = controller.getSnapshot().groups.find((g) => g.lane && !before.has(g.id))\n if (lane) { ui.selection.getState().select({ kind: 'group', id: lane.id }); ui.edit.getState().editGroup(lane.id) }\n }}>Add lane</button>\n <select aria-label=\"Lane orientation\" value={orientation} disabled={lanes.length === 0} onChange={(e) => {\n const next: LaneOrientation = e.target.value === 'vertical' ? 'vertical' : 'horizontal'\n apply([{ op: 'arrangeLanes', orientation: next }], 'Change swimlane orientation')\n }}>\n <option value=\"horizontal\">Horizontal lanes</option><option value=\"vertical\">Vertical lanes</option>\n </select>\n {selected && <>\n <button className=\"dg-btn\" type=\"button\" onClick={() => ui.edit.getState().editGroup(selected.id)}>Edit lane</button>\n <button className=\"dg-btn\" type=\"button\" aria-label=\"Move lane earlier\" disabled={lanes[0].id === selected.id} onClick={() => reorder(-1)}>Earlier</button>\n <button className=\"dg-btn\" type=\"button\" aria-label=\"Move lane later\" disabled={lanes.at(-1)?.id === selected.id} onClick={() => reorder(1)}>Later</button>\n <button className=\"dg-btn\" type=\"button\" onClick={() => apply([{ op: 'deleteLane', id: selected.id }], 'Delete swimlane (keep nodes)')}>Delete lane</button>\n </>}\n {error && <span role=\"alert\">{error}</span>}\n </div>\n )\n}\n","import { ColorControl } from './ColorControl'\nimport { EdgeStyleControl } from './EdgeStyleControl'\nimport { SwimlaneControls } from './SwimlaneControls'\n\n// The title along the top, and the controls for whatever is selected: its colour, and for an edge its line.\nexport function DiagramToolbar({ title }: { title: string }) {\n return (\n <div className=\"canvas-head\">\n <h1>{title}</h1>\n <div className=\"canvas-tools\">\n <EdgeStyleControl />\n <ColorControl />\n </div>\n <SwimlaneControls />\n </div>\n )\n}\n","import { useViewport } from './context'\n\ninterface ZoomControlsConfig {\n onZoom: (factor: number) => void\n onFit: () => void\n}\n\nconst STEP = 1.2\n\nexport function ZoomControls({ config }: { config: ZoomControlsConfig }) {\n const { onZoom, onFit } = config\n const scale = useViewport((s) => s.scale)\n\n return (\n <div className=\"zoom\" onPointerDown={(e) => e.stopPropagation()}>\n <button className=\"dg-icon-btn\" type=\"button\" onClick={() => onZoom(STEP)} aria-label=\"Zoom in\">\n +\n </button>\n <span className=\"zoom-pct\">{Math.round(scale * 100)}%</span>\n <button className=\"dg-icon-btn\" type=\"button\" onClick={() => onZoom(1 / STEP)} aria-label=\"Zoom out\">\n −\n </button>\n <button className=\"dg-btn\" type=\"button\" onClick={onFit}>\n Fit canvas\n </button>\n </div>\n )\n}\n","import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { HANDLES, diagramBounds, dragRect, edgeGeometry, labelWidth, membersOf, minSize } from '@glyphlab/diagram-core'\nimport type { DiagramFile, EditKind, EditMode, Rect } from '@glyphlab/diagram-core'\nimport { ArrowHeads } from './ArrowHeads'\nimport { LinkBadge } from './LinkBadge'\nimport type { NodeLinkState } from './LinkBadge'\nimport { arrowId, edgeColor, edgeStyle, layerStyle } from './colors'\nimport type { Highlights } from '@glyphlab/diagram-core'\n\nconst MIN_SCALE = 0.1\nconst MAX_SCALE = 2.5\nconst GRID = 24\n\ninterface View {\n x: number\n y: number\n scale: number\n}\n\nfunction fitView(width: number, height: number, bounds: { w: number; h: number }): View {\n if (bounds.w === 0 || bounds.h === 0 || width === 0 || height === 0) return { x: 0, y: 0, scale: 1 }\n const margin = 32\n const scale = Math.min(Math.max(Math.min((width - margin * 2) / bounds.w, (height - margin * 2) / bounds.h), MIN_SCALE), 1)\n return { scale, x: (width - bounds.w * scale) / 2, y: (height - bounds.h * scale) / 2 }\n}\n\nexport interface DiagramViewerConfig {\n diagram: DiagramFile\n highlights?: Highlights\n // Fade what the current step does not involve.\n focus?: boolean\n // Draws a node's content (Markdown). Without it the text is shown as it is.\n renderMarkdown?: (source: string) => ReactNode\n // Opens a node's full content (or its decision log). With it, each node has an expand button and, when it has one, a Decisions tag.\n openNodeContent?: (id: string, section?: 'decisions' | 'code') => void\n // Staleness of each node's code links, from a link check someone ran. A node without an entry, or that is ok, shows nothing.\n linkStates?: Record<string, NodeLinkState>\n // Lets the person drag nodes and groups (a group takes what is inside it along) and resize them, to see the diagram another way.\n // Changes are kept only while it is shown, never saved.\n movableNodes?: boolean\n}\n\n// A diagram drawn from a file, with nothing to select or edit and no controller: a saved copy (a report's), a preview, a page that only\n// shows. It can be panned and zoomed, lights up as a scenario plays and, with movableNodes, has nodes that can be dragged.\nexport function DiagramViewer({ config }: { config: DiagramViewerConfig }) {\n const { diagram, highlights, focus = false, renderMarkdown, openNodeContent, movableNodes = false, linkStates } = config\n const arrow = `snap-arrow-${useId().replace(/:/g, '')}`\n const ref = useRef<HTMLElement>(null)\n const [view, setView] = useState<View>({ x: 0, y: 0, scale: 1 })\n const drag = useRef<{ x: number; y: number; vx: number; vy: number } | null>(null)\n const [panning, setPanning] = useState(false)\n // The node or group being moved or resized, with where it and what it carries started.\n const gesture = useRef<{ kind: EditKind; id: string; mode: EditMode; x: number; y: number; start: Rect; nodes: Record<string, Rect>; groups: Record<string, Rect> } | null>(null)\n const [moving, setMoving] = useState<string | null>(null)\n const [picked, setPicked] = useState<{ kind: EditKind; id: string } | null>(null)\n // Where dragged or resized nodes and groups were put, for this diagram only: a new diagram starts from its saved geometry.\n const [moved, setMoved] = useState<{ diagram: DiagramFile; nodes: Record<string, Rect>; groups: Record<string, Rect> }>({ diagram, nodes: {}, groups: {} })\n const at = moved.diagram === diagram ? moved.nodes : undefined\n const groupAt = moved.diagram === diagram ? moved.groups : undefined\n\n // The view is fitted to the saved positions, so dragging a node does not refit it.\n const bounds = useMemo(() => diagramBounds(diagram.groups, diagram.nodes), [diagram])\n const nodes = useMemo(() => (at ? diagram.nodes.map((n) => (at[n.id] ? { ...n, ...at[n.id] } : n)) : diagram.nodes), [diagram, at])\n const groups = useMemo(() => (groupAt ? diagram.groups.map((g) => (groupAt[g.id] ? { ...g, ...groupAt[g.id] } : g)) : diagram.groups), [diagram, groupAt])\n const nodesById = useMemo(() => new Map(nodes.map((n) => [n.id, n])), [nodes])\n\n const fit = useCallback(() => {\n const el = ref.current\n if (el) setView(fitView(el.clientWidth, el.clientHeight, bounds))\n }, [bounds])\n\n // Fitted when shown and whenever the box changes size, until the person pans or zooms.\n const touched = useRef(false)\n useEffect(() => {\n touched.current = false\n fit()\n const el = ref.current\n if (!el || typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(() => {\n if (!touched.current) fit()\n })\n observer.observe(el)\n return () => observer.disconnect()\n }, [fit])\n\n const zoomAround = (factor: number, px: number, py: number) => {\n touched.current = true\n setView((v) => {\n const scale = Math.min(Math.max(v.scale * factor, MIN_SCALE), MAX_SCALE)\n const k = scale / v.scale\n return { scale, x: px - (px - v.x) * k, y: py - (py - v.y) * k }\n })\n }\n\n const zoomCenter = (factor: number) => {\n const el = ref.current\n if (el) zoomAround(factor, el.clientWidth / 2, el.clientHeight / 2)\n }\n\n // Wheel zoom needs a non-passive listener to stop the page from scrolling.\n useEffect(() => {\n const el = ref.current\n if (!el) return\n const onWheel = (e: WheelEvent) => {\n e.preventDefault()\n const rect = el.getBoundingClientRect()\n zoomAround(Math.exp(-e.deltaY * 0.0015), e.clientX - rect.left, e.clientY - rect.top)\n }\n el.addEventListener('wheel', onWheel, { passive: false })\n return () => el.removeEventListener('wheel', onWheel)\n }, [])\n\n const edges = diagram.edges.flatMap((edge) => {\n const a = nodesById.get(edge.from)\n const b = nodesById.get(edge.to)\n return a && b ? [{ edge, geometry: edgeGeometry(a, b) }] : []\n })\n\n const stop = () => {\n drag.current = null\n setPanning(false)\n }\n\n const stopGesture = () => {\n gesture.current = null\n setMoving(null)\n }\n\n // Starts moving or resizing a node or group. Moving a group takes the nodes and groups inside it along.\n const begin = (e: React.PointerEvent, kind: EditKind, id: string, mode: EditMode) => {\n if (e.button !== 0) return\n // The element moves instead of the canvas panning, and no text is selected on the way.\n e.stopPropagation()\n e.preventDefault()\n const target = kind === 'node' ? nodesById.get(id) : groups.find((g) => g.id === id)\n if (!target) return\n const carried = kind === 'group' && mode === 'move' ? membersOf(groups.find((g) => g.id === id)!, nodes, groups) : { nodes: [], groups: [] }\n const rect = ({ x, y, w, h }: Rect): Rect => ({ x, y, w, h })\n gesture.current = {\n kind, id, mode, x: e.clientX, y: e.clientY, start: rect(target),\n nodes: Object.fromEntries((kind === 'node' ? [target as Rect & { id: string }] : carried.nodes).map((n) => [(n as { id: string }).id, rect(n)])),\n groups: Object.fromEntries(carried.groups.map((g) => [g.id, rect(g)])),\n }\n setPicked({ kind, id })\n setMoving(id)\n e.currentTarget.setPointerCapture(e.pointerId)\n }\n\n const pickedRect = picked ? (picked.kind === 'node' ? nodesById.get(picked.id) : groups.find((g) => g.id === picked.id)) : undefined\n const resizeFrom = (e: React.PointerEvent, handle: EditMode) => {\n if (picked) begin(e, picked.kind, picked.id, handle)\n }\n\n const gestureMove = (e: React.PointerEvent) => {\n const g = gesture.current\n if (!g) return false\n const dx = (e.clientX - g.x) / view.scale\n const dy = (e.clientY - g.y) / view.scale\n if (g.mode !== 'move') {\n const next = dragRect(g.start, g.mode, dx, dy, minSize(g.kind))\n setMoved((m) => {\n const base = m.diagram === diagram ? m : { diagram, nodes: {}, groups: {} }\n return g.kind === 'node' ? { ...base, nodes: { ...base.nodes, [g.id]: next } } : { ...base, groups: { ...base.groups, [g.id]: next } }\n })\n return true\n }\n const shift = (r: Rect): Rect => ({ ...r, x: Math.round(r.x + dx), y: Math.round(r.y + dy) })\n setMoved((m) => {\n const base = m.diagram === diagram ? m : { diagram, nodes: {}, groups: {} }\n const nextNodes = { ...base.nodes }\n const nextGroups = { ...base.groups }\n for (const [id, r] of Object.entries(g.nodes)) nextNodes[id] = shift(r)\n for (const [id, r] of Object.entries(g.groups)) nextGroups[id] = shift(r)\n if (g.kind === 'group') nextGroups[g.id] = shift(g.start)\n return { diagram, nodes: nextNodes, groups: nextGroups }\n })\n return true\n }\n\n return (\n <section\n ref={ref}\n className={`canvas snapshot-canvas${panning ? ' dragging' : ''}`}\n aria-label=\"Diagram snapshot\"\n style={{ backgroundSize: `${GRID * view.scale}px ${GRID * view.scale}px`, backgroundPosition: `${view.x}px ${view.y}px` }}\n onPointerDown={(e) => {\n if (e.button !== 0) return\n drag.current = { x: e.clientX, y: e.clientY, vx: view.x, vy: view.y }\n setPicked(null)\n touched.current = true\n setPanning(true)\n e.currentTarget.setPointerCapture(e.pointerId)\n }}\n onPointerMove={(e) => {\n if (gestureMove(e)) return\n const d = drag.current\n if (d) setView((v) => ({ ...v, x: d.vx + e.clientX - d.x, y: d.vy + e.clientY - d.y }))\n }}\n onPointerUp={() => { stop(); stopGesture() }}\n onPointerCancel={() => { stop(); stopGesture() }}\n >\n <div className={focus ? 'world focus' : 'world'} style={{ transform: `translate(${view.x}px, ${view.y}px) scale(${view.scale})` }}>\n {groups.map((g) => {\n const grab = movableNodes ? (e: React.PointerEvent) => begin(e, 'group', g.id, 'move') : undefined\n const selected = picked?.kind === 'group' && picked.id === g.id\n return (\n <div key={g.id} className={`group${g.lane ? ' swimlane' : ''}${selected ? ' selected' : ''}`} style={{ left: g.x, top: g.y, width: g.w, height: g.h, ...layerStyle(g.color) }}>\n <div className={movableNodes ? 'group-bar movable' : 'group-bar'} onPointerDown={grab}>\n <span className=\"group-title\">{g.title}</span>\n {g.lane && <span className=\"lane-description\">{g.lane.body}</span>}\n </div>\n {movableNodes && (\n <>\n <span className=\"group-edge group-edge-s\" onPointerDown={grab} />\n <span className=\"group-edge group-edge-w\" onPointerDown={grab} />\n <span className=\"group-edge group-edge-e\" onPointerDown={grab} />\n </>\n )}\n </div>\n )\n })}\n\n <svg className=\"edges\" width={bounds.w} height={bounds.h} aria-hidden=\"true\">\n <defs>\n <ArrowHeads id={arrow} colors={edges.map(({ edge }) => edge.color)} />\n </defs>\n {edges.map(({ edge, geometry }) => {\n const hl = highlights?.edges[edge.id]\n const className = ['edge', edge.dashed ? 'dashed' : '', edge.optional ? 'optional' : '', edgeColor(edge.color) ? 'colored' : '', hl ? `hl-${hl}` : ''].filter(Boolean).join(' ')\n return <path key={edge.id} d={geometry.d} className={className} style={edgeStyle(edge.color)} markerEnd={`url(#${arrowId(arrow, edge.color)})`} />\n })}\n </svg>\n\n {nodes.map((node) => {\n const hl = highlights?.nodes[node.id]\n const className = ['node', movableNodes ? 'movable' : '', picked?.kind === 'node' && picked.id === node.id ? 'selected' : '', moving === node.id ? 'moving' : '', hl ? `hl-${hl}` : ''].filter(Boolean).join(' ')\n return (\n <article\n key={node.id}\n data-node-id={node.id}\n className={className}\n style={{ left: node.x, top: node.y, width: node.w, height: node.h, ...layerStyle(node.color) }}\n onPointerDown={movableNodes ? (e) => begin(e, 'node', node.id, 'move') : undefined}\n >\n <h2>{node.title}</h2>\n {openNodeContent && <LinkBadge title={node.title} state={linkStates?.[node.id]} onOpen={() => openNodeContent(node.id, 'code')} />}\n {openNodeContent && (\n <button\n className=\"node-expand\"\n type=\"button\"\n aria-label={`Open full content for ${node.title}`}\n title=\"View full content\"\n // Kept from the canvas, which would otherwise start panning and take the click.\n onPointerDown={(e) => e.stopPropagation()}\n onClick={() => openNodeContent(node.id)}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden=\"true\">\n <path d=\"M8 3H3v5m13-5h5v5M3 16v5h5m13-5v5h-5M3 3l6 6m12-6-6 6M3 21l6-6m12 6-6-6\" />\n </svg>\n </button>\n )}\n {openNodeContent && node.decisions?.trim() && (\n <button\n className=\"node-decisions\"\n type=\"button\"\n aria-label={`Open the decision log for ${node.title}`}\n title=\"Decisions recorded: why this was chosen and what else was considered\"\n onPointerDown={(e) => e.stopPropagation()}\n onClick={() => openNodeContent(node.id, 'decisions')}\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M16 3h5v5M8 3H3v5M12 22v-8.3a4 4 0 0 0-1.17-2.87L3 3M15 9l6-6\" />\n </svg>\n Decisions\n </button>\n )}\n {renderMarkdown ? renderMarkdown(node.body) : <div className=\"dg-plain\">{node.body}</div>}\n </article>\n )\n })}\n\n {movableNodes && picked && pickedRect && (\n <div className=\"resize-box\" style={{ left: pickedRect.x, top: pickedRect.y, width: pickedRect.w, height: pickedRect.h, ['--inv' as string]: Math.min(3, Math.max(0.75, 1 / view.scale)) }}>\n {HANDLES.map((handle) => (\n <span key={handle} className={`resize-handle resize-${handle}`} role=\"presentation\" title=\"Resize\" onPointerDown={(e) => resizeFrom(e, handle)} />\n ))}\n </div>\n )}\n\n <svg className=\"labels\" width={bounds.w} height={bounds.h} aria-hidden=\"true\">\n {edges.map(({ edge, geometry }) => {\n if (!edge.label) return null\n const hl = highlights?.edges[edge.id]\n const width = labelWidth(edge)\n return (\n <g key={edge.id} className={['edge-label', hl ? `hl-${hl}` : ''].filter(Boolean).join(' ')} transform={`translate(${geometry.lx}, ${geometry.ly})`}>\n <rect x={-width / 2} y={-9} width={width} height={18} rx={4} className=\"label-bg\" />\n <text textAnchor=\"middle\" dy=\"3.5\" className=\"label-text\">\n {edge.label}\n </text>\n </g>\n )\n })}\n </svg>\n </div>\n\n <div className=\"zoom\" onPointerDown={(e) => e.stopPropagation()}>\n <button className=\"dg-icon-btn\" type=\"button\" onClick={() => zoomCenter(1.2)} aria-label=\"Zoom in snapshot\">\n +\n </button>\n <span className=\"zoom-pct\">{Math.round(view.scale * 100)}%</span>\n <button className=\"dg-icon-btn\" type=\"button\" onClick={() => zoomCenter(1 / 1.2)} aria-label=\"Zoom out snapshot\">\n −\n </button>\n <button\n className=\"dg-btn\"\n type=\"button\"\n onClick={() => {\n touched.current = false\n fit()\n }}\n >\n Fit\n </button>\n </div>\n </section>\n )\n}\n","import { createStore } from 'zustand/vanilla'\nimport type { StoreApi } from 'zustand/vanilla'\nimport type { Bounds, EdgeHighlight, Highlights, NodeHighlight, Selection, Size } from '@glyphlab/diagram-core'\n\n// What the canvas keeps about how it is being used, apart from the diagram: where it is panned to, what is selected, what is being edited\n// in place, what is being connected, and what is highlighted. One set for each canvas, so two diagrams can be on a page. None of it is part\n// of the document and none of it is saved.\n\n// ---- viewport ----\n\nexport const MIN_SCALE = 0.2\nexport const MAX_SCALE = 2\nconst PADDING = 48\nconst INITIAL_MIN_SCALE = 0.5\n// Leaves room for the title bar when the diagram first opens.\nconst INITIAL_TOP_OFFSET = 40\n\nexport interface ViewportState {\n x: number\n y: number\n scale: number\n panning: boolean\n setPanning: (panning: boolean) => void\n setPosition: (x: number, y: number) => void\n panBy: (dx: number, dy: number) => void\n zoomAround: (factor: number, cx: number, cy: number) => void\n fit: (size: Size, bounds: Bounds) => void\n reset: (size: Size, bounds: Bounds) => void\n}\n\nfunction clamp(v: number, lo: number, hi: number) {\n return Math.min(hi, Math.max(lo, v))\n}\n\nfunction fitScale(size: Size, bounds: Bounds, min: number) {\n if (bounds.w === 0 || bounds.h === 0) return 1\n return clamp(Math.min((size.width - PADDING * 2) / bounds.w, (size.height - PADDING * 2) / bounds.h), min, MAX_SCALE)\n}\n\nexport const createViewportStore = () =>\n createStore<ViewportState>()((set) => ({\n x: PADDING,\n y: PADDING,\n scale: INITIAL_MIN_SCALE,\n panning: false,\n setPanning: (panning) => set({ panning }),\n setPosition: (x, y) => set({ x, y }),\n panBy: (dx, dy) => set((s) => ({ x: s.x + dx, y: s.y + dy })),\n zoomAround: (factor, cx, cy) =>\n set((s) => {\n const scale = clamp(s.scale * factor, MIN_SCALE, MAX_SCALE)\n const k = scale / s.scale\n return { scale, x: cx - (cx - s.x) * k, y: cy - (cy - s.y) * k }\n }),\n // Whole diagram visible and centered.\n fit: (size, bounds) => {\n const scale = fitScale(size, bounds, MIN_SCALE)\n set({ scale, x: (size.width - bounds.w * scale) / 2, y: (size.height - bounds.h * scale) / 2 })\n },\n // Readable starting view: never below the initial minimum, anchored top-left.\n reset: (size, bounds) => set({ scale: fitScale(size, bounds, INITIAL_MIN_SCALE), x: PADDING, y: PADDING + INITIAL_TOP_OFFSET }),\n }))\n\n// ---- selection ----\n\nexport interface SelectionState {\n selection: Selection | null\n select: (selection: Selection) => void\n clearSelection: () => void\n}\n\nexport const createSelectionStore = () =>\n createStore<SelectionState>()((set) => ({\n selection: null,\n select: (selection) => set({ selection }),\n clearSelection: () => set((s) => (s.selection ? { selection: null } : s)),\n }))\n\n// ---- editing in place: one node (its title and content), one edge (its label) or one group (its title) ----\n\nexport interface EditState {\n node: { id: string; field: 'title' | 'body' } | null\n edge: string | null\n group: string | null\n editNode: (id: string, field: 'title' | 'body') => void\n editEdge: (id: string) => void\n editGroup: (id: string) => void\n end: () => void\n}\n\nexport const createEditStore = () =>\n createStore<EditState>()((set) => ({\n node: null,\n edge: null,\n group: null,\n editNode: (id, field) => set({ node: { id, field }, edge: null, group: null }),\n editEdge: (id) => set({ edge: id, node: null, group: null }),\n editGroup: (id) => set({ group: id, node: null, edge: null }),\n end: () => set((s) => (s.node || s.edge || s.group ? { node: null, edge: null, group: null } : s)),\n }))\n\n// ---- connecting: dragging an edge out of a node ----\n\nexport interface ConnectState {\n // The node the pointer is over (or just left), whose connect handles are showing.\n hovered: string | null\n // While an edge is being dragged out: where it started, the pointer in diagram units, and the node it would land on.\n source: string | null\n side: 'n' | 'e' | 's' | 'w'\n cursor: { x: number; y: number } | null\n target: string | null\n hover: (id: string) => void\n leave: () => void\n start: (source: string, side: ConnectState['side'], cursor: { x: number; y: number }) => void\n move: (cursor: { x: number; y: number }, target: string | null) => void\n end: () => void\n}\n\n// Moving from a node to its handles leaves the node for a moment; hiding is delayed so they don't vanish.\nconst LEAVE_DELAY = 250\n\nexport const createConnectStore = () => {\n let timer: ReturnType<typeof setTimeout> | undefined\n const cancel = () => {\n if (timer) clearTimeout(timer)\n timer = undefined\n }\n return createStore<ConnectState>()((set) => ({\n hovered: null,\n source: null,\n side: 'e',\n cursor: null,\n target: null,\n hover: (id) => {\n cancel()\n set((s) => (s.hovered === id ? s : { hovered: id }))\n },\n leave: () => {\n cancel()\n timer = setTimeout(() => set({ hovered: null }), LEAVE_DELAY)\n },\n start: (source, side, cursor) => {\n cancel()\n set({ source, side, cursor, target: null })\n },\n move: (cursor, target) => set({ cursor, target }),\n end: () => set({ source: null, cursor: null, target: null }),\n }))\n}\n\n// ---- highlights ----\n\n// The kinds of highlight, and their shape, are @glyphlab/diagram-core's (highlights.ts): what produces them and the canvas share them there.\nexport interface HighlightState {\n nodes: Record<string, NodeHighlight>\n edges: Record<string, EdgeHighlight>\n dimmed: boolean\n set: (highlights: Highlights) => void\n clear: () => void\n}\n\nconst NO_HIGHLIGHTS = { nodes: {}, edges: {}, dimmed: false }\n\nexport const createHighlightStore = () =>\n createStore<HighlightState>()((set) => ({\n ...NO_HIGHLIGHTS,\n set: ({ nodes, edges, dimmed = false }) => set({ nodes, edges, dimmed }),\n clear: () => set((s) => (s.dimmed || Object.keys(s.nodes).length || Object.keys(s.edges).length ? NO_HIGHLIGHTS : s)),\n }))\n\n// ---- all of them ----\n\nexport interface CanvasUi {\n viewport: StoreApi<ViewportState>\n selection: StoreApi<SelectionState>\n edit: StoreApi<EditState>\n connect: StoreApi<ConnectState>\n highlight: StoreApi<HighlightState>\n}\n\nexport const createCanvasUi = (): CanvasUi => ({\n viewport: createViewportStore(),\n selection: createSelectionStore(),\n edit: createEditStore(),\n connect: createConnectStore(),\n highlight: createHighlightStore(),\n})\n","import type { DiagramController } from '@glyphlab/diagram-core'\nimport { createCanvasUi } from './ui'\nimport type { CanvasUi } from './ui'\n\n// One diagram on screen: the controller that holds it and the state of the canvas that shows it. Make one for each diagram a page shows,\n// and give it to a DiagramProvider.\nexport interface DiagramInstance {\n // Unique, so the ids a canvas puts in the page (arrow heads) do not meet another canvas's.\n readonly uid: string\n readonly controller: DiagramController\n readonly ui: CanvasUi\n // The element the canvas draws in, so pointer positions can be turned into diagram positions. Set by DiagramCanvas.\n readonly surface: { el: HTMLElement | null }\n // Stops what the instance listens to. After it, the controller is left as it is.\n dispose(): void\n}\n\nlet counter = 0\n\nexport function createDiagramInstance(controller: DiagramController): DiagramInstance {\n const ui = createCanvasUi()\n\n // What the diagram is now makes the canvas forget what it can no longer show: an edit in progress on something that is gone (deleted, or\n // another diagram loaded) ends with it, and so does a selection of it.\n const dropWhatIsGone = () => {\n const next = controller.getSnapshot()\n const editing = ui.edit.getState()\n if (\n (editing.node && !next.nodes.some((n) => n.id === editing.node!.id)) ||\n (editing.edge && !next.edges.some((e) => e.id === editing.edge)) ||\n (editing.group && !next.groups.some((g) => g.id === editing.group))\n ) {\n editing.end()\n }\n const { selection, clearSelection } = ui.selection.getState()\n if (!selection) return\n const collection = selection.kind === 'node' ? next.nodes : selection.kind === 'group' ? next.groups : next.edges\n if (!collection.some((item) => item.id === selection.id)) clearSelection()\n }\n const offs = [\n controller.subscribe(dropWhatIsGone),\n // Another diagram is not the one that was selected, even where the ids are the same.\n controller.onLoad(() => {\n ui.edit.getState().end()\n ui.selection.getState().clearSelection()\n }),\n ]\n\n return {\n uid: `dg${++counter}`,\n controller,\n ui,\n surface: { el: null },\n dispose: () => offs.forEach((off) => off()),\n }\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","useEffect","useMemo","useRef","useState","useEffect","useRef","jsx","useRef","useEffect","useEffect","useRef","useState","LIMITS","jsx","jsxs","useState","useRef","useEffect","LIMITS","jsx","useEffect","useRef","jsx","jsxs","useRef","useEffect","jsx","edgeGeometry","edgeGeometry","jsx","jsxs","DiagramEdge","memo","useState","jsx","jsxs","memo","DiagramGroup","useState","memo","Fragment","jsx","jsxs","LABEL","useEffect","useRef","useState","LIMITS","jsx","jsxs","useState","useRef","useEffect","LIMITS","Fragment","jsx","jsxs","memo","DiagramNode","memo","jsx","jsxs","memo","EdgeLabel","jsx","jsxs","jsx","jsxs","useState","Fragment","jsx","jsxs","useState","jsx","jsxs","jsx","jsxs","jsx","jsxs","CLICK_SLOP","useRef","useState","useMemo","useEffect","useCallback","useEffect","useMemo","useRef","useState","HANDLES","diagramBounds","dragRect","edgeGeometry","labelWidth","membersOf","minSize","Fragment","jsx","jsxs","GRID","useRef","useState","useMemo","diagramBounds","useCallback","useEffect","edgeGeometry","membersOf","dragRect","minSize","HANDLES","labelWidth","MIN_SCALE","MAX_SCALE"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glyphlab/diagram-react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "The default React canvas for a @glyphlab/diagram-core controller: pan and zoom, nodes, groups and edges, editing in place, colours, and a read-only viewer.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./index.js",
|
|
8
|
+
"types": "./index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"default": "./index.js"
|
|
13
|
+
},
|
|
14
|
+
"./diagram.css": "./diagram.css",
|
|
15
|
+
"./theme.css": "./theme.css"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"*.js",
|
|
19
|
+
"*.js.map",
|
|
20
|
+
"*.d.ts",
|
|
21
|
+
"*.css",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": [
|
|
26
|
+
"./diagram.css",
|
|
27
|
+
"./theme.css"
|
|
28
|
+
],
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@glyphlab/diagram-core": "^0.1.1",
|
|
31
|
+
"react": "^19",
|
|
32
|
+
"zustand": "^5"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/subtubes-io/subtubes-editor.git",
|
|
37
|
+
"directory": "packages/diagram-react"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"diagram",
|
|
44
|
+
"react",
|
|
45
|
+
"system-design",
|
|
46
|
+
"glyph"
|
|
47
|
+
]
|
|
48
|
+
}
|
package/theme.css
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* Default theme for @glyphlab/diagram-react: every CSS variable the canvas reads, for a light and a dark theme. A host that has its own theme
|
|
2
|
+
defines these itself (the Glyph app does, in src/index.css) and does not import this file. Dark applies with data-theme="dark" on the
|
|
3
|
+
root element, or when the system prefers dark and nothing is set. */
|
|
4
|
+
:root {
|
|
5
|
+
--font: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
:root,
|
|
9
|
+
:root[data-theme='light'] {
|
|
10
|
+
color-scheme: light;
|
|
11
|
+
--bg: #f4f5f7;
|
|
12
|
+
--surface: #ffffff;
|
|
13
|
+
--surface-2: #f0f2f5;
|
|
14
|
+
--border: #dfe3e8;
|
|
15
|
+
--text: #14171a;
|
|
16
|
+
--muted: #667085;
|
|
17
|
+
--accent: #2563eb;
|
|
18
|
+
--dot: #cfd5dd;
|
|
19
|
+
--group-bg: rgba(15, 23, 42, 0.03);
|
|
20
|
+
--node-bg: #ffffff;
|
|
21
|
+
--node-shadow: 0 1px 2px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06);
|
|
22
|
+
--edge: #3b82f6;
|
|
23
|
+
--edge-dashed: #8a94a6;
|
|
24
|
+
--edge-optional: #8b5cf6;
|
|
25
|
+
--ok: #059669;
|
|
26
|
+
--tools: #d97706;
|
|
27
|
+
--danger: #dc2626;
|
|
28
|
+
--node-default: #94a3b8;
|
|
29
|
+
--c-red: #dc2626;
|
|
30
|
+
--c-orange: #d97706;
|
|
31
|
+
--c-yellow: #ca8a04;
|
|
32
|
+
--c-green: #059669;
|
|
33
|
+
--c-teal: #0d9488;
|
|
34
|
+
--c-blue: #2563eb;
|
|
35
|
+
--c-purple: #7c3aed;
|
|
36
|
+
--c-pink: #db2777;
|
|
37
|
+
--c-gray: #64748b;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:root[data-theme='dark'] {
|
|
41
|
+
color-scheme: dark;
|
|
42
|
+
--bg: #161718;
|
|
43
|
+
--surface: #1f2022;
|
|
44
|
+
--surface-2: #2a2b2e;
|
|
45
|
+
--border: #35373b;
|
|
46
|
+
--text: #e8eaed;
|
|
47
|
+
--muted: #9aa0a8;
|
|
48
|
+
--accent: #3b82f6;
|
|
49
|
+
--dot: #2c2e31;
|
|
50
|
+
--group-bg: rgba(255, 255, 255, 0.03);
|
|
51
|
+
--node-bg: #262729;
|
|
52
|
+
--node-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 6px 16px rgba(0, 0, 0, 0.35);
|
|
53
|
+
--edge: #38a1e8;
|
|
54
|
+
--edge-dashed: #7d8590;
|
|
55
|
+
--edge-optional: #a78bfa;
|
|
56
|
+
--ok: #34d399;
|
|
57
|
+
--tools: #fbbf24;
|
|
58
|
+
--danger: #f87171;
|
|
59
|
+
--node-default: #64748b;
|
|
60
|
+
--c-red: #f87171;
|
|
61
|
+
--c-orange: #fbbf24;
|
|
62
|
+
--c-yellow: #facc15;
|
|
63
|
+
--c-green: #34d399;
|
|
64
|
+
--c-teal: #2dd4bf;
|
|
65
|
+
--c-blue: #60a5fa;
|
|
66
|
+
--c-purple: #a78bfa;
|
|
67
|
+
--c-pink: #f472b6;
|
|
68
|
+
--c-gray: #94a3b8;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@media (prefers-color-scheme: dark) {
|
|
72
|
+
:root:not([data-theme]) {
|
|
73
|
+
color-scheme: dark;
|
|
74
|
+
--bg: #161718;
|
|
75
|
+
--surface: #1f2022;
|
|
76
|
+
--surface-2: #2a2b2e;
|
|
77
|
+
--border: #35373b;
|
|
78
|
+
--text: #e8eaed;
|
|
79
|
+
--muted: #9aa0a8;
|
|
80
|
+
--accent: #3b82f6;
|
|
81
|
+
--dot: #2c2e31;
|
|
82
|
+
--group-bg: rgba(255, 255, 255, 0.03);
|
|
83
|
+
--node-bg: #262729;
|
|
84
|
+
--node-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 6px 16px rgba(0, 0, 0, 0.35);
|
|
85
|
+
--edge: #38a1e8;
|
|
86
|
+
--edge-dashed: #7d8590;
|
|
87
|
+
--edge-optional: #a78bfa;
|
|
88
|
+
--ok: #34d399;
|
|
89
|
+
--tools: #fbbf24;
|
|
90
|
+
--danger: #f87171;
|
|
91
|
+
--node-default: #64748b;
|
|
92
|
+
--c-red: #f87171;
|
|
93
|
+
--c-orange: #fbbf24;
|
|
94
|
+
--c-yellow: #facc15;
|
|
95
|
+
--c-green: #34d399;
|
|
96
|
+
--c-teal: #2dd4bf;
|
|
97
|
+
--c-blue: #60a5fa;
|
|
98
|
+
--c-purple: #a78bfa;
|
|
99
|
+
--c-pink: #f472b6;
|
|
100
|
+
--c-gray: #94a3b8;
|
|
101
|
+
}
|
|
102
|
+
}
|