archrip 0.2.2 → 0.2.4

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.
@@ -20,9 +20,16 @@ Analyze the current codebase and generate `.archrip/architecture.json`.
20
20
 
21
21
  ## Phase 2: Documentation Discovery
22
22
  Read existing documentation to understand architecture context:
23
- 1. Check for: README.md, CLAUDE.md, docs/, doc/, wiki/, ARCHITECTURE.md, CONTRIBUTING.md
24
- 2. Extract: system overview, component descriptions, external service integrations, design decisions
25
- 3. Use this knowledge to inform the analysis — documentation often reveals architectural intent that code alone does not show (use cases, business context, external dependencies)
23
+ 1. Check for: README.md, CLAUDE.md, docs/, doc/, wiki/, ARCHITECTURE.md, CONTRIBUTING.md, ADR/
24
+ 2. For each document, extract and take notes on:
25
+ - **Business context**: What problem does this system solve? Who are the users?
26
+ - **Component responsibilities**: What each module/service does and why it exists
27
+ - **Design decisions & constraints**: Why certain patterns/libraries were chosen, known limitations
28
+ - **Data flow**: How data moves through the system (request lifecycle, event flow, etc.)
29
+ - **External integrations**: What external services are used, why, and how
30
+ - **Non-functional requirements**: SLAs, performance targets, security policies
31
+ - **Deployment & infrastructure**: Hosting, CI/CD, environment details
32
+ 3. Keep these notes — you will use them in Phase 4 to write rich node/edge descriptions and metadata
26
33
 
27
34
  ## Phase 3: Layer Identification
28
35
  Assign each component a `layer` integer. The rule: **higher layer = closer to domain core (more stable, fewer external dependencies). Lower layer = closer to external world (more volatile, I/O-bound).**
@@ -58,6 +65,21 @@ For each layer, read representative files to extract:
58
65
  - Public methods/routes
59
66
  - Database schemas (from migrations or model definitions)
60
67
 
68
+ **Enrich descriptions from documentation:** Cross-reference code with your Phase 2 notes.
69
+ For each component, compose a `description` (1-3 sentences) that covers:
70
+ - **What**: Its responsibility (from code analysis)
71
+ - **Why**: Business context or design rationale (from docs)
72
+ - **How**: Key implementation details, constraints, or patterns worth noting
73
+
74
+ A good description tells the reader something they cannot see from the label alone.
75
+ - BAD: "User service" (just echoes the label)
76
+ - GOOD: "Handles user registration, login, and profile management. Uses JWT for session tokens with 24h expiry. Password hashing via bcrypt (cost=12)."
77
+
78
+ Also identify metadata candidates:
79
+ - SLA/performance notes → `metadata` with `type: "list"`
80
+ - Related doc links → `metadata` with `type: "link"`
81
+ - Infrastructure details (Lambda ARN, DB engine, etc.) → `metadata` with `type: "code"` or `"text"`
82
+
61
83
  **Do NOT read every file.** Focus on entry points, core logic, interfaces, and data models.
62
84
 
63
85
  ## Phase 5: Map Relationships
@@ -129,10 +151,11 @@ After writing the file:
129
151
  - UseCase: `id`, `name`, `nodeIds` — all required
130
152
 
131
153
  ### Node Rules
132
- - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, ext-, job-, dto-)
154
+ - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, db-, ext-, job-, dto-)
133
155
  - `layer`: non-negative integer. **Higher = closer to domain core / more stable. Lower = closer to external world / more volatile.** Dagre (TB) places higher layers lower on screen; concentric places them at center. Use as many layers as the architecture requires (typically 3-6). Example for DDD: 0=external, 1=adapters, 2=controllers, 3=app services, 4=ports, 5=domain entities. Example for MVC: 0=external, 1=controllers, 2=services, 3=models.
134
- - `category`: one of controller, service, port, adapter, model, external, job, dto (or custom)
156
+ - `category`: one of controller, service, port, adapter, model, database, external, job, dto (or custom). Use `model` for domain entities/value objects (core business logic). Use `database` for DB tables, migrations, ORMs, and infrastructure persistence.
135
157
  - `label`: display name for the node
158
+ - `description`: 1-3 sentences explaining responsibility + business context. Do NOT just echo the label. Cross-reference documentation for richer context (see Description Guidelines below)
136
159
  - `filePath`: relative from project root
