@principal-ai/subsystems-react 0.51.0 → 0.51.2
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/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/pierre/PierreTrailCodeView.d.ts +1 -1
- package/dist/pierre/PierreTrailCodeView.d.ts.map +1 -1
- package/dist/pierre/PierreTrailCodeView.js +44 -21
- package/dist/pierre/PierreTrailCodeView.js.map +1 -1
- package/dist/stories/Subsystem/C4Graph/c4ProposedElements.fixture.d.ts +493 -0
- package/dist/stories/Subsystem/C4Graph/c4ProposedElements.fixture.d.ts.map +1 -0
- package/dist/stories/Subsystem/C4Graph/c4ProposedElements.fixture.js +329 -0
- package/dist/stories/Subsystem/C4Graph/c4ProposedElements.fixture.js.map +1 -0
- package/dist/subsystem/C4Graph.d.ts +2 -2
- package/dist/subsystem/C4Graph.d.ts.map +1 -1
- package/dist/subsystem/C4Graph.js +25 -16
- package/dist/subsystem/C4Graph.js.map +1 -1
- package/dist/subsystem/C4NodeCard.d.ts +85 -35
- package/dist/subsystem/C4NodeCard.d.ts.map +1 -1
- package/dist/subsystem/C4NodeCard.js +112 -83
- package/dist/subsystem/C4NodeCard.js.map +1 -1
- package/dist/subsystem/FileDrawer.d.ts.map +1 -1
- package/dist/subsystem/FileDrawer.js +20 -21
- package/dist/subsystem/FileDrawer.js.map +1 -1
- package/dist/subsystem/IssueList.d.ts.map +1 -1
- package/dist/subsystem/IssueList.js +12 -3
- package/dist/subsystem/IssueList.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +85 -7
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/c4.d.ts +273 -0
- package/dist/subsystem/c4.d.ts.map +1 -0
- package/dist/subsystem/c4.js +322 -0
- package/dist/subsystem/c4.js.map +1 -0
- package/dist/subsystem/c4Evidence.d.ts +143 -0
- package/dist/subsystem/c4Evidence.d.ts.map +1 -0
- package/dist/subsystem/c4Evidence.js +240 -0
- package/dist/subsystem/c4Evidence.js.map +1 -0
- package/dist/subsystem/model.d.ts +2 -6
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js.map +1 -1
- package/package.json +5 -4
- package/src/index.ts +26 -28
- package/src/pierre/PierreTrailCodeView.tsx +49 -21
- package/src/stories/Subsystem/C4Graph/C4NodeGallery.stories.tsx +171 -80
- package/src/stories/Subsystem/C4Graph/ProposedElements.stories.tsx +293 -0
- package/src/stories/Subsystem/C4Graph/c4ProposedElements.fixture.ts +366 -0
- package/src/stories/Subsystem/ComponentGraph/IssueOverlay.stories.tsx +1 -1
- package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +169 -3
- package/src/subsystem/C4Graph.tsx +39 -24
- package/src/subsystem/C4NodeCard.test.ts +204 -62
- package/src/subsystem/C4NodeCard.tsx +146 -101
- package/src/subsystem/FileDrawer.tsx +32 -34
- package/src/subsystem/IssueList.tsx +13 -2
- package/src/subsystem/SubsystemComponentGraph.tsx +98 -7
- package/src/subsystem/c4.test.ts +573 -0
- package/src/subsystem/c4.ts +559 -0
- package/src/subsystem/c4Evidence.test.ts +386 -0
- package/src/subsystem/c4Evidence.ts +329 -0
- package/src/subsystem/model.ts +2 -6
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.d.ts +0 -95
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.d.ts.map +0 -1
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.js +0 -340
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.js.map +0 -1
- package/dist/stories/Subsystem/C4Graph/c4Fixture.d.ts +0 -7
- package/dist/stories/Subsystem/C4Graph/c4Fixture.d.ts.map +0 -1
- package/dist/stories/Subsystem/C4Graph/c4Fixture.js +0 -7335
- package/dist/stories/Subsystem/C4Graph/c4Fixture.js.map +0 -1
- package/dist/stories/Subsystem/C4Graph/generateFixture.d.ts +0 -2
- package/dist/stories/Subsystem/C4Graph/generateFixture.d.ts.map +0 -1
- package/dist/stories/Subsystem/C4Graph/generateFixture.js +0 -145
- package/dist/stories/Subsystem/C4Graph/generateFixture.js.map +0 -1
- package/dist/subsystem/c4Associations.d.ts +0 -186
- package/dist/subsystem/c4Associations.d.ts.map +0 -1
- package/dist/subsystem/c4Associations.js +0 -284
- package/dist/subsystem/c4Associations.js.map +0 -1
- package/dist/subsystem/toC4.d.ts +0 -214
- package/dist/subsystem/toC4.d.ts.map +0 -1
- package/dist/subsystem/toC4.js +0 -282
- package/dist/subsystem/toC4.js.map +0 -1
- package/src/stories/Subsystem/C4Graph/C4Associations.stories.tsx +0 -273
- package/src/stories/Subsystem/C4Graph/C4Container.stories.tsx +0 -101
- package/src/stories/Subsystem/C4Graph/c4Associations.fixture.ts +0 -344
- package/src/stories/Subsystem/C4Graph/c4Fixture.ts +0 -7339
- package/src/stories/Subsystem/C4Graph/generateFixture.ts +0 -161
- package/src/subsystem/c4Associations.test.ts +0 -484
- package/src/subsystem/c4Associations.ts +0 -398
- package/src/subsystem/toC4.test.ts +0 -114
- package/src/subsystem/toC4.ts +0 -478
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
import { ThemeProvider, defaultEditorTheme, useTheme } from '@principal-ade/industry-theme';
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
C4NodeCard,
|
|
6
|
+
nodeStyle,
|
|
7
|
+
nodeSubtitle,
|
|
8
|
+
nodeTag,
|
|
9
|
+
nodeTypeLabel,
|
|
10
|
+
nodeShape,
|
|
11
|
+
nodeSize,
|
|
12
|
+
nodeMissing,
|
|
13
|
+
NODE_W,
|
|
14
|
+
} from '../../../subsystem/C4NodeCard';
|
|
15
|
+
import type { C4Node } from '../../../subsystem/c4';
|
|
6
16
|
|
|
7
17
|
// ---------------------------------------------------------------------------
|
|
8
18
|
// A card gallery: every C4 box variant, outside the graph.
|
|
@@ -14,6 +24,10 @@ import type { C4Node, C4ElementType } from '../../../subsystem/toC4';
|
|
|
14
24
|
// Rendering the card directly (not through React Flow) is the point: the node
|
|
15
25
|
// is a plain presentational component, so it can be reviewed and diffed
|
|
16
26
|
// without a layout engine in the way.
|
|
27
|
+
//
|
|
28
|
+
// Every card here is a flattened `C4Node` — exactly what `buildC4Model`
|
|
29
|
+
// produces from an authored element, with the per-kind fields already resolved
|
|
30
|
+
// to the one shape the card draws with.
|
|
17
31
|
// ---------------------------------------------------------------------------
|
|
18
32
|
|
|
19
33
|
const meta = {
|
|
@@ -39,33 +53,27 @@ function node(over: Partial<C4Node> & { id: string; label: string }): C4Node {
|
|
|
39
53
|
kind: 'container',
|
|
40
54
|
members: [],
|
|
41
55
|
constructs: [],
|
|
42
|
-
|
|
56
|
+
state: 'proposed',
|
|
43
57
|
...over,
|
|
44
58
|
};
|
|
45
59
|
}
|
|
46
60
|
|
|
47
|
-
const CONFIRMED = {
|
|
48
|
-
id: 'container:studio-host',
|
|
49
|
-
label: 'Studio Host',
|
|
50
|
-
type: 'application' as C4ElementType,
|
|
51
|
-
technology: 'Bun + Electrobun',
|
|
52
|
-
description: 'Runs the audit pipeline, owns the model store, serves the RPC surface.',
|
|
53
|
-
state: 'accepted' as const,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
61
|
const VARIANTS: Array<{ group: string; note: string; node: C4Node }> = [
|
|
57
62
|
// `id` on each variant is its caption key, not a component field.
|
|
63
|
+
|
|
58
64
|
// --- confirmation state: the axis that matters most --------------------
|
|
59
65
|
{
|
|
60
66
|
group: 'Confirmation state',
|
|
61
|
-
note: '
|
|
67
|
+
note: 'Solid = a person signed off. Dashed = an agent asked and nobody answered. This is the only field that changes how a box is drawn, so it is the only one a confirm UI needs to move.',
|
|
62
68
|
node: node({
|
|
63
69
|
id: 'a1',
|
|
64
|
-
label: '
|
|
65
|
-
key: 'subsystems-studio/host',
|
|
70
|
+
label: 'Subsystem Studio — host',
|
|
66
71
|
members: ['a', 'b', 'c'],
|
|
67
72
|
constructs: ['function', 'store'],
|
|
68
|
-
|
|
73
|
+
containerKind: 'application',
|
|
74
|
+
technology: 'Bun + Electrobun',
|
|
75
|
+
description: 'Runs the audit pipeline, owns the model store, serves the RPC surface.',
|
|
76
|
+
state: 'accepted',
|
|
69
77
|
}),
|
|
70
78
|
},
|
|
71
79
|
{
|
|
@@ -73,16 +81,12 @@ const VARIANTS: Array<{ group: string; note: string; node: C4Node }> = [
|
|
|
73
81
|
note: '',
|
|
74
82
|
node: node({
|
|
75
83
|
id: 'a2',
|
|
76
|
-
label: 'subsystems-
|
|
77
|
-
key: 'subsystems-core/types',
|
|
84
|
+
label: 'subsystems-react (proposed container?)',
|
|
78
85
|
members: ['x', 'y'],
|
|
79
|
-
constructs: ['
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type: 'library',
|
|
84
|
-
state: 'proposed',
|
|
85
|
-
},
|
|
86
|
+
constructs: ['function', 'interface'],
|
|
87
|
+
containerKind: 'application',
|
|
88
|
+
technology: 'React',
|
|
89
|
+
state: 'proposed',
|
|
86
90
|
}),
|
|
87
91
|
},
|
|
88
92
|
{
|
|
@@ -90,79 +94,99 @@ const VARIANTS: Array<{ group: string; note: string; node: C4Node }> = [
|
|
|
90
94
|
note: '',
|
|
91
95
|
node: node({
|
|
92
96
|
id: 'a3',
|
|
93
|
-
label: '
|
|
94
|
-
key: 'principal-studio-cli',
|
|
97
|
+
label: 'Subsystem Modeling CLI',
|
|
95
98
|
members: ['cli-create'],
|
|
96
99
|
constructs: ['function'],
|
|
100
|
+
containerKind: 'application',
|
|
101
|
+
technology: 'Node',
|
|
102
|
+
description: 'Creates and updates models from the terminal.',
|
|
103
|
+
state: 'accepted',
|
|
97
104
|
}),
|
|
98
105
|
},
|
|
99
106
|
{
|
|
100
107
|
group: '',
|
|
101
|
-
note: '',
|
|
108
|
+
note: 'Rejected elements are not drawn at all. This card exists to prove the fallback branch exists, not because a diagram ever shows one.',
|
|
102
109
|
node: node({
|
|
103
110
|
id: 'a4',
|
|
104
111
|
label: 'graphify/extract',
|
|
105
|
-
key: 'graphify/extract',
|
|
106
112
|
members: ['extract'],
|
|
107
113
|
constructs: ['function'],
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
type: 'application',
|
|
112
|
-
state: 'rejected',
|
|
113
|
-
},
|
|
114
|
+
containerKind: 'application',
|
|
115
|
+
technology: 'Bun',
|
|
116
|
+
state: 'rejected',
|
|
114
117
|
}),
|
|
115
118
|
},
|
|
116
119
|
{
|
|
117
120
|
group: '',
|
|
118
|
-
note: '',
|
|
119
|
-
node: node({
|
|
121
|
+
note: 'A box that consolidated two derived keys says so — the inputs are hidden once merged, and silently losing them would be a lie about provenance.',
|
|
122
|
+
node: node({
|
|
123
|
+
id: 'a5',
|
|
124
|
+
label: 'Subsystem Studio — host',
|
|
125
|
+
derivedFrom: ['subsystems-studio/host', 'principal-studio/host'],
|
|
126
|
+
members: ['a'],
|
|
127
|
+
constructs: ['function'],
|
|
128
|
+
containerKind: 'application',
|
|
129
|
+
technology: 'Bun + Electrobun',
|
|
130
|
+
state: 'accepted',
|
|
131
|
+
}),
|
|
120
132
|
},
|
|
121
133
|
|
|
122
|
-
// ---
|
|
134
|
+
// --- the four kinds ------------------------------------------------------
|
|
123
135
|
{
|
|
124
|
-
group: '
|
|
125
|
-
note: 'C4
|
|
136
|
+
group: 'The four kinds',
|
|
137
|
+
note: 'C4 has a closed vocabulary: software system, container, component, code. Outside the boundary it adds people. There is no "library" kind — c4model says a module typically is not an element at all, so a library is a review comment, not a fifth box.',
|
|
126
138
|
node: node({
|
|
127
139
|
id: 'b1',
|
|
128
140
|
label: 'Subsystem model store',
|
|
129
141
|
members: ['s1'],
|
|
130
142
|
constructs: ['store'],
|
|
131
|
-
|
|
143
|
+
containerKind: 'data-store',
|
|
144
|
+
technology: 'JSON files on disk',
|
|
145
|
+
description: 'Every stored model plus its index.',
|
|
146
|
+
state: 'accepted',
|
|
132
147
|
}),
|
|
133
148
|
},
|
|
134
149
|
{
|
|
135
150
|
group: '',
|
|
136
|
-
note: '',
|
|
151
|
+
note: 'A queue or topic is a data store, not its own kind. C4 says an individual queue is a bucket of messages — a data store — and that the message bus itself is not a container at all. The queue-ness lives in the label and technology.',
|
|
137
152
|
node: node({
|
|
138
153
|
id: 'b2',
|
|
139
154
|
label: 'Audit correction queue',
|
|
140
155
|
members: ['s2'],
|
|
141
156
|
constructs: ['store'],
|
|
142
|
-
|
|
157
|
+
containerKind: 'data-store',
|
|
158
|
+
technology: 'agent session transport',
|
|
159
|
+
description: 'Proposals awaiting a human decision.',
|
|
160
|
+
state: 'accepted',
|
|
143
161
|
}),
|
|
144
162
|
},
|
|
145
163
|
{
|
|
146
164
|
group: '',
|
|
147
|
-
note: '',
|
|
165
|
+
note: 'A component is a real square, not a smaller rectangle. Border weight drops to 1px as a second signal, so the level survives grayscale.',
|
|
148
166
|
node: node({
|
|
149
167
|
id: 'b3',
|
|
150
|
-
label: '
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
label: 'Boundary layout builder',
|
|
169
|
+
kind: 'component',
|
|
170
|
+
parentId: 'container:shared-ui',
|
|
171
|
+
members: ['h1', 'h2'],
|
|
172
|
+
constructs: ['function'],
|
|
173
|
+
technology: 'React + ELK',
|
|
174
|
+
description: 'Turns claims into nested compound frames.',
|
|
175
|
+
state: 'accepted',
|
|
154
176
|
}),
|
|
155
177
|
},
|
|
156
178
|
{
|
|
157
179
|
group: '',
|
|
158
|
-
note: '',
|
|
180
|
+
note: 'An external system keeps the rectangle but goes dashed — it is outside the boundary, which is a different statement from "inside, and unconfirmed".',
|
|
159
181
|
node: node({
|
|
160
182
|
id: 'b4',
|
|
161
183
|
label: 'OpenCode v2 service',
|
|
162
|
-
kind: 'external',
|
|
184
|
+
kind: 'external-system',
|
|
163
185
|
members: ['oc2'],
|
|
164
186
|
constructs: ['external'],
|
|
165
|
-
|
|
187
|
+
technology: 'HTTP',
|
|
188
|
+
description: 'Runs maintain agent sessions.',
|
|
189
|
+
state: 'accepted',
|
|
166
190
|
}),
|
|
167
191
|
},
|
|
168
192
|
{
|
|
@@ -171,24 +195,26 @@ const VARIANTS: Array<{ group: string; note: string; node: C4Node }> = [
|
|
|
171
195
|
node: node({
|
|
172
196
|
id: 'b5',
|
|
173
197
|
label: 'Maintain operator',
|
|
174
|
-
kind: '
|
|
198
|
+
kind: 'person',
|
|
175
199
|
members: ['a'],
|
|
176
200
|
constructs: ['custom_entity'],
|
|
177
|
-
|
|
201
|
+
description: 'Reviews and accepts correction proposals.',
|
|
202
|
+
state: 'proposed',
|
|
178
203
|
}),
|
|
179
204
|
},
|
|
180
205
|
|
|
181
206
|
// --- the gaps C4 keeps asking about ------------------------------------
|
|
182
207
|
{
|
|
183
208
|
group: 'Notation gaps',
|
|
184
|
-
note: 'C4 requires technology and description on every container. A
|
|
209
|
+
note: 'C4 requires technology and description on every container. A box that never got either says so on its face rather than looking finished — and `technology` is required by the type, so the only way to have the gap is an empty string.',
|
|
185
210
|
node: node({
|
|
186
211
|
id: 'c1',
|
|
187
|
-
label: '
|
|
188
|
-
key: 'site/web',
|
|
212
|
+
label: 'In-memory renderer state',
|
|
189
213
|
members: ['w1', 'w2', 'w3'],
|
|
190
|
-
constructs: ['
|
|
191
|
-
|
|
214
|
+
constructs: ['store'],
|
|
215
|
+
containerKind: 'application',
|
|
216
|
+
technology: '',
|
|
217
|
+
state: 'accepted',
|
|
192
218
|
}),
|
|
193
219
|
},
|
|
194
220
|
{
|
|
@@ -196,25 +222,50 @@ const VARIANTS: Array<{ group: string; note: string; node: C4Node }> = [
|
|
|
196
222
|
note: '',
|
|
197
223
|
node: node({
|
|
198
224
|
id: 'c2',
|
|
199
|
-
label: '
|
|
200
|
-
key: 'subsystems-studio/renderer',
|
|
225
|
+
label: 'Subsystem Studio — renderer',
|
|
201
226
|
members: ['r1', 'r2'],
|
|
202
227
|
constructs: ['function'],
|
|
203
|
-
|
|
228
|
+
containerKind: 'application',
|
|
229
|
+
technology: 'React 19',
|
|
230
|
+
state: 'accepted',
|
|
204
231
|
}),
|
|
205
232
|
},
|
|
206
233
|
|
|
207
|
-
// ---
|
|
234
|
+
// --- the pair that was confusing, side by side ------------------------
|
|
235
|
+
{
|
|
236
|
+
group: 'Container vs component',
|
|
237
|
+
note: 'The case that started this. Same border colour and same state, previously identical. Now a wide rectangle says "container" and a square says "component", so the level is readable before the text is.',
|
|
238
|
+
node: node({
|
|
239
|
+
id: 'e1',
|
|
240
|
+
label: 'Subsystem Studio — host',
|
|
241
|
+
members: ['a', 'b', 'c'],
|
|
242
|
+
constructs: ['function', 'store'],
|
|
243
|
+
containerKind: 'application',
|
|
244
|
+
technology: 'Bun + Electrobun',
|
|
245
|
+
description: 'Runs the audit pipeline.',
|
|
246
|
+
state: 'accepted',
|
|
247
|
+
}),
|
|
248
|
+
},
|
|
208
249
|
{
|
|
209
|
-
group: '
|
|
210
|
-
note: '
|
|
250
|
+
group: '',
|
|
251
|
+
note: '',
|
|
211
252
|
node: node({
|
|
212
|
-
id: '
|
|
213
|
-
label: '
|
|
253
|
+
id: 'e2',
|
|
254
|
+
label: 'Studio Host',
|
|
214
255
|
kind: 'component',
|
|
215
|
-
|
|
256
|
+
parentId: 'container:studio-host',
|
|
257
|
+
members: ['h1'],
|
|
216
258
|
constructs: ['function'],
|
|
217
|
-
|
|
259
|
+
technology: 'Bun',
|
|
260
|
+
description: 'Resolves the model root and registers repos.',
|
|
261
|
+
state: 'accepted',
|
|
262
|
+
component: {
|
|
263
|
+
alias: 'h1',
|
|
264
|
+
name: 'StudioHost',
|
|
265
|
+
construct: 'function',
|
|
266
|
+
file: 'packages/subsystems-studio/src/bun/index.ts',
|
|
267
|
+
purl: 'pkg:x#packages/subsystems-studio/src/bun/index.ts',
|
|
268
|
+
},
|
|
218
269
|
}),
|
|
219
270
|
},
|
|
220
271
|
];
|
|
@@ -242,6 +293,8 @@ function Case({ caption, children }: { caption: string; children: React.ReactNod
|
|
|
242
293
|
return (
|
|
243
294
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 5, alignItems: 'flex-start' }}>
|
|
244
295
|
{children}
|
|
296
|
+
{/* Caption spans the container box so every card's caption starts at the
|
|
297
|
+
same x — otherwise the narrower square column looks misaligned. */}
|
|
245
298
|
<span
|
|
246
299
|
style={{
|
|
247
300
|
fontFamily: 'monospace',
|
|
@@ -257,14 +310,16 @@ function Case({ caption, children }: { caption: string; children: React.ReactNod
|
|
|
257
310
|
);
|
|
258
311
|
}
|
|
259
312
|
|
|
313
|
+
const KINDS = ['container', 'component', 'external-system', 'person'] as const;
|
|
314
|
+
|
|
260
315
|
function Gallery() {
|
|
261
316
|
const { theme } = useTheme();
|
|
262
317
|
const muted = theme.colors.textMuted ?? '#9a9aa0';
|
|
263
318
|
|
|
264
319
|
const legend: Array<[string, string]> = [
|
|
265
|
-
['accepted', nodeStyle({ id: 'x',
|
|
266
|
-
['proposed', nodeStyle({ id: 'x',
|
|
267
|
-
['
|
|
320
|
+
['accepted', nodeStyle(node({ id: 'x', label: '', state: 'accepted' }), theme).color],
|
|
321
|
+
['proposed', nodeStyle(node({ id: 'x', label: '', state: 'proposed' }), theme).color],
|
|
322
|
+
['rejected', nodeStyle(node({ id: 'x', label: '', state: 'rejected' }), theme).color],
|
|
268
323
|
];
|
|
269
324
|
|
|
270
325
|
let currentGroup = '';
|
|
@@ -277,13 +332,45 @@ function Gallery() {
|
|
|
277
332
|
encoding.
|
|
278
333
|
</p>
|
|
279
334
|
|
|
280
|
-
<div style={{
|
|
281
|
-
{
|
|
282
|
-
<span
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
335
|
+
<div style={{ fontFamily: 'monospace', fontSize: 11, marginBottom: 26, lineHeight: 1.9 }}>
|
|
336
|
+
<div style={{ display: 'flex', gap: 20, flexWrap: 'wrap' }}>
|
|
337
|
+
<span style={{ color: '#e8e8ea' }}>KIND — shape, icon, and border weight</span>
|
|
338
|
+
</div>
|
|
339
|
+
<div style={{ display: 'flex', gap: 18, flexWrap: 'wrap', marginTop: 4 }}>
|
|
340
|
+
{KINDS.map((kind) => {
|
|
341
|
+
const s = nodeShape(node({ id: 'x', label: '', kind }));
|
|
342
|
+
const size = nodeSize(node({ id: 'x', label: '', kind }));
|
|
343
|
+
const color = nodeStyle(node({ id: 'x', label: '', kind }), theme).color;
|
|
344
|
+
const weight = kind === 'component' ? 1 : 2;
|
|
345
|
+
// Drawn at the real aspect ratio — the whole signal is square vs
|
|
346
|
+
// rectangle, so a legend that flattened both would lie.
|
|
347
|
+
return (
|
|
348
|
+
<span key={kind} style={{ display: 'flex', alignItems: 'center', gap: 6, color: muted }}>
|
|
349
|
+
<span
|
|
350
|
+
style={{
|
|
351
|
+
width: 28,
|
|
352
|
+
height: Math.round((28 * size.height) / size.width),
|
|
353
|
+
borderRadius: Math.min(s.radius, 9),
|
|
354
|
+
border: `${weight} ${s.dash} ${color}`,
|
|
355
|
+
display: 'inline-block',
|
|
356
|
+
}}
|
|
357
|
+
/>
|
|
358
|
+
{kind}
|
|
359
|
+
</span>
|
|
360
|
+
);
|
|
361
|
+
})}
|
|
362
|
+
</div>
|
|
363
|
+
<div style={{ display: 'flex', gap: 20, flexWrap: 'wrap', marginTop: 14 }}>
|
|
364
|
+
<span style={{ color: '#e8e8ea' }}>CONFIRMATION — colour and dash, never the shape</span>
|
|
365
|
+
</div>
|
|
366
|
+
<div style={{ display: 'flex', gap: 18, flexWrap: 'wrap', marginTop: 4 }}>
|
|
367
|
+
{legend.map(([name, color]) => (
|
|
368
|
+
<span key={name} style={{ display: 'flex', alignItems: 'center', gap: 6, color: muted }}>
|
|
369
|
+
<span style={{ width: 22, height: 0, borderTop: `3px solid ${color}`, display: 'inline-block' }} />
|
|
370
|
+
{name}
|
|
371
|
+
</span>
|
|
372
|
+
))}
|
|
373
|
+
</div>
|
|
287
374
|
</div>
|
|
288
375
|
|
|
289
376
|
<Row>
|
|
@@ -291,14 +378,18 @@ function Gallery() {
|
|
|
291
378
|
const showHeader = v.group && v.group !== currentGroup;
|
|
292
379
|
if (v.group) currentGroup = v.group;
|
|
293
380
|
return (
|
|
294
|
-
<React.Fragment key={v.
|
|
381
|
+
<React.Fragment key={v.node.id}>
|
|
295
382
|
{showHeader && (
|
|
296
383
|
<div style={{ width: '100%' }}>
|
|
297
384
|
<Section title={v.group} note={v.note} />
|
|
298
385
|
</div>
|
|
299
386
|
)}
|
|
300
387
|
<Case
|
|
301
|
-
caption={`${v.node.id} ·
|
|
388
|
+
caption={`${v.node.id} · "${nodeTag(v.node)}"${
|
|
389
|
+
nodeTypeLabel(v.node) ? ` / ${nodeTypeLabel(v.node)}` : ''
|
|
390
|
+
} · ${v.node.state} · ${nodeShape(v.node).kind} ${
|
|
391
|
+
nodeSize(v.node).width
|
|
392
|
+
}×${nodeSize(v.node).height} · ${nodeSubtitle(v.node)}${
|
|
302
393
|
nodeMissing(v.node).length ? ` · missing ${nodeMissing(v.node).join('+')}` : ''
|
|
303
394
|
}`}
|
|
304
395
|
>
|