@arach/arc 0.5.0 → 0.7.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/README.md +6 -6
- package/bin/arc-mcp.mjs +31826 -0
- package/docs/llm.txt +208 -0
- package/lib/MarkupPanel-C4yZc7tU.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-DM8JwQYr.js → index-BQcljODC.js} +1 -1
- package/lib/index-BtUi_w1W.js +964 -0
- package/lib/{index-iG7ybQea.js → index-BzHLvtbw.js} +25924 -25462
- 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-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.d.ts +68 -3
- package/package.json +34 -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
package/lib/index.d.ts
CHANGED
|
@@ -22,7 +22,21 @@ export declare interface ArcConnectorStyle {
|
|
|
22
22
|
dashed?: boolean;
|
|
23
23
|
}
|
|
24
24
|
|
|
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;
|
|
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, defaultViewMode, defaultIsoStyle, }: ArcDiagramProps): JSX.Element;
|
|
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
|
+
}
|
|
26
40
|
|
|
27
41
|
export declare interface ArcDiagramData {
|
|
28
42
|
id?: string;
|
|
@@ -86,6 +100,10 @@ declare interface ArcDiagramProps {
|
|
|
86
100
|
onNodeHover?: (nodeId: string | null) => void;
|
|
87
101
|
/** Override the engineering title-block fields (shown when the theme opts in). */
|
|
88
102
|
titleBlock?: TitleBlockInfo;
|
|
103
|
+
/** Render the diagram in isometric projection. Default: '2d' */
|
|
104
|
+
defaultViewMode?: ViewMode_2;
|
|
105
|
+
/** Isometric render style — 'solid' | 'blueprint' | 'cyanotype'. Default: 'solid' */
|
|
106
|
+
defaultIsoStyle?: IsoStyleId;
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
declare interface ArcDiagramProps_2 {
|
|
@@ -108,6 +126,8 @@ export declare interface ArcNodeData {
|
|
|
108
126
|
subtitle?: string;
|
|
109
127
|
description?: string;
|
|
110
128
|
color: DiagramColor;
|
|
129
|
+
/** Per-node silhouette. Omit to follow the theme's own node shape. */
|
|
130
|
+
shape?: NodeShape;
|
|
111
131
|
}
|
|
112
132
|
|
|
113
133
|
export declare interface ArcNodePosition {
|
|
@@ -282,7 +302,7 @@ export declare function deleteDiagramSession(id: string): void;
|
|
|
282
302
|
/** Derive a URL-safe session ID from a diagram's source path or ID */
|
|
283
303
|
export declare function deriveSessionId(source: string): string;
|
|
284
304
|
|
|
285
|
-
export declare function DiagramCanvas({ onViewportChange, embedConfig, zoomConfig, themeOverride, isDark }: DiagramCanvasProps): JSX.Element;
|
|
305
|
+
export declare function DiagramCanvas({ onViewportChange, embedConfig, zoomConfig, surface, themeOverride, isDark }: DiagramCanvasProps): JSX.Element;
|
|
286
306
|
|
|
287
307
|
declare interface DiagramCanvasProps {
|
|
288
308
|
onViewportChange?: (bounds: {
|
|
@@ -293,6 +313,10 @@ declare interface DiagramCanvasProps {
|
|
|
293
313
|
}) => void;
|
|
294
314
|
embedConfig?: EmbedConfig;
|
|
295
315
|
zoomConfig?: ZoomConfig;
|
|
316
|
+
/** Workspace backdrop: 'theme' paints the diagram theme's container (embeds,
|
|
317
|
+
* where the frame is part of the artifact), 'chrome' paints the app canvas
|
|
318
|
+
* so the editor's infinite surface matches the shell skin. */
|
|
319
|
+
surface?: 'theme' | 'chrome';
|
|
296
320
|
/** Override canvas background with an Arc theme. */
|
|
297
321
|
themeOverride?: string;
|
|
298
322
|
isDark?: boolean;
|
|
@@ -368,6 +392,17 @@ export declare function DiagramEditor({ initialData, themeId, colorMode, session
|
|
|
368
392
|
initialDiagramMeta?: Record<string, any>;
|
|
369
393
|
}): JSX.Element;
|
|
370
394
|
|
|
395
|
+
declare interface DiagramImage {
|
|
396
|
+
id: string;
|
|
397
|
+
src: string;
|
|
398
|
+
name: string;
|
|
399
|
+
x: number;
|
|
400
|
+
y: number;
|
|
401
|
+
width: number;
|
|
402
|
+
height: number;
|
|
403
|
+
opacity: number;
|
|
404
|
+
}
|
|
405
|
+
|
|
371
406
|
export declare interface DiagramLayout {
|
|
372
407
|
width: number;
|
|
373
408
|
height: number;
|
|
@@ -459,6 +494,13 @@ export declare interface EmbedConfig {
|
|
|
459
494
|
showGrid?: boolean;
|
|
460
495
|
}
|
|
461
496
|
|
|
497
|
+
declare interface ExportZone {
|
|
498
|
+
x: number;
|
|
499
|
+
y: number;
|
|
500
|
+
width: number;
|
|
501
|
+
height: number;
|
|
502
|
+
}
|
|
503
|
+
|
|
462
504
|
export declare interface FocusConnectorRef {
|
|
463
505
|
from: string;
|
|
464
506
|
to: string;
|
|
@@ -511,6 +553,14 @@ export declare function getThemeList(): {
|
|
|
511
553
|
description: string;
|
|
512
554
|
}[];
|
|
513
555
|
|
|
556
|
+
declare interface GridConfig {
|
|
557
|
+
enabled: boolean;
|
|
558
|
+
size: number;
|
|
559
|
+
color: string;
|
|
560
|
+
opacity: number;
|
|
561
|
+
type: 'dots' | 'lines';
|
|
562
|
+
}
|
|
563
|
+
|
|
514
564
|
export declare type GroupLayoutDirection = 'horizontal' | 'vertical';
|
|
515
565
|
|
|
516
566
|
declare type GroupLayoutDirection_2 = 'horizontal' | 'vertical';
|
|
@@ -628,6 +678,8 @@ declare const initialState: {
|
|
|
628
678
|
};
|
|
629
679
|
};
|
|
630
680
|
|
|
681
|
+
export declare function isDiagramShape(value: unknown): boolean;
|
|
682
|
+
|
|
631
683
|
/** Preset HSL palettes matching Arc's diagram colors. */
|
|
632
684
|
export declare const ISO_COLORS: {
|
|
633
685
|
violet: IsoColorDef;
|
|
@@ -748,6 +800,8 @@ declare interface NodeData {
|
|
|
748
800
|
subtitle?: string;
|
|
749
801
|
description?: string;
|
|
750
802
|
color: DiagramColor_2;
|
|
803
|
+
/** Per-node silhouette. Omit to follow the theme's own node shape. */
|
|
804
|
+
shape?: NodeShape;
|
|
751
805
|
}
|
|
752
806
|
|
|
753
807
|
export declare interface NodeLayoutHint {
|
|
@@ -783,11 +837,13 @@ declare interface NodePosition_2 {
|
|
|
783
837
|
size: NodeSize_2;
|
|
784
838
|
}
|
|
785
839
|
|
|
840
|
+
declare type NodeShape = 'rounded' | 'square' | 'chamfer' | 'notch' | 'pill';
|
|
841
|
+
|
|
786
842
|
export declare type NodeSize = 'xs' | 's' | 'm' | 'l';
|
|
787
843
|
|
|
788
844
|
declare type NodeSize_2 = 'xs' | 's' | 'm' | 'l';
|
|
789
845
|
|
|
790
|
-
declare type NodeSize_3 = '
|
|
846
|
+
declare type NodeSize_3 = 'xs' | 's' | 'm' | 'l';
|
|
791
847
|
|
|
792
848
|
/**
|
|
793
849
|
* Parse YAML config into DiagramConfig
|
|
@@ -936,6 +992,10 @@ declare interface TitleBlockInfo {
|
|
|
936
992
|
sheet?: string;
|
|
937
993
|
}
|
|
938
994
|
|
|
995
|
+
export declare function toExportFormat(diagram: ArcDiagram_2): ArcDiagramData_2;
|
|
996
|
+
|
|
997
|
+
export declare function toTypeScriptSource(diagram: ArcDiagram_2, name?: string): string;
|
|
998
|
+
|
|
939
999
|
export declare function useColorMode(): string;
|
|
940
1000
|
|
|
941
1001
|
export declare function useDiagram(): {
|
|
@@ -1005,8 +1065,13 @@ export declare function useThemeId(): string;
|
|
|
1005
1065
|
|
|
1006
1066
|
export declare function useViewMode(): string;
|
|
1007
1067
|
|
|
1068
|
+
/** Human-readable reason this is not a diagram, or null if it is. */
|
|
1069
|
+
export declare function validateDiagramShape(value: unknown): string | null;
|
|
1070
|
+
|
|
1008
1071
|
export declare type ViewMode = '2d' | 'isometric';
|
|
1009
1072
|
|
|
1073
|
+
declare type ViewMode_2 = '2d' | 'isometric';
|
|
1074
|
+
|
|
1010
1075
|
declare interface ZoomConfig {
|
|
1011
1076
|
defaultZoom?: number | 'fit';
|
|
1012
1077
|
zoomLevels?: number[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arach/arc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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,16 @@
|
|
|
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",
|
|
67
|
+
"mcp:http": "bun scripts/mcp/http-server.ts",
|
|
53
68
|
"build:iso": "vite build --config vite.config.iso.js && vite build --config vite.config.iso-slim.js",
|
|
54
69
|
"lint": "eslint .",
|
|
55
70
|
"typecheck": "tsc --noEmit",
|
|
56
71
|
"preview": "vite preview",
|
|
57
72
|
"generate-og": "node scripts/generate-og.js",
|
|
58
73
|
"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"
|
|
74
|
+
"prepublishOnly": "bun run build:lib && bun run build:mcp && bun run check:dist"
|
|
60
75
|
},
|
|
61
76
|
"peerDependencies": {
|
|
62
77
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -66,13 +81,24 @@
|
|
|
66
81
|
"@arach/dewey": "^0.2.0",
|
|
67
82
|
"@arethetypeswrong/cli": "^0.18.4",
|
|
68
83
|
"@base-ui/react": "^1.0.0",
|
|
84
|
+
"@codemirror/commands": "^6.10.4",
|
|
85
|
+
"@codemirror/lang-css": "^6.3.1",
|
|
86
|
+
"@codemirror/lang-html": "^6.4.12",
|
|
87
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
88
|
+
"@codemirror/lang-json": "^6.0.2",
|
|
89
|
+
"@codemirror/lang-markdown": "^6.5.2",
|
|
90
|
+
"@codemirror/language": "^6.12.4",
|
|
91
|
+
"@codemirror/state": "^6.7.1",
|
|
92
|
+
"@codemirror/view": "^6.43.8",
|
|
69
93
|
"@eslint/js": "^9.39.1",
|
|
94
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
70
95
|
"@tailwindcss/vite": "^4.1.18",
|
|
71
96
|
"@types/js-yaml": "^4.0.9",
|
|
72
97
|
"@types/react": "^19.2.5",
|
|
73
98
|
"@types/react-dom": "^19.2.3",
|
|
74
99
|
"@types/three": "^0.182.0",
|
|
75
100
|
"@vitejs/plugin-react": "^5.1.1",
|
|
101
|
+
"codemirror": "^6.0.2",
|
|
76
102
|
"eslint": "^9.39.1",
|
|
77
103
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
78
104
|
"eslint-plugin-react-refresh": "^0.4.24",
|
|
@@ -91,7 +117,9 @@
|
|
|
91
117
|
"tailwindcss": "^4.1.18",
|
|
92
118
|
"three": "^0.182.0",
|
|
93
119
|
"typescript": "^5.9.3",
|
|
120
|
+
"typescript-eslint": "^8.67.0",
|
|
94
121
|
"vite": "^7.2.4",
|
|
95
|
-
"vite-plugin-dts": "^4.5.4"
|
|
122
|
+
"vite-plugin-dts": "^4.5.4",
|
|
123
|
+
"zod": "^3.25.76"
|
|
96
124
|
}
|
|
97
125
|
}
|
|
@@ -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
|
+
}
|