@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.
- package/LICENSE +201 -0
- package/README.md +156 -0
- package/dist/clusters.d.ts +34 -0
- package/dist/clusters.d.ts.map +1 -0
- package/dist/clusters.js +195 -0
- package/dist/clusters.js.map +1 -0
- package/dist/document.d.ts +190 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +308 -0
- package/dist/document.js.map +1 -0
- package/dist/element.d.ts +95 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +174 -0
- package/dist/element.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +122 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +297 -0
- package/dist/layout.js.map +1 -0
- package/dist/mount.d.ts +64 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +402 -0
- package/dist/mount.js.map +1 -0
- package/dist/navigation.d.ts +56 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +121 -0
- package/dist/navigation.js.map +1 -0
- package/dist/parts.d.ts +89 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +214 -0
- package/dist/parts.js.map +1 -0
- package/dist/projections/graph.d.ts +30 -0
- package/dist/projections/graph.d.ts.map +1 -0
- package/dist/projections/graph.js +644 -0
- package/dist/projections/graph.js.map +1 -0
- package/dist/projections/linear.d.ts +35 -0
- package/dist/projections/linear.d.ts.map +1 -0
- package/dist/projections/linear.js +157 -0
- package/dist/projections/linear.js.map +1 -0
- package/dist/projections/tree.d.ts +17 -0
- package/dist/projections/tree.d.ts.map +1 -0
- package/dist/projections/tree.js +209 -0
- package/dist/projections/tree.js.map +1 -0
- package/dist/render.d.ts +35 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +45 -0
- package/dist/render.js.map +1 -0
- package/dist/scene.d.ts +94 -0
- package/dist/scene.d.ts.map +1 -0
- package/dist/scene.js +48 -0
- package/dist/scene.js.map +1 -0
- package/dist/styles.d.ts +17 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +389 -0
- package/dist/styles.js.map +1 -0
- package/dist/theme.d.ts +71 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +169 -0
- package/dist/theme.js.map +1 -0
- package/dist/vocabulary.d.ts +107 -0
- package/dist/vocabulary.d.ts.map +1 -0
- package/dist/vocabulary.js +98 -0
- package/dist/vocabulary.js.map +1 -0
- package/package.json +56 -0
package/dist/layout.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph geometry, computed — never eyeballed.
|
|
3
|
+
*
|
|
4
|
+
* Three columns, three jobs: the LEFT GUTTER holds open issues outside the
|
|
5
|
+
* order that explain a hold, the CENTRE SPINE is the work order itself, and the
|
|
6
|
+
* RIGHT GUTTER holds issues the order never works. Sequence is vertical
|
|
7
|
+
* position on the spine; dependency is everything off it.
|
|
8
|
+
*
|
|
9
|
+
* Two rules carry most of the weight, and both come from the design's
|
|
10
|
+
* implementation note rather than from taste:
|
|
11
|
+
*
|
|
12
|
+
* - **Every edge endpoint is derived from a node's computed bounds.** An edge
|
|
13
|
+
* terminates ON a bound, never at a remembered offset, so a node that
|
|
14
|
+
* changes size moves its edges with it.
|
|
15
|
+
* - **Arcs stay out of the occupied x-ranges** and out of the station band.
|
|
16
|
+
* The colour-blind-safety claim rests on four redundant channels, and the
|
|
17
|
+
* terminal marker is the one that separates `decomposed-from` from
|
|
18
|
+
* `duplicate-of` — a marker hidden under an opaque card silently drops the
|
|
19
|
+
* encoding to three.
|
|
20
|
+
*
|
|
21
|
+
* Deterministic by construction: no measurement, no randomness, no clock. The
|
|
22
|
+
* same document always produces the same coordinates, which is what lets a
|
|
23
|
+
* panel whose job is to be authoritative be trusted between refreshes.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Custom properties carrying LAYOUT OUTPUT rather than theme input.
|
|
27
|
+
*
|
|
28
|
+
* A theme token is a value a host chooses; these are values this module
|
|
29
|
+
* COMPUTES and writes onto individual elements, so the rail can sit on the node
|
|
30
|
+
* it names without either side hard-coding a coordinate. They are declared here
|
|
31
|
+
* so `styles.test.ts` can tell the two kinds apart — a `var()` naming neither a
|
|
32
|
+
* theme token nor one of these is still a defect, and still fails.
|
|
33
|
+
*/
|
|
34
|
+
export const LAYOUT_PROPERTIES = Object.freeze([
|
|
35
|
+
'--ig-stage-w',
|
|
36
|
+
'--ig-stage-h',
|
|
37
|
+
'--ig-row-x',
|
|
38
|
+
'--ig-row-y',
|
|
39
|
+
'--ig-row-w',
|
|
40
|
+
'--ig-row-h',
|
|
41
|
+
]);
|
|
42
|
+
function metric(theme, token) {
|
|
43
|
+
return theme.metrics[token];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A node's width follows its own contents rather than the column, so an edge
|
|
47
|
+
* terminating on its bound lands where the reader sees the box end. Clamped to
|
|
48
|
+
* the column so the channels stay free.
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* The label as it fits the box the layout gave it.
|
|
52
|
+
*
|
|
53
|
+
* `boxWidth` CLAMPS to the column, so a title longer than the column gets a box
|
|
54
|
+
* narrower than its text — and an SVG `<text>` neither wraps nor clips, so the
|
|
55
|
+
* overflow ran straight across the routing channel and the neighbouring nodes,
|
|
56
|
+
* hiding the edges and labels the graph exists to show. Long issue titles are
|
|
57
|
+
* ordinary, so this was the common case rather than an edge one.
|
|
58
|
+
*
|
|
59
|
+
* IT MEASURES WITH THE SAME METRIC `boxWidth` SIZES WITH, which is the whole
|
|
60
|
+
* reason this belongs beside it rather than in the projection. Both read
|
|
61
|
+
* `--ig-char-width`, so the renderer's idea of what fits and the layout's cannot
|
|
62
|
+
* disagree — a separate estimate in the drawing code would be a second opinion
|
|
63
|
+
* about the same question, and the two would drift.
|
|
64
|
+
*
|
|
65
|
+
* THE ELLIPSIS IS THIS PACKAGE'S OWN TREATMENT, not a new convention: the rail's
|
|
66
|
+
* HTML rows already resolve an over-long title with `text-overflow: ellipsis`,
|
|
67
|
+
* so a canvas label that simply stopped mid-word would make the two surfaces
|
|
68
|
+
* disagree about what a truncated title looks like.
|
|
69
|
+
*
|
|
70
|
+
* NOTHING IS LOST TO A READER — the full title stays in the node's accessible
|
|
71
|
+
* name and its `<title>`, so this shortens what is DRAWN and never what is
|
|
72
|
+
* available.
|
|
73
|
+
*/
|
|
74
|
+
export function fitLabel(theme, label, width) {
|
|
75
|
+
const room = width - metric(theme, '--ig-space') * 2;
|
|
76
|
+
const fits = Math.floor(room / metric(theme, '--ig-char-width'));
|
|
77
|
+
if (fits >= label.length)
|
|
78
|
+
return label;
|
|
79
|
+
// Below two characters there is no room for a glyph AND the ellipsis, and an
|
|
80
|
+
// ellipsis alone names nothing — so the box has become too small to label at
|
|
81
|
+
// all, and drawing nothing is honester than drawing a lone dot.
|
|
82
|
+
if (fits < 2)
|
|
83
|
+
return '';
|
|
84
|
+
return `${label.slice(0, fits - 1)}\u2026`;
|
|
85
|
+
}
|
|
86
|
+
function boxWidth(theme, label, columnWidth) {
|
|
87
|
+
const padding = metric(theme, '--ig-space') * 2;
|
|
88
|
+
const measured = label.length * metric(theme, '--ig-char-width') + padding;
|
|
89
|
+
return Math.min(columnWidth, Math.max(columnWidth / 2, measured));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Assign every key that needs a box to a column.
|
|
93
|
+
*
|
|
94
|
+
* Totality is the requirement, not a nicety: every kept edge's endpoints must
|
|
95
|
+
* have bounds or its geometry is undefined, and `normalizeDocument` has already
|
|
96
|
+
* dropped the edges whose ends this document does not carry. Anything touched
|
|
97
|
+
* by an edge and not on the spine therefore lands in a gutter — the right one
|
|
98
|
+
* when the order deliberately never works it, the left one when it is an open
|
|
99
|
+
* issue standing in the way.
|
|
100
|
+
*/
|
|
101
|
+
function assignColumns(document) {
|
|
102
|
+
const spine = [];
|
|
103
|
+
const slotMembers = new Map();
|
|
104
|
+
const placed = new Set();
|
|
105
|
+
for (const slot of document.order.slots) {
|
|
106
|
+
slotMembers.set(slot.lead, slot.members);
|
|
107
|
+
for (const member of slot.members) {
|
|
108
|
+
if (placed.has(member))
|
|
109
|
+
continue;
|
|
110
|
+
placed.add(member);
|
|
111
|
+
spine.push(member);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const neverWorked = new Set(document.order.excluded.map((exclusion) => exclusion.key));
|
|
115
|
+
for (const edge of document.edges) {
|
|
116
|
+
if (edge.field !== 'decomposed-from')
|
|
117
|
+
continue;
|
|
118
|
+
const origin = document.byKey.get(edge.to);
|
|
119
|
+
if (origin !== undefined && !origin.open && !placed.has(edge.to))
|
|
120
|
+
neverWorked.add(edge.to);
|
|
121
|
+
}
|
|
122
|
+
const left = [];
|
|
123
|
+
const right = [];
|
|
124
|
+
const seen = new Set(placed);
|
|
125
|
+
for (const edge of document.edges) {
|
|
126
|
+
for (const end of [edge.from, edge.to]) {
|
|
127
|
+
if (seen.has(end))
|
|
128
|
+
continue;
|
|
129
|
+
seen.add(end);
|
|
130
|
+
(neverWorked.has(end) ? right : left).push(end);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
for (const key of neverWorked) {
|
|
134
|
+
if (seen.has(key))
|
|
135
|
+
continue;
|
|
136
|
+
seen.add(key);
|
|
137
|
+
right.push(key);
|
|
138
|
+
}
|
|
139
|
+
return { spine, left, right, slotMembers };
|
|
140
|
+
}
|
|
141
|
+
/** Lay a document out. Pure: coordinates depend only on the document and the theme. */
|
|
142
|
+
export function layoutGraph(document, theme) {
|
|
143
|
+
const rowHeight = metric(theme, '--ig-row-height');
|
|
144
|
+
const gap = metric(theme, '--ig-space');
|
|
145
|
+
const gutterWidth = metric(theme, '--ig-gutter-width');
|
|
146
|
+
const spineWidth = metric(theme, '--ig-spine-width');
|
|
147
|
+
const channelWidth = metric(theme, '--ig-gutter-width') / 2;
|
|
148
|
+
// THE CANVAS RESERVES WHAT THE ENCLOSURE NEEDS, AND WHAT THE FOCUS RING DOES.
|
|
149
|
+
// A `together-with` enclosure pads clear of its members' bounds, so a unit on
|
|
150
|
+
// the first or last row drew at a negative coordinate or past the bottom edge
|
|
151
|
+
// — outside the viewBox, and outside the stage, which hides its overflow.
|
|
152
|
+
// The focus ring reaches FURTHER than the enclosure and was clipped by the
|
|
153
|
+
// same edge: `:focus-visible` sits `--ig-space-tight` clear of the element and
|
|
154
|
+
// is `--ig-focus-ring` thick, so it extends their SUM outward, while a margin
|
|
155
|
+
// of `--ig-space-tight` alone left the top segment outside the stage — and on
|
|
156
|
+
// a one-row graph the bottom segment with it. A partial ring is exactly the
|
|
157
|
+
// indicator a keyboard reader depends on, so the margin covers the larger of
|
|
158
|
+
// the two demands rather than the one that happens to be named here.
|
|
159
|
+
// SUMMED FROM THE TOKENS, never written as 8: geometry is theme data in this
|
|
160
|
+
// package, so a retheme that changes either token moves the reservation with
|
|
161
|
+
// it instead of silently reintroducing the clip.
|
|
162
|
+
// The ENCLOSURE's own inset stays `--ig-space-tight` — this is the canvas
|
|
163
|
+
// margin, which must merely be big enough for both, not the same quantity.
|
|
164
|
+
const pad = metric(theme, '--ig-space-tight') + metric(theme, '--ig-focus-ring');
|
|
165
|
+
const { spine, left, right, slotMembers } = assignColumns(document);
|
|
166
|
+
const leftX = pad;
|
|
167
|
+
const spineX = pad + gutterWidth + channelWidth;
|
|
168
|
+
const rightX = spineX + spineWidth + channelWidth;
|
|
169
|
+
const width = rightX + gutterWidth + pad;
|
|
170
|
+
// The channels sit between the columns, so no arc routed through one can
|
|
171
|
+
// cross an occupied x-range.
|
|
172
|
+
const leftChannel = pad + gutterWidth + channelWidth / 2;
|
|
173
|
+
const rightChannel = spineX + spineWidth + channelWidth / 2;
|
|
174
|
+
const rankOf = new Map();
|
|
175
|
+
const heldOf = new Map();
|
|
176
|
+
for (const slot of document.order.slots) {
|
|
177
|
+
for (const member of slot.members) {
|
|
178
|
+
rankOf.set(member, slot.rank);
|
|
179
|
+
heldOf.set(member, !slot.ready);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const nodes = new Map();
|
|
183
|
+
const place = (keys, column, x, columnWidth) => {
|
|
184
|
+
keys.forEach((key, index) => {
|
|
185
|
+
const label = document.byKey.get(key)?.title ?? key;
|
|
186
|
+
nodes.set(key, {
|
|
187
|
+
key,
|
|
188
|
+
column,
|
|
189
|
+
x,
|
|
190
|
+
y: pad + index * (rowHeight + gap),
|
|
191
|
+
width: boxWidth(theme, label, columnWidth),
|
|
192
|
+
height: rowHeight,
|
|
193
|
+
rank: rankOf.get(key) ?? null,
|
|
194
|
+
held: heldOf.get(key) ?? false,
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
place(spine, 'spine', spineX, spineWidth);
|
|
199
|
+
place(left, 'left', leftX, gutterWidth);
|
|
200
|
+
place(right, 'right', rightX, gutterWidth);
|
|
201
|
+
const rows = Math.max(spine.length, left.length, right.length);
|
|
202
|
+
const height = rows === 0 ? 0 : rows * (rowHeight + gap) - gap + pad * 2;
|
|
203
|
+
return {
|
|
204
|
+
width,
|
|
205
|
+
height,
|
|
206
|
+
nodes,
|
|
207
|
+
spineOrder: spine,
|
|
208
|
+
slotMembers,
|
|
209
|
+
leftChannel,
|
|
210
|
+
rightChannel,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Where an edge leaves and enters, in the fraction of a box's height it uses.
|
|
215
|
+
*
|
|
216
|
+
* Departures leave low and arrivals enter high, so a path never runs along the
|
|
217
|
+
* centre line where the readiness station sits. That is the design's
|
|
218
|
+
* station-collision rule expressed as two numbers instead of a special case.
|
|
219
|
+
*/
|
|
220
|
+
const DEPART_FRACTION = 0.75;
|
|
221
|
+
const ARRIVE_FRACTION = 0.25;
|
|
222
|
+
/**
|
|
223
|
+
* Which bound of `box` the edge should leave from or arrive at.
|
|
224
|
+
*
|
|
225
|
+
* PAIRWISE, NOT PER-COLUMN, and the difference is the whole correctness of the
|
|
226
|
+
* drawing. Deciding from a box's own column alone made every spine endpoint the
|
|
227
|
+
* LEFT bound — so an arc to the right gutter left the spine on its far side and
|
|
228
|
+
* had to cross the node to reach its own terminal, occluding exactly the marker
|
|
229
|
+
* the colour-blind-safety claim depends on.
|
|
230
|
+
*
|
|
231
|
+
* ON A TIE, FACE THE CHANNEL. Two nodes in the same column have the same x, so
|
|
232
|
+
* "face the other" says nothing — and defaulting LEFT was right for the spine
|
|
233
|
+
* only by coincidence: the left channel happens to sit left of it. For two
|
|
234
|
+
* left-gutter nodes the same channel is on their RIGHT, so the default sent
|
|
235
|
+
* both endpoints out of the canvas and dragged the path back across the boxes.
|
|
236
|
+
* Facing the channel is the rule the spine case was an instance of, so it keeps
|
|
237
|
+
* "arcs bow left of the spine" while fixing the gutter.
|
|
238
|
+
*/
|
|
239
|
+
function facingSide(box, other, channelX) {
|
|
240
|
+
const centre = box.x + box.width / 2;
|
|
241
|
+
const otherCentre = other.x + other.width / 2;
|
|
242
|
+
if (otherCentre !== centre)
|
|
243
|
+
return otherCentre > centre ? 'right' : 'left';
|
|
244
|
+
return channelX > centre ? 'right' : 'left';
|
|
245
|
+
}
|
|
246
|
+
function anchor(box, fraction, side) {
|
|
247
|
+
return {
|
|
248
|
+
x: side === 'left' ? box.x : box.x + box.width,
|
|
249
|
+
y: box.y + box.height * fraction,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The geometry for one edge, derived entirely from the two boxes' bounds.
|
|
254
|
+
*
|
|
255
|
+
* Returns `null` when either end has no box — which `normalizeDocument` has
|
|
256
|
+
* already made impossible for a kept edge, so a `null` here means a caller
|
|
257
|
+
* built a layout from a different document than the edge came from. Refusing is
|
|
258
|
+
* better than drawing at coordinates nobody computed.
|
|
259
|
+
*/
|
|
260
|
+
export function edgeGeometry(layout, edge) {
|
|
261
|
+
const from = layout.nodes.get(edge.from);
|
|
262
|
+
const to = layout.nodes.get(edge.to);
|
|
263
|
+
if (from === undefined || to === undefined)
|
|
264
|
+
return null;
|
|
265
|
+
// The channel is chosen FIRST, because on a same-column tie it is what
|
|
266
|
+
// decides which bound each endpoint uses. A pair of spine nodes bows LEFT, as
|
|
267
|
+
// the design fixes; anything touching the right gutter uses the right channel
|
|
268
|
+
// so the two families never tangle.
|
|
269
|
+
const usesRight = from.column === 'right' || to.column === 'right';
|
|
270
|
+
const controlX = usesRight ? layout.rightChannel : layout.leftChannel;
|
|
271
|
+
const start = anchor(from, DEPART_FRACTION, facingSide(from, to, controlX));
|
|
272
|
+
const end = anchor(to, ARRIVE_FRACTION, facingSide(to, from, controlX));
|
|
273
|
+
const controlY = (start.y + end.y) / 2;
|
|
274
|
+
const round = (value) => (Math.round(value * 100) / 100).toFixed(2);
|
|
275
|
+
const d = `M ${round(start.x)} ${round(start.y)} Q ${round(controlX)} ${round(controlY)} ${round(end.x)} ${round(end.y)}`;
|
|
276
|
+
return {
|
|
277
|
+
d,
|
|
278
|
+
start,
|
|
279
|
+
end,
|
|
280
|
+
endAngle: Math.atan2(end.y - controlY, end.x - controlX),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/** The box enclosing a together unit's members, padded clear of their bounds. */
|
|
284
|
+
export function enclosureBounds(layout, members, theme) {
|
|
285
|
+
const boxes = members
|
|
286
|
+
.map((member) => layout.nodes.get(member))
|
|
287
|
+
.filter((box) => box !== undefined);
|
|
288
|
+
if (boxes.length < 2)
|
|
289
|
+
return null;
|
|
290
|
+
const pad = metric(theme, '--ig-space-tight');
|
|
291
|
+
const x = Math.min(...boxes.map((box) => box.x)) - pad;
|
|
292
|
+
const y = Math.min(...boxes.map((box) => box.y)) - pad;
|
|
293
|
+
const right = Math.max(...boxes.map((box) => box.x + box.width)) + pad;
|
|
294
|
+
const bottom = Math.max(...boxes.map((box) => box.y + box.height)) + pad;
|
|
295
|
+
return { x, y, width: right - x, height: bottom - y };
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
|
package/dist/mount.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The DOM shell — the only module in this package that touches nodes.
|
|
3
|
+
*
|
|
4
|
+
* It is deliberately thin. Everything that could be wrong about WHAT is drawn
|
|
5
|
+
* lives in the projections, everything that could be wrong about WHERE
|
|
6
|
+
* navigation goes lives in `navigate`, and what is left here is three
|
|
7
|
+
* listeners, an index from key to element, and a teardown. A shell that grew
|
|
8
|
+
* decisions would be a second implementation of the parts above it, testable
|
|
9
|
+
* only through a DOM.
|
|
10
|
+
*
|
|
11
|
+
* IT REACHES NO GLOBAL. The document comes from the container the caller
|
|
12
|
+
* passed, which is what keeps this module importable on a runtime that has no
|
|
13
|
+
* DOM — the property the workspace smoke test measures against the published
|
|
14
|
+
* entry.
|
|
15
|
+
*/
|
|
16
|
+
import { type ViewerDocument } from './document.ts';
|
|
17
|
+
import { type SpecDocument, type SpecElement } from './element.ts';
|
|
18
|
+
import { type NavigationState } from './navigation.ts';
|
|
19
|
+
import { type RenderOptions } from './render.ts';
|
|
20
|
+
import { type Projection } from './scene.ts';
|
|
21
|
+
/** The slice of an element `mount` needs beyond building. */
|
|
22
|
+
export interface MountElement extends SpecElement {
|
|
23
|
+
readonly ownerDocument: SpecDocument;
|
|
24
|
+
/** Upper-case, as the DOM reports it. Absent on an implementation that has none. */
|
|
25
|
+
readonly tagName?: string;
|
|
26
|
+
addEventListener(type: string, handler: (event: MountEvent) => void): void;
|
|
27
|
+
removeEventListener(type: string, handler: (event: MountEvent) => void): void;
|
|
28
|
+
removeChild(child: SpecElement): void;
|
|
29
|
+
getAttribute(name: string): string | null;
|
|
30
|
+
readonly parentElement: MountElement | null;
|
|
31
|
+
focus?(): void;
|
|
32
|
+
}
|
|
33
|
+
/** The slice of an event `mount` reads. */
|
|
34
|
+
export interface MountEvent {
|
|
35
|
+
readonly target?: MountElement | null;
|
|
36
|
+
/** Present on a keyboard event. */
|
|
37
|
+
readonly key?: string;
|
|
38
|
+
preventDefault?(): void;
|
|
39
|
+
}
|
|
40
|
+
export interface MountOptions extends RenderOptions {
|
|
41
|
+
/** Called when a key is selected — by click, `Enter`, or `select()`. */
|
|
42
|
+
readonly onSelect?: ((key: string | null) => void) | undefined;
|
|
43
|
+
/** Called with the hovered key, and with `null` when nothing is hovered. */
|
|
44
|
+
readonly onHover?: ((key: string | null) => void) | undefined;
|
|
45
|
+
}
|
|
46
|
+
export interface ViewerHandle {
|
|
47
|
+
/** Redraw. A still-present selection survives; focus follows it. */
|
|
48
|
+
update(input: ViewerDocument, options?: MountOptions): void;
|
|
49
|
+
/** Switch projection. The subject is kept; only the representation changes. */
|
|
50
|
+
setProjection(projection: Projection): void;
|
|
51
|
+
/** Select a key programmatically. Fires `onSelect` exactly as a click does. */
|
|
52
|
+
select(key: string | null): void;
|
|
53
|
+
readonly state: NavigationState;
|
|
54
|
+
/** Remove every listener this handle added and empty the container. */
|
|
55
|
+
destroy(): void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Mount a viewer into a container.
|
|
59
|
+
*
|
|
60
|
+
* Returns a handle rather than nothing, because a host that cannot tear this
|
|
61
|
+
* down leaks a listener on every re-render — the shell's one genuine hazard.
|
|
62
|
+
*/
|
|
63
|
+
export declare function mountViewer(container: MountElement, input: ViewerDocument, options?: MountOptions): ViewerHandle;
|
|
64
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAA2B,KAAK,cAAc,EAAqB,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAe,MAAM,cAAc,CAAC;AAChF,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,aAAa,EAAY,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAkC,KAAK,UAAU,EAAc,MAAM,YAAY,CAAC;AAGzF,6DAA6D;AAC7D,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,aAAa,EAAE,YAAY,CAAC;IACrC,oFAAoF;IACpF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3E,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IAC9E,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,IAAI,IAAI,CAAC;CAChB;AAED,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACtC,mCAAmC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,IAAI,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/D,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC/D;AAED,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5C,+EAA+E;IAC/E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,uEAAuE;IACvE,OAAO,IAAI,IAAI,CAAC;CACjB;AAoED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,YAAY,EACvB,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,YAAiB,GACzB,YAAY,CAqTd"}
|