@principal-ai/subsystems-react 0.49.0 → 0.51.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.
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/pierre/PierreFileView.d.ts +1 -1
- package/dist/pierre/PierreFileView.d.ts.map +1 -1
- package/dist/pierre/PierreFileView.js +2 -1
- package/dist/pierre/PierreFileView.js.map +1 -1
- package/dist/pierre/PierreSnippetView.d.ts +1 -1
- package/dist/pierre/PierreSnippetView.d.ts.map +1 -1
- package/dist/pierre/PierreSnippetView.js +2 -1
- package/dist/pierre/PierreSnippetView.js.map +1 -1
- package/dist/pierre/PierreTrailCodeView.d.ts +7 -1
- package/dist/pierre/PierreTrailCodeView.d.ts.map +1 -1
- package/dist/pierre/PierreTrailCodeView.js +71 -18
- package/dist/pierre/PierreTrailCodeView.js.map +1 -1
- package/dist/pierre/pierreBackground.d.ts +36 -2
- package/dist/pierre/pierreBackground.d.ts.map +1 -1
- package/dist/pierre/pierreBackground.js +40 -13
- package/dist/pierre/pierreBackground.js.map +1 -1
- package/dist/pierre/visibleStep.d.ts +48 -0
- package/dist/pierre/visibleStep.d.ts.map +1 -0
- package/dist/pierre/visibleStep.js +53 -0
- package/dist/pierre/visibleStep.js.map +1 -0
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.d.ts +95 -0
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.d.ts.map +1 -0
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.js +340 -0
- package/dist/stories/Subsystem/C4Graph/c4Associations.fixture.js.map +1 -0
- package/dist/stories/Subsystem/C4Graph/c4Fixture.d.ts +4 -0
- package/dist/stories/Subsystem/C4Graph/c4Fixture.d.ts.map +1 -1
- package/dist/stories/Subsystem/C4Graph/c4Fixture.js +7334 -1
- package/dist/stories/Subsystem/C4Graph/c4Fixture.js.map +1 -1
- package/dist/stories/Subsystem/C4Graph/generateFixture.d.ts +2 -0
- package/dist/stories/Subsystem/C4Graph/generateFixture.d.ts.map +1 -0
- package/dist/stories/Subsystem/C4Graph/generateFixture.js +145 -0
- package/dist/stories/Subsystem/C4Graph/generateFixture.js.map +1 -0
- package/dist/subsystem/C4Graph.d.ts.map +1 -1
- package/dist/subsystem/C4Graph.js +16 -60
- package/dist/subsystem/C4Graph.js.map +1 -1
- package/dist/subsystem/C4NodeCard.d.ts +84 -0
- package/dist/subsystem/C4NodeCard.d.ts.map +1 -0
- package/dist/subsystem/C4NodeCard.js +229 -0
- package/dist/subsystem/C4NodeCard.js.map +1 -0
- package/dist/subsystem/DiagnosticToggle.d.ts +8 -1
- package/dist/subsystem/DiagnosticToggle.d.ts.map +1 -1
- package/dist/subsystem/DiagnosticToggle.js +40 -6
- package/dist/subsystem/DiagnosticToggle.js.map +1 -1
- package/dist/subsystem/FileDrawer.d.ts +10 -1
- package/dist/subsystem/FileDrawer.d.ts.map +1 -1
- package/dist/subsystem/FileDrawer.js +61 -40
- package/dist/subsystem/FileDrawer.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts +6 -0
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +21 -10
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/c4Associations.d.ts +186 -0
- package/dist/subsystem/c4Associations.d.ts.map +1 -0
- package/dist/subsystem/c4Associations.js +284 -0
- package/dist/subsystem/c4Associations.js.map +1 -0
- package/dist/subsystem/model.d.ts +25 -1
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js +15 -0
- package/dist/subsystem/model.js.map +1 -1
- package/dist/subsystem/nodes.d.ts.map +1 -1
- package/dist/subsystem/nodes.js +78 -7
- package/dist/subsystem/nodes.js.map +1 -1
- package/dist/subsystem/toC4.d.ts +119 -0
- package/dist/subsystem/toC4.d.ts.map +1 -1
- package/dist/subsystem/toC4.js +95 -5
- package/dist/subsystem/toC4.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +39 -0
- package/src/pierre/PierreFileView.tsx +2 -1
- package/src/pierre/PierreSnippetView.tsx +2 -1
- package/src/pierre/PierreTrailCodeView.tsx +81 -22
- package/src/pierre/pierreBackground.ts +62 -12
- package/src/pierre/visibleStep.test.ts +108 -0
- package/src/pierre/visibleStep.ts +76 -0
- package/src/stories/Subsystem/C4Graph/C4Associations.stories.tsx +273 -0
- package/src/stories/Subsystem/C4Graph/C4NodeGallery.stories.tsx +325 -0
- package/src/stories/Subsystem/C4Graph/c4Associations.fixture.ts +344 -0
- package/src/stories/Subsystem/C4Graph/c4Fixture.ts +7337 -4
- package/src/stories/Subsystem/C4Graph/generateFixture.ts +161 -0
- package/src/stories/Subsystem/ComponentGraph/Deprecated.stories.tsx +358 -0
- package/src/stories/Subsystem/ComponentGraph/Diagnostics.stories.tsx +27 -2
- package/src/stories/Subsystem/ComponentGraph/{Flows.stories.tsx → Trails.stories.tsx} +10 -4
- package/src/subsystem/C4Graph.tsx +51 -92
- package/src/subsystem/C4NodeCard.test.ts +196 -0
- package/src/subsystem/C4NodeCard.tsx +307 -0
- package/src/subsystem/DiagnosticToggle.tsx +58 -4
- package/src/subsystem/FileDrawer.tsx +112 -63
- package/src/subsystem/SubsystemComponentGraph.tsx +29 -5
- package/src/subsystem/c4Associations.test.ts +484 -0
- package/src/subsystem/c4Associations.ts +398 -0
- package/src/subsystem/model.ts +34 -1
- package/src/subsystem/nodes.tsx +124 -5
- package/src/subsystem/toC4.ts +210 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toC4.d.ts","sourceRoot":"","sources":["../../src/subsystem/toC4.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE1E,4DAA4D;AAC5D,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;AAEjF,+EAA+E;AAC/E,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;AAE/C,mDAAmD;AACnD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qEAAqE;IACrE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wEAAwE;AACxE,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,+DAA+D;AAC/D,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"toC4.d.ts","sourceRoot":"","sources":["../../src/subsystem/toC4.ts"],"names":[],"mappings":"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"}
|
package/dist/subsystem/toC4.js
CHANGED
|
@@ -25,6 +25,40 @@ const UNASSIGNED = '(unassigned)';
|
|
|
25
25
|
export function isGroundedComponent(c) {
|
|
26
26
|
return c.construct !== 'external' && c.construct !== 'custom_entity';
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Index confirmed associations by the derived keys they claim.
|
|
30
|
+
*
|
|
31
|
+
* First writer wins on a contested key so the result does not depend on array
|
|
32
|
+
* order, and the loser is reported so the conflict is visible rather than
|
|
33
|
+
* silently dropped.
|
|
34
|
+
*/
|
|
35
|
+
export function indexAssociations(associations) {
|
|
36
|
+
const byKey = new Map();
|
|
37
|
+
const contested = [];
|
|
38
|
+
if (!associations)
|
|
39
|
+
return { byKey, contested };
|
|
40
|
+
// Stable order: accepted before proposed, so a confirmed decision outranks a
|
|
41
|
+
// speculative one for the same key.
|
|
42
|
+
const ordered = [...associations].sort((a, b) => {
|
|
43
|
+
const rank = (s) => (s === 'accepted' ? 0 : s === 'proposed' ? 1 : 2);
|
|
44
|
+
return rank(a.state) - rank(b.state) || a.id.localeCompare(b.id);
|
|
45
|
+
});
|
|
46
|
+
for (const a of ordered) {
|
|
47
|
+
for (const key of a.sourceKeys) {
|
|
48
|
+
const existing = byKey.get(key);
|
|
49
|
+
if (existing && existing.id !== a.id) {
|
|
50
|
+
contested.push({ key, kept: existing.id, dropped: a.id });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
byKey.set(key, a);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { byKey, contested };
|
|
57
|
+
}
|
|
58
|
+
/** True when a resolved association means this box should not be drawn. */
|
|
59
|
+
function isSuppressed(a) {
|
|
60
|
+
return a?.state === 'rejected';
|
|
61
|
+
}
|
|
28
62
|
/** `owner/name` from a purl, trimmed of scheme and fragment. */
|
|
29
63
|
export function labelFromPurl(purl) {
|
|
30
64
|
const base = purl.replace(/^external:/, '').split('#')[0]?.trim() ?? '';
|
|
@@ -60,6 +94,12 @@ export function toC4(doc, options = {}) {
|
|
|
60
94
|
const view = options.view ?? 'container';
|
|
61
95
|
const repoKey = options.repoKey ?? deriveRepoKey(doc) ?? 'system';
|
|
62
96
|
const systemId = `system:${repoKey}`;
|
|
97
|
+
const { byKey: assocByKey } = indexAssociations(options.associations);
|
|
98
|
+
// Id -> association, so a container frame can be labelled from its
|
|
99
|
+
// association even when no node exists for it (component view).
|
|
100
|
+
const assocById = new Map();
|
|
101
|
+
for (const a of options.associations ?? [])
|
|
102
|
+
assocById.set(a.id, a);
|
|
63
103
|
const system = {
|
|
64
104
|
id: systemId,
|
|
65
105
|
kind: 'system',
|
|
@@ -73,12 +113,32 @@ export function toC4(doc, options = {}) {
|
|
|
73
113
|
const ownerOf = new Map();
|
|
74
114
|
const containerNodeId = (key) => `container:${key}`;
|
|
75
115
|
const componentNodeId = (alias) => `component:${alias}`;
|
|
116
|
+
/**
|
|
117
|
+
* Resolve one derived container key into the box that should carry it.
|
|
118
|
+
*
|
|
119
|
+
* An accepted association wins: its id becomes the node id, so every key it
|
|
120
|
+
* claims rolls into one node (that is the dedup), and its label / type /
|
|
121
|
+
* technology / description become the node's presentation. A rejected one
|
|
122
|
+
* means the box is not drawn at all. Unclaimed keys keep the raw derived
|
|
123
|
+
* behaviour, so the projection is still useful with zero associations.
|
|
124
|
+
*/
|
|
125
|
+
const resolveContainer = (key) => {
|
|
126
|
+
const assoc = assocByKey.get(key);
|
|
127
|
+
if (assoc && assoc.level === 'container') {
|
|
128
|
+
return { id: assoc.id, label: assoc.label, assoc };
|
|
129
|
+
}
|
|
130
|
+
if (view === 'component') {
|
|
131
|
+
return { id: containerNodeId(key), label: key === UNASSIGNED ? 'Unassigned' : key, assoc: undefined };
|
|
132
|
+
}
|
|
133
|
+
return { id: containerNodeId(key), label: key === UNASSIGNED ? 'Unassigned' : key, assoc: undefined };
|
|
134
|
+
};
|
|
76
135
|
for (const c of doc.components) {
|
|
77
136
|
let id;
|
|
78
137
|
let kind;
|
|
79
138
|
let label;
|
|
80
139
|
let parentId;
|
|
81
140
|
let key;
|
|
141
|
+
let assoc;
|
|
82
142
|
if (c.construct === 'external') {
|
|
83
143
|
key = externalKey(c);
|
|
84
144
|
id = `external:${key}`;
|
|
@@ -93,17 +153,25 @@ export function toC4(doc, options = {}) {
|
|
|
93
153
|
}
|
|
94
154
|
else if (view === 'component') {
|
|
95
155
|
key = containerKey(c);
|
|
156
|
+
const resolved = resolveContainer(key);
|
|
157
|
+
if (isSuppressed(resolved.assoc))
|
|
158
|
+
continue;
|
|
96
159
|
id = componentNodeId(c.alias);
|
|
97
160
|
kind = 'component';
|
|
98
161
|
label = c.name;
|
|
99
|
-
parentId =
|
|
162
|
+
parentId = resolved.id;
|
|
163
|
+
assoc = undefined; // the component itself has no association
|
|
100
164
|
}
|
|
101
165
|
else {
|
|
102
166
|
key = containerKey(c);
|
|
103
|
-
|
|
167
|
+
const resolved = resolveContainer(key);
|
|
168
|
+
if (isSuppressed(resolved.assoc))
|
|
169
|
+
continue;
|
|
170
|
+
id = resolved.id;
|
|
104
171
|
kind = 'container';
|
|
105
|
-
label =
|
|
172
|
+
label = resolved.label;
|
|
106
173
|
parentId = systemId;
|
|
174
|
+
assoc = resolved.assoc;
|
|
107
175
|
}
|
|
108
176
|
ownerOf.set(c.alias, id);
|
|
109
177
|
let node = nodes.get(id);
|
|
@@ -117,7 +185,12 @@ export function toC4(doc, options = {}) {
|
|
|
117
185
|
members: [],
|
|
118
186
|
constructs: [],
|
|
119
187
|
isStore: false,
|
|
188
|
+
// A merged box is built from several derived keys. Track them as a
|
|
189
|
+
// set so the confirm UI can show what was folded together — without
|
|
190
|
+
// this, the accumulation would run once per member, not per key.
|
|
191
|
+
...(assoc && assoc.sourceKeys.length > 1 ? { sourceKeys: [...assoc.sourceKeys] } : {}),
|
|
120
192
|
...(kind === 'component' ? { component: c } : {}),
|
|
193
|
+
...(assoc ? { decoration: toDecoration(assoc) } : {}),
|
|
121
194
|
};
|
|
122
195
|
nodes.set(id, node);
|
|
123
196
|
}
|
|
@@ -133,6 +206,9 @@ export function toC4(doc, options = {}) {
|
|
|
133
206
|
}
|
|
134
207
|
// --- Groups (compound frames) ------------------------------------------
|
|
135
208
|
const groups = [];
|
|
209
|
+
const labelForContainerId = (id) => nodes.get(id)?.label ??
|
|
210
|
+
assocById.get(id)?.label ??
|
|
211
|
+
(id.startsWith('container:') ? id.slice('container:'.length) : id);
|
|
136
212
|
if (view === 'container') {
|
|
137
213
|
const containerIds = [...nodes.values()].filter((n) => n.kind === 'container').map((n) => n.id);
|
|
138
214
|
if (containerIds.length > 0) {
|
|
@@ -150,8 +226,7 @@ export function toC4(doc, options = {}) {
|
|
|
150
226
|
}
|
|
151
227
|
const containerIds = [];
|
|
152
228
|
for (const [id, memberIds] of byContainer) {
|
|
153
|
-
|
|
154
|
-
groups.push({ id, kind: 'container', label: label === UNASSIGNED ? 'Unassigned' : label, parentId: systemId, memberIds });
|
|
229
|
+
groups.push({ id, kind: 'container', label: labelForContainerId(id), parentId: systemId, memberIds });
|
|
155
230
|
containerIds.push(id);
|
|
156
231
|
}
|
|
157
232
|
if (containerIds.length > 0) {
|
|
@@ -163,6 +238,10 @@ export function toC4(doc, options = {}) {
|
|
|
163
238
|
const addEdge = (bucket, source, target, kind, mechanism) => {
|
|
164
239
|
if (!source || !target || source === target)
|
|
165
240
|
return;
|
|
241
|
+
// An endpoint whose box was rejected has no owner; the edge cannot be
|
|
242
|
+
// drawn, so drop it rather than inventing a dangling arrow.
|
|
243
|
+
if (!nodes.has(source) || !nodes.has(target))
|
|
244
|
+
return;
|
|
166
245
|
const key = `${source}\0${target}`;
|
|
167
246
|
let edge = bucket.get(key);
|
|
168
247
|
if (!edge) {
|
|
@@ -189,4 +268,15 @@ export function toC4(doc, options = {}) {
|
|
|
189
268
|
edges,
|
|
190
269
|
};
|
|
191
270
|
}
|
|
271
|
+
/** Project an association down to the attributes a node carries. */
|
|
272
|
+
function toDecoration(a) {
|
|
273
|
+
return {
|
|
274
|
+
id: a.id,
|
|
275
|
+
label: a.label,
|
|
276
|
+
type: a.type,
|
|
277
|
+
technology: a.technology,
|
|
278
|
+
description: a.description,
|
|
279
|
+
state: a.state,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
192
282
|
//# sourceMappingURL=toC4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toC4.js","sourceRoot":"","sources":["../../src/subsystem/toC4.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"toC4.js","sourceRoot":"","sources":["../../src/subsystem/toC4.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principal-ai/subsystems-react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React UI for Subsystem Models
|
|
3
|
+
"version": "0.51.0",
|
|
4
|
+
"description": "React UI for Subsystem Models \u2014 graph, Pierre code views, and session-event feeds",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
package/src/index.ts
CHANGED
|
@@ -239,6 +239,45 @@ export type {
|
|
|
239
239
|
SubsystemSignatureClaim,
|
|
240
240
|
SubsystemSignatureParameter,
|
|
241
241
|
} from './subsystem/model';
|
|
242
|
+
// --- C4 projection + the confirmed association layer ------------------
|
|
243
|
+
export { C4Graph } from './subsystem/C4Graph';
|
|
244
|
+
export type { C4GraphProps } from './subsystem/C4Graph';
|
|
245
|
+
export { C4NodeCard, nodeStyle, nodeSubtitle, nodeTag, nodeMissing, NODE_W, NODE_H } from './subsystem/C4NodeCard';
|
|
246
|
+
export type { C4NodeCardProps, NodeStyle } from './subsystem/C4NodeCard';
|
|
247
|
+
export {
|
|
248
|
+
toC4,
|
|
249
|
+
isGroundedComponent,
|
|
250
|
+
labelFromPurl,
|
|
251
|
+
deriveRepoKey,
|
|
252
|
+
indexAssociations,
|
|
253
|
+
} from './subsystem/toC4';
|
|
254
|
+
export type {
|
|
255
|
+
C4Kind,
|
|
256
|
+
C4View,
|
|
257
|
+
C4Node,
|
|
258
|
+
C4Group,
|
|
259
|
+
C4Edge,
|
|
260
|
+
C4Model,
|
|
261
|
+
C4Decoration,
|
|
262
|
+
C4ElementType,
|
|
263
|
+
C4Association,
|
|
264
|
+
C4AssociationState,
|
|
265
|
+
ToC4Options,
|
|
266
|
+
} from './subsystem/toC4';
|
|
267
|
+
export {
|
|
268
|
+
deriveConcerns,
|
|
269
|
+
suggestMerges,
|
|
270
|
+
buildAssociations,
|
|
271
|
+
mergeAssociations,
|
|
272
|
+
associationWeight,
|
|
273
|
+
summarizeAssociations,
|
|
274
|
+
} from './subsystem/c4Associations';
|
|
275
|
+
export type {
|
|
276
|
+
C4AssociationSet,
|
|
277
|
+
C4AssociationReason,
|
|
278
|
+
C4ConcernKind,
|
|
279
|
+
C4MemberView,
|
|
280
|
+
} from './subsystem/c4Associations';
|
|
242
281
|
export {
|
|
243
282
|
constructBadgeLabel,
|
|
244
283
|
constructBadgeColor,
|
|
@@ -33,10 +33,11 @@ export function PierreFileView({
|
|
|
33
33
|
filePath,
|
|
34
34
|
fileName,
|
|
35
35
|
readFile,
|
|
36
|
-
background,
|
|
36
|
+
background: backgroundProp,
|
|
37
37
|
focusLine,
|
|
38
38
|
}: PierreFileViewProps) {
|
|
39
39
|
const { theme } = useTheme();
|
|
40
|
+
const background = backgroundProp ?? theme.colors.background;
|
|
40
41
|
const [contents, setContents] = useState<string | null>(null);
|
|
41
42
|
const [error, setError] = useState<string | null>(null);
|
|
42
43
|
// Pierre highlights on the main thread with no worker pool: a cold first
|
|
@@ -47,9 +47,10 @@ export function PierreSnippetView({
|
|
|
47
47
|
focusLine,
|
|
48
48
|
contextLines = 2,
|
|
49
49
|
readFile,
|
|
50
|
-
background,
|
|
50
|
+
background: backgroundProp,
|
|
51
51
|
}: PierreSnippetViewProps) {
|
|
52
52
|
const { theme } = useTheme();
|
|
53
|
+
const background = backgroundProp ?? theme.colors.background;
|
|
53
54
|
const [contents, setContents] = useState<string | null>(null);
|
|
54
55
|
const [error, setError] = useState<string | null>(null);
|
|
55
56
|
// Warm the shared highlighter before mounting <File>; a cold first render
|
|
@@ -42,6 +42,7 @@ import type { SubsystemOpenFileOptions } from '../subsystem/declarationRef';
|
|
|
42
42
|
import { buildPierreOptions, PIERRE_FILE_STYLE } from './pierreBackground';
|
|
43
43
|
import { pierreLangForPath } from './pierreFileLang';
|
|
44
44
|
import { resolvePierreSyntaxThemeName } from './pierreSyntaxTheme';
|
|
45
|
+
import { resolveVisibleStepIndex, type VisibleStepRect } from './visibleStep';
|
|
45
46
|
import { fileUnavailableNotice, isFileUnavailableError } from './fileAvailability';
|
|
46
47
|
import {
|
|
47
48
|
remapSnippetLineNumbers,
|
|
@@ -67,6 +68,16 @@ function stepIndexFromItemContext(context: unknown): number | null {
|
|
|
67
68
|
return Number.isFinite(index) ? index : null;
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Assumed height of the compact file header, in px.
|
|
73
|
+
*
|
|
74
|
+
* Must track the header chrome passed to `buildPierreOptions` (fontSizes[0] at
|
|
75
|
+
* line-height 1.15 plus 2px vertical padding) — CodeView sizes its
|
|
76
|
+
* virtualization window and sticky offset from this, and the library's own
|
|
77
|
+
* default of 44 is more than double the compact header.
|
|
78
|
+
*/
|
|
79
|
+
const TRAIL_HEADER_HEIGHT = 18;
|
|
80
|
+
|
|
70
81
|
/** Pointer/dotted-underline affordance for a clickable construct token. */
|
|
71
82
|
function paintSymbolToken(el: HTMLElement | undefined, active: boolean): void {
|
|
72
83
|
if (el == null) return;
|
|
@@ -88,6 +99,12 @@ export interface PierreTrailCodeViewProps {
|
|
|
88
99
|
background?: string;
|
|
89
100
|
/** Open the step's full source file (header button or double-click snippet body). */
|
|
90
101
|
onOpenFile?: (path: string, opts?: SubsystemOpenFileOptions) => void;
|
|
102
|
+
/**
|
|
103
|
+
* Fires when scrolling brings a different step to the top of the view, with
|
|
104
|
+
* that step's index. Drives a progress readout that tracks the viewport
|
|
105
|
+
* rather than the selected step. Only fires on change, not per scroll event.
|
|
106
|
+
*/
|
|
107
|
+
onVisibleStepChange?: (index: number) => void;
|
|
91
108
|
/**
|
|
92
109
|
* Aliases of components marked `proposed`. A step whose file can't be read
|
|
93
110
|
* but whose endpoint is proposed reads as "planned" rather than "missing".
|
|
@@ -193,12 +210,15 @@ export function PierreTrailCodeView({
|
|
|
193
210
|
contextLines = 8,
|
|
194
211
|
background,
|
|
195
212
|
onOpenFile,
|
|
213
|
+
onVisibleStepChange,
|
|
196
214
|
proposedAliases,
|
|
197
215
|
resolveSymbol,
|
|
198
216
|
onSymbolClick,
|
|
199
217
|
}: PierreTrailCodeViewProps) {
|
|
200
218
|
const { theme, mode } = useTheme();
|
|
201
219
|
const viewRef = useRef<CodeViewHandle<undefined>>(null);
|
|
220
|
+
// CodeView's scroll container — also the box we measure items against.
|
|
221
|
+
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
202
222
|
const [load, setLoad] = useState<FileLoadState>({ status: 'loading' });
|
|
203
223
|
|
|
204
224
|
// Keep the newest symbol callbacks in refs so the Pierre options object stays
|
|
@@ -207,6 +227,43 @@ export function PierreTrailCodeView({
|
|
|
207
227
|
resolveSymbolRef.current = resolveSymbol;
|
|
208
228
|
const onSymbolClickRef = useRef(onSymbolClick);
|
|
209
229
|
onSymbolClickRef.current = onSymbolClick;
|
|
230
|
+
const onVisibleStepChangeRef = useRef(onVisibleStepChange);
|
|
231
|
+
onVisibleStepChangeRef.current = onVisibleStepChange;
|
|
232
|
+
const visibleStepRef = useRef<number | null>(null);
|
|
233
|
+
|
|
234
|
+
// Report which step the viewport is on. The geometry lives in `visibleStep` so
|
|
235
|
+
// it can be tested — the answer depends on how tall the final snippet is
|
|
236
|
+
// relative to the viewport, which is not something to eyeball.
|
|
237
|
+
const reportVisibleStep = useCallback(() => {
|
|
238
|
+
const container = containerRef.current;
|
|
239
|
+
const viewer = viewRef.current?.getInstance();
|
|
240
|
+
if (container == null || viewer == null) return;
|
|
241
|
+
const rect = container.getBoundingClientRect();
|
|
242
|
+
const rects: VisibleStepRect[] = [];
|
|
243
|
+
for (const rendered of viewer.getRenderedItems()) {
|
|
244
|
+
const index = Number.parseInt(rendered.id.split(':').pop() ?? '', 10);
|
|
245
|
+
if (!Number.isFinite(index)) continue;
|
|
246
|
+
const itemRect = rendered.element.getBoundingClientRect();
|
|
247
|
+
rects.push({ index, top: itemRect.top, bottom: itemRect.bottom });
|
|
248
|
+
}
|
|
249
|
+
const next = resolveVisibleStepIndex(
|
|
250
|
+
{
|
|
251
|
+
top: rect.top,
|
|
252
|
+
bottom: rect.bottom,
|
|
253
|
+
scrollTop: container.scrollTop,
|
|
254
|
+
clientHeight: container.clientHeight,
|
|
255
|
+
scrollHeight: container.scrollHeight,
|
|
256
|
+
},
|
|
257
|
+
rects,
|
|
258
|
+
);
|
|
259
|
+
if (next == null || next === visibleStepRef.current) return;
|
|
260
|
+
visibleStepRef.current = next;
|
|
261
|
+
onVisibleStepChangeRef.current?.(next);
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
const onCodeViewScroll = useCallback(() => {
|
|
265
|
+
reportVisibleStep();
|
|
266
|
+
}, [reportVisibleStep]);
|
|
210
267
|
|
|
211
268
|
// A step onto a proposed component is planned work; label its missing file
|
|
212
269
|
// accordingly instead of showing a bare "not found".
|
|
@@ -346,32 +403,19 @@ export function PierreTrailCodeView({
|
|
|
346
403
|
context?: { item?: { id?: string } },
|
|
347
404
|
) => {
|
|
348
405
|
const id = context?.item?.id;
|
|
406
|
+
// Item-level renders don't move the viewport, but the first paint does
|
|
407
|
+
// decide which step is on screen.
|
|
408
|
+
reportVisibleStep();
|
|
349
409
|
if (id == null) return;
|
|
350
410
|
const sliceStart = sliceStartByItemId.get(id);
|
|
351
411
|
if (sliceStart == null) return;
|
|
352
412
|
remapSnippetLineNumbers(node, sliceStart);
|
|
353
413
|
},
|
|
354
|
-
[sliceStartByItemId],
|
|
414
|
+
[sliceStartByItemId, reportVisibleStep],
|
|
355
415
|
);
|
|
356
416
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const index = Number.parseInt(item.id.split(':').pop() ?? '', 10);
|
|
360
|
-
if (!trail.steps[index]) return null;
|
|
361
|
-
return (
|
|
362
|
-
<span
|
|
363
|
-
style={{
|
|
364
|
-
fontFamily: theme.fonts.monospace,
|
|
365
|
-
fontSize: theme.fontSizes[0],
|
|
366
|
-
color: theme.colors.textSecondary,
|
|
367
|
-
marginRight: 8,
|
|
368
|
-
}}
|
|
369
|
-
>
|
|
370
|
-
{index + 1}.
|
|
371
|
-
</span>
|
|
372
|
-
);
|
|
373
|
-
};
|
|
374
|
-
}, [trail.steps, theme]);
|
|
417
|
+
// No step numbers in the file header: the sidebar already numbers the steps,
|
|
418
|
+
// and the drawer header carries a segmented progress readout.
|
|
375
419
|
|
|
376
420
|
const renderHeaderMetadata = useMemo(() => {
|
|
377
421
|
return (item: CodeViewItem) => {
|
|
@@ -495,15 +539,29 @@ export function PierreTrailCodeView({
|
|
|
495
539
|
light: resolvePierreSyntaxThemeName('light'),
|
|
496
540
|
},
|
|
497
541
|
stickyHeaders: true,
|
|
542
|
+
// CodeView never injects `unsafeCSS` into its own shadow root, but it
|
|
543
|
+
// forwards the option to each file item (CODE_VIEW_FILE_OPTION_KEYS),
|
|
544
|
+
// which does — so this retints the file surfaces and headers. It cannot
|
|
545
|
+
// reach CodeView's host, hence the spread only carries
|
|
546
|
+
// PIERRE_BASE_OPTIONS and `disableFileHeader` must follow it.
|
|
547
|
+
...buildPierreOptions(background, {
|
|
548
|
+
background: theme.colors.backgroundSecondary,
|
|
549
|
+
fontSize: `${theme.fontSizes[0]}px`,
|
|
550
|
+
lineHeight: '1.15',
|
|
551
|
+
padding: '2px 8px',
|
|
552
|
+
}),
|
|
498
553
|
disableFileHeader: false,
|
|
554
|
+
// The library assumes a 44px header (DEFAULT_VIRTUAL_FILE_METRICS); the
|
|
555
|
+
// compact chrome above is ~18px. CodeView uses this for its
|
|
556
|
+
// virtualization window and sticky offset, so leaving it at 44 drifts.
|
|
557
|
+
itemMetrics: { diffHeaderHeight: TRAIL_HEADER_HEIGHT },
|
|
499
558
|
layout: { paddingTop: 0, paddingBottom: 0, gap: 4 },
|
|
500
559
|
onPostRender,
|
|
501
560
|
...(onOpenFile ? { onLineClick } : {}),
|
|
502
561
|
...symbolHandlers,
|
|
503
|
-
...(background ? buildPierreOptions(background) : {}),
|
|
504
562
|
...(mode === 'light' || mode === 'dark' ? { themeType: mode } : {}),
|
|
505
563
|
};
|
|
506
|
-
}, [background, mode, onPostRender, onOpenFile, onLineClick, symbolHandlers]);
|
|
564
|
+
}, [background, theme.colors.backgroundSecondary, theme.fontSizes, mode, onPostRender, onOpenFile, onLineClick, symbolHandlers]);
|
|
507
565
|
|
|
508
566
|
useEffect(() => {
|
|
509
567
|
if (load.status !== 'ready' || stepIndex == null) return;
|
|
@@ -549,10 +607,11 @@ export function PierreTrailCodeView({
|
|
|
549
607
|
return (
|
|
550
608
|
<CodeViewLoose
|
|
551
609
|
ref={viewRef}
|
|
610
|
+
containerRef={containerRef}
|
|
552
611
|
items={items}
|
|
553
612
|
options={options}
|
|
613
|
+
onScroll={onCodeViewScroll}
|
|
554
614
|
selectedLines={selectedLines}
|
|
555
|
-
renderHeaderPrefix={renderHeaderPrefix}
|
|
556
615
|
renderHeaderMetadata={renderHeaderMetadata}
|
|
557
616
|
renderAnnotation={renderAnnotation}
|
|
558
617
|
style={{ ...PIERRE_FILE_STYLE, height: '100%', overflow: 'auto' }}
|
|
@@ -6,28 +6,78 @@ export const PIERRE_BASE_OPTIONS = {
|
|
|
6
6
|
disableFileHeader: true,
|
|
7
7
|
} as const;
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/** Chrome overrides for the per-file header (`[data-diffs-header]`). */
|
|
10
|
+
export interface PierreHeaderStyle {
|
|
11
|
+
/** Fill behind the header row. */
|
|
12
|
+
background?: string;
|
|
13
|
+
/** Rule under the header row. */
|
|
14
|
+
borderBottom?: string;
|
|
15
|
+
/** Explicit size — the library leaves the header to inherit its line box. */
|
|
16
|
+
fontSize?: string;
|
|
17
|
+
lineHeight?: string;
|
|
18
|
+
/** Vertical padding. The library ships none, so this is the only breathing room. */
|
|
19
|
+
padding?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Retint Pierre's code surface to `background`, optionally restyling the file
|
|
24
|
+
* header.
|
|
25
|
+
*
|
|
26
|
+
* Every background in `@pierre/diffs` resolves to `--diffs-bg`, which is
|
|
27
|
+
* `light-dark(var(--diffs-light-bg, #fff), var(--diffs-dark-bg, #000))` — so
|
|
28
|
+
* overriding both inputs re-tints the whole surface from one variable and lets
|
|
29
|
+
* the diff / selection / hover layers keep recomputing their `color-mix` tints
|
|
30
|
+
* against it.
|
|
31
|
+
*
|
|
32
|
+
* `:host` still needs a direct override: the theme layer writes a literal
|
|
33
|
+
* `background-color` there from the Shiki theme, which does not go through
|
|
34
|
+
* `--diffs-bg`.
|
|
35
|
+
*
|
|
36
|
+
* Header rules land in each file item's shadow root, which is where
|
|
37
|
+
* `FileRenderer` puts the header — `CodeView` forwards `unsafeCSS` to its file
|
|
38
|
+
* items even though it never injects it into its own shadow root.
|
|
39
|
+
*
|
|
40
|
+
* Changing header height also invalidates `itemMetrics.diffHeaderHeight`, which
|
|
41
|
+
* `CodeView` uses for its virtualization window and sticky offset. Keep the two
|
|
42
|
+
* in step when overriding `fontSize` / `lineHeight` / `padding`.
|
|
43
|
+
*/
|
|
44
|
+
export function buildBackgroundCSS(
|
|
45
|
+
background: string,
|
|
46
|
+
header?: PierreHeaderStyle,
|
|
47
|
+
): string {
|
|
48
|
+
const headerDeclarations = header
|
|
49
|
+
? Object.entries(header)
|
|
50
|
+
.map(([property, value]) => ` ${kebab(property)}: ${value};`)
|
|
51
|
+
.join("\n")
|
|
52
|
+
: "";
|
|
53
|
+
|
|
10
54
|
return `
|
|
11
55
|
:host {
|
|
56
|
+
--diffs-light-bg: ${background};
|
|
57
|
+
--diffs-dark-bg: ${background};
|
|
12
58
|
background: ${background} !important;
|
|
13
59
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
[data-line] span {
|
|
22
|
-
background: ${background} !important;
|
|
60
|
+
${
|
|
61
|
+
headerDeclarations
|
|
62
|
+
? `[data-diffs-header] {
|
|
63
|
+
${headerDeclarations}
|
|
64
|
+
}`
|
|
65
|
+
: ""
|
|
23
66
|
}
|
|
24
67
|
`;
|
|
25
68
|
}
|
|
26
69
|
|
|
27
|
-
|
|
70
|
+
function kebab(property: string): string {
|
|
71
|
+
return property.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function buildPierreOptions(
|
|
75
|
+
background?: string,
|
|
76
|
+
header?: PierreHeaderStyle,
|
|
77
|
+
) {
|
|
28
78
|
if (!background) return PIERRE_BASE_OPTIONS;
|
|
29
79
|
return {
|
|
30
80
|
...PIERRE_BASE_OPTIONS,
|
|
31
|
-
unsafeCSS: buildBackgroundCSS(background),
|
|
81
|
+
unsafeCSS: buildBackgroundCSS(background, header),
|
|
32
82
|
};
|
|
33
83
|
}
|