@principal-ai/principal-view-react 0.13.7 → 0.13.8

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 (37) hide show
  1. package/dist/components/GraphRenderer.d.ts +1 -15
  2. package/dist/components/GraphRenderer.d.ts.map +1 -1
  3. package/dist/components/GraphRenderer.js +94 -269
  4. package/dist/components/GraphRenderer.js.map +1 -1
  5. package/dist/components/NodeInfoPanel.d.ts.map +1 -1
  6. package/dist/components/NodeInfoPanel.js.map +1 -1
  7. package/dist/edges/CustomEdge.d.ts +2 -2
  8. package/dist/edges/CustomEdge.d.ts.map +1 -1
  9. package/dist/edges/CustomEdge.js +5 -4
  10. package/dist/edges/CustomEdge.js.map +1 -1
  11. package/dist/hooks/usePathBasedEvents.d.ts.map +1 -1
  12. package/dist/hooks/usePathBasedEvents.js +2 -1
  13. package/dist/hooks/usePathBasedEvents.js.map +1 -1
  14. package/dist/index.d.ts +0 -4
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +0 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/nodes/CustomNode.d.ts +2 -2
  19. package/dist/nodes/CustomNode.d.ts.map +1 -1
  20. package/dist/nodes/CustomNode.js +41 -10
  21. package/dist/nodes/CustomNode.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/components/GraphRenderer.tsx +106 -354
  24. package/src/edges/CustomEdge.tsx +8 -7
  25. package/src/hooks/usePathBasedEvents.ts +2 -1
  26. package/src/index.ts +0 -6
  27. package/src/nodes/CustomNode.tsx +50 -13
  28. package/src/stories/ColorPriority.stories.tsx +2 -0
  29. package/src/stories/EventDrivenAnimations.stories.tsx +332 -326
  30. package/src/stories/GraphRenderer.stories.tsx +2 -2
  31. package/src/stories/NodeDefinitionComparison.stories.tsx +1 -1
  32. package/src/stories/NodeDimensionsTesting.stories.tsx +2 -2
  33. package/src/stories/OtelComponents.stories.tsx +0 -47
  34. package/src/stories/data/graph-converter-test-execution.json +244 -26
  35. package/src/stories/data/graph-converter-validated-execution.json +6 -6
  36. package/src/components/EdgeInfoPanel.tsx +0 -247
  37. package/src/components/NodeInfoPanel.tsx +0 -724
