@arach/arc 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/arc-mcp.mjs +31826 -0
- package/docs/llm.txt +208 -0
- package/lib/MarkupPanel-CroO7O49.js +182 -0
- package/lib/arc.css +1 -1
- package/lib/arc.es.js +31 -27
- package/lib/arc.umd.js +155 -141
- package/lib/index-B4esAiHG.js +1006 -0
- package/lib/index-BtUi_w1W.js +964 -0
- package/lib/index-CI-w1U9t.js +2725 -0
- package/lib/index-CQhCoaVM.js +77 -0
- package/lib/index-CVhUGF67.js +1309 -0
- package/lib/{index-iG7ybQea.js → index-CbEv7M-m.js} +24924 -24546
- package/lib/index-Cg52_-j6.js +959 -0
- package/lib/index-Cmm99d2_.js +1925 -0
- package/lib/index-CnGsbmkP.js +7884 -0
- package/lib/index-CvsZLy9v.js +2344 -0
- package/lib/index-DBTOQDAV.js +1886 -0
- package/lib/index-Ds2bIH9V.js +967 -0
- package/lib/{index-DM8JwQYr.js → index-gm9Hs3ZB.js} +1 -1
- package/lib/index.d.ts +61 -2
- package/package.json +33 -6
- package/skills/arc-diagrams/SKILL.md +218 -0
- package/src/types/diagram.ts +197 -0
- package/lib/commands_hudsonkit_false-tNYQZ4nZ.js +0 -5
- package/lib/highlight_hudsonkit_false-CGjCyNxW.js +0 -5
- package/lib/lang-css_hudsonkit_false-oeV3Hq1J.js +0 -5
- package/lib/lang-html_hudsonkit_false-CCxA3CYh.js +0 -5
- package/lib/lang-javascript_hudsonkit_false-SQgz3iJM.js +0 -5
- package/lib/lang-json_hudsonkit_false-BksH8zxC.js +0 -5
- package/lib/lang-markdown_hudsonkit_false-B5TeQsd5.js +0 -5
- package/lib/language_hudsonkit_false-D4r7WoC5.js +0 -5
- package/lib/state_hudsonkit_false-Rl5x6lAJ.js +0 -5
- package/lib/view_hudsonkit_false-Cv9f7Eek.js +0 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { o as Re, a as ee, f as $, m as v, s as de, c as Vn, p as te, r as wn, b as ue, d as pn, e as mr, g as M, h as dr, i as gr, j as hn, k as ne, n as Ce, l as Qe, q as yr, t as xr, v as It, u as kr } from "./index-B47Ukxqu.js";
|
|
2
2
|
import { Fragment as Tt, jsxs as br, jsx as wr } from "react/jsx-runtime";
|
|
3
3
|
import { useState as qn, useEffect as Sr, createElement as Er } from "react";
|
|
4
|
-
import { g as Pt } from "./index-
|
|
4
|
+
import { g as Pt } from "./index-CbEv7M-m.js";
|
|
5
5
|
function Cr(e, n) {
|
|
6
6
|
const t = {};
|
|
7
7
|
return (e[e.length - 1] === "" ? [...e, ""] : e).join(
|
package/lib/index.d.ts
CHANGED
|
@@ -24,6 +24,20 @@ export declare interface ArcConnectorStyle {
|
|
|
24
24
|
|
|
25
25
|
export declare function ArcDiagram({ data, className, interactive, mode, theme, label, labelPosition, defaultZoom, zoomLevels, showArcToggle, showAutoLayout, showControls, showMinimap, showLegend, showFocusStory, frame, hoverEffects, onNodeHover, titleBlock, maxFitZoom, }: ArcDiagramProps): JSX.Element;
|
|
26
26
|
|
|
27
|
+
declare interface ArcDiagram_2 {
|
|
28
|
+
layout: DiagramLayout_2;
|
|
29
|
+
grid: GridConfig;
|
|
30
|
+
layoutHints?: LayoutHints_2;
|
|
31
|
+
nodes: Record<string, NodePosition_2>;
|
|
32
|
+
nodeData: Record<string, NodeData>;
|
|
33
|
+
connectors: Connector[];
|
|
34
|
+
connectorStyles: Record<string, ConnectorStyle_2>;
|
|
35
|
+
groups?: GroupShape_2[];
|
|
36
|
+
focusTargets?: Record<string, FocusTarget_2>;
|
|
37
|
+
images?: DiagramImage[];
|
|
38
|
+
exportZone?: ExportZone | null;
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
export declare interface ArcDiagramData {
|
|
28
42
|
id?: string;
|
|
29
43
|
layout: DiagramLayout;
|
|
@@ -108,6 +122,8 @@ export declare interface ArcNodeData {
|
|
|
108
122
|
subtitle?: string;
|
|
109
123
|
description?: string;
|
|
110
124
|
color: DiagramColor;
|
|
125
|
+
/** Per-node silhouette. Omit to follow the theme's own node shape. */
|
|
126
|
+
shape?: NodeShape;
|
|
111
127
|
}
|
|
112
128
|
|
|
113
129
|
export declare interface ArcNodePosition {
|
|
@@ -282,7 +298,7 @@ export declare function deleteDiagramSession(id: string): void;
|
|
|
282
298
|
/** Derive a URL-safe session ID from a diagram's source path or ID */
|
|
283
299
|
export declare function deriveSessionId(source: string): string;
|
|
284
300
|
|
|
285
|
-
export declare function DiagramCanvas({ onViewportChange, embedConfig, zoomConfig, themeOverride, isDark }: DiagramCanvasProps): JSX.Element;
|
|
301
|
+
export declare function DiagramCanvas({ onViewportChange, embedConfig, zoomConfig, surface, themeOverride, isDark }: DiagramCanvasProps): JSX.Element;
|
|
286
302
|
|
|
287
303
|
declare interface DiagramCanvasProps {
|
|
288
304
|
onViewportChange?: (bounds: {
|
|
@@ -293,6 +309,10 @@ declare interface DiagramCanvasProps {
|
|
|
293
309
|
}) => void;
|
|
294
310
|
embedConfig?: EmbedConfig;
|
|
295
311
|
zoomConfig?: ZoomConfig;
|
|
312
|
+
/** Workspace backdrop: 'theme' paints the diagram theme's container (embeds,
|
|
313
|
+
* where the frame is part of the artifact), 'chrome' paints the app canvas
|
|
314
|
+
* so the editor's infinite surface matches the shell skin. */
|
|
315
|
+
surface?: 'theme' | 'chrome';
|
|
296
316
|
/** Override canvas background with an Arc theme. */
|
|
297
317
|
themeOverride?: string;
|
|
298
318
|
isDark?: boolean;
|
|
@@ -368,6 +388,17 @@ export declare function DiagramEditor({ initialData, themeId, colorMode, session
|
|
|
368
388
|
initialDiagramMeta?: Record<string, any>;
|
|
369
389
|
}): JSX.Element;
|
|
370
390
|
|
|
391
|
+
declare interface DiagramImage {
|
|
392
|
+
id: string;
|
|
393
|
+
src: string;
|
|
394
|
+
name: string;
|
|
395
|
+
x: number;
|
|
396
|
+
y: number;
|
|
397
|
+
width: number;
|
|
398
|
+
height: number;
|
|
399
|
+
opacity: number;
|
|
400
|
+
}
|
|
401
|
+
|
|
371
402
|
export declare interface DiagramLayout {
|
|
372
403
|
width: number;
|
|
373
404
|
height: number;
|
|
@@ -459,6 +490,13 @@ export declare interface EmbedConfig {
|
|
|
459
490
|
showGrid?: boolean;
|
|
460
491
|
}
|
|
461
492
|
|
|
493
|
+
declare interface ExportZone {
|
|
494
|
+
x: number;
|
|
495
|
+
y: number;
|
|
496
|
+
width: number;
|
|
497
|
+
height: number;
|
|
498
|
+
}
|
|
499
|
+
|
|
462
500
|
export declare interface FocusConnectorRef {
|
|
463
501
|
from: string;
|
|
464
502
|
to: string;
|
|
@@ -511,6 +549,14 @@ export declare function getThemeList(): {
|
|
|
511
549
|
description: string;
|
|
512
550
|
}[];
|
|
513
551
|
|
|
552
|
+
declare interface GridConfig {
|
|
553
|
+
enabled: boolean;
|
|
554
|
+
size: number;
|
|
555
|
+
color: string;
|
|
556
|
+
opacity: number;
|
|
557
|
+
type: 'dots' | 'lines';
|
|
558
|
+
}
|
|
559
|
+
|
|
514
560
|
export declare type GroupLayoutDirection = 'horizontal' | 'vertical';
|
|
515
561
|
|
|
516
562
|
declare type GroupLayoutDirection_2 = 'horizontal' | 'vertical';
|
|
@@ -628,6 +674,8 @@ declare const initialState: {
|
|
|
628
674
|
};
|
|
629
675
|
};
|
|
630
676
|
|
|
677
|
+
export declare function isDiagramShape(value: unknown): boolean;
|
|
678
|
+
|
|
631
679
|
/** Preset HSL palettes matching Arc's diagram colors. */
|
|
632
680
|
export declare const ISO_COLORS: {
|
|
633
681
|
violet: IsoColorDef;
|
|
@@ -748,6 +796,8 @@ declare interface NodeData {
|
|
|
748
796
|
subtitle?: string;
|
|
749
797
|
description?: string;
|
|
750
798
|
color: DiagramColor_2;
|
|
799
|
+
/** Per-node silhouette. Omit to follow the theme's own node shape. */
|
|
800
|
+
shape?: NodeShape;
|
|
751
801
|
}
|
|
752
802
|
|
|
753
803
|
export declare interface NodeLayoutHint {
|
|
@@ -783,11 +833,13 @@ declare interface NodePosition_2 {
|
|
|
783
833
|
size: NodeSize_2;
|
|
784
834
|
}
|
|
785
835
|
|
|
836
|
+
declare type NodeShape = 'rounded' | 'square' | 'chamfer' | 'notch' | 'pill';
|
|
837
|
+
|
|
786
838
|
export declare type NodeSize = 'xs' | 's' | 'm' | 'l';
|
|
787
839
|
|
|
788
840
|
declare type NodeSize_2 = 'xs' | 's' | 'm' | 'l';
|
|
789
841
|
|
|
790
|
-
declare type NodeSize_3 = '
|
|
842
|
+
declare type NodeSize_3 = 'xs' | 's' | 'm' | 'l';
|
|
791
843
|
|
|
792
844
|
/**
|
|
793
845
|
* Parse YAML config into DiagramConfig
|
|
@@ -936,6 +988,10 @@ declare interface TitleBlockInfo {
|
|
|
936
988
|
sheet?: string;
|
|
937
989
|
}
|
|
938
990
|
|
|
991
|
+
export declare function toExportFormat(diagram: ArcDiagram_2): ArcDiagramData_2;
|
|
992
|
+
|
|
993
|
+
export declare function toTypeScriptSource(diagram: ArcDiagram_2, name?: string): string;
|
|
994
|
+
|
|
939
995
|
export declare function useColorMode(): string;
|
|
940
996
|
|
|
941
997
|
export declare function useDiagram(): {
|
|
@@ -1005,6 +1061,9 @@ export declare function useThemeId(): string;
|
|
|
1005
1061
|
|
|
1006
1062
|
export declare function useViewMode(): string;
|
|
1007
1063
|
|
|
1064
|
+
/** Human-readable reason this is not a diagram, or null if it is. */
|
|
1065
|
+
export declare function validateDiagramShape(value: unknown): string | null;
|
|
1066
|
+
|
|
1008
1067
|
export declare type ViewMode = '2d' | 'isometric';
|
|
1009
1068
|
|
|
1010
1069
|
declare interface ZoomConfig {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arach/arc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "bun@1.3.11",
|
|
6
6
|
"workspaces": [
|
|
@@ -11,7 +11,14 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/arach/arc.git"
|
|
14
|
+
"url": "git+https://github.com/arach/arc.git"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/arach/arc#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/arach/arc/issues"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
15
22
|
},
|
|
16
23
|
"publishConfig": {
|
|
17
24
|
"access": "public",
|
|
@@ -27,13 +34,18 @@
|
|
|
27
34
|
"isometric"
|
|
28
35
|
],
|
|
29
36
|
"bin": {
|
|
30
|
-
"arc-ascii": "./bin/arc-ascii.mjs"
|
|
37
|
+
"arc-ascii": "./bin/arc-ascii.mjs",
|
|
38
|
+
"arc-mcp": "./bin/arc-mcp.mjs"
|
|
31
39
|
},
|
|
32
40
|
"files": [
|
|
33
41
|
"lib/*.js",
|
|
34
42
|
"lib/*.d.ts",
|
|
35
43
|
"lib/*.css",
|
|
36
|
-
"bin/arc-ascii.mjs"
|
|
44
|
+
"bin/arc-ascii.mjs",
|
|
45
|
+
"bin/arc-mcp.mjs",
|
|
46
|
+
"docs/llm.txt",
|
|
47
|
+
"skills/arc-diagrams/SKILL.md",
|
|
48
|
+
"src/types/diagram.ts"
|
|
37
49
|
],
|
|
38
50
|
"main": "./lib/arc.umd.js",
|
|
39
51
|
"module": "./lib/arc.es.js",
|
|
@@ -50,13 +62,15 @@
|
|
|
50
62
|
"dev": "vite",
|
|
51
63
|
"build": "tsc && vite build && node scripts/generate-docs-html.js",
|
|
52
64
|
"build:lib": "vite build --config vite.config.lib.js",
|
|
65
|
+
"build:mcp": "bun scripts/build-arc-mcp.mjs",
|
|
66
|
+
"mcp": "bun scripts/mcp/server.ts",
|
|
53
67
|
"build:iso": "vite build --config vite.config.iso.js && vite build --config vite.config.iso-slim.js",
|
|
54
68
|
"lint": "eslint .",
|
|
55
69
|
"typecheck": "tsc --noEmit",
|
|
56
70
|
"preview": "vite preview",
|
|
57
71
|
"generate-og": "node scripts/generate-og.js",
|
|
58
72
|
"check:dist": "attw --pack . --ignore-rules cjs-resolves-to-esm unexpected-module-syntax && publint && node scripts/check-packlist.mjs",
|
|
59
|
-
"prepublishOnly": "bun run build:lib && bun run check:dist"
|
|
73
|
+
"prepublishOnly": "bun run build:lib && bun run build:mcp && bun run check:dist"
|
|
60
74
|
},
|
|
61
75
|
"peerDependencies": {
|
|
62
76
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -66,13 +80,24 @@
|
|
|
66
80
|
"@arach/dewey": "^0.2.0",
|
|
67
81
|
"@arethetypeswrong/cli": "^0.18.4",
|
|
68
82
|
"@base-ui/react": "^1.0.0",
|
|
83
|
+
"@codemirror/commands": "^6.10.4",
|
|
84
|
+
"@codemirror/lang-css": "^6.3.1",
|
|
85
|
+
"@codemirror/lang-html": "^6.4.12",
|
|
86
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
87
|
+
"@codemirror/lang-json": "^6.0.2",
|
|
88
|
+
"@codemirror/lang-markdown": "^6.5.2",
|
|
89
|
+
"@codemirror/language": "^6.12.4",
|
|
90
|
+
"@codemirror/state": "^6.7.1",
|
|
91
|
+
"@codemirror/view": "^6.43.8",
|
|
69
92
|
"@eslint/js": "^9.39.1",
|
|
93
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
70
94
|
"@tailwindcss/vite": "^4.1.18",
|
|
71
95
|
"@types/js-yaml": "^4.0.9",
|
|
72
96
|
"@types/react": "^19.2.5",
|
|
73
97
|
"@types/react-dom": "^19.2.3",
|
|
74
98
|
"@types/three": "^0.182.0",
|
|
75
99
|
"@vitejs/plugin-react": "^5.1.1",
|
|
100
|
+
"codemirror": "^6.0.2",
|
|
76
101
|
"eslint": "^9.39.1",
|
|
77
102
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
78
103
|
"eslint-plugin-react-refresh": "^0.4.24",
|
|
@@ -91,7 +116,9 @@
|
|
|
91
116
|
"tailwindcss": "^4.1.18",
|
|
92
117
|
"three": "^0.182.0",
|
|
93
118
|
"typescript": "^5.9.3",
|
|
119
|
+
"typescript-eslint": "^8.67.0",
|
|
94
120
|
"vite": "^7.2.4",
|
|
95
|
-
"vite-plugin-dts": "^4.5.4"
|
|
121
|
+
"vite-plugin-dts": "^4.5.4",
|
|
122
|
+
"zod": "^3.25.76"
|
|
96
123
|
}
|
|
97
124
|
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: arc-diagrams
|
|
3
|
+
description: Create architecture diagrams using Arc's JSON format. Use when asked to "create an architecture diagram", "draw a system diagram", "visualize the architecture", or "make a diagram of".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Arc Diagrams
|
|
7
|
+
|
|
8
|
+
Arc is a visual diagram editor for creating architecture diagrams. This skill enables you to generate Arc-compatible diagram configs that can be rendered in React applications.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Activate this skill when the user asks to:
|
|
13
|
+
- "Create an architecture diagram"
|
|
14
|
+
- "Draw a system diagram"
|
|
15
|
+
- "Visualize the architecture"
|
|
16
|
+
- "Make a diagram showing..."
|
|
17
|
+
- "Design a flow diagram"
|
|
18
|
+
|
|
19
|
+
## Diagram Format
|
|
20
|
+
|
|
21
|
+
Arc diagrams are JSON objects with this structure:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
interface ArcDiagramData {
|
|
25
|
+
layout: { width: number; height: number }
|
|
26
|
+
nodes: Record<string, NodePosition>
|
|
27
|
+
nodeData: Record<string, NodeData>
|
|
28
|
+
connectors: Connector[]
|
|
29
|
+
connectorStyles: Record<string, ConnectorStyle>
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Creating a Diagram
|
|
34
|
+
|
|
35
|
+
### 1. Define Layout
|
|
36
|
+
|
|
37
|
+
Set canvas dimensions (default 1600x900 for editor, smaller for exports):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
"layout": { "width": 860, "height": 400 }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. Position Nodes
|
|
44
|
+
|
|
45
|
+
Each node needs an `x`, `y` position and `size`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
"nodes": {
|
|
49
|
+
"frontend": { "x": 50, "y": 100, "size": "l" },
|
|
50
|
+
"api": { "x": 300, "y": 100, "size": "m" },
|
|
51
|
+
"database": { "x": 550, "y": 100, "size": "m" }
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Size options** (canonical — use these):
|
|
56
|
+
| Size | Key | Dimensions (px) |
|
|
57
|
+
|------|-----|-----------------|
|
|
58
|
+
| Extra Small | `xs` | 80 × 36 |
|
|
59
|
+
| Small | `s` | 110 × 48 |
|
|
60
|
+
| Medium | `m` | 160 × 75 |
|
|
61
|
+
| Large | `l` | 220 × 90 |
|
|
62
|
+
|
|
63
|
+
Source: `src/utils/constants.ts` → `NODE_SIZES`. Do **not** use `large`/`normal`/`small`.
|
|
64
|
+
|
|
65
|
+
### 3. Define Node Data
|
|
66
|
+
|
|
67
|
+
Each node needs an icon, name, and color:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
"nodeData": {
|
|
71
|
+
"frontend": {
|
|
72
|
+
"icon": "Monitor",
|
|
73
|
+
"name": "Frontend",
|
|
74
|
+
"subtitle": "React",
|
|
75
|
+
"description": "User interface",
|
|
76
|
+
"color": "violet"
|
|
77
|
+
},
|
|
78
|
+
"api": {
|
|
79
|
+
"icon": "Server",
|
|
80
|
+
"name": "API",
|
|
81
|
+
"subtitle": "Node.js",
|
|
82
|
+
"description": "REST endpoints",
|
|
83
|
+
"color": "emerald"
|
|
84
|
+
},
|
|
85
|
+
"database": {
|
|
86
|
+
"icon": "Database",
|
|
87
|
+
"name": "PostgreSQL",
|
|
88
|
+
"subtitle": "Storage",
|
|
89
|
+
"description": "Persistent data",
|
|
90
|
+
"color": "blue"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Available icons (from Lucide):**
|
|
96
|
+
- **Devices:** Monitor, Server, Smartphone, Watch, Cloud, Cpu, Database, HardDrive
|
|
97
|
+
- **Network:** Wifi, Globe
|
|
98
|
+
- **Users:** User, Users
|
|
99
|
+
- **Security:** Lock, Key, Shield
|
|
100
|
+
- **Media:** Mic, Camera, Speaker, Headphones
|
|
101
|
+
- **Code:** Code, Terminal, FileCode, Folder
|
|
102
|
+
- **Data:** Zap, Activity, BarChart, PieChart
|
|
103
|
+
- **Flow:** ArrowRight, ArrowDown, RefreshCw, Repeat
|
|
104
|
+
- **Structure:** Box, Package, Layers, Grid
|
|
105
|
+
- **UI:** Settings, Bell, Mail, MessageSquare, Search, Filter
|
|
106
|
+
- **Actions:** Download, Upload, Play, Pause, Square, Circle
|
|
107
|
+
|
|
108
|
+
**Available colors:**
|
|
109
|
+
`violet` | `emerald` | `blue` | `amber` | `sky` | `zinc` | `rose` | `orange`
|
|
110
|
+
|
|
111
|
+
### 4. Connect Nodes
|
|
112
|
+
|
|
113
|
+
Define connections between nodes:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
"connectors": [
|
|
117
|
+
{
|
|
118
|
+
"from": "frontend",
|
|
119
|
+
"to": "api",
|
|
120
|
+
"fromAnchor": "right",
|
|
121
|
+
"toAnchor": "left",
|
|
122
|
+
"style": "http"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"from": "api",
|
|
126
|
+
"to": "database",
|
|
127
|
+
"fromAnchor": "right",
|
|
128
|
+
"toAnchor": "left",
|
|
129
|
+
"style": "sql"
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Anchor positions:**
|
|
135
|
+
`top` | `bottom` | `left` | `right` | `bottomLeft` | `bottomRight` | `topLeft` | `topRight`
|
|
136
|
+
|
|
137
|
+
**Optional:** Add `"curve": "natural"` or `"curve": "step"` for curved connectors.
|
|
138
|
+
|
|
139
|
+
### 5. Style Connectors
|
|
140
|
+
|
|
141
|
+
Define appearance for each connector style:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
"connectorStyles": {
|
|
145
|
+
"http": { "color": "amber", "strokeWidth": 2, "label": "HTTP" },
|
|
146
|
+
"sql": { "color": "blue", "strokeWidth": 2, "label": "SQL" },
|
|
147
|
+
"async": { "color": "zinc", "strokeWidth": 1.5, "dashed": true }
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Complete Example
|
|
152
|
+
|
|
153
|
+
Here's a full diagram for a typical web application:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"layout": { "width": 700, "height": 300 },
|
|
158
|
+
"nodes": {
|
|
159
|
+
"client": { "x": 50, "y": 100, "size": "l" },
|
|
160
|
+
"api": { "x": 300, "y": 100, "size": "m" },
|
|
161
|
+
"cache": { "x": 300, "y": 220, "size": "s" },
|
|
162
|
+
"database": { "x": 520, "y": 100, "size": "m" }
|
|
163
|
+
},
|
|
164
|
+
"nodeData": {
|
|
165
|
+
"client": { "icon": "Monitor", "name": "Client", "subtitle": "React", "color": "violet" },
|
|
166
|
+
"api": { "icon": "Server", "name": "API", "subtitle": "Express", "color": "emerald" },
|
|
167
|
+
"cache": { "icon": "Zap", "name": "Cache", "subtitle": "Redis", "color": "amber" },
|
|
168
|
+
"database": { "icon": "Database", "name": "Database", "subtitle": "Postgres", "color": "blue" }
|
|
169
|
+
},
|
|
170
|
+
"connectors": [
|
|
171
|
+
{ "from": "client", "to": "api", "fromAnchor": "right", "toAnchor": "left", "style": "http" },
|
|
172
|
+
{ "from": "api", "to": "database", "fromAnchor": "right", "toAnchor": "left", "style": "sql" },
|
|
173
|
+
{ "from": "api", "to": "cache", "fromAnchor": "bottom", "toAnchor": "top", "style": "cache" }
|
|
174
|
+
],
|
|
175
|
+
"connectorStyles": {
|
|
176
|
+
"http": { "color": "amber", "strokeWidth": 2, "label": "HTTP" },
|
|
177
|
+
"sql": { "color": "blue", "strokeWidth": 2, "label": "SQL" },
|
|
178
|
+
"cache": { "color": "emerald", "strokeWidth": 2, "label": "cache" }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Layout Tips
|
|
184
|
+
|
|
185
|
+
1. **Prefer auto-layout** — use `autoLayout()` from `@arach/arc` when you don't need pixel-perfect placement
|
|
186
|
+
2. **Grid alignment:** Position nodes on a ~50px grid for clean manual layouts
|
|
187
|
+
3. **Spacing:** Leave ~150–200px between connected nodes horizontally
|
|
188
|
+
4. **Flow direction:** Left-to-right or top-to-bottom for data flow
|
|
189
|
+
5. **Grouping:** Use `groups` + `layoutHints` for framed sections (see `docs/group-layout.md`)
|
|
190
|
+
6. **Large nodes:** Use `l` size for primary/entry-point components
|
|
191
|
+
7. **Connectors:** Match connector colors to the source or destination node
|
|
192
|
+
|
|
193
|
+
## Validation
|
|
194
|
+
|
|
195
|
+
Before handing off JSON, ensure every `nodes` key has a matching `nodeData` entry.
|
|
196
|
+
In the repo, `validateDiagramShape()` in `src/utils/diagramValidation.ts` returns a
|
|
197
|
+
human-readable error or `null`.
|
|
198
|
+
|
|
199
|
+
## Output
|
|
200
|
+
|
|
201
|
+
When generating a diagram, output:
|
|
202
|
+
1. The complete JSON config
|
|
203
|
+
2. Brief explanation of the architecture shown
|
|
204
|
+
3. Suggest the user save it as a `.arc.json` file or paste into the Arc editor
|
|
205
|
+
|
|
206
|
+
## TypeScript Export
|
|
207
|
+
|
|
208
|
+
For React projects, diagrams can be exported as TypeScript:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import type { ArcDiagramData } from '@arach/arc'
|
|
212
|
+
|
|
213
|
+
const diagram: ArcDiagramData = {
|
|
214
|
+
// ... config here
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export default diagram
|
|
218
|
+
```
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Arc Diagram Types
|
|
2
|
+
// Shared format for Arc editor and consumers (Talkie docs, etc.)
|
|
3
|
+
|
|
4
|
+
import type { NodeShape } from '../utils/nodeShape'
|
|
5
|
+
|
|
6
|
+
export type { NodeShape }
|
|
7
|
+
|
|
8
|
+
export type NodeSize = 'xs' | 's' | 'm' | 'l'
|
|
9
|
+
|
|
10
|
+
export type AnchorPosition =
|
|
11
|
+
| 'left' | 'right' | 'top' | 'bottom'
|
|
12
|
+
| 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight'
|
|
13
|
+
|
|
14
|
+
export type DiagramColor =
|
|
15
|
+
| 'violet' | 'emerald' | 'blue' | 'amber'
|
|
16
|
+
| 'sky' | 'zinc' | 'rose' | 'orange'
|
|
17
|
+
|
|
18
|
+
export interface NodePosition {
|
|
19
|
+
x: number
|
|
20
|
+
y: number
|
|
21
|
+
size: NodeSize
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface NodeData {
|
|
25
|
+
icon: string
|
|
26
|
+
name: string
|
|
27
|
+
subtitle?: string
|
|
28
|
+
description?: string
|
|
29
|
+
color: DiagramColor
|
|
30
|
+
/** Per-node silhouette. Omit to follow the theme's own node shape. */
|
|
31
|
+
shape?: NodeShape
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface Connector {
|
|
35
|
+
from: string
|
|
36
|
+
to: string
|
|
37
|
+
fromAnchor: AnchorPosition
|
|
38
|
+
toAnchor: AnchorPosition
|
|
39
|
+
style: string
|
|
40
|
+
curve?: 'natural' | 'step'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ConnectorStyle {
|
|
44
|
+
color: DiagramColor
|
|
45
|
+
strokeWidth: number
|
|
46
|
+
label?: string
|
|
47
|
+
dashed?: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface DiagramLayout {
|
|
51
|
+
width: number
|
|
52
|
+
height: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface GridConfig {
|
|
56
|
+
enabled: boolean
|
|
57
|
+
size: number
|
|
58
|
+
color: string
|
|
59
|
+
opacity: number
|
|
60
|
+
type: 'dots' | 'lines'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface GroupShape {
|
|
64
|
+
id: string
|
|
65
|
+
x: number
|
|
66
|
+
y: number
|
|
67
|
+
width: number
|
|
68
|
+
height: number
|
|
69
|
+
type: 'rect' | 'circle'
|
|
70
|
+
color: DiagramColor
|
|
71
|
+
label?: string
|
|
72
|
+
dashed?: boolean
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface FocusConnectorRef {
|
|
76
|
+
from: string
|
|
77
|
+
to: string
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface FocusStep {
|
|
81
|
+
icon: string
|
|
82
|
+
label: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** A declarative highlight story activated by hovering or selecting a node. */
|
|
86
|
+
export interface FocusTarget {
|
|
87
|
+
/** `append` includes direct neighbors; `replace` uses only the explicit story. */
|
|
88
|
+
mode?: 'append' | 'replace'
|
|
89
|
+
nodes?: string[]
|
|
90
|
+
connectors?: FocusConnectorRef[]
|
|
91
|
+
caption?: string
|
|
92
|
+
steps?: FocusStep[]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type LayoutAlignment = 'start' | 'center' | 'end'
|
|
96
|
+
export type GroupLayoutDirection = 'horizontal' | 'vertical'
|
|
97
|
+
|
|
98
|
+
/** Optional placement hints used by autoLayout when nodes belong to groups. */
|
|
99
|
+
export interface NodeLayoutHint {
|
|
100
|
+
/** ID of the group frame that owns this node. */
|
|
101
|
+
group?: string
|
|
102
|
+
/** Explicit layer within the group. Connected nodes are layered automatically otherwise. */
|
|
103
|
+
layer?: number
|
|
104
|
+
/** Stable ordering within a layer. Lower values render first. */
|
|
105
|
+
order?: number
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Layout policy for the nodes inside one group frame. */
|
|
109
|
+
export interface GroupLayoutHint {
|
|
110
|
+
/** `horizontal` lays layers left-to-right; `vertical` lays them top-to-bottom. */
|
|
111
|
+
direction?: GroupLayoutDirection
|
|
112
|
+
padding?: number
|
|
113
|
+
layerGap?: number
|
|
114
|
+
itemGap?: number
|
|
115
|
+
align?: LayoutAlignment
|
|
116
|
+
justify?: LayoutAlignment | 'space-between'
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface LayoutHints {
|
|
120
|
+
nodes?: Record<string, NodeLayoutHint>
|
|
121
|
+
groups?: Record<string, GroupLayoutHint>
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface DiagramImage {
|
|
125
|
+
id: string
|
|
126
|
+
src: string
|
|
127
|
+
name: string
|
|
128
|
+
x: number
|
|
129
|
+
y: number
|
|
130
|
+
width: number
|
|
131
|
+
height: number
|
|
132
|
+
opacity: number
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface ExportZone {
|
|
136
|
+
x: number
|
|
137
|
+
y: number
|
|
138
|
+
width: number
|
|
139
|
+
height: number
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Full diagram format (internal Arc state)
|
|
143
|
+
export interface ArcDiagram {
|
|
144
|
+
layout: DiagramLayout
|
|
145
|
+
grid: GridConfig
|
|
146
|
+
layoutHints?: LayoutHints
|
|
147
|
+
nodes: Record<string, NodePosition>
|
|
148
|
+
nodeData: Record<string, NodeData>
|
|
149
|
+
connectors: Connector[]
|
|
150
|
+
connectorStyles: Record<string, ConnectorStyle>
|
|
151
|
+
groups?: GroupShape[]
|
|
152
|
+
focusTargets?: Record<string, FocusTarget>
|
|
153
|
+
images?: DiagramImage[]
|
|
154
|
+
exportZone?: ExportZone | null
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Clean export format (for consumers)
|
|
158
|
+
export interface ArcDiagramData {
|
|
159
|
+
id?: string
|
|
160
|
+
layout: DiagramLayout
|
|
161
|
+
layoutHints?: LayoutHints
|
|
162
|
+
nodes: Record<string, NodePosition>
|
|
163
|
+
nodeData: Record<string, NodeData>
|
|
164
|
+
connectors: Connector[]
|
|
165
|
+
connectorStyles: Record<string, ConnectorStyle>
|
|
166
|
+
focusTargets?: Record<string, FocusTarget>
|
|
167
|
+
groups?: GroupShape[]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Convert full diagram to clean export format
|
|
171
|
+
export function toExportFormat(diagram: ArcDiagram): ArcDiagramData {
|
|
172
|
+
return {
|
|
173
|
+
layout: diagram.layout,
|
|
174
|
+
layoutHints: diagram.layoutHints,
|
|
175
|
+
nodes: diagram.nodes,
|
|
176
|
+
nodeData: diagram.nodeData,
|
|
177
|
+
connectors: diagram.connectors,
|
|
178
|
+
connectorStyles: diagram.connectorStyles,
|
|
179
|
+
focusTargets: diagram.focusTargets,
|
|
180
|
+
groups: diagram.groups,
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Generate TypeScript source file content
|
|
185
|
+
export function toTypeScriptSource(diagram: ArcDiagram, name: string = 'diagram'): string {
|
|
186
|
+
const data = toExportFormat(diagram)
|
|
187
|
+
const json = JSON.stringify(data, null, 2)
|
|
188
|
+
.replace(/"([^"]+)":/g, '$1:') // Remove quotes from keys
|
|
189
|
+
.replace(/"/g, "'") // Use single quotes
|
|
190
|
+
|
|
191
|
+
return `import type { ArcDiagramData } from '@arach/arc'
|
|
192
|
+
|
|
193
|
+
const ${name}: ArcDiagramData = ${json}
|
|
194
|
+
|
|
195
|
+
export default ${name}
|
|
196
|
+
`
|
|
197
|
+
}
|