@principal-ai/subsystems-react 0.17.0 → 0.19.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.
Files changed (108) hide show
  1. package/README.md +11 -85
  2. package/dist/index.d.ts +7 -44
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +6 -32
  5. package/dist/index.js.map +1 -1
  6. package/dist/subsystem/SubsystemCarousel.d.ts +36 -0
  7. package/dist/subsystem/SubsystemCarousel.d.ts.map +1 -0
  8. package/dist/subsystem/SubsystemCarousel.js +163 -0
  9. package/dist/subsystem/SubsystemCarousel.js.map +1 -0
  10. package/dist/subsystem/SubsystemComponentGraph.d.ts +25 -0
  11. package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
  12. package/dist/subsystem/SubsystemComponentGraph.js +329 -68
  13. package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
  14. package/package.json +4 -4
  15. package/src/index.ts +9 -199
  16. package/src/subsystem/SubsystemComponentGraph.tsx +396 -50
  17. package/src/components/ConfigurationSelector.tsx +0 -133
  18. package/src/components/GraphRenderer.tsx +0 -3195
  19. package/src/components/MultiCanvasRenderer.tsx +0 -295
  20. package/src/components/NodeTooltip.tsx +0 -279
  21. package/src/components/PendingChanges.test.tsx +0 -375
  22. package/src/components/SelectionSidebar.tsx +0 -352
  23. package/src/components/SequenceDiagramRenderer.tsx +0 -1156
  24. package/src/components/WorkflowSequenceDiagram.tsx +0 -270
  25. package/src/components/dashboard/DashboardRenderer.tsx +0 -317
  26. package/src/components/dashboard/MetricPanel.tsx +0 -254
  27. package/src/components/dashboard/MockDataProvider.ts +0 -330
  28. package/src/components/dashboard/components/BarChart.tsx +0 -299
  29. package/src/components/dashboard/components/LineChart.tsx +0 -279
  30. package/src/components/dashboard/components/MetricCard.tsx +0 -270
  31. package/src/components/dashboard/components/SourceLink.tsx +0 -63
  32. package/src/components/dashboard/components/TimeRangeSelector.tsx +0 -280
  33. package/src/components/dashboard/components/index.ts +0 -5
  34. package/src/components/dashboard/index.ts +0 -47
  35. package/src/components/dashboard/types.ts +0 -126
  36. package/src/components/state-view/PipelineView.tsx +0 -347
  37. package/src/components/state-view/index.ts +0 -14
  38. package/src/components/state-view/types.ts +0 -261
  39. package/src/components/state-view/useStateView.ts +0 -205
  40. package/src/contexts/GraphEditContext.tsx +0 -27
  41. package/src/contexts/TooltipPortalContext.ts +0 -8
  42. package/src/edges/CustomEdge.tsx +0 -402
  43. package/src/edges/GenericEdge.tsx +0 -36
  44. package/src/hooks/usePathBasedEvents.ts +0 -192
  45. package/src/hooks/useSequenceLayout.ts +0 -543
  46. package/src/hooks/useUndoRedo.ts +0 -144
  47. package/src/nodes/CustomNode.tsx +0 -1231
  48. package/src/nodes/GenericNode.tsx +0 -55
  49. package/src/nodes/otel/OtelBoundaryNode.tsx +0 -224
  50. package/src/nodes/otel/OtelEventNode.tsx +0 -225
  51. package/src/nodes/otel/OtelResourceNode.tsx +0 -251
  52. package/src/nodes/otel/OtelScopeNode.tsx +0 -221
  53. package/src/nodes/otel/OtelSpanConventionNode.tsx +0 -295
  54. package/src/nodes/otel/index.ts +0 -23
  55. package/src/nodes/otel/shared/NodeBadges.tsx +0 -295
  56. package/src/nodes/otel/shared/NodeContent.tsx +0 -204
  57. package/src/nodes/otel/shared/index.ts +0 -8
  58. package/src/nodes/otel/shared/types.ts +0 -138
  59. package/src/nodes/otel/shared/useNodeBehavior.ts +0 -114
  60. package/src/stories/Audit/BoundaryNodes.stories.tsx +0 -385
  61. package/src/stories/Audit/CanvasEdgeTypes.stories.tsx +0 -1448
  62. package/src/stories/Audit/CanvasNodeTypes.stories.tsx +0 -1049
  63. package/src/stories/Audit/ColorPriority.stories.tsx +0 -895
  64. package/src/stories/Audit/DiamondBadges.stories.tsx +0 -629
  65. package/src/stories/Audit/NodeDimensionsTesting.stories.tsx +0 -724
  66. package/src/stories/Audit/NodeFieldsAudit.stories.tsx +0 -996
  67. package/src/stories/Audit/NodeFontSizeTesting.stories.tsx +0 -715
  68. package/src/stories/Audit/NodeShapes.stories.tsx +0 -1208
  69. package/src/stories/Audit/WideNodesTesting.stories.tsx +0 -1045
  70. package/src/stories/Components/DashboardRenderer.stories.tsx +0 -263
  71. package/src/stories/Components/GraphRenderer.stories.tsx +0 -3236
  72. package/src/stories/Components/MultiCanvasRenderer.stories.tsx +0 -370
  73. package/src/stories/Components/SequenceDiagram.stories.tsx +0 -255
  74. package/src/stories/Components/StateView.stories.tsx +0 -417
  75. package/src/stories/Components/TraceViewer.stories.tsx +0 -442
  76. package/src/stories/Components/WorkflowSequenceDiagram.stories.tsx +0 -802
  77. package/src/stories/Features/AnimationWorkshop.stories.tsx +0 -727
  78. package/src/stories/Features/ChangeTypeVisual.stories.tsx +0 -67
  79. package/src/stories/Features/EventDrivenAnimations.stories.tsx +0 -513
  80. package/src/stories/Features/MultiConfig.stories.tsx +0 -539
  81. package/src/stories/Layout/ElkEdgeRouting.stories.tsx +0 -539
  82. package/src/stories/Layout/GraphOrientation.stories.tsx +0 -500
  83. package/src/stories/Layout/MultiDirectionalConnections.stories.tsx +0 -352
  84. package/src/stories/Nodes/NodeDefinitionComparison.stories.tsx +0 -560
  85. package/src/stories/Nodes/NodeNameFallbacks.stories.tsx +0 -491
  86. package/src/stories/Nodes/NumericColors.stories.tsx +0 -440
  87. package/src/stories/OTEL/EventNameDisplay.stories.tsx +0 -694
  88. package/src/stories/OTEL/EventNameFallback.stories.tsx +0 -578
  89. package/src/stories/OTEL/OtelComponents.stories.tsx +0 -422
  90. package/src/stories/OTEL/OtelNodeTypesPrototype.stories.tsx +0 -806
  91. package/src/stories/OTEL/RawEventCards.stories.tsx +0 -57
  92. package/src/stories/OTEL/SpanBadges.stories.tsx +0 -840
  93. package/src/stories/OTEL/ValidationEventsCanvas.stories.tsx +0 -209
  94. package/src/stories/RealWorld/BacklogMdCanvases.stories.tsx +0 -721
  95. package/src/stories/RealWorld/FileCitySequence.stories.tsx +0 -516
  96. package/src/stories/RealWorld/RealCanvasFiles.stories.tsx +0 -336
  97. package/src/stories/__traces__/test-run.canvas.json +0 -241
  98. package/src/stories/data/activity-feed-analytics.dashboard.json +0 -300
  99. package/src/stories/data/file-city-images-transformed.otel.canvas.json +0 -295
  100. package/src/stories/data/file-city-workflows.json +0 -269
  101. package/src/stories/data/graph-converter-test-execution.json +0 -443
  102. package/src/stories/data/graph-converter-test.workflow.json +0 -105
  103. package/src/stories/data/graph-converter-validated-execution.json +0 -58
  104. package/src/utils/animationMapping.ts +0 -166
  105. package/src/utils/canvasBounds.ts +0 -146
  106. package/src/utils/graphConverter.ts +0 -148
  107. package/src/utils/iconResolver.tsx +0 -53
  108. package/src/utils/orientationUtils.ts +0 -73