137
160
  - `depth` (optional): 0=overview, 1=structure, 2=detail. Auto-inferred from `layer` if omitted: with 3+ unique layers, lowest → 0, middle → 1, highest → 2. With 1-2 layers, all nodes get depth 0 (always visible).
138
161
  - `useCases`: array of use case IDs this node participates in
@@ -158,6 +181,31 @@ After writing the file:
158
181
  - DDD / Clean Architecture / Hexagonal / Onion Architecture → add `"layout": "concentric"` to `project`
159
182
  - MVC / standard layered → `"layout": "dagre"` (default, can be omitted)
160
183
 
184
+ ### Description Guidelines
185
+
186
+ #### Node `description`
187
+ Write 1-3 sentences that explain responsibility AND business context.
188
+ Cross-reference project documentation (README, CLAUDE.md, docs/) for richer context.
189
+ - BAD: "User service" (just echoes the label)
190
+ - BAD: "Handles users" (too vague)
191
+ - GOOD: "Handles user registration, authentication, and profile management. Uses JWT for session tokens; password hashing via bcrypt. Rate-limited to 10 req/s per IP."
192
+
193
+ #### Edge `description`
194
+ Explain WHY the dependency exists, not just THAT it exists.
195
+ - BAD: "calls" / "depends on"
196
+ - GOOD: "Delegates payment processing via Stripe SDK; retries on timeout (3x with exponential backoff)"
197
+
198
+ #### `metadata` for supplementary details
199
+ Use `metadata` to capture information from docs that doesn't fit in `description`:
200
+ ```json
201
+ "metadata": [
202
+ { "label": "SLA", "value": ["99.9% uptime", "p95 < 200ms"], "type": "list" },
203
+ { "label": "Design Doc", "value": "https://...", "type": "link" },
204
+ { "label": "Infrastructure", "value": "Lambda + DynamoDB (on-demand)", "type": "text" },
205
+ { "label": "Rate Limit", "value": "10 req/s per IP", "type": "text" }
206
+ ]
207
+ ```
208
+
161
209
  ### Schema Rules
162
210
  - Include table schema only when migration files or model annotations are available
163
211
  - Reference from node data using schema key name
@@ -20,9 +20,16 @@ Analyze the current codebase and generate `.archrip/architecture.json`.
20
20
 
21
21
  ## Phase 2: Documentation Discovery
22
22
  Read existing documentation to understand architecture context:
23
- 1. Check for: README.md, CLAUDE.md, docs/, doc/, wiki/, ARCHITECTURE.md, CONTRIBUTING.md
24
- 2. Extract: system overview, component descriptions, external service integrations, design decisions
25
- 3. Use this knowledge to inform the analysis — documentation often reveals architectural intent that code alone does not show (use cases, business context, external dependencies)
23
+ 1. Check for: README.md, CLAUDE.md, docs/, doc/, wiki/, ARCHITECTURE.md, CONTRIBUTING.md, ADR/
24
+ 2. For each document, extract and take notes on:
25
+ - **Business context**: What problem does this system solve? Who are the users?
26
+ - **Component responsibilities**: What each module/service does and why it exists
27
+ - **Design decisions & constraints**: Why certain patterns/libraries were chosen, known limitations
28
+ - **Data flow**: How data moves through the system (request lifecycle, event flow, etc.)
29
+ - **External integrations**: What external services are used, why, and how
30
+ - **Non-functional requirements**: SLAs, performance targets, security policies
31
+ - **Deployment & infrastructure**: Hosting, CI/CD, environment details
32
+ 3. Keep these notes — you will use them in Phase 4 to write rich node/edge descriptions and metadata
26
33
 
27
34
  ## Phase 3: Layer Identification
28
35
  Assign each component a `layer` integer. The rule: **higher layer = closer to domain core (more stable, fewer external dependencies). Lower layer = closer to external world (more volatile, I/O-bound).**
@@ -58,6 +65,21 @@ For each layer, read representative files to extract:
58
65
  - Public methods/routes
59
66
  - Database schemas (from migrations or model definitions)
60
67
 