@@ -117,391 +117,397 @@ const sampleCanvas: ExtendedCanvas = {
117
117
  * Story: Automatic Event Sequence
118
118
  * Demonstrates automatic event playback with animations
119
119
  */
120
- export const AutomaticEventSequence: Story = {
121
- render: () => {
122
- const [events, setEvents] = useState<GraphEvent[]>([]);
123
- const [eventLog, setEventLog] = useState<string[]>([]);
120
+ const AutomaticEventSequenceRenderer = () => {
121
+ const [events, setEvents] = useState<GraphEvent[]>([]);
122
+ const [eventLog, setEventLog] = useState<string[]>([]);
124
123
 
125
- useEffect(() => {
126
- // Define event sequence
127
- const eventSequence: Array<{ delay: number; event: GraphEvent }> = [
128
- {
129
- delay: 500,
130
- event: {
131
- id: 'evt-1',
132
- type: 'edge_animated',
133
- timestamp: Date.now(),
134
- category: 'edge',
124
+ useEffect(() => {
125
+ // Define event sequence
126
+ const eventSequence: Array<{ delay: number; event: GraphEvent }> = [
127
+ {
128
+ delay: 500,
129
+ event: {
130
+ id: 'evt-1',
131
+ type: 'edge_animated',
132
+ timestamp: Date.now(),
133
+ category: 'edge',
134
+ operation: 'animate',
135
+ payload: {
135
136
  operation: 'animate',
136
- payload: {
137
- operation: 'animate',
138
- edgeId: 'edge-1',
139
- edgeType: 'dataflow',
140
- from: 'node-1',
141
- to: 'node-2',
142
- animation: {
143
- duration: 1000,
144
- direction: 'forward' as const,
145
- },
137
+ edgeId: 'edge-1',
138
+ edgeType: 'dataflow',
139
+ from: 'node-1',
140
+ to: 'node-2',
141
+ animation: {
142
+ duration: 1000,
143
+ direction: 'forward' as const,
146
144
  },
147
145
  },
148
146
  },
149
- {
150
- delay: 1500,
151
- event: {
152
- id: 'evt-2',
153
- type: 'state_changed',
154
- timestamp: Date.now(),
155
- category: 'state',
156
- operation: 'update',
157
- payload: {
158
- nodeId: 'node-2',
159
- newState: 'processing',
160
- },
147
+ },
148
+ {
149
+ delay: 1500,
150
+ event: {
151
+ id: 'evt-2',
152
+ type: 'state_changed',
153
+ timestamp: Date.now(),
154
+ category: 'state',
155
+ operation: 'update',
156
+ payload: {
157
+ nodeId: 'node-2',
158
+ newState: 'processing',
161
159
  },
162
160
  },
163
- {
164
- delay: 3000,
165
- event: {
166
- id: 'evt-3',
167
- type: 'edge_animated',
168
- timestamp: Date.now(),
169
- category: 'edge',
161
+ },
162
+ {
163
+ delay: 3000,
164
+ event: {
165
+ id: 'evt-3',
166
+ type: 'edge_animated',
167
+ timestamp: Date.now(),
168
+ category: 'edge',
169
+ operation: 'animate',
170
+ payload: {
170
171
  operation: 'animate',
171
- payload: {
172
- operation: 'animate',
173
- edgeId: 'edge-2',
174
- edgeType: 'dataflow',
175
- from: 'node-2',
176
- to: 'node-3',
177
- animation: {
178
- duration: 1000,
179
- direction: 'forward' as const,
180
- },
172
+ edgeId: 'edge-2',
173
+ edgeType: 'dataflow',
174
+ from: 'node-2',
175
+ to: 'node-3',
176
+ animation: {
177
+ duration: 1000,
178
+ direction: 'forward' as const,
181
179
  },
182
180
  },
183
181
  },
184
- {
185
- delay: 4000,
186
- event: {
187
- id: 'evt-4',
188
- type: 'state_changed',
189
- timestamp: Date.now(),
190
- category: 'state',
191
- operation: 'update',
192
- payload: {
193
- nodeId: 'node-2',
194
- newState: 'completed',
195
- },
182
+ },
183
+ {
184
+ delay: 4000,
185
+ event: {
186
+ id: 'evt-4',
187
+ type: 'state_changed',
188
+ timestamp: Date.now(),
189
+ category: 'state',
190
+ operation: 'update',
191
+ payload: {
192
+ nodeId: 'node-2',
193
+ newState: 'completed',
196
194
  },
197
195
  },
198
- ];
196
+ },
197
+ ];
199
198
 
200
- // Play events with delays
199
+ // Play events with delays
200
+ eventSequence.forEach(({ delay, event }) => {
201
+ setTimeout(() => {
202
+ setEvents((prev) => [...prev, event]);
203
+ setEventLog((prev) => [...prev, `${event.type} at ${delay}ms`]);
204
+ }, delay);
205
+ });
206
+
207
+ // Loop the sequence
208
+ const loopInterval = setInterval(() => {
209
+ setEvents([]);
210
+ setEventLog(['--- Sequence restart ---']);
201
211
  eventSequence.forEach(({ delay, event }) => {
202
212
  setTimeout(() => {
203
213
  setEvents((prev) => [...prev, event]);
204
214
  setEventLog((prev) => [...prev, `${event.type} at ${delay}ms`]);
205
215
  }, delay);
206
216
  });
217
+ }, 5000);
207
218
 
208
- // Loop the sequence
209
- const loopInterval = setInterval(() => {
210
- setEvents([]);
211
- setEventLog(['--- Sequence restart ---']);
212
- eventSequence.forEach(({ delay, event }) => {
213
- setTimeout(() => {
214
- setEvents((prev) => [...prev, event]);
215
- setEventLog((prev) => [...prev, `${event.type} at ${delay}ms`]);
216
- }, delay);
217
- });
218
- }, 5000);
219
+ return () => clearInterval(loopInterval);
220
+ }, []);
219
221
 
220
- return () => clearInterval(loopInterval);
221
- }, []);
222
-
223
- return (
224
- <div style={{ display: 'flex', height: '100vh' }}>
225
- <div style={{ flex: 1 }}>
226
- <GraphRenderer
227
- canvas={sampleCanvas}
228
- events={events}
229
- width="100%"
230
- height="100%"
231
- onEventProcessed={(event) => {
232
- console.log('Event processed:', event);
233
- }}
234
- />
235
- </div>
236
- <div
237
- style={{
238
- width: '300px',
239
- backgroundColor: '#f5f5f5',
240
- padding: '16px',
241
- overflowY: 'auto',
242
- borderLeft: '1px solid #ddd',
222
+ return (
223
+ <div style={{ display: 'flex', height: '100vh' }}>
224
+ <div style={{ flex: 1 }}>
225
+ <GraphRenderer
226
+ canvas={sampleCanvas}
227
+ events={events}
228
+ width="100%"
229
+ height="100%"
230
+ onEventProcessed={(event) => {
231
+ console.log('Event processed:', event);
243
232
  }}
244
- >
245
- <h3 style={{ marginTop: 0 }}>Event Log</h3>
246
- <div style={{ fontSize: '12px', fontFamily: 'monospace' }}>
247
- {eventLog.map((log, idx) => (
248
- <div key={idx} style={{ padding: '4px 0', borderBottom: '1px solid #e0e0e0' }}>
249
- {log}
250
- </div>
251
- ))}
252
- </div>
233
+ />
234
+ </div>
235
+ <div
236
+ style={{
237
+ width: '300px',
238
+ backgroundColor: '#f5f5f5',
239
+ padding: '16px',
240
+ overflowY: 'auto',
241
+ borderLeft: '1px solid #ddd',
242
+ }}
243
+ >
244
+ <h3 style={{ marginTop: 0 }}>Event Log</h3>
245
+ <div style={{ fontSize: '12px', fontFamily: 'monospace' }}>
246
+ {eventLog.map((log, idx) => (
247
+ <div key={idx} style={{ padding: '4px 0', borderBottom: '1px solid #e0e0e0' }}>
248
+ {log}
249
+ </div>
250
+ ))}
253
251
  </div>
254
252
  </div>
255
- );
256
- },
253
+ </div>
254
+ );
255
+ };
256
+
257
+ export const AutomaticEventSequence: Story = {
258
+ render: () => <AutomaticEventSequenceRenderer />,
257
259
  };
258
260
 
259
261
  /**
260
262
  * Story: Interactive Event Triggers
261
263
  * Allows user to manually trigger animation events
262
264
  */
263
- export const InteractiveEventTriggers: Story = {
264
- render: () => {
265
- const [events, setEvents] = useState<GraphEvent[]>([]);
265
+ const InteractiveEventTriggersRenderer = () => {
266
+ const [events, setEvents] = useState<GraphEvent[]>([]);
266
267
 
267
- const triggerEdgeAnimation = (edgeId: string) => {
268
- const event: GraphEvent = {
269
- id: `evt-${Date.now()}`,
270
- type: 'edge_animated',
271
- timestamp: Date.now(),
272
- category: 'edge',
268
+ const triggerEdgeAnimation = (edgeId: string) => {
269
+ const event: GraphEvent = {
270
+ id: `evt-${Date.now()}`,
271
+ type: 'edge_animated',
272
+ timestamp: Date.now(),
273
+ category: 'edge',
274
+ operation: 'animate',
275
+ payload: {
273
276
  operation: 'animate',
274
- payload: {
275
- operation: 'animate',
276
- edgeId,
277
- edgeType: 'dataflow',
278
- from: edgeId === 'edge-1' ? 'node-1' : 'node-2',
279
- to: edgeId === 'edge-1' ? 'node-2' : 'node-3',
280
- animation: {
281
- duration: 1000,
282
- direction: 'forward' as const,
283
- },
277
+ edgeId,
278
+ edgeType: 'dataflow',
279
+ from: edgeId === 'edge-1' ? 'node-1' : 'node-2',
280
+ to: edgeId === 'edge-1' ? 'node-2' : 'node-3',
281
+ animation: {
282
+ duration: 1000,
283
+ direction: 'forward' as const,
284
284
  },
285
- };
286
- setEvents((prev) => [...prev, event]);
285
+ },
287
286
  };
287
+ setEvents((prev) => [...prev, event]);
288
+ };
288
289
 
289
- const triggerNodeState = (nodeId: string, state: string) => {
290
- const event: GraphEvent = {
291
- id: `evt-${Date.now()}`,
292
- type: 'state_changed',
293
- timestamp: Date.now(),
294
- category: 'state',
295
- operation: 'update',
296
- payload: {
297
- nodeId,
298
- newState: state,
299
- },
300
- };
301
- setEvents((prev) => [...prev, event]);
290
+ const triggerNodeState = (nodeId: string, state: string) => {
291
+ const event: GraphEvent = {
292
+ id: `evt-${Date.now()}`,
293
+ type: 'state_changed',
294
+ timestamp: Date.now(),
295
+ category: 'state',
296
+ operation: 'update',
297
+ payload: {
298
+ nodeId,
299
+ newState: state,
300
+ },
302
301
  };
302
+ setEvents((prev) => [...prev, event]);
303
+ };
303
304
 
304
- return (
305
- <div style={{ display: 'flex', height: '100vh' }}>
306
- <div style={{ flex: 1 }}>
307
- <GraphRenderer canvas={sampleCanvas} events={events} width="100%" height="100%" />
308
- </div>
309
- <div
310
- style={{
311
- width: '300px',
312
- backgroundColor: '#f5f5f5',
313
- padding: '16px',
314
- overflowY: 'auto',
315
- borderLeft: '1px solid #ddd',
316
- }}
317
- >
318
- <h3 style={{ marginTop: 0 }}>Event Controls</h3>
305
+ return (
306
+ <div style={{ display: 'flex', height: '100vh' }}>
307
+ <div style={{ flex: 1 }}>
308
+ <GraphRenderer canvas={sampleCanvas} events={events} width="100%" height="100%" />
309
+ </div>
310
+ <div
311
+ style={{
312
+ width: '300px',
313
+ backgroundColor: '#f5f5f5',
314
+ padding: '16px',
315
+ overflowY: 'auto',
316
+ borderLeft: '1px solid #ddd',
317
+ }}
318
+ >
319
+ <h3 style={{ marginTop: 0 }}>Event Controls</h3>
319
320
 
320
- <div style={{ marginBottom: '24px' }}>
321
- <h4>Edge Animations</h4>
322
- <button
323
- onClick={() => triggerEdgeAnimation('edge-1')}
324
- style={{
325
- width: '100%',
326
- padding: '8px',
327
- marginBottom: '8px',
328
- backgroundColor: '#50E3C2',
329
- border: 'none',
330
- borderRadius: '4px',
331
- cursor: 'pointer',
332
- }}
333
- >
334
- Animate Edge 1
335
- </button>
336
- <button
337
- onClick={() => triggerEdgeAnimation('edge-2')}
338
- style={{
339
- width: '100%',
340
- padding: '8px',
341
- backgroundColor: '#50E3C2',
342
- border: 'none',
343
- borderRadius: '4px',
344
- cursor: 'pointer',
345
- }}
346
- >
347
- Animate Edge 2
348
- </button>
349
- </div>
321
+ <div style={{ marginBottom: '24px' }}>
322
+ <h4>Edge Animations</h4>
323
+ <button
324
+ onClick={() => triggerEdgeAnimation('edge-1')}
325
+ style={{
326
+ width: '100%',
327
+ padding: '8px',
328
+ marginBottom: '8px',
329
+ backgroundColor: '#50E3C2',
330
+ border: 'none',
331
+ borderRadius: '4px',
332
+ cursor: 'pointer',
333
+ }}
334
+ >
335
+ Animate Edge 1
336
+ </button>
337
+ <button
338
+ onClick={() => triggerEdgeAnimation('edge-2')}
339
+ style={{
340
+ width: '100%',
341
+ padding: '8px',
342
+ backgroundColor: '#50E3C2',
343
+ border: 'none',
344
+ borderRadius: '4px',
345
+ cursor: 'pointer',
346
+ }}
347
+ >
348
+ Animate Edge 2
349
+ </button>
350
+ </div>
350
351
 
351
- <div>
352
- <h4>Node States</h4>
353
- <button
354
- onClick={() => triggerNodeState('node-2', 'processing')}
355
- style={{
356
- width: '100%',
357
- padding: '8px',
358
- marginBottom: '8px',
359
- backgroundColor: '#4A90E2',
360
- color: 'white',
361
- border: 'none',
362
- borderRadius: '4px',
363
- cursor: 'pointer',
364
- }}
365
- >
366
- Set Node 2: Processing
367
- </button>
368
- <button
369
- onClick={() => triggerNodeState('node-2', 'completed')}
370
- style={{
371
- width: '100%',
372
- padding: '8px',
373
- marginBottom: '8px',
374
- backgroundColor: '#10B981',
375
- color: 'white',
376
- border: 'none',
377
- borderRadius: '4px',
378
- cursor: 'pointer',
379
- }}
380
- >
381
- Set Node 2: Completed
382
- </button>
383
- <button
384
- onClick={() => triggerNodeState('node-2', 'error')}
385
- style={{
386
- width: '100%',
387
- padding: '8px',
388
- backgroundColor: '#EF4444',
389
- color: 'white',
390
- border: 'none',
391
- borderRadius: '4px',
392
- cursor: 'pointer',
393
- }}
394
- >
395
- Set Node 2: Error
396
- </button>
397
- </div>
352
+ <div>
353
+ <h4>Node States</h4>
354
+ <button
355
+ onClick={() => triggerNodeState('node-2', 'processing')}
356
+ style={{
357
+ width: '100%',
358
+ padding: '8px',
359
+ marginBottom: '8px',
360
+ backgroundColor: '#4A90E2',
361
+ color: 'white',
362
+ border: 'none',
363
+ borderRadius: '4px',
364
+ cursor: 'pointer',
365
+ }}
366
+ >
367
+ Set Node 2: Processing
368
+ </button>
369
+ <button
370
+ onClick={() => triggerNodeState('node-2', 'completed')}
371
+ style={{
372
+ width: '100%',
373
+ padding: '8px',
374
+ marginBottom: '8px',
375
+ backgroundColor: '#10B981',
376
+ color: 'white',
377
+ border: 'none',
378
+ borderRadius: '4px',
379
+ cursor: 'pointer',
380
+ }}
381
+ >
382
+ Set Node 2: Completed
383
+ </button>
384
+ <button
385
+ onClick={() => triggerNodeState('node-2', 'error')}
386
+ style={{
387
+ width: '100%',
388
+ padding: '8px',
389
+ backgroundColor: '#EF4444',
390
+ color: 'white',
391
+ border: 'none',
392
+ borderRadius: '4px',
393
+ cursor: 'pointer',
394
+ }}
395
+ >
396
+ Set Node 2: Error
397
+ </button>
398
398
  </div>
399
399
  </div>
400
- );
401
- },
400
+ </div>
401
+ );
402
+ };
403
+
404
+ export const InteractiveEventTriggers: Story = {
405
+ render: () => <InteractiveEventTriggersRenderer />,
402
406
  };
403
407
 
404
408
  /**
405
409
  * Story: Pipeline Processing Flow
406
410
  * Shows a realistic data pipeline with cascading animations
407
411
  */
408
- export const PipelineProcessingFlow: Story = {
409
- render: () => {
410
- const [events, setEvents] = useState<GraphEvent[]>([]);
411
- const [isRunning, setIsRunning] = useState(false);
412
+ const PipelineProcessingFlowRenderer = () => {
413
+ const [events, setEvents] = useState<GraphEvent[]>([]);
414
+ const [isRunning, setIsRunning] = useState(false);
412
415
 
413
- const runPipeline = () => {
414
- setIsRunning(true);
415
- setEvents([]);
416
+ const runPipeline = () => {
417
+ setIsRunning(true);
418
+ setEvents([]);
416
419
 
417
- // Simulate pipeline execution
418
- const sequence = [
419
- { delay: 0, type: 'edge', target: 'edge-1' },
420
- { delay: 800, type: 'state', target: 'node-2', state: 'processing' },
421
- { delay: 2500, type: 'edge', target: 'edge-2' },
422
- { delay: 3200, type: 'state', target: 'node-2', state: 'completed' },
423
- ];
420
+ // Simulate pipeline execution
421
+ const sequence = [
422
+ { delay: 0, type: 'edge', target: 'edge-1' },
423
+ { delay: 800, type: 'state', target: 'node-2', state: 'processing' },
424
+ { delay: 2500, type: 'edge', target: 'edge-2' },
425
+ { delay: 3200, type: 'state', target: 'node-2', state: 'completed' },
426
+ ];
424
427
 
425
- sequence.forEach(({ delay, type, target, state }) => {
426
- setTimeout(() => {
427
- if (type === 'edge') {
428
- setEvents((prev) => [
429
- ...prev,
430
- {
431
- id: `evt-${Date.now()}`,
432
- type: 'edge_animated',
433
- timestamp: Date.now(),
434
- category: 'edge',
428
+ sequence.forEach(({ delay, type, target, state }) => {
429
+ setTimeout(() => {
430
+ if (type === 'edge') {
431
+ setEvents((prev) => [
432
+ ...prev,
433
+ {
434
+ id: `evt-${Date.now()}`,
435
+ type: 'edge_animated',
436
+ timestamp: Date.now(),
437
+ category: 'edge',
438
+ operation: 'animate',
439
+ payload: {
435
440
  operation: 'animate',
436
- payload: {
437
- operation: 'animate',
438
- edgeId: target,
439
- edgeType: 'dataflow',
440
- from: target === 'edge-1' ? 'node-1' : 'node-2',
441
- to: target === 'edge-1' ? 'node-2' : 'node-3',
442
- animation: {
443
- duration: 1000,
444
- direction: 'forward' as const,
445
- },
441
+ edgeId: target,
442
+ edgeType: 'dataflow',
443
+ from: target === 'edge-1' ? 'node-1' : 'node-2',
444
+ to: target === 'edge-1' ? 'node-2' : 'node-3',
445
+ animation: {
446
+ duration: 1000,
447
+ direction: 'forward' as const,
446
448
  },
447
449
  },
448
- ]);
449
- } else if (type === 'state' && state) {
450
- setEvents((prev) => [
451
- ...prev,
452
- {
453
- id: `evt-${Date.now()}`,
454
- type: 'state_changed',
455
- timestamp: Date.now(),
456
- category: 'state',
457
- operation: 'update',
458
- payload: {
459
- nodeId: target,
460
- newState: state,
461
- },
450
+ },
451
+ ]);
452
+ } else if (type === 'state' && state) {
453
+ setEvents((prev) => [
454
+ ...prev,
455
+ {
456
+ id: `evt-${Date.now()}`,
457
+ type: 'state_changed',
458
+ timestamp: Date.now(),
459
+ category: 'state',
460
+ operation: 'update',
461
+ payload: {
462
+ nodeId: target,
463
+ newState: state,
462
464
  },
463
- ]);
464
- }
465
- }, delay);
466
- });
465
+ },
466
+ ]);
467
+ }
468
+ }, delay);
469
+ });
467
470
 
468
- setTimeout(() => setIsRunning(false), 4000);
469
- };
471
+ setTimeout(() => setIsRunning(false), 4000);
472
+ };
470
473
 
471
- return (
472
- <div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
473
- <div
474
+ return (
475
+ <div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
476
+ <div
477
+ style={{
478
+ padding: '16px',
479
+ backgroundColor: '#f5f5f5',
480
+ borderBottom: '1px solid #ddd',
481
+ display: 'flex',
482
+ justifyContent: 'space-between',
483
+ alignItems: 'center',
484
+ }}
485
+ >
486
+ <h3 style={{ margin: 0 }}>Pipeline Processing Flow</h3>
487
+ <button
488
+ onClick={runPipeline}
489
+ disabled={isRunning}
474
490
  style={{
475
- padding: '16px',
476
- backgroundColor: '#f5f5f5',
477
- borderBottom: '1px solid #ddd',
478
- display: 'flex',
479
- justifyContent: 'space-between',
480
- alignItems: 'center',
491
+ padding: '12px 24px',
492
+ backgroundColor: isRunning ? '#ccc' : '#4A90E2',
493
+ color: 'white',
494
+ border: 'none',
495
+ borderRadius: '4px',
496
+ fontSize: '14px',
497
+ fontWeight: 'bold',
498
+ cursor: isRunning ? 'not-allowed' : 'pointer',
481
499
  }}
482
500
  >
483
- <h3 style={{ margin: 0 }}>Pipeline Processing Flow</h3>
484
- <button
485
- onClick={runPipeline}
486
- disabled={isRunning}
487
- style={{
488
- padding: '12px 24px',
489
- backgroundColor: isRunning ? '#ccc' : '#4A90E2',
490
- color: 'white',
491
- border: 'none',
492
- borderRadius: '4px',
493
- fontSize: '14px',
494
- fontWeight: 'bold',
495
- cursor: isRunning ? 'not-allowed' : 'pointer',
496
- }}
497
- >
498
- {isRunning ? 'Running...' : 'Run Pipeline'}
499
- </button>
500
- </div>
501
- <div style={{ flex: 1 }}>
502
- <GraphRenderer canvas={sampleCanvas} events={events} width="100%" height="100%" />
503
- </div>
501
+ {isRunning ? 'Running...' : 'Run Pipeline'}
502
+ </button>
504
503
  </div>
505
- );
506
- },
504
+ <div style={{ flex: 1 }}>
505
+ <GraphRenderer canvas={sampleCanvas} events={events} width="100%" height="100%" />
506
+ </div>
507
+ </div>
508
+ );
509
+ };
510
+
511
+ export const PipelineProcessingFlow: Story = {
512
+ render: () => <PipelineProcessingFlowRenderer />,
507
513
  };