@graview/layout 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 (47) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +20 -0
  3. package/dist/band.d.ts +103 -0
  4. package/dist/band.d.ts.map +1 -0
  5. package/dist/band.js +344 -0
  6. package/dist/band.js.map +1 -0
  7. package/dist/city.d.ts +161 -0
  8. package/dist/city.d.ts.map +1 -0
  9. package/dist/city.js +319 -0
  10. package/dist/city.js.map +1 -0
  11. package/dist/ids.d.ts +79 -0
  12. package/dist/ids.d.ts.map +1 -0
  13. package/dist/ids.js +115 -0
  14. package/dist/ids.js.map +1 -0
  15. package/dist/index.d.ts +19 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +10 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/interpolate.d.ts +27 -0
  20. package/dist/interpolate.d.ts.map +1 -0
  21. package/dist/interpolate.js +217 -0
  22. package/dist/interpolate.js.map +1 -0
  23. package/dist/label-fit.d.ts +115 -0
  24. package/dist/label-fit.d.ts.map +1 -0
  25. package/dist/label-fit.js +162 -0
  26. package/dist/label-fit.js.map +1 -0
  27. package/dist/layout.d.ts +99 -0
  28. package/dist/layout.d.ts.map +1 -0
  29. package/dist/layout.js +1391 -0
  30. package/dist/layout.js.map +1 -0
  31. package/dist/rank.d.ts +35 -0
  32. package/dist/rank.d.ts.map +1 -0
  33. package/dist/rank.js +84 -0
  34. package/dist/rank.js.map +1 -0
  35. package/dist/related.d.ts +42 -0
  36. package/dist/related.d.ts.map +1 -0
  37. package/dist/related.js +207 -0
  38. package/dist/related.js.map +1 -0
  39. package/dist/types.d.ts +404 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +27 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/view-state.d.ts +189 -0
  44. package/dist/view-state.d.ts.map +1 -0
  45. package/dist/view-state.js +350 -0
  46. package/dist/view-state.js.map +1 -0
  47. package/package.json +54 -0