68
+ **Enrich descriptions from documentation:** Cross-reference code with your Phase 2 notes.
69
+ For each component, compose a `description` (1-3 sentences) that covers:
70
+ - **What**: Its responsibility (from code analysis)
71
+ - **Why**: Business context or design rationale (from docs)
72
+ - **How**: Key implementation details, constraints, or patterns worth noting
73
+
74
+ A good description tells the reader something they cannot see from the label alone.
75
+ - BAD: "User service" (just echoes the label)
76
+ - GOOD: "Handles user registration, login, and profile management. Uses JWT for session tokens with 24h expiry. Password hashing via bcrypt (cost=12)."
77
+
78
+ Also identify metadata candidates:
79
+ - SLA/performance notes → `metadata` with `type: "list"`
80
+ - Related doc links → `metadata` with `type: "link"`
81
+ - Infrastructure details (Lambda ARN, DB engine, etc.) → `metadata` with `type: "code"` or `"text"`
82
+
61
83
  **Do NOT read every file.** Focus on entry points, core logic, interfaces, and data models.
62
84
 
63
85
  ## Phase 5: Map Relationships
@@ -129,10 +151,11 @@ After writing the file:
129
151
  - UseCase: `id`, `name`, `nodeIds` — all required
130
152
 
131
153
  ### Node Rules
132
- - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, ext-, job-, dto-)
154
+ - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, db-, ext-, job-, dto-)
133
155
  - `layer`: non-negative integer. **Higher = closer to domain core / more stable. Lower = closer to external world / more volatile.** Dagre (TB) places higher layers lower on screen; concentric places them at center. Use as many layers as the architecture requires (typically 3-6). Example for DDD: 0=external, 1=adapters, 2=controllers, 3=app services, 4=ports, 5=domain entities. Example for MVC: 0=external, 1=controllers, 2=services, 3=models.
134
- - `category`: one of controller, service, port, adapter, model, external, job, dto (or custom)
156
+ - `category`: one of controller, service, port, adapter, model, database, external, job, dto (or custom). Use `model` for domain entities/value objects (core business logic). Use `database` for DB tables, migrations, ORMs, and infrastructure persistence.
135
157
  - `label`: display name for the node
158
+ - `description`: 1-3 sentences explaining responsibility + business context. Do NOT just echo the label. Cross-reference documentation for richer context (see Description Guidelines below)
136
159
  - `filePath`: relative from project root
137
160
  - `depth` (optional): 0=overview, 1=structure, 2=detail. Auto-inferred from `layer` if omitted: with 3+ unique layers, lowest → 0, middle → 1, highest → 2. With 1-2 layers, all nodes get depth 0 (always visible).
138
161
  - `useCases`: array of use case IDs this node participates in
@@ -158,6 +181,31 @@ After writing the file:
158
181
  - DDD / Clean Architecture / Hexagonal / Onion Architecture → add `"layout": "concentric"` to `project`
159
182
  - MVC / standard layered → `"layout": "dagre"` (default, can be omitted)
160
183
 
184
+ ### Description Guidelines
185
+
186
+ #### Node `description`
187
+ Write 1-3 sentences that explain responsibility AND business context.
188
+ Cross-reference project documentation (README, CLAUDE.md, docs/) for richer context.
189
+ - BAD: "User service" (just echoes the label)
190
+ - BAD: "Handles users" (too vague)
191
+ - GOOD: "Handles user registration, authentication, and profile management. Uses JWT for session tokens; password hashing via bcrypt. Rate-limited to 10 req/s per IP."
192
+
193
+ #### Edge `description`
194
+ Explain WHY the dependency exists, not just THAT it exists.
195
+ - BAD: "calls" / "depends on"
196
+ - GOOD: "Delegates payment processing via Stripe SDK; retries on timeout (3x with exponential backoff)"
197
+
198
+ #### `metadata` for supplementary details
199
+ Use `metadata` to capture information from docs that doesn't fit in `description`:
200
+ ```json
201
+ "metadata": [
202
+ { "label": "SLA", "value": ["99.9% uptime", "p95 < 200ms"], "type": "list" },
203
+ { "label": "Design Doc", "value": "https://...", "type": "link" },
204
+ { "label": "Infrastructure", "value": "Lambda + DynamoDB (on-demand)", "type": "text" },
205
+ { "label": "Rate Limit", "value": "10 req/s per IP", "type": "text" }
206
+ ]
207
+ ```
208
+
161
209
  ### Schema Rules
162
210
  - Include table schema only when migration files or model annotations are available
163
211
  - Reference from node data using schema key name
