@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
package/LICENSE ADDED
@@ -0,0 +1,96 @@
1
+ Elastic License 2.0
2
+
3
+ ## Acceptance
4
+
5
+ By using the software, you agree to all of the terms and conditions below.
6
+
7
+ ## Copyright License
8
+
9
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
10
+ non-sublicensable, non-transferable license to use, copy, distribute, make
11
+ available, and prepare derivative works of the software, in each case subject
12
+ to the limitations and conditions below.
13
+
14
+ ## Limitations
15
+
16
+ You may not provide the software to third parties as a hosted or managed
17
+ service, where the service provides users with access to any substantial set
18
+ of the features or functionality of the software.
19
+
20
+ You may not move, change, disable, or circumvent the license key
21
+ functionality in the software, and you may not remove or obscure any
22
+ functionality in the software that is protected by the license key.
23
+
24
+ You may not alter, remove, or obscure any licensing, copyright, or other
25
+ notices of the licensor in the software. Any use of the licensor's trademarks
26
+ is subject to applicable law.
27
+
28
+ ## Patents
29
+
30
+ The licensor grants you a license, under any patent claims the licensor can
31
+ license, or becomes able to license, to make, have made, use, sell, offer for
32
+ sale, import and have imported the software, in each case subject to the
33
+ limitations and conditions in this license. This license does not cover any
34
+ patent claims that you cause to be infringed by modifications or additions to
35
+ the software. If you or your company make any written claim that the software
36
+ infringes or contributes to infringement of any patent, your patent license
37
+ for the software granted under these terms ends immediately. If your company
38
+ makes such a claim, your patent license ends immediately for work on behalf
39
+ of your company.
40
+
41
+ ## Notices
42
+
43
+ You must ensure that anyone who gets a copy of any part of the software from
44
+ you also gets a copy of these terms.
45
+
46
+ If you modify the software, you must include in any modified copies of the
47
+ software prominent notices stating that you have modified the software.
48
+
49
+ ## No Other Rights
50
+
51
+ These terms do not imply any licenses other than those expressly granted in
52
+ these terms.
53
+
54
+ ## Termination
55
+
56
+ If you use the software in violation of these terms, such use is not
57
+ licensed, and your licenses will automatically terminate. If the licensor
58
+ provides you with a notice of your violation, and you cease all violation of
59
+ this license no later than 30 days after you receive that notice, your
60
+ licenses will be reinstated retroactively. However, if you violate these
61
+ terms after such reinstatement, any additional violation of these terms will
62
+ cause your licenses to terminate automatically and permanently.
63
+
64
+ ## No Liability
65
+
66
+ *As far as the law allows, the software comes as is, without any warranty or
67
+ condition, and the licensor will not be liable to you for any damages arising
68
+ out of these terms or the use or nature of the software, under any kind of
69
+ legal claim.*
70
+
71
+ ## Definitions
72
+
73
+ The **licensor** is the entity offering these terms, and the **software** is
74
+ the software the licensor makes available under these terms, including any
75
+ portion of it.
76
+
77
+ **you** refers to the individual or entity agreeing to these terms.
78
+
79
+ **your company** is any legal entity, sole proprietorship, or other kind of
80
+ organization that you work for, plus all organizations that have control
81
+ over, are under the control of, or are under common control with that
82
+ organization. **control** means ownership of substantially all the assets of
83
+ an entity, or the power to direct its management and policies by vote,
84
+ contract, or otherwise. Control can be direct or indirect.
85
+
86
+ **your licenses** are all the licenses granted to you for the software under
87
+ these terms.
88
+
89
+ **use** means anything you do with the software requiring one of your
90
+ licenses.
91
+
92
+ **trademark** means trademarks, service marks, and similar rights.
93
+
94
+ ---
95
+
96
+ Copyright 2025-2026 En Dash Consulting
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # @graview/layout
2
+
3
+ Where everything goes, as a pure function.
4
+
5
+ ```ts
6
+ layout(graph, schema, view, options) -> Layout
7
+ ```
8
+
9
+ Same graph and same view state in, identical positions out. That purity is
10
+ what pays for the animation: `interpolate(a, b, t)` tweens ANY two layouts, so
11
+ a kind of navigation nobody anticipated animates like the ones that were
12
+ designed, and no transition is written by hand.
13
+
14
+ Three planes — focus, relations, context — plus a fourth altitude above the
15
+ stack where the kinds sit on a ring and your own interface stays live, shrunk,
16
+ in the middle of it. A node may declare a `natural` size distinct from the size
17
+ it is drawn at, and the renderer scales between them.
18
+
19
+ View state is a URL. Every stop has an address, the back button works, and
20
+ `sameView` decides whether two addresses are the same place.
package/dist/band.d.ts ADDED
@@ -0,0 +1,103 @@
1
+ import { type AnySchema, type ArrangeNode, type DateBucket, type GraphReader } from "@graview/core";
2
+ import type { Aggregate, Opens, Via } from "./types.js";
3
+ /** What makes a member stand as itself when not all can. */
4
+ export interface Relevance {
5
+ /** The selection, and what it reaches. */
6
+ readonly chosen?: ReadonlySet<string>;
7
+ /** What the search found. */
8
+ readonly hits?: ReadonlySet<string>;
9
+ /** What the rules implicate. */
10
+ readonly flagged?: ReadonlySet<string>;
11
+ /** Recently written, by the op log (`touchWeights`). */
12
+ readonly touched?: ReadonlyMap<string, number>;
13
+ }
14
+ export interface BandAggregate extends Aggregate {
15
+ readonly opens: Opens;
16
+ }
17
+ export interface BandItem<N extends ArrangeNode> {
18
+ readonly id: string;
19
+ readonly kind: string;
20
+ readonly node?: N;
21
+ readonly via?: Via;
22
+ readonly aggregate?: BandAggregate;
23
+ }
24
+ export interface Related<N> {
25
+ readonly node: N;
26
+ readonly via?: Via;
27
+ }
28
+ export interface BandOptions<N extends ArrangeNode> {
29
+ readonly schema: AnySchema;
30
+ readonly graph: GraphReader<N>;
31
+ /** Cards the band can hold legibly. */
32
+ readonly budget: number;
33
+ /** The focus the band is about: the far ends' filter for "+N more". */
34
+ readonly focusId: string | undefined;
35
+ readonly expanded: ReadonlySet<string>;
36
+ readonly relevance?: Relevance;
37
+ /** The stop's selection: it stands as itself before anything else. */
38
+ readonly selection?: readonly string[];
39
+ readonly plural: (kind: string) => string;
40
+ readonly today?: string;
41
+ }
42
+ /** A band aggregate's id: the kind, the relation, and which part of it. */
43
+ export declare const BAND_PREFIX = "aggregate:";
44
+ /** Whether an id names a band aggregate — a group or the rest of a relation — rather than a kind's group. */
45
+ export declare function isBandAggregate(id: string): boolean;
46
+ /**
47
+ * A band aggregate in words: "Albums — released by, type: album". Its id is
48
+ * the picture's own bookkeeping (`aggregate:album|released-by|in|type=album`)
49
+ * and was what the seat called it, in its header and to a screen reader.
50
+ */
51
+ export declare function bandAggregateWords(id: string, schema: AnySchema): string | null;
52
+ /**
53
+ * The share each run of the band gets: none below one, the small runs whole,
54
+ * the rest divided among the big ones — water-filling, so a relation of
55
+ * three is never squeezed to make room for a relation of a thousand.
56
+ */
57
+ export declare function shares(sizes: readonly number[], budget: number): number[];
58
+ /** The relation a related node is on: one edge kind in one direction, or a raised kind. */
59
+ export declare function runOf(entry: {
60
+ readonly node: {
61
+ readonly kind: string;
62
+ };
63
+ readonly via?: Via | undefined;
64
+ }): string;
65
+ /** Rows of `perRow`, each relation in order starting a row unless it fits the rest of the current one. */
66
+ export declare function packRuns(counts: readonly number[], perRow: number): number[][];
67
+ /**
68
+ * The cards each relation may draw so that, packed by relation, the band
69
+ * holds `rows` rows of `perRow`: water-filled as `shares` does, then the
70
+ * largest trimmed until the packing fits. Arithmetic only — the band is
71
+ * planned once, not tried.
72
+ */
73
+ export declare function bandCaps(sizes: readonly number[], perRow: number, rows: number): number[];
74
+ interface Grouping {
75
+ readonly by: string;
76
+ readonly bucket?: DateBucket;
77
+ readonly groups: readonly {
78
+ readonly key: string;
79
+ readonly label: string;
80
+ readonly nodes: readonly ArrangeNode[];
81
+ }[];
82
+ }
83
+ /**
84
+ * The best grouping of one kind's members into at most `share` groups, from
85
+ * what the kind's declaration offers — never the relation's own edge (every
86
+ * song on this band is BY the focus), never one group holding everything,
87
+ * and only when most of them are in a named group rather than "none".
88
+ */
89
+ export declare function chooseGrouping<N extends ArrangeNode>(members: readonly N[], share: number, options: {
90
+ readonly schema: AnySchema;
91
+ readonly graph: GraphReader<N>;
92
+ readonly exclude?: string;
93
+ readonly today?: string;
94
+ }): Grouping | undefined;
95
+ /**
96
+ * What the band draws: every related node when they fit; otherwise each
97
+ * relation within its share, as itself, as groups, or as the most relevant
98
+ * and one "+N more". Expanded groups stand open, their members within the
99
+ * relation's share.
100
+ */
101
+ export declare function bandOf<N extends ArrangeNode>(related: readonly Related<N>[], options: BandOptions<N>): BandItem<N>[];
102
+ export {};
103
+ //# sourceMappingURL=band.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"band.d.ts","sourceRoot":"","sources":["../src/band.ts"],"names":[],"mappings":"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"}
package/dist/band.js ADDED
@@ -0,0 +1,344 @@
1
+ import { arrange, arrangeable, fieldWords, humaniseField } from "@graview/core";
2
+ import { aggregateId } from "./ids.js";
3
+ /** A band aggregate's id: the kind, the relation, and which part of it. */
4
+ export const BAND_PREFIX = "aggregate:";
5
+ const runKey = (via, kind) => (via ? `${via.edgeKind}|${via.direction}` : `raised|${kind}`);
6
+ const groupId = (kind, run, part) => `${BAND_PREFIX}${kind}|${run}|${part}`;
7
+ /** Whether an id names a band aggregate — a group or the rest of a relation — rather than a kind's group. */
8
+ export function isBandAggregate(id) {
9
+ return id.startsWith(BAND_PREFIX) && id.includes("|");
10
+ }
11
+ /**
12
+ * A band aggregate in words: "Albums — released by, type: album". Its id is
13
+ * the picture's own bookkeeping (`aggregate:album|released-by|in|type=album`)
14
+ * and was what the seat called it, in its header and to a screen reader.
15
+ */
16
+ export function bandAggregateWords(id, schema) {
17
+ if (!isBandAggregate(id))
18
+ return null;
19
+ const [kind = "", first = "", second = "", part = ""] = id.slice(BAND_PREFIX.length).split("|");
20
+ const definition = schema.definitions.find((one) => one.kind === kind);
21
+ const plural = definition?.plural ?? humaniseField(`${kind}s`);
22
+ const relation = first === "raised"
23
+ ? null
24
+ : (() => {
25
+ const declared = schema.definitions.map((one) => one.edges[first]).find(Boolean);
26
+ const said = second === "in" ? declared?.inverse : declared?.description;
27
+ return (said ?? humaniseField(first)).toLowerCase();
28
+ })();
29
+ const [by = "", key = ""] = part.split("=");
30
+ const field = by.split(":")[0];
31
+ const detail = part === "" || part === "kind" || part.startsWith("more")
32
+ ? null
33
+ : `${fieldWords(definition, field).toLowerCase()}: ${key === "none" ? "none" : key}`;
34
+ const more = part.startsWith("more") ? `More ${plural.toLowerCase()}` : plural;
35
+ return [more, [relation, detail].filter(Boolean).join(", ")].filter(Boolean).join(" — ");
36
+ }
37
+ /**
38
+ * The share each run of the band gets: none below one, the small runs whole,
39
+ * the rest divided among the big ones — water-filling, so a relation of
40
+ * three is never squeezed to make room for a relation of a thousand.
41
+ */
42
+ export function shares(sizes, budget) {
43
+ const out = sizes.map(() => 0);
44
+ const order = sizes.map((size, index) => ({ size, index })).sort((a, b) => a.size - b.size || a.index - b.index);
45
+ let left = Math.max(budget, sizes.length);
46
+ let runs = sizes.length;
47
+ for (const { size, index } of order) {
48
+ const fair = Math.max(1, Math.floor(left / runs));
49
+ out[index] = Math.min(size, fair);
50
+ left -= out[index];
51
+ runs -= 1;
52
+ }
53
+ return out;
54
+ }
55
+ /** The relation a related node is on: one edge kind in one direction, or a raised kind. */
56
+ export function runOf(entry) {
57
+ return runKey(entry.via, entry.node.kind);
58
+ }
59
+ /*
60
+ * A CROWDED BAND IS LAID OUT BY RELATION (docs/scale.md, "What a crowd
61
+ * taught the band"). Relations filled one grid in turn, so a relation began
62
+ * wherever the last one ended — mid-row — and its caption, hung in the
63
+ * gutter above its first card, sat on the cards of the row before. A
64
+ * relation starts its own row unless all of it fits in what is left of the
65
+ * current one; then every caption has open ground above it.
66
+ */
67
+ /** Rows of `perRow`, each relation in order starting a row unless it fits the rest of the current one. */
68
+ export function packRuns(counts, perRow) {
69
+ const rows = [];
70
+ let left = 0;
71
+ counts.forEach((count, run) => {
72
+ if (count <= 0)
73
+ return;
74
+ if (rows.length > 0 && count <= left) {
75
+ for (let i = 0; i < count; i++)
76
+ rows[rows.length - 1].push(run);
77
+ left -= count;
78
+ return;
79
+ }
80
+ let rest = count;
81
+ while (rest > 0) {
82
+ const take = Math.min(perRow, rest);
83
+ rows.push(Array.from({ length: take }, () => run));
84
+ rest -= take;
85
+ left = perRow - take;
86
+ }
87
+ });
88
+ return rows;
89
+ }
90
+ /**
91
+ * The cards each relation may draw so that, packed by relation, the band
92
+ * holds `rows` rows of `perRow`: water-filled as `shares` does, then the
93
+ * largest trimmed until the packing fits. Arithmetic only — the band is
94
+ * planned once, not tried.
95
+ */
96
+ export function bandCaps(sizes, perRow, rows) {
97
+ const caps = shares(sizes, perRow * rows);
98
+ while (packRuns(caps, perRow).length > rows) {
99
+ let largest = -1;
100
+ caps.forEach((cap, index) => {
101
+ if (cap > 1 && (largest < 0 || cap > caps[largest]))
102
+ largest = index;
103
+ });
104
+ if (largest < 0)
105
+ break;
106
+ caps[largest] = caps[largest] - 1;
107
+ }
108
+ return caps;
109
+ }
110
+ /** Relevance as a sort key: lower first. Deterministic, stable by the given order. */
111
+ function byRelevance(members, relevance, graph) {
112
+ const score = (node) => [
113
+ relevance.chosen?.has(node.id) ? 0 : 1,
114
+ relevance.hits?.has(node.id) ? 0 : 1,
115
+ relevance.flagged?.has(node.id) ? 0 : 1,
116
+ -(relevance.touched?.get(node.id) ?? 0),
117
+ -graph.neighbors(node.id).length,
118
+ ];
119
+ return members
120
+ .map((node, index) => ({ node, index, key: score(node) }))
121
+ .sort((a, b) => {
122
+ for (let i = 0; i < a.key.length; i++)
123
+ if (a.key[i] !== b.key[i])
124
+ return a.key[i] - b.key[i];
125
+ return a.index - b.index;
126
+ })
127
+ .map((entry) => entry.node);
128
+ }
129
+ /** How many groups a glance takes in: a grouping nearer this reads best. */
130
+ const READABLE_GROUPS = 5;
131
+ /** Lexicographic: whether `a` sorts before `b`. */
132
+ const before = (a, b) => {
133
+ for (let i = 0; i < a.length; i++)
134
+ if (a[i] !== b[i])
135
+ return a[i] < b[i];
136
+ return false;
137
+ };
138
+ /**
139
+ * The best grouping of one kind's members into at most `share` groups, from
140
+ * what the kind's declaration offers — never the relation's own edge (every
141
+ * song on this band is BY the focus), never one group holding everything,
142
+ * and only when most of them are in a named group rather than "none".
143
+ */
144
+ export function chooseGrouping(members, share, options) {
145
+ if (members.length === 0 || share < 2)
146
+ return undefined;
147
+ const kind = members[0].kind;
148
+ const ctx = { schema: options.schema, graph: options.graph, ...(options.today ? { today: options.today } : {}) };
149
+ const candidates = [];
150
+ for (const offer of arrangeable(options.schema, kind).groups) {
151
+ if (offer.key === options.exclude)
152
+ continue;
153
+ if (offer.buckets)
154
+ for (const bucket of ["decade", "year", "month"])
155
+ candidates.push({ by: offer.key, bucket });
156
+ else
157
+ candidates.push({ by: offer.key });
158
+ }
159
+ let best;
160
+ candidates.forEach((candidate, order) => {
161
+ const arranged = arrange(members, { group: candidate }, ctx);
162
+ const groups = arranged.groups;
163
+ if (groups.length < 2 || groups.length > share)
164
+ return;
165
+ const named = groups.filter((group) => group.key !== "").reduce((sum, group) => sum + group.nodes.length, 0);
166
+ const coverage = named / members.length;
167
+ if (coverage < 0.5)
168
+ return;
169
+ /*
170
+ * Not one group holding nearly all of them either. An album's songs by
171
+ * artist were "Tech N9ne, 38 songs" and six cards of "1 song": a
172
+ * grouping that says what everyone already knew, in seven cards that
173
+ * could have been seven songs.
174
+ */
175
+ if (groups.some((group) => group.nodes.length > members.length * 0.75))
176
+ return;
177
+ // Most in named groups, then nearest the five a glance takes in, then the declaration's order.
178
+ const score = [-Math.round(coverage * 100), Math.abs(groups.length - READABLE_GROUPS), order];
179
+ if (!best || before(score, best.score)) {
180
+ best = { grouping: { by: candidate.by, ...(candidate.bucket ? { bucket: candidate.bucket } : {}), groups }, score };
181
+ }
182
+ });
183
+ return best?.grouping;
184
+ }
185
+ /**
186
+ * What the band draws: every related node when they fit; otherwise each
187
+ * relation within its share, as itself, as groups, or as the most relevant
188
+ * and one "+N more". Expanded groups stand open, their members within the
189
+ * relation's share.
190
+ */
191
+ export function bandOf(related, options) {
192
+ const whole = (entry) => ({ id: entry.node.id, kind: entry.node.kind, node: entry.node, ...(entry.via ? { via: entry.via } : {}) });
193
+ if (related.length <= options.budget)
194
+ return related.map(whole);
195
+ const relevance = {
196
+ ...options.relevance,
197
+ chosen: new Set([...(options.relevance?.chosen ?? []), ...(options.selection ?? [])]),
198
+ };
199
+ const runs = new Map();
200
+ for (const entry of related) {
201
+ const key = runKey(entry.via, entry.node.kind);
202
+ const run = runs.get(key);
203
+ if (run)
204
+ run.push(entry);
205
+ else
206
+ runs.set(key, [entry]);
207
+ }
208
+ const plans = [...runs.entries()].map(([key, run]) => ({
209
+ key,
210
+ run,
211
+ via: run[0].via,
212
+ kinds: [...new Set(run.map((entry) => entry.node.kind))],
213
+ members: [],
214
+ whole: false,
215
+ extra: 0,
216
+ }));
217
+ const fair = shares(plans.map((plan) => plan.run.length), options.budget);
218
+ plans.forEach((plan, index) => (plan.whole = plan.run.length <= fair[index]));
219
+ const over = plans.filter((plan) => !plan.whole);
220
+ const standingWhole = plans.filter((plan) => plan.whole).reduce((sum, plan) => sum + plan.run.length, 0);
221
+ let room = Math.max(over.length, options.budget - standingWhole);
222
+ for (const plan of over) {
223
+ plan.members = byRelevance(plan.run.map((entry) => entry.node), relevance, options.graph);
224
+ const most = room - (over.length - 1);
225
+ if (plan.kinds.length > 1 && plan.kinds.length <= most)
226
+ plan.byKind = true;
227
+ else if (plan.kinds.length === 1)
228
+ plan.grouping = chooseGrouping(plan.members, most, {
229
+ schema: options.schema,
230
+ graph: options.graph,
231
+ ...(plan.via ? { exclude: plan.via.edgeKind } : {}),
232
+ ...(options.today ? { today: options.today } : {}),
233
+ });
234
+ }
235
+ const need = (plan) => (plan.byKind ? plan.kinds.length : plan.grouping ? plan.grouping.groups.length : 1);
236
+ // Too many cards in all: the biggest groupings give way to a door.
237
+ while (over.reduce((sum, plan) => sum + need(plan), 0) > room) {
238
+ const biggest = [...over].filter((plan) => need(plan) > 1).sort((a, b) => need(b) - need(a))[0];
239
+ if (!biggest)
240
+ break;
241
+ biggest.grouping = undefined;
242
+ biggest.byKind = false;
243
+ }
244
+ room -= over.reduce((sum, plan) => sum + need(plan), 0);
245
+ // The rest of the room: to a door's standing members, or into an opened group.
246
+ const opened = (plan) => plan.byKind
247
+ ? plan.kinds.some((kind) => options.expanded.has(groupId(kind, plan.key, "kind")))
248
+ : plan.grouping?.groups.some((group) => options.expanded.has(groupId(plan.kinds[0], plan.key, partOf(plan.grouping, group.key))));
249
+ const taking = over.filter((plan) => !plan.grouping && !plan.byKind ? true : opened(plan));
250
+ const extra = shares(taking.map((plan) => plan.members.length), Math.max(0, room));
251
+ taking.forEach((plan, index) => (plan.extra = room > 0 ? extra[index] : 0));
252
+ const out = [];
253
+ for (const plan of plans) {
254
+ const { key, via } = plan;
255
+ if (plan.whole) {
256
+ out.push(...plan.run.map(whole));
257
+ continue;
258
+ }
259
+ const stand = (node) => ({ id: node.id, kind: node.kind, node, ...(via ? { via } : {}) });
260
+ /*
261
+ * THE REST: the most relevant stand; one door holds the others. Relevance
262
+ * decides WHO stands, never WHERE: the standing keep the relation's own
263
+ * order, so selecting a card does not send it jumping to the front.
264
+ */
265
+ const natural = new Map(plan.run.map((entry, at) => [entry.node.id, at]));
266
+ const rest = (members, standing, filter) => {
267
+ const picked = [...members.slice(0, standing)].sort((a, b) => natural.get(a.id) - natural.get(b.id));
268
+ out.push(...picked.map(stand));
269
+ const held = members.slice(standing);
270
+ if (held.length === 0)
271
+ return;
272
+ const kind = held[0].kind;
273
+ out.push({
274
+ id: groupId(kind, key, filter ? `more:${filter}` : "more"),
275
+ kind,
276
+ ...(via ? { via } : {}),
277
+ aggregate: {
278
+ kind,
279
+ memberIds: held.map((node) => node.id),
280
+ label: standing > 0 ? `${held.length} more ${options.plural(kind).toLowerCase()}` : `${held.length} ${options.plural(kind).toLowerCase()}`,
281
+ opens: { in: "picture", focus: aggregateId(kind), within: filter ? { filter } : {} },
282
+ },
283
+ });
284
+ };
285
+ const relationFilter = via && options.focusId ? `${via.edgeKind}:${options.focusId}` : undefined;
286
+ /* A RUN OF SEVERAL KINDS is grouped by kind first: that is what it is. */
287
+ if (plan.byKind) {
288
+ // An opened kind takes its card's place with its members, as many as the room gives.
289
+ const open = plan.kinds.find((kind) => options.expanded.has(groupId(kind, key, "kind")));
290
+ for (const kind of plan.kinds) {
291
+ const ofKind = plan.members.filter((node) => node.kind === kind);
292
+ if (kind === open) {
293
+ const fits = plan.extra + 1;
294
+ if (ofKind.length <= fits)
295
+ out.push(...ofKind.map(stand));
296
+ else
297
+ rest(ofKind, fits - 1, relationFilter);
298
+ continue;
299
+ }
300
+ out.push({ id: groupId(kind, key, "kind"), kind, ...(via ? { via } : {}), aggregate: { kind, memberIds: ofKind.map((node) => node.id), label: options.plural(kind), opens: { in: "place" } } });
301
+ }
302
+ continue;
303
+ }
304
+ const grouping = plan.grouping;
305
+ if (!grouping) {
306
+ rest(plan.members, plan.extra, relationFilter);
307
+ continue;
308
+ }
309
+ const kind = plan.kinds[0];
310
+ const open = grouping.groups.find((group) => options.expanded.has(groupId(kind, key, partOf(grouping, group.key))));
311
+ for (const group of grouping.groups) {
312
+ if (group === open) {
313
+ const inside = plan.members.filter((node) => group.nodes.includes(node));
314
+ // The opened group's place in the row takes its members, as many as the room gives.
315
+ const fits = plan.extra + 1;
316
+ if (inside.length <= fits)
317
+ out.push(...inside.map(stand));
318
+ else {
319
+ const single = group.key !== "" && !group.key.includes(",") && !grouping.bucket;
320
+ const filter = [relationFilter, single ? `${grouping.by}:${group.key}` : undefined].filter(Boolean).join(",") || undefined;
321
+ rest(inside, fits - 1, filter);
322
+ }
323
+ continue;
324
+ }
325
+ out.push({
326
+ id: groupId(kind, key, partOf(grouping, group.key)),
327
+ kind,
328
+ ...(via ? { via } : {}),
329
+ aggregate: {
330
+ kind,
331
+ // Relevance order inside the group too: the names a card shows first are the ones worth seeing.
332
+ memberIds: plan.members.filter((node) => group.nodes.includes(node)).map((node) => node.id),
333
+ // A value reads as a word: "Single", not the enum's "single".
334
+ label: group.label.charAt(0).toUpperCase() + group.label.slice(1),
335
+ opens: { in: "place" },
336
+ },
337
+ });
338
+ }
339
+ }
340
+ return out;
341
+ }
342
+ /** A group's part of its id: what it is grouped by, and which value. */
343
+ const partOf = (grouping, key) => `${grouping.by}${grouping.bucket ? `:${grouping.bucket}` : ""}=${key || "none"}`;
344
+ //# sourceMappingURL=band.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"band.js","sourceRoot":"","sources":["../src/band.ts"],"names":[],"mappings":"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"}