@@ -1,516 +0,0 @@
1
- import React from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react';
3
- import { SequenceDiagramRenderer } from '../../components/SequenceDiagramRenderer';
4
- import { WorkflowSequenceDiagram } from '../../components/WorkflowSequenceDiagram';
5
- import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
6
- import workflowData from '../data/file-city-workflows.json';
7
- import type { WorkflowScenario } from '@principal-ai/subsystems-core';
8
-
9
- const meta = {
10
- title: 'RealWorld/FileCitySequence',
11
- component: SequenceDiagramRenderer,
12
- parameters: {
13
- layout: 'fullscreen',
14
- docs: {
15
- description: {
16
- component: `
17
- # File City Image Generation Workflows
18
-
19
- This demonstrates the **graph-to-sequence** concepts applied to the File City image generation system.
20
-
21
- ## Participant Model
22
-
23
- Following the sequence-first architecture:
24
-
25
- - **Nodes** = Participants (Main Process, Renderer Process)
26
- - **Edges** = Move Events (IPC calls crossing process boundaries)
27
- - **Transform Events** = Internal processing within each participant
28
-
29
- ## Key Concepts
30
-
31
- - **Sequence diagrams are primary** - They show actual execution traces
32
- - **Graphs aggregate sequences** - The canvas shows all possible paths
33
- - **Move vs Transform Events**:
34
- - **Move**: Data crossing participant boundaries (IPC calls)
35
- - **Transform**: Internal processing within a participant
36
-
37
- See \`/docs/GRAPH_TO_SEQUENCE_CONCEPTS.md\` for the full conceptual model.
38
- `,
39
- },
40
- },
41
- },
42
- tags: ['autodocs'],
43
- decorators: [
44
- (Story) => (
45
- <ThemeProvider theme={defaultEditorTheme}>
46
- <div style={{ height: '100vh', boxSizing: 'border-box' }}>
47
- <Story />
48
- </div>
49
- </ThemeProvider>
50
- ),
51
- ],
52
- } satisfies Meta<typeof SequenceDiagramRenderer>;
53
-
54
- export default meta;
55
- type Story = StoryObj<typeof meta>;
56
-
57
- // ============================================================================
58
- // Helper Components
59
- // ============================================================================
60
-
61
- interface SequenceWithEventsProps {
62
- events: SequenceEvent[];
63
- edges: SequenceEdge[];
64
- height?: number;
65
- layoutOptions?: any;
66
- }
67
-
68
- const SequenceWithEventsList: React.FC<SequenceWithEventsProps> = ({
69
- events,
70
- edges,
71
- height = 500,
72
- layoutOptions,
73
- }) => {
74
- return (
75
- <div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
76
- {/* Top Half - Sequence Diagram */}
77
- <div style={{ flex: 1, overflow: 'hidden' }}>
78
- <SequenceDiagramRenderer
79
- events={events}
80
- edges={edges}
81
- height={height}
82
- layoutOptions={layoutOptions}
83
- />
84
- </div>
85
-
86
- {/* Bottom Half - Event List */}
87
- <div style={{
88
- flex: 1,
89
- overflow: 'auto',
90
- background: '#1e1e1e',
91
- color: '#d4d4d4',
92
- fontFamily: 'monospace',
93
- fontSize: 13,
94
- }}>
95
- <div style={{ padding: '16px' }}>
96
- <h3 style={{ margin: '0 0 12px 0', color: '#4ec9b0' }}>Event Sequence</h3>
97
- <table style={{ width: '100%', borderCollapse: 'collapse' }}>
98
- <thead>
99
- <tr style={{ borderBottom: '1px solid #3e3e3e' }}>
100
- <th style={{ textAlign: 'left', padding: '8px', color: '#9cdcfe' }}>Order</th>
101
- <th style={{ textAlign: 'left', padding: '8px', color: '#9cdcfe' }}>Event Name</th>
102
- <th style={{ textAlign: 'left', padding: '8px', color: '#9cdcfe' }}>Label</th>
103
- <th style={{ textAlign: 'left', padding: '8px', color: '#9cdcfe' }}>Type</th>
104
- </tr>
105
- </thead>
106
- <tbody>
107
- {events.map((event, index) => {
108
- const isMoveEvent = (event as any).moveEvent;
109
- const participant = event.name.split('.')[0];
110
- return (
111
- <tr key={event.id} style={{ borderBottom: '1px solid #2a2a2a' }}>
112
- <td style={{ padding: '8px', color: '#b5cea8' }}>{index + 1}</td>
113
- <td style={{
114
- padding: '8px',
115
- color: isMoveEvent ? '#ce9178' : '#dcdcaa',
116
- fontWeight: isMoveEvent ? 'bold' : 'normal'
117
- }}>
118
- {event.name}
119
- </td>
120
- <td style={{ padding: '8px', color: '#d4d4d4' }}>{event.label}</td>
121
- <td style={{
122
- padding: '8px',
123
- color: isMoveEvent ? '#f48771' : '#569cd6'
124
- }}>
125
- {isMoveEvent ? '→ Move Event (IPC)' : `Transform (${participant})`}
126
- </td>
127
- </tr>
128
- );
129
- })}
130
- </tbody>
131
- </table>
132
- </div>
133
- </div>
134
- </div>
135
- );
136
- };
137
-
138
- // ============================================================================
139
- // Workflow Stories
140
- // ============================================================================
141
-
142
- /**
143
- * **Happy Path - Cache Hit**
144
- *
145
- * Optimal execution path where a cached image already exists.
146
- *
147
- * **Flow:**
148
- * 1. Renderer requests image via IPC
149
- * 2. Main process checks cache → Hit!
150
- * 3. Returns cached URL immediately
151
- * 4. Renderer displays image
152
- *
153
- * **Move Events (cross-boundary):**
154
- * - `main.image_requested` (Renderer → Main)
155
- * - `renderer.cache_hit` (Main → Renderer)
156
- */
157
- export const CacheHitFlow: Story = {
158
- render: () => (
159
- <SequenceWithEventsList
160
- events={workflowData.workflows[0].events}
161
- edges={workflowData.workflows[0].edges}
162
- height={600}
163
- layoutOptions={{
164
- laneWidth: 200,
165
- eventSpacing: 80,
166
- }}
167
- />
168
- ),
169
- parameters: {
170
- docs: {
171
- description: {
172
- story: 'Fast path when cached image exists - only 2 IPC calls needed.',
173
- },
174
- },
175
- },
176
- };
177
-
178
- /**
179
- * **Full Generation Flow**
180
- *
181
- * Complete execution path when no cached image exists.
182
- *
183
- * **Flow:**
184
- * 1. Renderer requests image via IPC
185
- * 2. Main process checks cache → Miss
186
- * 3. Fetches file tree from repository cache
187
- * 4. Generates new File City visualization
188
- * 5. Saves to cache
189
- * 6. Returns generated URL via IPC
190
- * 7. Renderer displays image
191
- *
192
- * **Move Events (cross-boundary):**
193
- * - `main.image_requested` (Renderer → Main)
194
- * - `renderer.generation_complete` (Main → Renderer)
195
- *
196
- * **Transform Events (internal to Main):**
197
- * - `cache_checked`, `filetree_fetched`, `generation_started`
198
- */
199
- export const GenerateNewFlow: Story = {
200
- render: () => (
201
- <SequenceWithEventsList
202
- events={workflowData.workflows[1].events}
203
- edges={workflowData.workflows[1].edges}
204
- height={700}
205
- layoutOptions={{
206
- laneWidth: 200,
207
- eventSpacing: 80,
208
- }}
209
- />
210
- ),
211
- parameters: {
212
- docs: {
213
- description: {
214
- story: 'Full generation path with cache miss - includes image generation.',
215
- },
216
- },
217
- },
218
- };
219
-
220
- /**
221
- * **Error Path - No FileTree**
222
- *
223
- * Error handling when file tree is not available.
224
- *
225
- * **Flow:**
226
- * 1. Renderer requests image via IPC
227
- * 2. Main process checks cache → Miss
228
- * 3. Attempts to fetch file tree → Not available
229
- * 4. Skips generation, returns null
230
- * 5. Renderer displays fallback UI
231
- *
232
- * **Move Events:**
233
- * - `main.image_requested` (Renderer → Main)
234
- * - `renderer.generation_skipped` (Main → Renderer)
235
- */
236
- export const NoFileTreeFlow: Story = {
237
- render: () => (
238
- <SequenceWithEventsList
239
- events={workflowData.workflows[2].events}
240
- edges={workflowData.workflows[2].edges}
241
- height={600}
242
- layoutOptions={{
243
- laneWidth: 200,
244
- eventSpacing: 80,
245
- }}
246
- />
247
- ),
248
- parameters: {
249
- docs: {
250
- description: {
251
- story: 'Error handling when repository file tree is unavailable.',
252
- },
253
- },
254
- },
255
- };
256
-
257
- /**
258
- * **Error During Generation**
259
- *
260
- * Error handling when image generation fails.
261
- *
262
- * **Flow:**
263
- * 1. Renderer requests image via IPC
264
- * 2. Main process checks cache → Miss
265
- * 3. Fetches file tree successfully
266
- * 4. Starts generation → Error occurs
267
- * 5. Returns error via IPC
268
- * 6. Renderer displays fallback UI
269
- *
270
- * **Move Events:**
271
- * - `main.image_requested` (Renderer → Main)
272
- * - `renderer.generation_error` (Main → Renderer)
273
- */
274
- export const ErrorFlow: Story = {
275
- render: () => (
276
- <SequenceWithEventsList
277
- events={workflowData.workflows[3].events}
278
- edges={workflowData.workflows[3].edges}
279
- height={650}
280
- layoutOptions={{
281
- laneWidth: 200,
282
- eventSpacing: 80,
283
- }}
284
- />
285
- ),
286
- parameters: {
287
- docs: {
288
- description: {
289
- story: 'Error handling when image generation fails unexpectedly.',
290
- },
291
- },
292
- },
293
- };
294
-
295
- /**
296
- * **Comparison View**
297
- *
298
- * Side-by-side comparison of cache hit vs full generation.
299
- * Shows how the same canvas structure supports multiple execution paths.
300
- */
301
- export const ComparisonView: Story = {
302
- render: () => (
303
- <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', height: '100vh' }}>
304
- <div style={{ display: 'flex', flexDirection: 'column', borderRight: '1px solid #3e3e3e' }}>
305
- <h3 style={{ margin: '12px', color: '#d4d4d4' }}>Cache Hit (Fast)</h3>
306
- <div style={{ flex: 1 }}>
307
- <SequenceDiagramRenderer
308
- events={workflowData.workflows[0].events}
309
- edges={workflowData.workflows[0].edges}
310
- height={600}
311
- layoutOptions={{
312
- laneWidth: 180,
313
- eventSpacing: 70,
314
- }}
315
- />
316
- </div>
317
- </div>
318
- <div style={{ display: 'flex', flexDirection: 'column' }}>
319
- <h3 style={{ margin: '12px', color: '#d4d4d4' }}>Generate New (Full)</h3>
320
- <div style={{ flex: 1 }}>
321
- <SequenceDiagramRenderer
322
- events={workflowData.workflows[1].events}
323
- edges={workflowData.workflows[1].edges}
324
- height={600}
325
- layoutOptions={{
326
- laneWidth: 180,
327
- eventSpacing: 70,
328
- }}
329
- />
330
- </div>
331
- </div>
332
- </div>
333
- ),
334
- parameters: {
335
- docs: {
336
- description: {
337
- story: 'Visual comparison showing branching execution paths from the same canvas.',
338
- },
339
- },
340
- },
341
- };
342
-
343
- /**
344
- * **All Paths Overview**
345
- *
346
- * Grid view of all possible execution paths through the system.
347
- * Demonstrates the canvas as an "aggregation of sequences" - showing
348
- * the full possibility space that the canvas represents.
349
- */
350
- export const AllPathsOverview: Story = {
351
- render: () => (
352
- <div style={{
353
- display: 'grid',
354
- gridTemplateColumns: '1fr 1fr',
355
- height: '100vh',
356
- overflow: 'auto',
357
- background: '#1e1e1e'
358
- }}>
359
- {workflowData.workflows.map((workflow, index) => (
360
- <div
361
- key={workflow.id}
362
- style={{
363
- display: 'flex',
364
- flexDirection: 'column',
365
- borderRight: index % 2 === 0 ? '1px solid #3e3e3e' : 'none',
366
- borderBottom: index < 2 ? '1px solid #3e3e3e' : 'none'
367
- }}
368
- >
369
- <div style={{ padding: '12px', borderBottom: '1px solid #3e3e3e' }}>
370
- <h3 style={{ margin: '0 0 4px 0', color: '#d4d4d4' }}>{workflow.name}</h3>
371
- <p style={{ fontSize: 13, color: '#858585', margin: 0 }}>
372
- {workflow.description}
373
- </p>
374
- </div>
375
- <div style={{ flex: 1 }}>
376
- <SequenceDiagramRenderer
377
- events={workflow.events}
378
- edges={workflow.edges}
379
- height={400}
380
- layoutOptions={{
381
- laneWidth: 160,
382
- eventSpacing: 60,
383
- laneGap: 40,
384
- }}
385
- />
386
- </div>
387
- </div>
388
- ))}
389
- </div>
390
- ),
391
- parameters: {
392
- docs: {
393
- description: {
394
- story: 'Complete overview of all execution paths - the "library of possibilities".',
395
- },
396
- },
397
- },
398
- };
399
-
400
- /**
401
- * **Using WorkflowSequenceDiagram Wrapper**
402
- *
403
- * Demonstrates the simplified API using the WorkflowSequenceDiagram component.
404
- * This component automatically handles the conversion from workflow to sequence format.
405
- */
406
- export const UsingWorkflowWrapper: Story = {
407
- render: () => {
408
- // Convert our workflow data to the expected WorkflowScenario format
409
- const scenario: WorkflowScenario = {
410
- id: 'cache-hit-flow',
411
- name: 'Cache Hit Flow',
412
- description: 'Optimal path where cached image exists',
413
- events: workflowData.workflows[1].events.map(e => ({
414
- name: e.name,
415
- label: e.label,
416
- moveEvent: e.moveEvent,
417
- participant: e.participant,
418
- })),
419
- edges: workflowData.workflows[1].edges,
420
- template: {
421
- events: {},
422
- },
423
- };
424
-
425
- return (
426
- <div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
427
- <div style={{
428
- padding: '12px',
429
- background: '#1e1e1e',
430
- borderBottom: '1px solid #3e3e3e',
431
- color: '#d4d4d4'
432
- }}>
433
- <h3 style={{ margin: '0 0 4px 0' }}>WorkflowSequenceDiagram Component</h3>
434
- <p style={{ fontSize: 13, color: '#858585', margin: 0 }}>
435
- Cleaner API - just pass the workflow scenario and optional canvas
436
- </p>
437
- </div>
438
- <div style={{ flex: 1 }}>
439
- <WorkflowSequenceDiagram
440
- scenario={scenario}
441
- height="100%"
442
- layoutOptions={{
443
- laneWidth: 200,
444
- eventSpacing: 80,
445
- }}
446
- />
447
- </div>
448
- </div>
449
- );
450
- },
451
- parameters: {
452
- docs: {
453
- description: {
454
- story: 'Simplified API using the WorkflowSequenceDiagram wrapper component.',
455
- },
456
- },
457
- },
458
- };
459
-
460
- /**
461
- * **Interactive Drill-Down**
462
- *
463
- * Lanes default to top-level participants. Use the ▶ chevrons on a lane
464
- * header to drill into its sub-namespaces, and ‹ on a child lane to step
465
- * back out.
466
- */
467
- export const InteractiveDrillDown: Story = {
468
- render: () => {
469
- const [opened, setOpened] = React.useState<string[]>([]);
470
-
471
- const handleToggle = (namespace: string) => {
472
- setOpened((prev) =>
473
- prev.includes(namespace)
474
- ? prev.filter((n) => n !== namespace)
475
- : [...prev, namespace]
476
- );
477
- };
478
-
479
- return (
480
- <div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
481
- <div style={{
482
- padding: '12px',
483
- background: '#1e1e1e',
484
- borderBottom: '1px solid #3e3e3e',
485
- color: '#d4d4d4',
486
- }}>
487
- <strong>Opened:</strong>{' '}
488
- {opened.length ? opened.join(', ') : 'none (top-level participants)'}
489
- <p style={{ fontSize: 13, color: '#858585', marginTop: 8, marginBottom: 0 }}>
490
- ▶ on a lane drills into its sub-namespaces. ‹ on a child lane steps back out.
491
- </p>
492
- </div>
493
- <div style={{ flex: 1 }}>
494
- <SequenceDiagramRenderer
495
- events={workflowData.workflows[1].events}
496
- edges={workflowData.workflows[1].edges}
497
- height={700}
498
- layoutOptions={{
499
- openedNamespaces: opened,
500
- laneWidth: 200,
501
- eventSpacing: 80,
502
- }}
503
- onToggleNamespace={handleToggle}
504
- />
505
- </div>
506
- </div>
507
- );
508
- },
509
- parameters: {
510
- docs: {
511
- description: {
512
- story: 'Drill into participant lanes to reveal their sub-namespaces.',
513
- },
514
- },
515
- },
516
- };