@@ -20,9 +20,16 @@ Analyze the current codebase and generate `.archrip/architecture.json`.
20
20
 
21
21
  ## Phase 2: Documentation Discovery
22
22
  Read existing documentation to understand architecture context:
23
- 1. Check for: README.md, CLAUDE.md, docs/, doc/, wiki/, ARCHITECTURE.md, CONTRIBUTING.md
24
- 2. Extract: system overview, component descriptions, external service integrations, design decisions
25
- 3. Use this knowledge to inform the analysis — documentation often reveals architectural intent that code alone does not show (use cases, business context, external dependencies)
23
+ 1. Check for: README.md, CLAUDE.md, docs/, doc/, wiki/, ARCHITECTURE.md, CONTRIBUTING.md, ADR/
24
+ 2. For each document, extract and take notes on:
25
+ - **Business context**: What problem does this system solve? Who are the users?
26
+ - **Component responsibilities**: What each module/service does and why it exists
27
+ - **Design decisions & constraints**: Why certain patterns/libraries were chosen, known limitations
28
+ - **Data flow**: How data moves through the system (request lifecycle, event flow, etc.)
29
+ - **External integrations**: What external services are used, why, and how
30
+ - **Non-functional requirements**: SLAs, performance targets, security policies
31
+ - **Deployment & infrastructure**: Hosting, CI/CD, environment details
32
+ 3. Keep these notes — you will use them in Phase 4 to write rich node/edge descriptions and metadata
26
33
 
27
34
  ## Phase 3: Layer Identification
28
35
  Assign each component a `layer` integer. The rule: **higher layer = closer to domain core (more stable, fewer external dependencies). Lower layer = closer to external world (more volatile, I/O-bound).**
@@ -58,6 +65,21 @@ For each layer, read representative files to extract:
58
65
  - Public methods/routes
59
66
  - Database schemas (from migrations or model definitions)
60
67
 
68
+ **Enrich descriptions from documentation:** Cross-reference code with your Phase 2 notes.
69
+ For each component, compose a `description` (1-3 sentences) that covers:
70
+ - **What**: Its responsibility (from code analysis)
71
+ - **Why**: Business context or design rationale (from docs)
72
+ - **How**: Key implementation details, constraints, or patterns worth noting
73
+
74
+ A good description tells the reader something they cannot see from the label alone.
75
+ - BAD: "User service" (just echoes the label)
76
+ - GOOD: "Handles user registration, login, and profile management. Uses JWT for session tokens with 24h expiry. Password hashing via bcrypt (cost=12)."
77
+
78
+ Also identify metadata candidates:
79
+ - SLA/performance notes → `metadata` with `type: "list"`
80
+ - Related doc links → `metadata` with `type: "link"`
81
+ - Infrastructure details (Lambda ARN, DB engine, etc.) → `metadata` with `type: "code"` or `"text"`
82
+
61
83
  **Do NOT read every file.** Focus on entry points, core logic, interfaces, and data models.
62
84
 
63
85
  ## Phase 5: Map Relationships
@@ -129,10 +151,11 @@ After writing the file:
129
151
  - UseCase: `id`, `name`, `nodeIds` — all required
130
152
 
131
153
  ### Node Rules
132
- - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, ext-, job-, dto-)
154
+ - `id`: kebab-case, prefixed by category abbreviation (ctrl-, svc-, port-, adpt-, model-, db-, ext-, job-, dto-)
133
155
  - `layer`: non-negative integer. **Higher = closer to domain core / more stable. Lower = closer to external world / more volatile.** Dagre (TB) places higher layers lower on screen; concentric places them at center. Use as many layers as the architecture requires (typically 3-6). Example for DDD: 0=external, 1=adapters, 2=controllers, 3=app services, 4=ports, 5=domain entities. Example for MVC: 0=external, 1=controllers, 2=services, 3=models.
134
- - `category`: one of controller, service, port, adapter, model, external, job, dto (or custom)
156
+ - `category`: one of controller, service, port, adapter, model, database, external, job, dto (or custom). Use `model` for domain entities/value objects (core business logic). Use `database` for DB tables, migrations, ORMs, and infrastructure persistence.
135
157
  - `label`: display name for the node
158
+ - `description`: 1-3 sentences explaining responsibility + business context. Do NOT just echo the label. Cross-reference documentation for richer context (see Description Guidelines below)
136
159
  - `filePath`: relative from project root
