@issuegraph/viewer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +156 -0
  3. package/dist/clusters.d.ts +34 -0
  4. package/dist/clusters.d.ts.map +1 -0
  5. package/dist/clusters.js +195 -0
  6. package/dist/clusters.js.map +1 -0
  7. package/dist/document.d.ts +190 -0
  8. package/dist/document.d.ts.map +1 -0
  9. package/dist/document.js +308 -0
  10. package/dist/document.js.map +1 -0
  11. package/dist/element.d.ts +95 -0
  12. package/dist/element.d.ts.map +1 -0
  13. package/dist/element.js +174 -0
  14. package/dist/element.js.map +1 -0
  15. package/dist/index.d.ts +40 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +33 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/layout.d.ts +122 -0
  20. package/dist/layout.d.ts.map +1 -0
  21. package/dist/layout.js +297 -0
  22. package/dist/layout.js.map +1 -0
  23. package/dist/mount.d.ts +64 -0
  24. package/dist/mount.d.ts.map +1 -0
  25. package/dist/mount.js +402 -0
  26. package/dist/mount.js.map +1 -0
  27. package/dist/navigation.d.ts +56 -0
  28. package/dist/navigation.d.ts.map +1 -0
  29. package/dist/navigation.js +121 -0
  30. package/dist/navigation.js.map +1 -0
  31. package/dist/parts.d.ts +89 -0
  32. package/dist/parts.d.ts.map +1 -0
  33. package/dist/parts.js +214 -0
  34. package/dist/parts.js.map +1 -0
  35. package/dist/projections/graph.d.ts +30 -0
  36. package/dist/projections/graph.d.ts.map +1 -0
  37. package/dist/projections/graph.js +644 -0
  38. package/dist/projections/graph.js.map +1 -0
  39. package/dist/projections/linear.d.ts +35 -0
  40. package/dist/projections/linear.d.ts.map +1 -0
  41. package/dist/projections/linear.js +157 -0
  42. package/dist/projections/linear.js.map +1 -0
  43. package/dist/projections/tree.d.ts +17 -0
  44. package/dist/projections/tree.d.ts.map +1 -0
  45. package/dist/projections/tree.js +209 -0
  46. package/dist/projections/tree.js.map +1 -0
  47. package/dist/render.d.ts +35 -0
  48. package/dist/render.d.ts.map +1 -0
  49. package/dist/render.js +45 -0
  50. package/dist/render.js.map +1 -0
  51. package/dist/scene.d.ts +94 -0
  52. package/dist/scene.d.ts.map +1 -0
  53. package/dist/scene.js +48 -0
  54. package/dist/scene.js.map +1 -0
  55. package/dist/styles.d.ts +17 -0
  56. package/dist/styles.d.ts.map +1 -0
  57. package/dist/styles.js +389 -0
  58. package/dist/styles.js.map +1 -0
  59. package/dist/theme.d.ts +71 -0
  60. package/dist/theme.d.ts.map +1 -0
  61. package/dist/theme.js +169 -0
  62. package/dist/theme.js.map +1 -0
  63. package/dist/vocabulary.d.ts +107 -0
  64. package/dist/vocabulary.d.ts.map +1 -0
  65. package/dist/vocabulary.js +98 -0
  66. package/dist/vocabulary.js.map +1 -0
  67. package/package.json +56 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The pieces every projection draws the same way.
