@principal-ai/principal-view-react 0.6.9 → 0.6.11
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 +2 -5
- package/dist/components/ConfigurationSelector.js +4 -2
- package/dist/components/ConfigurationSelector.js.map +1 -1
- package/dist/components/EdgeInfoPanel.d.ts.map +1 -1
- package/dist/components/EdgeInfoPanel.js +43 -13
- package/dist/components/EdgeInfoPanel.js.map +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +135 -82
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/NodeInfoPanel.d.ts.map +1 -1
- package/dist/components/NodeInfoPanel.js +143 -45
- package/dist/components/NodeInfoPanel.js.map +1 -1
- package/dist/edges/CustomEdge.d.ts.map +1 -1
- package/dist/edges/CustomEdge.js +2 -2
- package/dist/edges/CustomEdge.js.map +1 -1
- package/dist/edges/GenericEdge.d.ts.map +1 -1
- package/dist/edges/GenericEdge.js +2 -2
- package/dist/edges/GenericEdge.js.map +1 -1
- package/dist/hooks/usePathBasedEvents.d.ts +1 -1
- package/dist/hooks/usePathBasedEvents.d.ts.map +1 -1
- package/dist/hooks/usePathBasedEvents.js +9 -9
- package/dist/hooks/usePathBasedEvents.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/nodes/CustomNode.d.ts.map +1 -1
- package/dist/nodes/CustomNode.js +61 -44
- package/dist/nodes/CustomNode.js.map +1 -1
- package/dist/nodes/GenericNode.d.ts.map +1 -1
- package/dist/nodes/GenericNode.js.map +1 -1
- package/dist/utils/animationMapping.d.ts.map +1 -1
- package/dist/utils/animationMapping.js +12 -12
- package/dist/utils/animationMapping.js.map +1 -1
- package/dist/utils/graphConverter.d.ts.map +1 -1
- package/dist/utils/graphConverter.js +23 -17
- package/dist/utils/graphConverter.js.map +1 -1
- package/dist/utils/iconResolver.d.ts.map +1 -1
- package/dist/utils/iconResolver.js +1 -1
- package/dist/utils/iconResolver.js.map +1 -1
- package/package.json +2 -1
- package/src/components/ConfigurationSelector.tsx +5 -5
- package/src/components/EdgeInfoPanel.tsx +79 -37
- package/src/components/GraphRenderer.tsx +528 -364
- package/src/components/NodeInfoPanel.tsx +209 -86
- package/src/edges/CustomEdge.tsx +6 -4
- package/src/edges/GenericEdge.tsx +2 -6
- package/src/hooks/usePathBasedEvents.ts +54 -45
- package/src/index.ts +11 -2
- package/src/nodes/CustomNode.tsx +132 -106
- package/src/nodes/GenericNode.tsx +4 -3
- package/src/stories/AnimationWorkshop.stories.tsx +131 -12
- package/src/stories/CanvasNodeTypes.stories.tsx +898 -0
- package/src/stories/ColorPriority.stories.tsx +20 -10
- package/src/stories/EventDrivenAnimations.stories.tsx +8 -0
- package/src/stories/EventLog.stories.tsx +1 -1
- package/src/stories/GraphRenderer.stories.tsx +23 -10
- package/src/stories/IndustryThemes.stories.tsx +481 -0
- package/src/stories/MultiConfig.stories.tsx +8 -0
- package/src/stories/MultiDirectionalConnections.stories.tsx +8 -0
- package/src/stories/NodeFieldsAudit.stories.tsx +124 -37
- package/src/stories/NodeShapes.stories.tsx +73 -59
- package/src/utils/animationMapping.ts +19 -23
- package/src/utils/graphConverter.ts +35 -19
- package/src/utils/iconResolver.tsx +5 -1
|
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
import { GraphRenderer } from '../components/GraphRenderer';
|
|
4
4
|
import type { ExtendedCanvas, GraphEvent } from '@principal-ai/principal-view-core';
|
|
5
|
+
import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
|
|
5
6
|
|
|
6
7
|
// Helper component that sets initial node states via events
|
|
7
8
|
const GraphWithInitialStates: React.FC<{
|
|
@@ -15,13 +16,15 @@ const GraphWithInitialStates: React.FC<{
|
|
|
15
16
|
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
if (initialStates) {
|
|
18
|
-
const stateEvents: GraphEvent[] = Object.entries(initialStates).map(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
const stateEvents: GraphEvent[] = Object.entries(initialStates).map(
|
|
20
|
+
([nodeId, newState], idx) => ({
|
|
21
|
+
id: `init-state-${idx}`,
|
|
22
|
+
type: 'state_changed',
|
|
23
|
+
timestamp: Date.now(),
|
|
24
|
+
category: 'state' as const,
|
|
25
|
+
payload: { nodeId, newState },
|
|
26
|
+
})
|
|
27
|
+
);
|
|
25
28
|
setEvents(stateEvents);
|
|
26
29
|
}
|
|
27
30
|
}, []);
|
|
@@ -44,6 +47,13 @@ const meta = {
|
|
|
44
47
|
layout: 'centered',
|
|
45
48
|
},
|
|
46
49
|
tags: ['autodocs'],
|
|
50
|
+
decorators: [
|
|
51
|
+
(Story) => (
|
|
52
|
+
<ThemeProvider theme={defaultEditorTheme}>
|
|
53
|
+
<Story />
|
|
54
|
+
</ThemeProvider>
|
|
55
|
+
),
|
|
56
|
+
],
|
|
47
57
|
} satisfies Meta<typeof GraphRenderer>;
|
|
48
58
|
|
|
49
59
|
export default meta;
|
|
@@ -425,7 +435,7 @@ const iconPriorityCanvas: ExtendedCanvas = {
|
|
|
425
435
|
pv: {
|
|
426
436
|
nodeType: 'icon-type-demo',
|
|
427
437
|
shape: 'rectangle',
|
|
428
|
-
icon: '
|
|
438
|
+
icon: 'Settings',
|
|
429
439
|
},
|
|
430
440
|
},
|
|
431
441
|
// 2. State icon (when in a state)
|
|
@@ -441,9 +451,9 @@ const iconPriorityCanvas: ExtendedCanvas = {
|
|
|
441
451
|
pv: {
|
|
442
452
|
nodeType: 'icon-state-demo',
|
|
443
453
|
shape: 'rectangle',
|
|
444
|
-
icon: '
|
|
454
|
+
icon: 'Settings', // Type icon - should be overridden
|
|
445
455
|
states: {
|
|
446
|
-
complete: { label: 'Complete', color: '#00FF00', icon: '
|
|
456
|
+
complete: { label: 'Complete', color: '#00FF00', icon: 'Check' },
|
|
447
457
|
},
|
|
448
458
|
},
|
|
449
459
|
},
|
|
@@ -3,6 +3,7 @@ import { GraphRenderer } from '../components/GraphRenderer';
|
|
|
3
3
|
import type { GraphEvent, ExtendedCanvas } from '@principal-ai/principal-view-core';
|
|
4
4
|
import { useState, useEffect } from 'react';
|
|
5
5
|
import React from 'react';
|
|
6
|
+
import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
|
|
6
7
|
|
|
7
8
|
const meta = {
|
|
8
9
|
title: 'Workshop/Event-Driven Animations',
|
|
@@ -11,6 +12,13 @@ const meta = {
|
|
|
11
12
|
layout: 'fullscreen',
|
|
12
13
|
},
|
|
13
14
|
tags: ['autodocs'],
|
|
15
|
+
decorators: [
|
|
16
|
+
(Story) => (
|
|
17
|
+
<ThemeProvider theme={defaultEditorTheme}>
|
|
18
|
+
<Story />
|
|
19
|
+
</ThemeProvider>
|
|
20
|
+
),
|
|
21
|
+
],
|
|
14
22
|
} satisfies Meta<typeof GraphRenderer>;
|
|
15
23
|
|
|
16
24
|
export default meta;
|
|
@@ -133,7 +133,7 @@ export const ManyEvents: Story = {
|
|
|
133
133
|
...sampleEvents,
|
|
134
134
|
...Array.from({ length: 20 }, (_, i) => ({
|
|
135
135
|
id: `evt-gen-${i}`,
|
|
136
|
-
timestamp: Date.now() -
|
|
136
|
+
timestamp: Date.now() - i * 500,
|
|
137
137
|
type: 'node_updated',
|
|
138
138
|
category: 'node' as const,
|
|
139
139
|
operation: 'update' as const,
|
|
@@ -3,6 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|
|
3
3
|
import { GraphRenderer } from '../components/GraphRenderer';
|
|
4
4
|
import type { GraphRendererHandle, PendingChanges } from '../components/GraphRenderer';
|
|
5
5
|
import type { ExtendedCanvas } from '@principal-ai/principal-view-core';
|
|
6
|
+
import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
|
|
6
7
|
|
|
7
8
|
const meta = {
|
|
8
9
|
title: 'Components/GraphRenderer',
|
|
@@ -11,6 +12,13 @@ const meta = {
|
|
|
11
12
|
layout: 'centered',
|
|
12
13
|
},
|
|
13
14
|
tags: ['autodocs'],
|
|
15
|
+
decorators: [
|
|
16
|
+
(Story) => (
|
|
17
|
+
<ThemeProvider theme={defaultEditorTheme}>
|
|
18
|
+
<Story />
|
|
19
|
+
</ThemeProvider>
|
|
20
|
+
),
|
|
21
|
+
],
|
|
14
22
|
} satisfies Meta<typeof GraphRenderer>;
|
|
15
23
|
|
|
16
24
|
export default meta;
|
|
@@ -283,11 +291,11 @@ const serviceArchitectureCanvas: ExtendedCanvas = {
|
|
|
283
291
|
pv: {
|
|
284
292
|
nodeType: 'client',
|
|
285
293
|
shape: 'circle',
|
|
286
|
-
icon: '
|
|
294
|
+
icon: 'User',
|
|
287
295
|
states: {
|
|
288
|
-
idle: { color: '#94a3b8', icon: '
|
|
289
|
-
connected: { color: '#22c55e', icon: '
|
|
290
|
-
error: { color: '#ef4444', icon: '
|
|
296
|
+
idle: { color: '#94a3b8', icon: 'User' },
|
|
297
|
+
connected: { color: '#22c55e', icon: 'UserCheck' },
|
|
298
|
+
error: { color: '#ef4444', icon: 'UserX' },
|
|
291
299
|
},
|
|
292
300
|
},
|
|
293
301
|
},
|
|
@@ -303,7 +311,7 @@ const serviceArchitectureCanvas: ExtendedCanvas = {
|
|
|
303
311
|
pv: {
|
|
304
312
|
nodeType: 'api-server',
|
|
305
313
|
shape: 'rectangle',
|
|
306
|
-
icon: '
|
|
314
|
+
icon: 'Server',
|
|
307
315
|
states: {
|
|
308
316
|
idle: { color: '#94a3b8' },
|
|
309
317
|
processing: { color: '#3b82f6' },
|
|
@@ -323,7 +331,7 @@ const serviceArchitectureCanvas: ExtendedCanvas = {
|
|
|
323
331
|
pv: {
|
|
324
332
|
nodeType: 'database',
|
|
325
333
|
shape: 'hexagon',
|
|
326
|
-
icon: '
|
|
334
|
+
icon: 'Database',
|
|
327
335
|
},
|
|
328
336
|
},
|
|
329
337
|
{
|
|
@@ -338,7 +346,7 @@ const serviceArchitectureCanvas: ExtendedCanvas = {
|
|
|
338
346
|
pv: {
|
|
339
347
|
nodeType: 'cache',
|
|
340
348
|
shape: 'diamond',
|
|
341
|
-
icon: '
|
|
349
|
+
icon: 'Zap',
|
|
342
350
|
},
|
|
343
351
|
},
|
|
344
352
|
],
|
|
@@ -537,12 +545,16 @@ const EditableTemplate = () => {
|
|
|
537
545
|
Reset
|
|
538
546
|
</button>
|
|
539
547
|
{hasChanges && (
|
|
540
|
-
<span style={{ fontSize: 12, color: '#f5a623', fontStyle: 'italic' }}>
|
|
548
|
+
<span style={{ fontSize: 12, color: '#f5a623', fontStyle: 'italic' }}>
|
|
549
|
+
Unsaved changes
|
|
550
|
+
</span>
|
|
541
551
|
)}
|
|
542
552
|
</div>
|
|
543
553
|
{lastSavedChanges && (
|
|
544
554
|
<div style={{ marginTop: 12 }}>
|
|
545
|
-
<div style={{ fontSize: 11, fontWeight: 'bold', color: '#666' }}>
|
|
555
|
+
<div style={{ fontSize: 11, fontWeight: 'bold', color: '#666' }}>
|
|
556
|
+
Last saved changes:
|
|
557
|
+
</div>
|
|
546
558
|
<pre
|
|
547
559
|
style={{
|
|
548
560
|
marginTop: 4,
|
|
@@ -621,7 +633,8 @@ export const ServiceArchitectureEditable: Story = {
|
|
|
621
633
|
parameters: {
|
|
622
634
|
docs: {
|
|
623
635
|
description: {
|
|
624
|
-
story:
|
|
636
|
+
story:
|
|
637
|
+
'Service architecture canvas with editing enabled. Edit nodes, create edges, and track changes.',
|
|
625
638
|
},
|
|
626
639
|
},
|
|
627
640
|
},
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { GraphRenderer } from '../components/GraphRenderer';
|
|
4
|
+
import type { ExtendedCanvas } from '@principal-ai/principal-view-core';
|
|
5
|
+
import {
|
|
6
|
+
terminalTheme,
|
|
7
|
+
matrixTheme,
|
|
8
|
+
slateTheme,
|
|
9
|
+
regalTheme,
|
|
10
|
+
glassmorphismTheme,
|
|
11
|
+
landingPageTheme,
|
|
12
|
+
defaultEditorTheme,
|
|
13
|
+
ThemeProvider,
|
|
14
|
+
} from '@principal-ade/industry-theme';
|
|
15
|
+
|
|
16
|
+
const meta = {
|
|
17
|
+
title: 'Themes/IndustryThemes',
|
|
18
|
+
component: GraphRenderer,
|
|
19
|
+
parameters: {
|
|
20
|
+
layout: 'fullscreen',
|
|
21
|
+
},
|
|
22
|
+
} satisfies Meta<typeof GraphRenderer>;
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
type Story = StoryObj<typeof meta>;
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Theme Registry from @principal-ade/industry-theme
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
interface IndustryTheme {
|
|
32
|
+
colors: {
|
|
33
|
+
text: string;
|
|
34
|
+
background: string;
|
|
35
|
+
primary: string;
|
|
36
|
+
secondary: string;
|
|
37
|
+
accent: string;
|
|
38
|
+
success: string;
|
|
39
|
+
warning: string;
|
|
40
|
+
error: string;
|
|
41
|
+
info: string;
|
|
42
|
+
border: string;
|
|
43
|
+
surface: string;
|
|
44
|
+
[key: string]: string;
|
|
45
|
+
};
|
|
46
|
+
fonts: {
|
|
47
|
+
body: string;
|
|
48
|
+
heading: string;
|
|
49
|
+
monospace: string;
|
|
50
|
+
};
|
|
51
|
+
[key: string]: unknown;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const themes: Record<string, { theme: IndustryTheme; name: string; description: string }> = {
|
|
55
|
+
terminal: {
|
|
56
|
+
theme: terminalTheme as IndustryTheme,
|
|
57
|
+
name: 'Terminal',
|
|
58
|
+
description: 'Dark terminal-style theme with monospace fonts',
|
|
59
|
+
},
|
|
60
|
+
matrix: {
|
|
61
|
+
theme: matrixTheme as IndustryTheme,
|
|
62
|
+
name: 'Matrix',
|
|
63
|
+
description: 'Green-on-black hacker aesthetic',
|
|
64
|
+
},
|
|
65
|
+
slate: {
|
|
66
|
+
theme: slateTheme as IndustryTheme,
|
|
67
|
+
name: 'Slate',
|
|
68
|
+
description: 'Modern dark gray theme with amber accents',
|
|
69
|
+
},
|
|
70
|
+
regal: {
|
|
71
|
+
theme: regalTheme as IndustryTheme,
|
|
72
|
+
name: 'Regal',
|
|
73
|
+
description: 'Elegant dark theme with gold accents',
|
|
74
|
+
},
|
|
75
|
+
glassmorphism: {
|
|
76
|
+
theme: glassmorphismTheme as IndustryTheme,
|
|
77
|
+
name: 'Glassmorphism',
|
|
78
|
+
description: 'Frosted glass effect with purple tones',
|
|
79
|
+
},
|
|
80
|
+
landingPage: {
|
|
81
|
+
theme: landingPageTheme as IndustryTheme,
|
|
82
|
+
name: 'Landing Page',
|
|
83
|
+
description: 'Cyan accent on dark background',
|
|
84
|
+
},
|
|
85
|
+
editor: {
|
|
86
|
+
theme: defaultEditorTheme as IndustryTheme,
|
|
87
|
+
name: 'Editor',
|
|
88
|
+
description: 'VS Code inspired dark theme',
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// Sample Canvas that uses theme colors
|
|
94
|
+
// ============================================================================
|
|
95
|
+
|
|
96
|
+
function createThemedCanvas(theme: IndustryTheme): ExtendedCanvas {
|
|
97
|
+
const colors = theme.colors;
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
nodes: [
|
|
101
|
+
{
|
|
102
|
+
id: 'api-gateway',
|
|
103
|
+
type: 'text',
|
|
104
|
+
x: 100,
|
|
105
|
+
y: 200,
|
|
106
|
+
width: 140,
|
|
107
|
+
height: 70,
|
|
108
|
+
text: '# API Gateway',
|
|
109
|
+
pv: {
|
|
110
|
+
nodeType: 'api-gateway',
|
|
111
|
+
shape: 'rectangle',
|
|
112
|
+
icon: 'Globe',
|
|
113
|
+
fill: colors.primary,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'auth-service',
|
|
118
|
+
type: 'text',
|
|
119
|
+
x: 320,
|
|
120
|
+
y: 100,
|
|
121
|
+
width: 140,
|
|
122
|
+
height: 70,
|
|
123
|
+
text: '# Auth Service',
|
|
124
|
+
pv: {
|
|
125
|
+
nodeType: 'service',
|
|
126
|
+
shape: 'hexagon',
|
|
127
|
+
icon: 'Shield',
|
|
128
|
+
fill: colors.success,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'user-service',
|
|
133
|
+
type: 'text',
|
|
134
|
+
x: 320,
|
|
135
|
+
y: 300,
|
|
136
|
+
width: 140,
|
|
137
|
+
height: 70,
|
|
138
|
+
text: '# User Service',
|
|
139
|
+
pv: {
|
|
140
|
+
nodeType: 'service',
|
|
141
|
+
shape: 'hexagon',
|
|
142
|
+
icon: 'Users',
|
|
143
|
+
fill: colors.info,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: 'database',
|
|
148
|
+
type: 'text',
|
|
149
|
+
x: 540,
|
|
150
|
+
y: 200,
|
|
151
|
+
width: 100,
|
|
152
|
+
height: 100,
|
|
153
|
+
text: '# Database',
|
|
154
|
+
pv: {
|
|
155
|
+
nodeType: 'database',
|
|
156
|
+
shape: 'circle',
|
|
157
|
+
icon: 'Database',
|
|
158
|
+
fill: colors.secondary,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'cache',
|
|
163
|
+
type: 'text',
|
|
164
|
+
x: 540,
|
|
165
|
+
y: 350,
|
|
166
|
+
width: 80,
|
|
167
|
+
height: 80,
|
|
168
|
+
text: '# Cache',
|
|
169
|
+
pv: {
|
|
170
|
+
nodeType: 'cache',
|
|
171
|
+
shape: 'diamond',
|
|
172
|
+
icon: 'Zap',
|
|
173
|
+
fill: colors.warning,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'queue',
|
|
178
|
+
type: 'text',
|
|
179
|
+
x: 320,
|
|
180
|
+
y: 450,
|
|
181
|
+
width: 80,
|
|
182
|
+
height: 80,
|
|
183
|
+
text: '# Queue',
|
|
184
|
+
pv: {
|
|
185
|
+
nodeType: 'queue',
|
|
186
|
+
shape: 'diamond',
|
|
187
|
+
icon: 'Inbox',
|
|
188
|
+
fill: colors.accent,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
edges: [
|
|
193
|
+
{
|
|
194
|
+
id: 'e1',
|
|
195
|
+
fromNode: 'api-gateway',
|
|
196
|
+
toNode: 'auth-service',
|
|
197
|
+
fromSide: 'right',
|
|
198
|
+
toSide: 'left',
|
|
199
|
+
pv: { edgeType: 'http' },
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: 'e2',
|
|
203
|
+
fromNode: 'api-gateway',
|
|
204
|
+
toNode: 'user-service',
|
|
205
|
+
fromSide: 'right',
|
|
206
|
+
toSide: 'left',
|
|
207
|
+
pv: { edgeType: 'http' },
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'e3',
|
|
211
|
+
fromNode: 'auth-service',
|
|
212
|
+
toNode: 'database',
|
|
213
|
+
fromSide: 'right',
|
|
214
|
+
toSide: 'left',
|
|
215
|
+
pv: { edgeType: 'query' },
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: 'e4',
|
|
219
|
+
fromNode: 'user-service',
|
|
220
|
+
toNode: 'database',
|
|
221
|
+
fromSide: 'right',
|
|
222
|
+
toSide: 'left',
|
|
223
|
+
pv: { edgeType: 'query' },
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
id: 'e5',
|
|
227
|
+
fromNode: 'user-service',
|
|
228
|
+
toNode: 'cache',
|
|
229
|
+
fromSide: 'right',
|
|
230
|
+
toSide: 'top',
|
|
231
|
+
pv: { edgeType: 'cache' },
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: 'e6',
|
|
235
|
+
fromNode: 'user-service',
|
|
236
|
+
toNode: 'queue',
|
|
237
|
+
fromSide: 'bottom',
|
|
238
|
+
toSide: 'top',
|
|
239
|
+
pv: { edgeType: 'async' },
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
pv: {
|
|
243
|
+
version: '1.0.0',
|
|
244
|
+
name: 'Themed Architecture',
|
|
245
|
+
edgeTypes: {
|
|
246
|
+
http: { style: 'solid', color: colors.primary, directed: true },
|
|
247
|
+
query: { style: 'dashed', color: colors.secondary, directed: true },
|
|
248
|
+
cache: { style: 'dotted', color: colors.warning, directed: true },
|
|
249
|
+
async: { style: 'dashed', color: colors.accent, directed: true },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ============================================================================
|
|
256
|
+
// Interactive Theme Switcher Component
|
|
257
|
+
// ============================================================================
|
|
258
|
+
|
|
259
|
+
const ThemeSwitcher = () => {
|
|
260
|
+
const [selectedTheme, setSelectedTheme] = useState<string>('terminal');
|
|
261
|
+
const themeConfig = themes[selectedTheme];
|
|
262
|
+
const canvas = createThemedCanvas(themeConfig.theme);
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<ThemeProvider theme={themeConfig.theme}>
|
|
266
|
+
<div
|
|
267
|
+
style={{
|
|
268
|
+
width: '100%',
|
|
269
|
+
height: '100vh',
|
|
270
|
+
display: 'flex',
|
|
271
|
+
flexDirection: 'column',
|
|
272
|
+
backgroundColor: themeConfig.theme.colors.background,
|
|
273
|
+
color: themeConfig.theme.colors.text,
|
|
274
|
+
fontFamily: themeConfig.theme.fonts.body,
|
|
275
|
+
}}
|
|
276
|
+
>
|
|
277
|
+
{/* Theme Selector Header */}
|
|
278
|
+
<div
|
|
279
|
+
style={{
|
|
280
|
+
padding: '16px 24px',
|
|
281
|
+
backgroundColor: themeConfig.theme.colors.surface,
|
|
282
|
+
display: 'flex',
|
|
283
|
+
alignItems: 'center',
|
|
284
|
+
gap: '16px',
|
|
285
|
+
borderBottom: `1px solid ${themeConfig.theme.colors.border}`,
|
|
286
|
+
}}
|
|
287
|
+
>
|
|
288
|
+
<label style={{ fontWeight: 600, fontSize: '14px' }}>Theme:</label>
|
|
289
|
+
<select
|
|
290
|
+
value={selectedTheme}
|
|
291
|
+
onChange={(e) => setSelectedTheme(e.target.value)}
|
|
292
|
+
style={{
|
|
293
|
+
padding: '8px 16px',
|
|
294
|
+
fontSize: '14px',
|
|
295
|
+
borderRadius: '6px',
|
|
296
|
+
border: `1px solid ${themeConfig.theme.colors.border}`,
|
|
297
|
+
backgroundColor: themeConfig.theme.colors.background,
|
|
298
|
+
color: themeConfig.theme.colors.text,
|
|
299
|
+
cursor: 'pointer',
|
|
300
|
+
minWidth: '200px',
|
|
301
|
+
}}
|
|
302
|
+
>
|
|
303
|
+
{Object.entries(themes).map(([key, config]) => (
|
|
304
|
+
<option key={key} value={key}>
|
|
305
|
+
{config.name}
|
|
306
|
+
</option>
|
|
307
|
+
))}
|
|
308
|
+
</select>
|
|
309
|
+
|
|
310
|
+
<div style={{ marginLeft: 'auto', fontSize: '12px', opacity: 0.7 }}>
|
|
311
|
+
@principal-ade/industry-theme
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
{/* Theme Description */}
|
|
316
|
+
<div
|
|
317
|
+
style={{
|
|
318
|
+
padding: '12px 24px',
|
|
319
|
+
backgroundColor: themeConfig.theme.colors.surface,
|
|
320
|
+
borderBottom: `1px solid ${themeConfig.theme.colors.border}`,
|
|
321
|
+
fontSize: '13px',
|
|
322
|
+
opacity: 0.8,
|
|
323
|
+
}}
|
|
324
|
+
>
|
|
325
|
+
<strong>{themeConfig.name}</strong>: {themeConfig.description}
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
{/* Graph Renderer */}
|
|
329
|
+
<div style={{ flex: 1, position: 'relative' }}>
|
|
330
|
+
<GraphRenderer canvas={canvas} width="100%" height="100%" />
|
|
331
|
+
</div>
|
|
332
|
+
|
|
333
|
+
{/* Color Palette Legend */}
|
|
334
|
+
<div
|
|
335
|
+
style={{
|
|
336
|
+
padding: '16px 24px',
|
|
337
|
+
backgroundColor: themeConfig.theme.colors.surface,
|
|
338
|
+
borderTop: `1px solid ${themeConfig.theme.colors.border}`,
|
|
339
|
+
display: 'flex',
|
|
340
|
+
flexWrap: 'wrap',
|
|
341
|
+
gap: '16px',
|
|
342
|
+
}}
|
|
343
|
+
>
|
|
344
|
+
{['primary', 'secondary', 'accent', 'success', 'warning', 'error', 'info'].map((colorKey) => (
|
|
345
|
+
<div
|
|
346
|
+
key={colorKey}
|
|
347
|
+
style={{
|
|
348
|
+
display: 'flex',
|
|
349
|
+
alignItems: 'center',
|
|
350
|
+
gap: '8px',
|
|
351
|
+
fontSize: '12px',
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
<div
|
|
355
|
+
style={{
|
|
356
|
+
width: '16px',
|
|
357
|
+
height: '16px',
|
|
358
|
+
borderRadius: '4px',
|
|
359
|
+
backgroundColor: themeConfig.theme.colors[colorKey],
|
|
360
|
+
border: `1px solid ${themeConfig.theme.colors.border}`,
|
|
361
|
+
}}
|
|
362
|
+
/>
|
|
363
|
+
<span style={{ fontFamily: themeConfig.theme.fonts.monospace }}>{colorKey}</span>
|
|
364
|
+
</div>
|
|
365
|
+
))}
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
</ThemeProvider>
|
|
369
|
+
);
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// ============================================================================
|
|
373
|
+
// Stories
|
|
374
|
+
// ============================================================================
|
|
375
|
+
|
|
376
|
+
export const ThemeSwitcherDemo: Story = {
|
|
377
|
+
render: () => <ThemeSwitcher />,
|
|
378
|
+
parameters: {
|
|
379
|
+
docs: {
|
|
380
|
+
description: {
|
|
381
|
+
story: `
|
|
382
|
+
**Industry Theme Switcher**
|
|
383
|
+
|
|
384
|
+
This demo uses the \`@principal-ade/industry-theme\` package to apply different visual themes to the graph.
|
|
385
|
+
|
|
386
|
+
Available themes:
|
|
387
|
+
- **Terminal**: Dark terminal-style with monospace fonts
|
|
388
|
+
- **Matrix**: Green-on-black hacker aesthetic
|
|
389
|
+
- **Slate**: Modern dark gray with amber accents
|
|
390
|
+
- **Regal**: Elegant dark theme with gold accents
|
|
391
|
+
- **Glassmorphism**: Frosted glass effect with purple tones
|
|
392
|
+
- **Landing Page**: Cyan accent on dark background
|
|
393
|
+
- **Editor**: VS Code inspired dark theme
|
|
394
|
+
|
|
395
|
+
Each theme provides a cohesive color palette that is applied to:
|
|
396
|
+
- Node fill colors
|
|
397
|
+
- Edge colors
|
|
398
|
+
- Background and UI elements
|
|
399
|
+
`,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
// Individual theme stories for direct access
|
|
406
|
+
export const TerminalTheme: Story = {
|
|
407
|
+
render: () => {
|
|
408
|
+
const canvas = createThemedCanvas(terminalTheme as IndustryTheme);
|
|
409
|
+
return (
|
|
410
|
+
<div style={{ backgroundColor: terminalTheme.colors.background, padding: 20 }}>
|
|
411
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
412
|
+
</div>
|
|
413
|
+
);
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
export const MatrixTheme: Story = {
|
|
418
|
+
render: () => {
|
|
419
|
+
const canvas = createThemedCanvas(matrixTheme as IndustryTheme);
|
|
420
|
+
return (
|
|
421
|
+
<div style={{ backgroundColor: matrixTheme.colors.background, padding: 20 }}>
|
|
422
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
423
|
+
</div>
|
|
424
|
+
);
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
export const SlateTheme: Story = {
|
|
429
|
+
render: () => {
|
|
430
|
+
const canvas = createThemedCanvas(slateTheme as IndustryTheme);
|
|
431
|
+
return (
|
|
432
|
+
<div style={{ backgroundColor: slateTheme.colors.background, padding: 20 }}>
|
|
433
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
434
|
+
</div>
|
|
435
|
+
);
|
|
436
|
+
},
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
export const RegalTheme: Story = {
|
|
440
|
+
render: () => {
|
|
441
|
+
const canvas = createThemedCanvas(regalTheme as IndustryTheme);
|
|
442
|
+
return (
|
|
443
|
+
<div style={{ backgroundColor: regalTheme.colors.background, padding: 20 }}>
|
|
444
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
445
|
+
</div>
|
|
446
|
+
);
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
export const GlassmorphismTheme: Story = {
|
|
451
|
+
render: () => {
|
|
452
|
+
const canvas = createThemedCanvas(glassmorphismTheme as IndustryTheme);
|
|
453
|
+
return (
|
|
454
|
+
<div style={{ backgroundColor: glassmorphismTheme.colors.background, padding: 20 }}>
|
|
455
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
456
|
+
</div>
|
|
457
|
+
);
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
export const LandingPageTheme: Story = {
|
|
462
|
+
render: () => {
|
|
463
|
+
const canvas = createThemedCanvas(landingPageTheme as IndustryTheme);
|
|
464
|
+
return (
|
|
465
|
+
<div style={{ backgroundColor: landingPageTheme.colors.background, padding: 20 }}>
|
|
466
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
467
|
+
</div>
|
|
468
|
+
);
|
|
469
|
+
},
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
export const EditorTheme: Story = {
|
|
473
|
+
render: () => {
|
|
474
|
+
const canvas = createThemedCanvas(defaultEditorTheme as IndustryTheme);
|
|
475
|
+
return (
|
|
476
|
+
<div style={{ backgroundColor: defaultEditorTheme.colors.background, padding: 20 }}>
|
|
477
|
+
<GraphRenderer canvas={canvas} width={800} height={500} />
|
|
478
|
+
</div>
|
|
479
|
+
);
|
|
480
|
+
},
|
|
481
|
+
};
|
|
@@ -3,6 +3,7 @@ import { useState } from 'react';
|
|
|
3
3
|
import { GraphRenderer } from '../components/GraphRenderer';
|
|
4
4
|
import type { ExtendedCanvas } from '@principal-ai/principal-view-core';
|
|
5
5
|
import React from 'react';
|
|
6
|
+
import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
|
|
6
7
|
|
|
7
8
|
const meta: Meta<typeof GraphRenderer> = {
|
|
8
9
|
title: 'Multi-Config/Configuration Switcher',
|
|
@@ -11,6 +12,13 @@ const meta: Meta<typeof GraphRenderer> = {
|
|
|
11
12
|
layout: 'fullscreen',
|
|
12
13
|
},
|
|
13
14
|
tags: ['autodocs'],
|
|
15
|
+
decorators: [
|
|
16
|
+
(Story) => (
|
|
17
|
+
<ThemeProvider theme={defaultEditorTheme}>
|
|
18
|
+
<Story />
|
|
19
|
+
</ThemeProvider>
|
|
20
|
+
),
|
|
21
|
+
],
|
|
14
22
|
};
|
|
15
23
|
|
|
16
24
|
export default meta;
|