137
160
  - `depth` (optional): 0=overview, 1=structure, 2=detail. Auto-inferred from `layer` if omitted: with 3+ unique layers, lowest → 0, middle → 1, highest → 2. With 1-2 layers, all nodes get depth 0 (always visible).
138
161
  - `useCases`: array of use case IDs this node participates in
@@ -158,6 +181,31 @@ After writing the file:
158
181
  - DDD / Clean Architecture / Hexagonal / Onion Architecture → add `"layout": "concentric"` to `project`
159
182
  - MVC / standard layered → `"layout": "dagre"` (default, can be omitted)
160
183
 
184
+ ### Description Guidelines
185
+
186
+ #### Node `description`
187
+ Write 1-3 sentences that explain responsibility AND business context.
188
+ Cross-reference project documentation (README, CLAUDE.md, docs/) for richer context.
189
+ - BAD: "User service" (just echoes the label)
190
+ - BAD: "Handles users" (too vague)
191
+ - GOOD: "Handles user registration, authentication, and profile management. Uses JWT for session tokens; password hashing via bcrypt. Rate-limited to 10 req/s per IP."
192
+
193
+ #### Edge `description`
194
+ Explain WHY the dependency exists, not just THAT it exists.
195
+ - BAD: "calls" / "depends on"
196
+ - GOOD: "Delegates payment processing via Stripe SDK; retries on timeout (3x with exponential backoff)"
197
+
198
+ #### `metadata` for supplementary details
199
+ Use `metadata` to capture information from docs that doesn't fit in `description`:
200
+ ```json
201
+ "metadata": [
202
+ { "label": "SLA", "value": ["99.9% uptime", "p95 < 200ms"], "type": "list" },
203
+ { "label": "Design Doc", "value": "https://...", "type": "link" },
204
+ { "label": "Infrastructure", "value": "Lambda + DynamoDB (on-demand)", "type": "text" },
205
+ { "label": "Rate Limit", "value": "10 req/s per IP", "type": "text" }
206
+ ]
207
+ ```
208
+
161
209
  ### Schema Rules
162
210
  - Include table schema only when migration files or model annotations are available
163
211
  - Reference from node data using schema key name
@@ -105,8 +105,9 @@ const CATEGORY_RING_PRIORITY = {
105
105
  dto: 3,
106
106
  controller: 4,
107
107
  adapter: 5,
108
- job: 6,
109
- external: 7,
108
+ database: 6,
109
+ job: 7,
110
+ external: 8,
110
111
  };
111
112
  const DEFAULT_RING_PRIORITY = 4; // unknown categories treated as controller-level
112
113
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/utils/layout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/utils/layout.ts"],"names":[],"mappings":"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"}
@@ -16,13 +16,17 @@ import type { ArchFlowNode, ArchNodeData } from './types.ts';
16
16
  import { getCategoryColors } from './types.ts';
17
17
  import { ArchNode } from './components/nodes/ArchNode.tsx';
18
18
  import { GroupNode } from './components/nodes/GroupNode.tsx';
19
+ import { CommandPalette } from './components/CommandPalette.tsx';
19
20
  import { DetailPanel } from './components/DetailPanel.tsx';
20
21
  import { UseCaseFilter } from './components/UseCaseFilter.tsx';
21
22
  import { DepthFilter } from './components/DepthFilter.tsx';
22
23
  import { Legend } from './components/Legend.tsx';
23
24
  import { ThemeToggle } from './components/ThemeToggle.tsx';
24
25
  import { useArchitecture } from './hooks/useArchitecture.ts';
26
+ import { useCategoryFilter } from './hooks/useCategoryFilter.ts';
27
+ import { useCommandPalette } from './hooks/useCommandPalette.ts';
25
28
  import { useDepthFilter } from './hooks/useDepthFilter.ts';
29
+ import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts.ts';
26
30
  import { useUseCaseFilter } from './hooks/useUseCaseFilter.ts';
27
31
  import { useTheme } from './hooks/useTheme.ts';
28
32
 