3
+ *
4
+ * Identity, provenance, holds, readiness stations and edge badges are one
5
+ * grammar, not three — the design's extensibility clause turns on that. Putting
6
+ * them here means a projection cannot invent a second spelling of "this issue
7
+ * is held", and a change to the grammar lands in every projection at once.
8
+ */
9
+ import type { NormalizedDocument, RankProvenance, ViewerHold, ViewerIssue, ViewerSlot } from './document.ts';
10
+ import { type ElementSpec } from './element.ts';
11
+ /** How a readiness station is filled — the parallelism channel. */
12
+ export type StationFill = 'filled' | 'hollow' | 'dashed';
13
+ /**
14
+ * Filled = ready now. Hollow = ready once a named rank lands. Dashed = held.
15
+ *
16
+ * The hollow case needs the host to have told us the rank; without it a ready
17
+ * slot is simply ready, and inventing a pending state would claim a dependency
18
+ * nobody declared.
19
+ */
20
+ export declare function stationFill(slot: ViewerSlot): StationFill;
21
+ export declare function station(fill: StationFill): ElementSpec;
22
+ /**
23
+ * The identity chip: the qualified reference, linked only when the host gave us
24
+ * a URL. The viewer never constructs one — knowing a tracker's URL shape is the
25
+ * kind of knowledge this layer exists not to have.
26
+ */
27
+ export declare function identity(issue: ViewerIssue): ElementSpec;
28
+ /**
29
+ * The provenance line, in the three forms the design fixes: a matched ordering
30
+ * query, the declared tier, and an effective-priority promotion that names the
31
+ * dependent the urgency arrived through.
32
+ */
33
+ export declare function provenanceLine(provenance: RankProvenance | undefined): ElementSpec | null;
34
+ /** One hold, rendered with the family it belongs to visible in the markup. */
35
+ export declare function holdLine(hold: ViewerHold): ElementSpec;
36
+ /**
37
+ * Every relationship touching a ROW, as badges in the format's own field order
38
+ * — so two rows with the same relationships always read identically.
39
+ *
40
+ * TAKES THE ROW'S WHOLE KEY SET, NOT ONE KEY, because a together unit is ONE
41
+ * row and its partners get no row of their own. Reading only the lead dropped
42
+ * every relationship a partner owned: a unit blocked through its partner
43
+ * rendered no blocking badge at all, so the order UI showed a held unit and
44
+ * silently withheld what was holding it. The keys are the row's identity, so
45
+ * `other` is whichever endpoint is OUTSIDE the set, and an edge internal to the
46
+ * unit still reads from its `from` end exactly as it did when the set was one
47
+ * key — a single-key row is unchanged by construction.
48
+ */
49
+ export declare function edgeBadges(document: NormalizedDocument, keys: readonly string[]): ElementSpec | null;
50
+ /** The legend. Rendered once per scene so the grammar is readable cold. */
51
+ export declare function legend(): ElementSpec;
52
+ /**
53
+ * Every key a projection draws under some OTHER key's station, mapped to it.
54
+ *
55
+ * One rule for the linear and graph projections, which both render a together
56
+ * unit as a single row or node keyed by its lead. Written once because two
57
+ * copies of "which key stands in for which" is exactly how a projection's
58
+ * markup and its published `navigable` came to disagree in the first place.
59
+ *
60
+ * Only non-identity entries, so a lookup that misses means "represents itself"
61
+ * and no projection has to enumerate the keys that are already their own.
62
+ */
63
+ export declare function stationsOf(document: NormalizedDocument): ReadonlyMap<string, string>;
64
+ /**
65
+ * The caller's options, with `selected` and `focused` named the way THIS
66
+ * projection names them.
67
+ *
68
+ * APPLIED BEFORE THE SCENE IS BUILT, and that is the whole point of it being
69
+ * here rather than only in `reconcile`. Reconciling afterwards fixed the state
70
+ * a handle reports and left the MARKUP built from the un-canonicalized key: the
71
+ * station's row was never marked `aria-current`, the roving tab stop stayed on
72
+ * whatever the fallback resolved to, and `renderViewer` — which never calls
73
+ * `reconcile` at all — was simply wrong. A viewer whose reported state and
74
+ * rendered DOM disagree is the defect, whichever half is right.
75
+ *
76
+ * The projection publishes the SAME map it canonicalized with, so `reconcile`
77
+ * cannot reach a different answer than the markup did.
78
+ */
79
+ export declare function atStations<T extends {
80
+ selected?: string | null | undefined;
81
+ focused?: string | null | undefined;
82
+ }>(options: T, stations: ReadonlyMap<string, string>): T;
83
+ /** The title of a slot, naming every member — a together unit is one row. */
84
+ export declare function slotTitle(document: NormalizedDocument, slot: ViewerSlot): string;
85
+ /** A slot's accessible name: what it is, where it sits, and whether it is held. */
86
+ export declare function slotLabel(document: NormalizedDocument, slot: ViewerSlot): string;
87
+ /** The empty state. A container with nothing in it reads as a bug. */
88
+ export declare function emptyState(message: string): ElementSpec;
89
+ //# sourceMappingURL=parts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../src/parts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,WAAW,EAAW,MAAM,cAAc,CAAC;AAGzD,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAIzD;AAQD,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAOtD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAgBxD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAuBzF;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAEtD;AAoBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,GAAG,IAAI,CA0BpG;AAED,2EAA2E;AAC3E,wBAAgB,MAAM,IAAI,WAAW,CAWpC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAQpF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,EAChH,OAAO,EAAE,CAAC,EACV,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,CAAC,CAKH;AAED,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAIhF;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAGhF;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAEvD"}
package/dist/parts.js ADDED
@@ -0,0 +1,214 @@
1
+ /**
2
+ * The pieces every projection draws the same way.
3
+ *
4
+ * Identity, provenance, holds, readiness stations and edge badges are one
5
+ * grammar, not three — the design's extensibility clause turns on that. Putting
6
+ * them here means a projection cannot invent a second spelling of "this issue
7
+ * is held", and a change to the grammar lands in every projection at once.
8
+ */
9
+ import { element } from "./element.js";
10
+ import { EDGE_ORDER, treatmentFor } from "./vocabulary.js";
11
+ /**
12
+ * Filled = ready now. Hollow = ready once a named rank lands. Dashed = held.
13
+ *
14
+ * The hollow case needs the host to have told us the rank; without it a ready
15
+ * slot is simply ready, and inventing a pending state would claim a dependency
16
+ * nobody declared.
17
+ */
18
+ export function stationFill(slot) {
19
+ if (!slot.ready)
20
+ return 'dashed';
21
+ const after = slot.readyAfterRank;
22
+ return after === undefined || after === null ? 'filled' : 'hollow';
23
+ }
24
+ const STATION_LABEL = Object.freeze({
25
+ filled: 'ready now',
26
+ hollow: 'ready after an earlier rank',
27
+ dashed: 'held',
28
+ });
29
+ export function station(fill) {
30
+ return element('span', {
31
+ class: 'ig-station',
32
+ 'data-fill': fill,
33
+ role: 'img',
34
+ 'aria-label': STATION_LABEL[fill],
35
+ });
36
+ }
37
+ /**
38
+ * The identity chip: the qualified reference, linked only when the host gave us
39
+ * a URL. The viewer never constructs one — knowing a tracker's URL shape is the
40
+ * kind of knowledge this layer exists not to have.
41
+ */
42
+ export function identity(issue) {
43
+ if (issue.url === undefined || issue.url === '') {
44
+ return element('span', { class: 'ig-id' }, [issue.key]);
45
+ }
46
+ return element('span', { class: 'ig-id' }, [
47
+ element('a', {
48
+ class: 'ig-link',
49
+ href: issue.url,
50
+ rel: 'noreferrer',
51
+ 'aria-label': `open ${issue.key}`,
52
+ }, [`${issue.key} ↗`]),
53
+ ]);
54
+ }
55
+ /**
56
+ * The provenance line, in the three forms the design fixes: a matched ordering
57
+ * query, the declared tier, and an effective-priority promotion that names the
58
+ * dependent the urgency arrived through.
59
+ */
60
+ export function provenanceLine(provenance) {
61
+ if (provenance === undefined)
62
+ return null;
63
+ switch (provenance.kind) {
64
+ case 'matched-query':
65
+ return element('p', { class: 'ig-provenance' }, [
66
+ `matched ordered query ${String(provenance.index)} · `,
67
+ element('span', { class: 'ig-id' }, [provenance.label]),
68
+ ]);
69
+ case 'declared-tier':
70
+ return element('p', { class: 'ig-provenance' }, [
71
+ `priority tier P${String(provenance.priority)}`,
72
+ ]);
73
+ case 'promotion': {
74
+ const via = provenance.promotedBy.length === 0
75
+ ? ''
76
+ : ` · inherited from ${provenance.promotedBy.join(', ')}`;
77
+ return element('p', { class: 'ig-provenance' }, [
78
+ element('span', { class: 'ig-id' }, [provenance.notation]),
79
+ `${via}`,
80
+ ]);
81
+ }
82
+ }
83
+ }
84
+ /** One hold, rendered with the family it belongs to visible in the markup. */
85
+ export function holdLine(hold) {
86
+ return element('p', { class: 'ig-hold', 'data-family': hold.family }, [hold.reason]);
87
+ }
88
+ /** A badge naming one relationship, on all four channels at once. */
89
+ function edgeBadge(field, detail) {
90
+ const treatment = treatmentFor(field);
91
+ return element('span', {
92
+ class: 'ig-badge',
93
+ 'data-edge': field,
94
+ title: `${treatment.label} ${detail}`,
95
+ 'aria-label': `${treatment.label} ${detail}`,
96
+ }, [
97
+ element('span', { class: 'ig-glyph', 'aria-hidden': 'true' }, [treatment.glyph]),
98
+ element('span', {}, [detail]),
99
+ ]);
100
+ }
101
+ /**
102
+ * Every relationship touching a ROW, as badges in the format's own field order
103
+ * — so two rows with the same relationships always read identically.
104
+ *
105
+ * TAKES THE ROW'S WHOLE KEY SET, NOT ONE KEY, because a together unit is ONE
106
+ * row and its partners get no row of their own. Reading only the lead dropped
107
+ * every relationship a partner owned: a unit blocked through its partner
108
+ * rendered no blocking badge at all, so the order UI showed a held unit and
109
+ * silently withheld what was holding it. The keys are the row's identity, so
110
+ * `other` is whichever endpoint is OUTSIDE the set, and an edge internal to the
111
+ * unit still reads from its `from` end exactly as it did when the set was one
112
+ * key — a single-key row is unchanged by construction.
113
+ */
114
+ export function edgeBadges(document, keys) {
115
+ const mine = new Set(keys);
116
+ const badges = [];
117
+ // ONE EDGE, ONE BADGE. Both endpoints of an intra-unit edge are members, so
118
+ // it appears in two `edgesOf` entries and would otherwise render twice on the
119
+ // row that owns both ends.
120
+ const seen = new Set();
121
+ for (const field of EDGE_ORDER) {
122
+ for (const key of keys) {
123
+ for (const edge of document.edgesOf.get(key) ?? []) {
124
+ if (edge.field !== field)
125
+ continue;
126
+ const identity = `${edge.field}\u0000${edge.from}\u0000${edge.to}`;
127
+ if (seen.has(identity))
128
+ continue;
129
+ seen.add(identity);
130
+ const treatment = treatmentFor(field);
131
+ // A symmetric edge states one fact whichever end you read it from, so it
132
+ // is announced as one relationship rather than as two directions.
133
+ const outgoing = mine.has(edge.from);
134
+ const other = outgoing ? edge.to : edge.from;
135
+ const detail = treatment.symmetric || outgoing ? other : `${other} (incoming)`;
136
+ badges.push(edgeBadge(field, detail));
137
+ }
138
+ }
139
+ }
140
+ if (badges.length === 0)
141
+ return null;
142
+ return element('span', { class: 'ig-badges' }, badges);
143
+ }
144
+ /** The legend. Rendered once per scene so the grammar is readable cold. */
145
+ export function legend() {
146
+ return element('fieldset', { class: 'ig-legend' }, [
147
+ element('legend', { class: 'ig-legend-caption' }, ['relationships']),
148
+ ...EDGE_ORDER.map((field) => {
149
+ const treatment = treatmentFor(field);
150
+ return element('span', { class: 'ig-badge', 'data-edge': field }, [
151
+ element('span', { class: 'ig-glyph', 'aria-hidden': 'true' }, [treatment.glyph]),
152
+ element('span', {}, [treatment.label]),
153
+ ]);
154
+ }),
155
+ ]);
156
+ }
157
+ /**
158
+ * Every key a projection draws under some OTHER key's station, mapped to it.
159
+ *
160
+ * One rule for the linear and graph projections, which both render a together
161
+ * unit as a single row or node keyed by its lead. Written once because two
162
+ * copies of "which key stands in for which" is exactly how a projection's
163
+ * markup and its published `navigable` came to disagree in the first place.
164
+ *
165
+ * Only non-identity entries, so a lookup that misses means "represents itself"
166
+ * and no projection has to enumerate the keys that are already their own.
167
+ */
168
+ export function stationsOf(document) {
169
+ const stations = new Map();
170
+ for (const slot of document.order.slots) {
171
+ for (const member of slot.members) {
172
+ if (member !== slot.lead)
173
+ stations.set(member, slot.lead);
174
+ }
175
+ }
176
+ return stations;
177
+ }
178
+ /**
179
+ * The caller's options, with `selected` and `focused` named the way THIS
180
+ * projection names them.
181
+ *
182
+ * APPLIED BEFORE THE SCENE IS BUILT, and that is the whole point of it being
183
+ * here rather than only in `reconcile`. Reconciling afterwards fixed the state
184
+ * a handle reports and left the MARKUP built from the un-canonicalized key: the
185
+ * station's row was never marked `aria-current`, the roving tab stop stayed on
186
+ * whatever the fallback resolved to, and `renderViewer` — which never calls
187
+ * `reconcile` at all — was simply wrong. A viewer whose reported state and
188
+ * rendered DOM disagree is the defect, whichever half is right.
189
+ *
190
+ * The projection publishes the SAME map it canonicalized with, so `reconcile`
191
+ * cannot reach a different answer than the markup did.
192
+ */
193
+ export function atStations(options, stations) {
194
+ if (stations.size === 0)
195
+ return options;
196
+ const at = (key) => key === null || key === undefined ? key : (stations.get(key) ?? key);
197
+ return { ...options, selected: at(options.selected), focused: at(options.focused) };
198
+ }
199
+ /** The title of a slot, naming every member — a together unit is one row. */
200
+ export function slotTitle(document, slot) {
201
+ return slot.members
202
+ .map((member) => document.byKey.get(member)?.title ?? member)
203
+ .join(' · ');
204
+ }
205
+ /** A slot's accessible name: what it is, where it sits, and whether it is held. */
206
+ export function slotLabel(document, slot) {
207
+ const position = slot.rank === null ? 'held, no rank' : `rank ${String(slot.rank)}`;
208
+ return `${slotTitle(document, slot)} — ${slot.members.join(', ')} — ${position}`;
209
+ }
210
+ /** The empty state. A container with nothing in it reads as a bug. */
211
+ export function emptyState(message) {
212
+ return element('p', { class: 'ig-empty' }, [message]);
213
+ }
214
+ //# sourceMappingURL=parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.js","sourceRoot":"","sources":["../src/parts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,OAAO,EAAoB,OAAO,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK3D;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAgB;IAC1C,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC;IAClC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;AACrE,CAAC;AAED,MAAM,aAAa,GAA0C,MAAM,CAAC,MAAM,CAAC;IACzE,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,6BAA6B;IACrC,MAAM,EAAE,MAAM;CACf,CAAC,CAAC;AAEH,MAAM,UAAU,OAAO,CAAC,IAAiB;IACvC,OAAO,OAAO,CAAC,MAAM,EAAE;QACrB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,IAAI;QACjB,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,aAAa,CAAC,IAAI,CAAC;KAClC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAkB;IACzC,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC;QAChD,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACzC,OAAO,CACL,GAAG,EACH;YACE,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,KAAK,CAAC,GAAG;YACf,GAAG,EAAE,YAAY;YACjB,YAAY,EAAE,QAAQ,KAAK,CAAC,GAAG,EAAE;SAClC,EACD,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CACnB;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,UAAsC;IACnE,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1C,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,eAAe;YAClB,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE;gBAC9C,yBAAyB,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK;gBACtD,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;aACxD,CAAC,CAAC;QACL,KAAK,eAAe;YAClB,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE;gBAC9C,kBAAkB,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;aAChD,CAAC,CAAC;QACL,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,GAAG,GACP,UAAU,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;gBAChC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,qBAAqB,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE;gBAC9C,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC1D,GAAG,GAAG,EAAE;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,QAAQ,CAAC,IAAgB;IACvC,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,qEAAqE;AACrE,SAAS,SAAS,CAAC,KAAgB,EAAE,MAAc;IACjD,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,OAAO,CACZ,MAAM,EACN;QACE,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,KAAK;QAClB,KAAK,EAAE,GAAG,SAAS,CAAC,KAAK,IAAI,MAAM,EAAE;QACrC,YAAY,EAAE,GAAG,SAAS,CAAC,KAAK,IAAI,MAAM,EAAE;KAC7C,EACD;QACE,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAChF,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;KAC9B,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,QAA4B,EAAE,IAAuB;IAC9E,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,4EAA4E;IAC5E,8EAA8E;IAC9E,2BAA2B;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnD,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;oBAAE,SAAS;gBACnC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,EAAE,CAAC;gBACnE,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACnB,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBACtC,yEAAyE;gBACzE,kEAAkE;gBAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,aAAa,CAAC;gBAC/E,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;AACzD,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,MAAM;IACpB,OAAO,OAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;QACjD,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC;QACpE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;YACtC,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;gBAChE,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAChF,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;aACvC,CAAC,CAAC;QACL,CAAC,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,QAA4B;IACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,KAAK,IAAI,CAAC,IAAI;gBAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,UAAU,CACxB,OAAU,EACV,QAAqC;IAErC,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,MAAM,EAAE,GAAG,CAAC,GAA8B,EAA6B,EAAE,CACvE,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;AACtF,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,QAA4B,EAAE,IAAgB;IACtE,OAAO,IAAI,CAAC,OAAO;SAChB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC;SAC5D,IAAI,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,SAAS,CAAC,QAA4B,EAAE,IAAgB;IACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACpF,OAAO,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,QAAQ,EAAE,CAAC;AACnF,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The graph projection: the ordered spine with gutters, and arcs for everything
3
+ * off it.
4
+ *
5
+ * Sequence is vertical position on the spine. Dependency is the arcs. Both
6
+ * readings work at once because they use different visual channels, which is
7
+ * the whole reason this shape was chosen over a force-directed or layered
8
+ * drawing — those make dependency legible and sequence a hunt, and their layout
9
+ * shifts between refreshes, which destroys trust in a panel whose job is to be
10
+ * authoritative.
11
+ *
12
+ * IT REFUSES RATHER THAN DEGRADES. The list scales; the canvas is a local
13
+ * instrument answering "what surrounds this issue", so past its budget it says
14
+ * so and offers the next move instead of drawing a hairball.
15
+ */
16
+ import type { NormalizedDocument } from '../document.ts';
17
+ import { type Scene } from '../scene.ts';
18
+ import { type Theme } from '../theme.ts';
19
+ import { type SceneOptions } from './linear.ts';
20
+ /**
21
+ * The node budget, from the design's scale table. Above the first threshold the
22
+ * canvas shows component capsules; above the second, clusters only.
23
+ */
24
+ export declare const GRAPH_NODE_BUDGET = 60;
25
+ export declare const CLUSTER_ONLY_BUDGET = 300;
26
+ export interface GraphOptions extends SceneOptions {
27
+ readonly theme?: Theme | undefined;
28
+ }
29
+ export declare function graphScene(document: NormalizedDocument, rawOptions?: GraphOptions): Scene;
30
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/projections/graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAInB,MAAM,gBAAgB,CAAC;AAoBxB,OAAO,EAA0B,KAAK,KAAK,EAAmB,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,KAAK,KAAK,EAAgB,MAAM,aAAa,CAAC;AAEvD,OAAO,EAAE,KAAK,YAAY,EAA6B,MAAM,aAAa,CAAC;AAE3E;;;GAGG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;CACpC;AA4bD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,EAAE,UAAU,GAAE,YAAiB,GAAG,KAAK,CA4Q7F"}