@@ -0,0 +1,404 @@
1
+ export type Plane = 0 | 1 | 2;
2
+ /**
3
+ * An aggregate node is first-class, not a scale fallback. "People" is a
4
+ * legitimate view of a kind, which is why grouping and semantic zoom are one
5
+ * mechanism running in both directions.
6
+ */
7
+ export interface Aggregate {
8
+ readonly kind: string;
9
+ readonly memberIds: readonly string[];
10
+ /** Plural label from the kind's declaration, e.g. "People". */
11
+ readonly label: string;
12
+ /**
13
+ * How many members sit BEHIND the horizon — retired under their kind's
14
+ * declared lifecycle and not in memberIds while the view is on "now".
15
+ * Advertised, never hidden: archived must not mean invisible-and-
16
+ * forgotten.
17
+ */
18
+ readonly retired?: number;
19
+ /**
20
+ * Where pressing it goes, for an aggregate the relation band drew because
21
+ * not all could stand (docs/scale.md): a group opens in place, through the
22
+ * `expanded` stop; "+N more" opens the kind's picture, filtered by the
23
+ * relation. Absent on a kind's own group, which travels as it always did.
24
+ */
25
+ readonly opens?: Opens;
26
+ }
27
+ /** Where pressing a band aggregate goes: open in place, or through to the kind's picture. */
28
+ export type Opens = {
29
+ readonly in: "place";
30
+ } | {
31
+ readonly in: "picture";
32
+ readonly focus: string;
33
+ readonly within: Readonly<Record<string, string>>;
34
+ };
35
+ /**
36
+ * Why a node is on plane 1 at all: the edge that reached it, in the schema's
37
+ * own words.
38
+ *
39
+ * Every edge declaration already carries a description — "who does the run",
40
+ * "a nap that must not be interrupted" — and until now nothing in the
41
+ * interface ever showed it. Carrying it through the layout means a raised
42
+ * node can say what its relationship to the focus IS, rather than merely
43
+ * sitting near it and leaving the reader to guess.
44
+ */
45
+ export interface Via {
46
+ readonly edgeKind: string;
47
+ readonly direction: "out" | "in";
48
+ /**
49
+ * How the relation reads FROM THE FOCUS: the declaration's `description`
50
+ * along an outgoing edge, its `inverse` along an incoming one. Absent when
51
+ * the declaration has no words for this direction.
52
+ */
53
+ readonly description?: string;
54
+ }
55
+ export interface LayoutNode {
56
+ /** A real node id, or `aggregate:<kind>` for a group. */
57
+ readonly id: string;
58
+ readonly kind: string;
59
+ readonly plane: Plane;
60
+ readonly x: number;
61
+ readonly y: number;
62
+ readonly width: number;
63
+ readonly height: number;
64
+ /** Set when this node stands in for a group rather than one graph node. */
65
+ readonly aggregate?: Aggregate;
66
+ /**
67
+ * The size this view should LAY ITSELF OUT at, when that differs from the
68
+ * size it is drawn at.
69
+ *
70
+ * A view asked to lay out at a third of its intended width has no reason
71
+ * to work, and none of the lenses was written to: the coverage matrix
72
+ * piles its rotated headers into a corner and clips its rows. Shrinking
73
+ * should mean the same picture, smaller — render at the natural size and
74
+ * scale the result, which is what a captured texture would do anyway.
75
+ */
76
+ readonly natural?: {
77
+ readonly width: number;
78
+ readonly height: number;
79
+ };
80
+ /**
81
+ * How far back this node sits WITHIN its plane. 1 is fully at the plane's
82
+ * depth, 0 is pulled forward toward the one in front of it.
83
+ *
84
+ * The planes are discrete because the model is discrete, but a row of ten
85
+ * cards all at exactly plane 2 reads as a flat strip pinned to the bottom
86
+ * of the screen. Giving each a depth of its own turns the row into an arc
87
+ * curving away, and turns the thing in focus into something you are
88
+ * standing in front of.
89
+ */
90
+ readonly depth?: number;
91
+ /** Set on plane 1 when this node was reached by following an edge. */
92
+ readonly via?: Via;
93
+ /**
94
+ * A group whose members are currently raised onto plane 1.
95
+ *
96
+ * It stays where it was, emptied, so the eye can tie the relation plane
97
+ * back to where it came from. Without it the only evidence of what is
98
+ * raised is the breadcrumb, and a spatial interface should not need to be
99
+ * read.
100
+ */
101
+ readonly raised?: boolean;
102
+ /**
103
+ * How near this kind is to the one in focus: one declared edge away, or
104
+ * further.
105
+ *
106
+ * Nine kinds as nine identical thumbnails says nothing about which of them
107
+ * matter. The rank comes from the SCHEMA rather than the graph, so an
108
+ * unrelated edit can never promote a kind and shuffle the strip.
109
+ */
110
+ readonly rank?: "primary" | "secondary";
111
+ /**
112
+ * The kind card this one hangs off, when it is reachable only THROUGH that
113
+ * one. A nested relationship should read as nested rather than being
114
+ * flattened into a sibling.
115
+ */
116
+ readonly nestedUnder?: string;
117
+ /**
118
+ * The kinds this card STANDS FOR, when the row could not hold them all at
119
+ * a width their names can be read at.
120
+ *
121
+ * A district is read, not glanced at, so the row never squeezes a name
122
+ * below a word: past what it can hold it keeps the ones that fit and hands
123
+ * the rest to one card that names them. Not a kind of its own — it has no
124
+ * members and no figure — which is why it is said here rather than by
125
+ * giving it a kind nobody declared.
126
+ */
127
+ readonly beyond?: readonly string[];
128
+ /**
129
+ * A group standing for the kind currently in focus.
130
+ *
131
+ * It stays on the kinds plane rather than being removed, so the strip is a
132
+ * constant map and you can see that the picture above IS this kind.
133
+ */
134
+ readonly focused?: boolean;
135
+ /**
136
+ * An aggregate card OPENED IN PLACE — from altitude, a district showing
137
+ * its members without dissolving into them. Inside the stack an expanded
138
+ * aggregate dissolves instead; up on the ring dissolving would re-flow
139
+ * every stop and break the map.
140
+ */
141
+ readonly opened?: boolean;
142
+ /**
143
+ * HOW MANY ROWS OF MEMBERS an opened district has room for: what the
144
+ * layout reserved under its nameplate, in rows of `ROSTER_ROW`. The view
145
+ * lists that many and counts the rest, so the roster ends where the room
146
+ * does rather than running under the district below.
147
+ */
148
+ readonly openedRows?: number;
149
+ /**
150
+ * A card in a CROWDED band: drawn as a chip whatever its slot's size. Its
151
+ * row is sized for a group card's two lines, which is short of a record's
152
+ * summary, and a summary cut to its title and a sliver read as broken.
153
+ */
154
+ readonly compact?: boolean;
155
+ /**
156
+ * WHERE THIS DISTRICT STANDS IN THE CITY, in lattice cells — its address.
157
+ *
158
+ * Set on a kind card at altitude, from the declaration's own map
159
+ * (`cityMap`), never from the data: the corner a person remembers is the
160
+ * corner they get back. `side` is how many cells it takes today.
161
+ */
162
+ readonly plot?: {
163
+ readonly col: number;
164
+ readonly row: number;
165
+ readonly side: number;
166
+ };
167
+ /**
168
+ * THE SCREEN OF A DRIVE-IN: this plane-0 node is a kind's own picture,
169
+ * standing on that kind's plot from altitude rather than floating in the
170
+ * middle. Names the kind, so the audience strip in front of it can be
171
+ * found (`whereIs("screen:<kind>")`) and the tween can carry it.
172
+ */
173
+ readonly screenOf?: string;
174
+ /** True when the user pinned this position rather than the layout choosing it. */
175
+ readonly pinned: boolean;
176
+ }
177
+ export interface Connector {
178
+ readonly id: string;
179
+ /** The edge kind, so stroke treatment can carry meaning. */
180
+ readonly kind: string;
181
+ /**
182
+ * Both ends resolve to the same drawn thing — "a task waits for a task".
183
+ *
184
+ * Real and worth drawing: it is a fact about the domain, and the one place
185
+ * you would look for it is the picture of the whole domain. Drawn as a loop
186
+ * rather than as a line of zero length.
187
+ */
188
+ readonly loop?: boolean;
189
+ /**
190
+ * The ONE graph edge this line stands for, when it stands for exactly
191
+ * one — both drawn endpoints are the real nodes. A line into a group
192
+ * bundles many edges and says "some of these"; only a single line is an
193
+ * honest thing to select and act on.
194
+ */
195
+ readonly single?: {
196
+ readonly from: string;
197
+ readonly to: string;
198
+ };
199
+ /**
200
+ * EVERY graph edge this line stands for, in the order the walk met them.
201
+ *
202
+ * A line into a group is a bundle, and a bundle that only knew its count
203
+ * could not be unpicked: the week's panel draws each session as its own
204
+ * span, and a renderer that can see the span wants to start the session's
205
+ * line THERE rather than at the panel's centre. That needs the real ends
206
+ * of each edge, not just the drawn ends of the line. `single` is the
207
+ * one-edge case of this, kept because a line that stands for one edge is
208
+ * the only honest thing to select.
209
+ */
210
+ readonly edges: readonly {
211
+ readonly from: string;
212
+ readonly to: string;
213
+ }[];
214
+ readonly from: string;
215
+ readonly to: string;
216
+ /** Endpoints in layout space, centre to centre. */
217
+ readonly x1: number;
218
+ readonly y1: number;
219
+ readonly x2: number;
220
+ readonly y2: number;
221
+ }
222
+ /**
223
+ * THE LATTICE THE CITY WAS DRAWN ON, so the ground can draw the same one
224
+ * and the camera can know how far the city reaches. `cell` is one lattice
225
+ * cell's width in pixels (its height is half); `originX/Y` is where cell
226
+ * (0,0) meets the canvas before the pan. `extent` is the city's bounding
227
+ * box in canvas pixels, unpanned.
228
+ */
229
+ export interface CityFrame {
230
+ readonly cell: number;
231
+ readonly originX: number;
232
+ readonly originY: number;
233
+ /**
234
+ * THE PAN THIS CITY WAS PLACED WITH, so the ground can ride the same
235
+ * tween its cards do.
236
+ *
237
+ * The pan is baked into every card's coordinates at layout time, which
238
+ * is what lets two layouts be interpolated into motion. The lattice and
239
+ * the plots under them were drawn from the LIVE pan instead — so the
240
+ * ground snapped to its destination on the frame the view changed while
241
+ * the cards were still on their way, which reads as the picture flashing
242
+ * to the new place and the buildings catching up.
243
+ */
244
+ readonly pan: {
245
+ readonly x: number;
246
+ readonly y: number;
247
+ };
248
+ readonly extent: {
249
+ readonly x: number;
250
+ readonly y: number;
251
+ readonly width: number;
252
+ readonly height: number;
253
+ };
254
+ /** How much of an opened district's roster the city kept room for: 1 is all of it. */
255
+ readonly openedShare?: number;
256
+ }
257
+ export interface Layout {
258
+ readonly nodes: readonly LayoutNode[];
259
+ readonly connectors: readonly Connector[];
260
+ readonly width: number;
261
+ readonly height: number;
262
+ /** Present at altitude: the lattice the districts were placed on. */
263
+ readonly city?: CityFrame;
264
+ }
265
+ export interface LayoutOptions {
266
+ readonly width?: number;
267
+ readonly height?: number;
268
+ /** Size of the focus view at plane 0. */
269
+ readonly focusSize?: {
270
+ width: number;
271
+ height: number;
272
+ };
273
+ readonly relationSize?: {
274
+ width: number;
275
+ height: number;
276
+ };
277
+ readonly contextSize?: {
278
+ width: number;
279
+ height: number;
280
+ };
281
+ readonly gap?: number;
282
+ /**
283
+ * WHAT ONE `rem` IS WORTH, IN PIXELS — the reader's own text size.
284
+ *
285
+ * The cards in this layout hold text, and that text is sized in `rem` so
286
+ * a reader who asks for bigger words gets them everywhere. The cards were
287
+ * sized in pixels off the stage, so they did not hear about it: at 200%
288
+ * every name in the city doubled inside a district card that stayed
289
+ * exactly 230×97, and the picture came apart — a headline in a glyph.
290
+ *
291
+ * Sizing them in this unit instead makes the city grow WITH the reader.
292
+ * It grows until the ring is full and then stops, because a card is only
293
+ * worth making bigger while it still has somewhere to stand.
294
+ *
295
+ * 16 is the browser's own default and therefore the no-op: every existing
296
+ * caller lays out exactly as it did.
297
+ */
298
+ readonly unit?: number;
299
+ /** Plural labels by kind, from the schema. */
300
+ readonly plurals?: Readonly<Record<string, string>>;
301
+ /**
302
+ * The day the horizon is judged against (ISO date). Injectable so a test
303
+ * or a pinned survey judges a different day; defaults to the real one.
304
+ */
305
+ readonly today?: string;
306
+ /**
307
+ * Node kinds this installation has turned OFF — a workspace's disabled
308
+ * modules, projected once by the store. Their nodes stay in the graph and
309
+ * simply are not drawn: no kind card, no membership, no raised plane.
310
+ * Turning a module back on is the whole undo.
311
+ */
312
+ readonly hiddenKinds?: readonly string[];
313
+ /**
314
+ * WHAT A NODE JUDGES, by its id: the nodes its current violations name.
315
+ * A rule has no edges, so a focused rule used to raise nothing — or,
316
+ * with a relation named, every node of that kind wholesale — and its
317
+ * card said nothing was connected while the picture showed twelve. What
318
+ * a rule is about is derivable from its violations; the scene supplies
319
+ * them here so the layout can draw them as its neighbourhood.
320
+ */
321
+ readonly judged?: Readonly<Record<string, readonly string[]>>;
322
+ /**
323
+ * WHAT STANDS AS ITSELF when a relation does not fit the band: the
324
+ * selection and its reach, the search's hits, the flagged, the recently
325
+ * written. The scene knows them; the layout only ranks by them.
326
+ */
327
+ readonly relevance?: {
328
+ readonly chosen?: ReadonlySet<string>;
329
+ readonly hits?: ReadonlySet<string>;
330
+ readonly flagged?: ReadonlySet<string>;
331
+ readonly touched?: ReadonlyMap<string, number>;
332
+ };
333
+ /**
334
+ * Room the picture must leave for chrome that lives ON the scene — the
335
+ * left rail at altitude, where the relation key and the inspector sit.
336
+ * The ring and the focused card centre within what is left, so a
337
+ * district is never drawn under a pane. Nothing is reserved by default.
338
+ */
339
+ readonly inset?: {
340
+ readonly left?: number;
341
+ readonly right?: number;
342
+ };
343
+ /**
344
+ * Kinds whose group is shown by the framework's own list rather than a
345
+ * view the app wrote. From altitude a focused group of such a kind is its
346
+ * district, opened — drawing the list scaled in the middle AND the same
347
+ * names in the district was the same thing twice. A group with a real
348
+ * view — a week, a board — keeps its scaled card, since that picture is
349
+ * the thing you were standing in.
350
+ */
351
+ readonly plainGroups?: readonly string[];
352
+ /**
353
+ * THE ORDER A BLANK INSTALLATION FILLS ITS KINDS — `beginning(app).order`
354
+ * — which is the order the city is walked in. Sorted ids otherwise, which
355
+ * is deterministic too, only less meaningful.
356
+ */
357
+ readonly cityOrder?: readonly string[];
358
+ /** Hand-laid plots by kind, from a brand kit; a kind's own `plot` wins first. */
359
+ readonly plots?: Readonly<Record<string, {
360
+ readonly col: number;
361
+ readonly row: number;
362
+ }>>;
363
+ /**
364
+ * THE SHOWINGS each kind has — its named Places — so a focused picture
365
+ * from altitude can stand on its kind's plot as a screen, and a picture
366
+ * over two kinds (`across`) on the road between them. A kind with none
367
+ * has no drive-in: its group opens in place, as it always did.
368
+ */
369
+ readonly screens?: Readonly<Record<string, readonly {
370
+ readonly as: string;
371
+ readonly title: string;
372
+ readonly across?: string;
373
+ }[]>>;
374
+ /**
375
+ * FLY CLOSER. A factor on the city's cell from altitude — 1 is the whole
376
+ * map fitted to the window; 1.5 is the camera brought in toward the
377
+ * picture a person chose, plots and villages and roads all bigger, the
378
+ * city allowed past the window's edge (the camera pans to reach it).
379
+ */
380
+ readonly cityZoom?: number;
381
+ /**
382
+ * HOW TALL THE PICTURE ON THE BILLBOARD ACTUALLY DRAWS, in the lens's own
383
+ * natural pixels, measured by whoever renders it. A lens is laid out in a
384
+ * box as tall as the window so it never scrolls, but a short lens fills
385
+ * only the top of it — and a billboard sized to the whole box stood its
386
+ * picture a village's height above the kerb, floating over the next
387
+ * district with empty room beneath. Cut to what is drawn, the picture's
388
+ * foot is on the kerb. Absent (or not yet measured): the whole box.
389
+ */
390
+ readonly screenHeight?: number;
391
+ }
392
+ /**
393
+ * Three bands, chosen so the planes never overlap at their own scales.
394
+ *
395
+ * Sizes are in layout units; the plane's scale shrinks the drawn box in
396
+ * place, so a band's height is its size times that scale.
397
+ */
398
+ /**
399
+ * Sizes here are CAPS, not fixed boxes: a band fits its contents across the
400
+ * canvas and never exceeds the cap. Heights come from the band proportions in
401
+ * `layout()`, which is what keeps the composition together at any size.
402
+ */
403
+ export declare const DEFAULT_OPTIONS: Required<Omit<LayoutOptions, "plurals" | "today" | "hiddenKinds" | "inset" | "plainGroups" | "judged" | "relevance" | "cityOrder" | "plots" | "screens" | "cityZoom" | "screenHeight">>;
404
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Three bands, chosen so the planes never overlap at their own scales.
3
+ *
4
+ * Sizes are in layout units; the plane's scale shrinks the drawn box in
5
+ * place, so a band's height is its size times that scale.
6
+ */
7
+ /**
8
+ * Sizes here are CAPS, not fixed boxes: a band fits its contents across the
9
+ * canvas and never exceeds the cap. Heights come from the band proportions in
10
+ * `layout()`, which is what keeps the composition together at any size.
11
+ */
12
+ export const DEFAULT_OPTIONS = {
13
+ width: 1200,
14
+ height: 760,
15
+ focusSize: { width: 1200, height: 420 },
16
+ relationSize: { width: 240, height: 140 },
17
+ /*
18
+ * A kind card is a GLYPH: a name, a count, and how much of it is in
19
+ * trouble. At 150 it was sized for two clamped lines of prose that have
20
+ * since moved to the tooltip, and the band it sits in took a fifth of the
21
+ * window to hold cards covering a tenth of it.
22
+ */
23
+ contextSize: { width: 300, height: 104 },
24
+ gap: 16,
25
+ unit: 16,
26
+ };
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAoWA;;;;;GAKG;AACH;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAA4L;IACtN,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,GAAG;IACX,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACvC,YAAY,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACzC;;;;;OAKG;IACH,WAAW,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACxC,GAAG,EAAE,EAAE;IACP,IAAI,EAAE,EAAE;CACT,CAAC"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * A view state is a stop. Every stop is a URL, so the back button returns to
3
+ * exactly the view you left — no free orbit, nothing unnameable.
4
+ */
5
+ export interface Pin {
6
+ readonly x: number;
7
+ readonly y: number;
8
+ }
9
+ export interface ViewState {
10
+ /** The node at plane 0, live and editable. Null means the default view. */
11
+ readonly focusId: string | null;
12
+ /**
13
+ * What plane 1 shows: an edge kind to follow from the focus, or a node kind
14
+ * to raise. Null leaves plane 1 empty.
15
+ */
16
+ readonly relation: string | null;
17
+ /** Aggregates the user has opened, by aggregate id. */
18
+ readonly expanded: readonly string[];
19
+ /** User positions that override the computed ones. */
20
+ readonly pins: Readonly<Record<string, Pin>>;
21
+ /**
22
+ * Where the camera has been dragged, in canvas pixels.
23
+ *
24
+ * A stop, like everything else here: it goes in the URL, it interpolates,
25
+ * and the same address gives the same picture. A pan held outside the view
26
+ * state would be the one thing about the scene you could not share, link to
27
+ * or go back to.
28
+ */
29
+ readonly pan?: Pin;
30
+ /**
31
+ * Looking at the whole graph from outside the plane stack.
32
+ *
33
+ * A view state rather than a mode, because it has to INTERPOLATE from
34
+ * wherever you were: the kinds already on screen fly from their row into a
35
+ * ring, and the thing you were looking at recedes into the middle. A
36
+ * separate surface could only cut, and cutting loses the one thing an
37
+ * overview is for.
38
+ */
39
+ readonly overview?: boolean;
40
+ /**
41
+ * The HORIZON widened: retired nodes shown alongside current ones.
42
+ *
43
+ * A stop like every other — a URL, a back-button entry, tweenable — so
44
+ * "show me the retired agreements" is a place you go and come back from,
45
+ * not a setting you forget you flipped.
46
+ */
47
+ readonly past?: boolean;
48
+ /**
49
+ * Modules drawn only for those who administer them, SHOWN at this stop:
50
+ * the installation's own users and invitations raised beside the domain.
51
+ * A stop like any other — in the URL, so an embed can open on it and Back
52
+ * knows the way out — and never on for a seat that may not see them; the
53
+ * provider keeps what it may not show out of the picture whatever the
54
+ * address says.
55
+ */
56
+ readonly shown?: readonly string[];
57
+ /**
58
+ * What is SELECTED, as part of the stop.
59
+ *
60
+ * Selection used to live only in component state, which broke the central
61
+ * promise twice over: back/forward restored the view but stranded the
62
+ * selection — the inspector kept talking about a thing from a stop you had
63
+ * already left — and a shared link could name the place but not the thing.
64
+ * If the pane on the left depends on it, it is part of where you are.
65
+ */
66
+ readonly selection?: readonly string[];
67
+ /**
68
+ * Zoomed in close: the focus takes most of the scene — most, not all —
69
+ * and the kinds shelf and any raised relation recede rather than vanish.
70
+ *
71
+ * A view state rather than a page, because jacking in used to JUMP: a
72
+ * modal document over the scene, isolated from every relation the thing
73
+ * has. A stop interpolates from wherever you were, so going deeper reads
74
+ * as zooming in and leaving as zooming out, and the back button knows it.
75
+ */
76
+ readonly zoom?: boolean;
77
+ /**
78
+ * WHERE A VIEW IS INSIDE ITSELF.
79
+ *
80
+ * A calendar showing October is somewhere, and it is somewhere a person
81
+ * can be sent, come back to and press Back out of. Everything else about
82
+ * a stop is the framework's own vocabulary — a focus, a relation, an
83
+ * altitude — and a view that arranges its own dimension has nowhere to
84
+ * say so, which is why the week grid could only ever show one week.
85
+ *
86
+ * A flat map of short keys, written into the fragment as `in.<key>`,
87
+ * owned by whichever view is drawing. The framework never reads a key; it
88
+ * only carries it, so that "the month I was looking at" is a URL like
89
+ * every other place in this system rather than component state that the
90
+ * back button silently loses.
91
+ */
92
+ readonly within?: Readonly<Record<string, string>>;
93
+ /**
94
+ * WHAT IS BEING LOOKED FOR, over the whole picture.
95
+ *
96
+ * A search is a stop: `#q=van` lights what the words find and dims the
97
+ * rest wherever you are looking, a link carries it, and Back returns to
98
+ * it. Not a key of `within`, because it is not one view's business — it
99
+ * applies to every district at once — and it outlives a change of focus,
100
+ * so descending into a lit district keeps the rest of the city lit
101
+ * behind you. Typing is an ADJUSTMENT of the stop, like a pan: the
102
+ * address is replaced on each keystroke rather than pushed.
103
+ */
104
+ readonly q?: string;
105
+ }
106
+ export declare const EMPTY_VIEW: ViewState;
107
+ /**
108
+ * Serialises a view to a URL fragment. Keys are sorted and lists are sorted,
109
+ * so the same view always produces the same string — which is what makes
110
+ * "did the view change?" a string comparison and history entries stable.
111
+ */
112
+ export declare function toUrl(state: ViewState): string;
113
+ export declare function fromUrl(url: string): ViewState;
114
+ /** Two views are the same stop when they serialise the same. */
115
+ export declare function sameView(a: ViewState, b: ViewState): boolean;
116
+ /**
117
+ * A RELATION in the selection: `edge:<kind>:<from>:<to>`, each part escaped.
118
+ *
119
+ * Lines joined the selection model after nodes did, and for the same
120
+ * reason the selection is in the URL at all — an inspector about a thing
121
+ * you cannot name is an inspector you cannot share or return to.
122
+ *
123
+ * THE SEPARATOR CANNOT BE A CHARACTER AN ID MAY CONTAIN. This used to say
124
+ * that node ids never hold a ":" and leave it there, and the framework's own
125
+ * `ctx.freshId(label, kind)` mints "item:buy-milk" — so in every scaffolded
126
+ * app the three-part split came back with five parts, `edgeOfSelection`
127
+ * returned null, and a selected line fell through to the inspector's
128
+ * "nothing can be done with this mix of kinds" while the strip's title was
129
+ * the raw selection string. Escaping each part is the fix that does not
130
+ * depend on what an app calls things.
131
+ */
132
+ export declare const EDGE_SELECTION_PREFIX = "edge:";
133
+ export declare function edgeSelectionId(kind: string, from: string, to: string): string;
134
+ export interface EdgeRef {
135
+ readonly kind: string;
136
+ readonly from: string;
137
+ readonly to: string;
138
+ }
139
+ /** The edge a selection entry names, or null when it names a node. */
140
+ export declare function edgeOfSelection(id: string): EdgeRef | null;
141
+ export declare function withFocus(state: ViewState, focusId: string | null): ViewState;
142
+ export declare function withRelation(state: ViewState, relation: string | null): ViewState;
143
+ /**
144
+ * Moves a view along its own dimension — the month a calendar is showing,
145
+ * the range it is showing it in.
146
+ *
147
+ * A stop like any other: it goes in the address, Back returns to it, and a
148
+ * link carries it. `null` clears the key rather than writing an empty one,
149
+ * so "no answer" and "the answer is empty" stay different things.
150
+ */
151
+ export declare function withWithin(state: ViewState, key: string, value: string | null): ViewState;
152
+ export declare function withOverview(state: ViewState, overview: boolean): ViewState;
153
+ /** Show or hide a module drawn only for those who administer it. */
154
+ export declare function withShown(state: ViewState, module: string, shown: boolean): ViewState;
155
+ /** Look for words across the picture, or stop looking. Blank is no search. */
156
+ export declare function withQuery(state: ViewState, q: string | null): ViewState;
157
+ /**
158
+ * Stop looking: the search, and the words it carried into the district it
159
+ * lit. A row's own words — typed there, different from the search — stay.
160
+ */
161
+ export declare function withoutSearch(state: ViewState): ViewState;
162
+ /** Widen the horizon to include the past, or narrow it back to now. */
163
+ export declare function withPast(state: ViewState, past: boolean): ViewState;
164
+ /**
165
+ * Change what is selected. An empty selection leaves no key behind — the
166
+ * default state serialises to the default URL.
167
+ */
168
+ export declare function withSelection(state: ViewState, selection: readonly string[]): ViewState;
169
+ /** Zoom the focus in close, or back out. */
170
+ export declare function withZoom(state: ViewState, zoom: boolean): ViewState;
171
+ /**
172
+ * Expanding an aggregate and collapsing it are the same operation in two
173
+ * directions — one code path, so semantic zoom and grouping cannot drift
174
+ * apart.
175
+ */
176
+ export declare function toggleExpanded(state: ViewState, aggregateId: string): ViewState;
177
+ /**
178
+ * Move the camera. `null` puts it back.
179
+ *
180
+ * Panning is an ADJUSTMENT of the stop you are on rather than a new stop —
181
+ * the same reason a pin is. `useUrlSync` replaces rather than pushes for both,
182
+ * so one drag is one history entry rather than sixty, and Back still means
183
+ * "the place I was before", not "one pixel ago".
184
+ */
185
+ export declare function withPan(state: ViewState, pan: Pin | null): ViewState;
186
+ /** Put everything the user moved back where the layout wanted it. */
187
+ export declare function withoutMoves(state: ViewState): ViewState;
188
+ export declare function withPin(state: ViewState, id: string, pin: Pin | null): ViewState;
189
+ //# sourceMappingURL=view-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-state.d.ts","sourceRoot":"","sources":["../src/view-state.ts"],"names":[],"mappings":"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"}