@@ -31,10 +35,11 @@ const nodeTypes = { archNode: ArchNode, groupNode: GroupNode };
31
35
  function AppInner() {
32
36
  const { nodes, edges, useCases, projectName, layoutType, loading, error, onNodesChange, onEdgesChange } = useArchitecture();
33
37
  const { depthLevel, setDepthLevel, visibleNodes, visibleEdges } = useDepthFilter(nodes, edges, layoutType);
34
- const { selectedUseCase, setSelectedUseCase, categories, filteredNodes, filteredEdges } = useUseCaseFilter(visibleNodes, visibleEdges, useCases);
38
+ const { selectedUseCase, setSelectedUseCase, categories, filteredNodes, filteredEdges, flowInfo } = useUseCaseFilter(visibleNodes, visibleEdges, useCases);
39
+ const categoryFilter = useCategoryFilter();
35
40
  const [selectedNodeId, setSelectedNodeId] = useQueryState('node', parseAsString.withOptions({ history: 'replace' }));
36
41
  const { theme, toggleTheme } = useTheme();
37
- const { fitView } = useReactFlow();
42
+ const { fitView, setCenter, getNodes } = useReactFlow();
38
43
 
39
44
  const selectedNodeData: ArchNodeData | null = useMemo(() => {
40
45
  if (!selectedNodeId) return null;
@@ -66,6 +71,70 @@ function AppInner() {
66
71
  return () => cancelAnimationFrame(id);
67
72
  }, [depthLevel, selectedUseCase, fitView]);
68
73
 
74
+ // Auto-center viewport on active flow step
75
+ useEffect(() => {
76
+ if (!flowInfo.flowNodeIds || flowInfo.activeStep < 0) return;
77
+ const activeNodeId = flowInfo.flowNodeIds[flowInfo.activeStep];
78
+ if (!activeNodeId) return;
79
+ const rfNodes = getNodes();
80
+ const target = rfNodes.find((n) => n.id === activeNodeId);
81
+ if (!target) return;
82
+ const x = target.position.x + (target.measured?.width ?? 180) / 2;
83
+ const y = target.position.y + (target.measured?.height ?? 80) / 2;
84
+ void setCenter(x, y, { zoom: 1.2, duration: 400 });
85
+ }, [flowInfo.activeStep, flowInfo.flowNodeIds, getNodes, setCenter]);
86
+
87
+ // Category filter: dim hidden categories
88
+ const displayNodes = useMemo(() => {
89
+ if (categoryFilter.hiddenCategories.size === 0) return filteredNodes;
90
+ return filteredNodes.map((node) => {
91
+ if (categoryFilter.hiddenCategories.has(node.data.category)) {
92
+ return { ...node, style: { ...node.style, opacity: 0.08, transition: 'opacity 0.3s' } };
93
+ }
94
+ return node;
95
+ });
96
+ }, [filteredNodes, categoryFilter.hiddenCategories]);
97
+
98
+ const displayEdges = useMemo(() => {
99
+ if (categoryFilter.hiddenCategories.size === 0) return filteredEdges;
100
+ const hiddenNodeIds = new Set<string>();
101
+ for (const node of filteredNodes) {
102
+ if (categoryFilter.hiddenCategories.has(node.data.category)) {
103
+ hiddenNodeIds.add(node.id);
104
+ }
105
+ }
106
+ return filteredEdges.map((edge) => {
107
+ if (hiddenNodeIds.has(edge.source) || hiddenNodeIds.has(edge.target)) {
108
+ return {
109
+ ...edge,
110
+ style: { ...edge.style, opacity: 0.08, transition: 'opacity 0.3s' },
111
+ labelStyle: { ...((edge.labelStyle as Record<string, unknown>) ?? {}), opacity: 0 },
112
+ };
113
+ }
114
+ return edge;
115
+ });
116
+ }, [filteredEdges, filteredNodes, categoryFilter.hiddenCategories]);
117
+
118
+ // Command palette
119
+ const palette = useCommandPalette(displayNodes, categoryFilter.hiddenCategories);
120
+
121
+ const handlePaletteSelect = useCallback((nodeId: string) => {
122
+ palette.close();
123
+ void setSelectedNodeId(nodeId);
124
+ }, [palette, setSelectedNodeId]);
125
+
126
+ const handleEscape = useCallback(() => {
127
+ if (palette.isOpen) { palette.close(); return; }
128
+ if (selectedNodeId) { void setSelectedNodeId(null); return; }
129
+ if (selectedUseCase) { void setSelectedUseCase(null); return; }
130
+ }, [palette, selectedNodeId, setSelectedNodeId, selectedUseCase, setSelectedUseCase]);
131
+
132
+ useKeyboardShortcuts({
133
+ onTogglePalette: palette.toggle,
134
+ onEscape: handleEscape,
135
+ isPaletteOpen: palette.isOpen,
136
+ });
137
+
69
138
  if (loading) {
70
139
  return (
71
140
  <div className="w-full h-screen flex items-center justify-center" style={{ color: 'var(--color-content-tertiary)', background: 'var(--color-surface-canvas)' }}>
@@ -88,8 +157,8 @@ function AppInner() {
88
157
  return (
89
158
  <div className="w-full h-screen relative">
90
159
  <ReactFlow
91
- nodes={filteredNodes}
92
- edges={filteredEdges}
160
+ nodes={displayNodes}
161
+ edges={displayEdges}
93
162
  onNodesChange={onNodesChange}
94
163
  onEdgesChange={onEdgesChange}
95
164
  onNodeClick={onNodeClick}
@@ -120,11 +189,17 @@ function AppInner() {
120
189
  useCases={useCases}
121
190
  selectedUseCase={selectedUseCase}
122
191
  onSelect={handleUseCaseSelect}
192
+ flowInfo={flowInfo}
123
193
  />
124
194
  )}
125
195
  <DepthFilter depthLevel={depthLevel} onSelect={setDepthLevel} />
126
196
  </div>
127
- <Legend categories={categories} />
197
+ <Legend
198
+ categories={categories}
199
+ hiddenCategories={categoryFilter.hiddenCategories}
200
+ onToggleCategory={categoryFilter.toggleCategory}
201
+ onShowAll={categoryFilter.showAll}
202
+ />
128
203
 
129
204
  {/* Title + Theme Toggle */}
130
205
  <div className="absolute top-3 right-3 z-10 flex items-center gap-2">
@@ -157,6 +232,19 @@ function AppInner() {
157
232
  />
158
233
  </>
159
234
  )}
235
+
236
+ {palette.isOpen && (
237
+ <CommandPalette
238
+ query={palette.query}
239
+ onQueryChange={palette.setQuery}
240
+ results={palette.results}
241
+ activeIndex={palette.activeIndex}
242
+ onMoveUp={palette.moveUp}
243
+ onMoveDown={palette.moveDown}
244
+ onSelect={handlePaletteSelect}
245
+ onClose={palette.close}
246
+ />
247
+ )}
160
248
  </div>
161
249
  );
162
250
  }
@@ -0,0 +1,174 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ import { getCategoryColors, getCategoryLabel } from '../types.ts';
4
+ import type { CommandPaletteResult } from '../hooks/useCommandPalette.ts';
5
+
6
+ interface CommandPaletteProps {
7
+ query: string;
8
+ onQueryChange: (q: string) => void;
9
+ results: CommandPaletteResult[];
10
+ activeIndex: number;
11
+ onMoveUp: () => void;
12
+ onMoveDown: () => void;
13
+ onSelect: (id: string) => void;
14
+ onClose: () => void;
15
+ }
16
+
17
+ export function CommandPalette({
18
+ query,
19
+ onQueryChange,
20
+ results,
21
+ activeIndex,
22
+ onMoveUp,
23
+ onMoveDown,
24
+ onSelect,
25
+ onClose,
26
+ }: CommandPaletteProps) {
27
+ const inputRef = useRef<HTMLInputElement>(null);
28
+ const listRef = useRef<HTMLDivElement>(null);
29
+
30
+ useEffect(() => {
31
+ inputRef.current?.focus();
32
+ }, []);
33
+
34
+ // Scroll active item into view
35
+ useEffect(() => {
36
+ const list = listRef.current;
37
+ if (!list) return;
38
+ const item = list.children[activeIndex] as HTMLElement | undefined;
39
+ item?.scrollIntoView({ block: 'nearest' });
40
+ }, [activeIndex]);
41
+
42
+ function handleKeyDown(e: React.KeyboardEvent) {
43
+ if (e.key === 'ArrowUp') {
44
+ e.preventDefault();
45
+ onMoveUp();
46
+ } else if (e.key === 'ArrowDown') {
47
+ e.preventDefault();
48
+ onMoveDown();
49
+ } else if (e.key === 'Enter') {
50
+ e.preventDefault();
51
+ const item = results[activeIndex];
52
+ if (item) onSelect(item.id);
53
+ } else if (e.key === 'Escape') {
54
+ e.preventDefault();
55
+ onClose();
56
+ }
57
+ }
58
+
59
+ return (
60
+ <>
61
+ {/* Overlay */}
62
+ <div
63
+ className="fixed inset-0 z-60"
64
+ style={{ background: 'rgba(0, 0, 0, 0.3)' }}
65
+ onClick={onClose}
66
+ />
67
+
68
+ {/* Palette card */}
69
+ <div
70
+ className="fixed z-60 rounded-xl border overflow-hidden"
71
+ style={{
72
+ top: '20%',
73
+ left: '50%',
74
+ transform: 'translateX(-50%)',
75
+ width: 480,
76
+ maxWidth: 'calc(100vw - 32px)',
77
+ background: 'var(--color-surface-primary)',
78
+ borderColor: 'var(--color-border-primary)',
79
+ boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
80
+ }}
81
+ >
82
+ {/* Search input */}
83
+ <div
84
+ className="border-b"
85
+ style={{ borderColor: 'var(--color-border-primary)' }}
86
+ >
87
+ <input
88
+ ref={inputRef}
89
+ type="text"
90
+ value={query}
91
+ onChange={(e) => onQueryChange(e.target.value)}
92
+ onKeyDown={handleKeyDown}
93
+ placeholder="Search nodes..."
94
+ className="w-full px-4 py-3 text-sm bg-transparent outline-none"
95
+ style={{ color: 'var(--color-content-primary)' }}
96
+ />
97
+ </div>
98
+
99
+ {/* Results list */}
100
+ <div
101
+ ref={listRef}
102
+ className="overflow-y-auto"
103
+ style={{ maxHeight: 320 }}
104
+ >
105
+ {results.length === 0 && (
106
+ <div
107
+ className="px-4 py-6 text-center text-sm"
108
+ style={{ color: 'var(--color-content-tertiary)' }}
109
+ >
110
+ No nodes found
111
+ </div>
112
+ )}
113
+ {results.map((item, index) => {
114
+ const colors = getCategoryColors(item.category);
115
+ const isActive = index === activeIndex;
116
+ return (
117
+ <button
118
+ key={item.id}
119
+ onClick={() => onSelect(item.id)}
120
+ className="w-full px-4 py-2.5 flex items-start gap-3 text-left cursor-pointer border-none"
121
+ style={{
122
+ background: isActive ? 'var(--color-surface-tertiary)' : 'transparent',
123
+ }}
124
+ >
125
+ <div
126
+ className="w-3 h-3 rounded-sm border mt-0.5 shrink-0"
127
+ style={{ background: colors.bg, borderColor: colors.border }}
128
+ />
129
+ <div className="min-w-0 flex-1">
130
+ <div className="flex items-center gap-2">
131
+ <span
132
+ className="text-sm font-medium truncate"
133
+ style={{ color: 'var(--color-content-primary)' }}
134
+ >
135
+ {item.label}
136
+ </span>
137
+ <span
138
+ className="text-xs shrink-0"
139
+ style={{ color: 'var(--color-content-tertiary)' }}
140
+ >
141
+ {getCategoryLabel(item.category)}
142
+ </span>
143
+ </div>
144
+ {item.description && (
145
+ <p
146
+ className="text-xs mt-0.5 truncate"
147
+ style={{ color: 'var(--color-content-secondary)' }}
148
+ >
149
+ {item.description}
150
+ </p>
151
+ )}
152
+ </div>
153
+ </button>
154
+ );
155
+ })}
156
+ </div>
157
+
158
+ {/* Footer */}
159
+ <div
160
+ className="px-4 py-2 border-t flex items-center gap-4 text-xs"
161
+ style={{
162
+ borderColor: 'var(--color-border-primary)',
163
+ color: 'var(--color-content-tertiary)',
164
+ background: 'var(--color-surface-secondary)',
165
+ }}
166
+ >
167
+ <span><kbd className="font-mono">{'\u2191\u2193'}</kbd> Navigate</span>
168
+ <span><kbd className="font-mono">{'\u21B5'}</kbd> Select</span>
169
+ <span><kbd className="font-mono">Esc</kbd> Close</span>
170
+ </div>
171
+ </div>
172
+ </>
173
+ );
174
+ }