@capillaryjs/capillary-viz 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,3426 @@
1
+ var Tt = Object.defineProperty;
2
+ var zt = (t, e, r) => e in t ? Tt(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r;
3
+ var c = (t, e, r) => zt(t, typeof e != "symbol" ? e + "" : e, r);
4
+ import { Emitter as A, DerivedEmitter as z, BaseEmitter as xe, FetchState as k, combineFetchStates as Rt } from "@capillaryjs/capillary";
5
+ import { Component as Te, Button as oe, css as G, OptionGroup as At, readDeclarativeRegions as Ot, OptionGroupHeaderEnd as jt, OptionsBox as Lt, Checkbox as ae, GroupBox as ge } from "@capillaryjs/capillary-ui";
6
+ function Xe([t, e, r]) {
7
+ return {
8
+ "--c1": t,
9
+ "--c2": e,
10
+ "--c3": r,
11
+ "--colored-dark": t,
12
+ "--colored-base": e,
13
+ "--colored-light": r
14
+ };
15
+ }
16
+ class I {
17
+ constructor(e) {
18
+ c(this, "key");
19
+ c(this, "label");
20
+ c(this, "categories$");
21
+ c(this, "hidden$");
22
+ c(this, "visibleCategories$");
23
+ c(this, "allowResorting");
24
+ c(this, "ownedCategories");
25
+ c(this, "visibleCategoriesEmitter");
26
+ c(this, "seenKeys", /* @__PURE__ */ new Set());
27
+ c(this, "visibilityEmitters", /* @__PURE__ */ new Map());
28
+ c(this, "releaseCategoryDefaults");
29
+ c(this, "disposed", !1);
30
+ W(e, "Criterion options"), this.key = P(e.key, "Criterion key"), this.label = ze(e.label, "Criterion label"), pe(e.categories$, "Criterion categories$"), this.categories$ = e.categories$, this.allowResorting = e.allowResorting ?? !1, this.ownedCategories = e.ownedCategories, this.hidden$ = new A(
31
+ new Set(e.initialHiddenKeys ?? []),
32
+ { owner: this, purpose: `${this.key} hidden categories`, equals: Mt }
33
+ ), this.visibleCategoriesEmitter = new z(
34
+ [this.categories$, this.hidden$],
35
+ ([r, i]) => Object.freeze(
36
+ r.filter(({ key: n }) => !i.has(n))
37
+ ),
38
+ { owner: this, purpose: `${this.key} visible categories` }
39
+ ), this.visibleCategories$ = this.visibleCategoriesEmitter, this.releaseCategoryDefaults = this.categories$.subscribe(({ value: r }) => {
40
+ Array.isArray(r) && this.applyFirstSeenDefaults(r);
41
+ });
42
+ }
43
+ visibility(e) {
44
+ this.assertActive();
45
+ const r = P(e, "Category key");
46
+ let i = this.visibilityEmitters.get(r);
47
+ return i == null && (i = new Pt(this.hidden$, r, this), this.visibilityEmitters.set(r, i)), i;
48
+ }
49
+ setAllVisible(e, r) {
50
+ this.assertActive();
51
+ const i = new Set(this.categories$.get().map(({ key: s }) => s)), n = new Set(this.hidden$.get());
52
+ for (const s of i)
53
+ e ? n.delete(s) : n.add(s);
54
+ return this.hidden$.set(n, r ?? `${this.key} category visibility changed`);
55
+ }
56
+ pruneHidden(e) {
57
+ this.assertActive();
58
+ const r = new Set(this.categories$.get().map(({ key: n }) => n)), i = new Set([...this.hidden$.get()].filter((n) => r.has(n)));
59
+ return this.hidden$.set(i, e ?? `${this.key} hidden categories pruned`);
60
+ }
61
+ dispose() {
62
+ var e;
63
+ if (!this.disposed) {
64
+ this.disposed = !0, this.releaseCategoryDefaults();
65
+ for (const r of this.visibilityEmitters.values()) r.dispose();
66
+ this.visibilityEmitters.clear(), this.visibleCategoriesEmitter.dispose(), this.hidden$.dispose(), (e = this.ownedCategories) == null || e.dispose();
67
+ }
68
+ }
69
+ applyFirstSeenDefaults(e) {
70
+ Je(e, `${this.label} categories`);
71
+ const r = new Set(this.hidden$.get());
72
+ let i = !1;
73
+ for (const n of e)
74
+ this.seenKeys.has(n.key) || (this.seenKeys.add(n.key), n.hiddenByDefault === !0 && !r.has(n.key) && (r.add(n.key), i = !0));
75
+ i && this.hidden$.set(r, `${this.key} first-seen defaults applied`);
76
+ }
77
+ assertActive() {
78
+ if (this.disposed) throw new Error(`Criterion "${this.key}" is disposed`);
79
+ }
80
+ }
81
+ function si(t) {
82
+ W(t, "Static criterion options");
83
+ const e = Ze(t.categories, `${t.label} categories`), r = new A(e, {
84
+ purpose: `${t.key} static categories`
85
+ });
86
+ return new I({ ...t, categories$: r, ownedCategories: r });
87
+ }
88
+ function oi(t) {
89
+ if (W(t, "Derived criterion options"), pe(t.source$, "Derived criterion source$"), typeof t.extractKeys != "function")
90
+ throw new TypeError("Derived criterion extractKeys must be a function");
91
+ if (typeof t.describe != "function")
92
+ throw new TypeError("Derived criterion describe must be a function");
93
+ const e = new z(
94
+ [t.source$],
95
+ ([r]) => Dt(r, t),
96
+ { purpose: `${t.key} derived categories` }
97
+ );
98
+ return new I({
99
+ ...t,
100
+ allowResorting: t.allowResorting ?? !0,
101
+ categories$: e,
102
+ ownedCategories: e
103
+ });
104
+ }
105
+ function Dt(t, e) {
106
+ if (!Array.isArray(t)) throw new TypeError("Derived category items must be an array");
107
+ const r = /* @__PURE__ */ new Map();
108
+ let i = 0;
109
+ for (const o of t) {
110
+ const a = be(e.extractKeys(o));
111
+ if (a.length === 0) {
112
+ i += 1;
113
+ continue;
114
+ }
115
+ for (const l of a) r.set(l, (r.get(l) ?? 0) + 1);
116
+ }
117
+ const n = [...r].filter(([, o]) => o > 0).map(([o, a]) => ({ key: o, count: a, label: e.describe(o, a).label }));
118
+ n.sort(e.compare ?? ((o, a) => a.count - o.count || o.label.localeCompare(a.label) || o.key.localeCompare(a.key)));
119
+ const s = n.map(({ key: o, count: a }) => {
120
+ const l = e.describe(o, a);
121
+ return Ee({
122
+ key: o,
123
+ ...l,
124
+ generated: !0,
125
+ predicate: (u) => be(e.extractKeys(u)).includes(o)
126
+ }, "Derived category");
127
+ });
128
+ if (i > 0 && e.unmatched != null) {
129
+ const { key: o, ...a } = e.unmatched;
130
+ s.push(Ee({
131
+ key: o,
132
+ ...a,
133
+ generated: !0,
134
+ predicate: (l) => be(e.extractKeys(l)).length === 0
135
+ }, "Derived unmatched category"));
136
+ }
137
+ return Ze(s, "Derived categories");
138
+ }
139
+ function ai(t, e) {
140
+ pe(t, "filterByHidden items$"), Nt(e);
141
+ const r = [t];
142
+ for (const i of e) r.push(i.categories$, i.hidden$);
143
+ return new z(
144
+ r,
145
+ (i) => i[0].filter((s) => !e.some((o, a) => {
146
+ const l = i[a * 2 + 1], u = i[a * 2 + 2];
147
+ return l.some((h) => u.has(h.key) && h.predicate(s));
148
+ })),
149
+ { purpose: "items filtered by hidden visualization categories" }
150
+ );
151
+ }
152
+ function li(t, e) {
153
+ if (pe(t, "categoryCounts items$"), !(e instanceof I))
154
+ throw new TypeError("categoryCounts criterion must be a GroupingCriterion");
155
+ return new z(
156
+ [t, e.categories$],
157
+ (r) => {
158
+ const i = r[0], n = r[1];
159
+ return new Map(n.map((s) => [
160
+ s.key,
161
+ i.filter((o) => s.predicate(o)).length
162
+ ]));
163
+ },
164
+ { purpose: `${e.key} unfiltered category counts` }
165
+ );
166
+ }
167
+ function Mt(t, e) {
168
+ return t === e || t.size === e.size && [...t].every((r) => e.has(r));
169
+ }
170
+ class Pt extends xe {
171
+ constructor(r, i, n) {
172
+ super(r.get().has(i) ? "hidden" : "visible", {
173
+ owner: n,
174
+ purpose: `${i} category visibility`,
175
+ fetchState: r.getFetchState(),
176
+ error: r.getError()
177
+ });
178
+ c(this, "release");
179
+ this.source = r, this.categoryKey = i, this.release = r.subscribe((s) => this.updateFromSource(s), {
180
+ emitCurrent: !1
181
+ });
182
+ }
183
+ set(r, i) {
184
+ if (r !== "hidden" && r !== "visible")
185
+ throw new TypeError("Category visibility must be hidden or visible");
186
+ const n = new Set(this.source.get());
187
+ return r === "hidden" ? n.add(this.categoryKey) : n.delete(this.categoryKey), this.source.set(n, i ?? `${this.categoryKey} visibility changed`);
188
+ }
189
+ dispose() {
190
+ this.release(), super.dispose();
191
+ }
192
+ updateFromSource(r) {
193
+ this.setSnapshot({
194
+ value: r.value.has(this.categoryKey) ? "hidden" : "visible",
195
+ fetchState: r.fetchState,
196
+ error: r.error,
197
+ parentEvent: r.event,
198
+ cause: "hidden category membership changed"
199
+ });
200
+ }
201
+ }
202
+ function be(t) {
203
+ const r = (t == null ? [] : typeof t == "string" ? [t] : [...t]).map((i) => P(i, "Extracted category key"));
204
+ return [...new Set(r)];
205
+ }
206
+ function Ze(t, e) {
207
+ return Je(t, e), Object.freeze(t.map((r) => Ee(r, e)));
208
+ }
209
+ function Ee(t, e) {
210
+ W(t, e);
211
+ const r = {
212
+ ...t,
213
+ key: P(t.key, `${e} key`),
214
+ label: ze(t.label, `${e} label`),
215
+ colors: Qe(t.colors, `${e} colors`)
216
+ };
217
+ if (typeof t.predicate != "function")
218
+ throw new TypeError(`${e} predicate must be a function`);
219
+ return t.colorKey !== void 0 && P(t.colorKey, `${e} colorKey`), Object.freeze(r);
220
+ }
221
+ function Je(t, e) {
222
+ if (!Array.isArray(t)) throw new TypeError(`${e} must be an array`);
223
+ const r = /* @__PURE__ */ new Set();
224
+ for (const i of t) {
225
+ W(i, e);
226
+ const n = P(i.key, `${e} key`);
227
+ if (r.has(n)) throw new Error(`${e} contains duplicate key "${n}"`);
228
+ if (r.add(n), ze(i.label, `${e} label`), Qe(i.colors, `${e} colors`), typeof i.predicate != "function")
229
+ throw new TypeError(`${e} predicate must be a function`);
230
+ }
231
+ }
232
+ function Nt(t) {
233
+ if (!Array.isArray(t)) throw new TypeError("Criteria must be an array");
234
+ const e = /* @__PURE__ */ new Set();
235
+ for (const r of t) {
236
+ if (!(r instanceof I))
237
+ throw new TypeError("Criteria must contain GroupingCriterion instances");
238
+ if (e.has(r.key)) throw new Error(`Duplicate criterion key "${r.key}"`);
239
+ e.add(r.key);
240
+ }
241
+ }
242
+ function Qe(t, e) {
243
+ if (!Array.isArray(t) || t.length !== 3 || t.some((r) => typeof r != "string" || r.trim() === ""))
244
+ throw new TypeError(`${e} must contain three non-empty CSS color values`);
245
+ return Object.freeze([...t]);
246
+ }
247
+ function pe(t, e) {
248
+ if (t == null || typeof t != "object" && typeof t != "function" || typeof Reflect.get(t, "get") != "function" || typeof Reflect.get(t, "getFetchState") != "function" || typeof Reflect.get(t, "getError") != "function" || typeof Reflect.get(t, "subscribe") != "function")
249
+ throw new TypeError(`${e} must be a readable emitter`);
250
+ }
251
+ function W(t, e) {
252
+ if (t == null || typeof t != "object" || Array.isArray(t))
253
+ throw new TypeError(`${e} must be an object`);
254
+ }
255
+ function P(t, e) {
256
+ if (typeof t != "string" || t.trim() === "")
257
+ throw new TypeError(`${e} must be a non-empty string`);
258
+ return t;
259
+ }
260
+ function ze(t, e) {
261
+ if (typeof t != "string" || t.trim() === "")
262
+ throw new TypeError(`${e} must be a non-empty string`);
263
+ return t;
264
+ }
265
+ function we(t, e, r = {}) {
266
+ if (!Array.isArray(t)) throw new TypeError("Block layout items must be an array");
267
+ if (!Array.isArray(e)) throw new TypeError("Block layout splits must be an array");
268
+ const i = r.readabilityThreshold ?? 0.02;
269
+ if (!Number.isFinite(i) || i < 0 || i > 1)
270
+ throw new RangeError("Block readability threshold must be between zero and one");
271
+ const n = [], s = Object.freeze([...t]), o = et({
272
+ items: s,
273
+ splits: e,
274
+ splitIndex: 0,
275
+ path: Object.freeze([]),
276
+ criterion: null,
277
+ category: null,
278
+ parentCount: s.length,
279
+ totalShare: 1,
280
+ readabilityThreshold: i,
281
+ issues: n,
282
+ rootLabel: r.rootLabel ?? "All items"
283
+ });
284
+ return Object.freeze({ valid: n.length === 0, root: o, issues: Object.freeze(n) });
285
+ }
286
+ function Kt(t) {
287
+ if (!(t instanceof I))
288
+ throw new TypeError("criterionSnapshot requires a GroupingCriterion");
289
+ return Object.freeze({
290
+ key: t.key,
291
+ label: t.label,
292
+ categories: t.categories$.get(),
293
+ allowResorting: t.allowResorting
294
+ });
295
+ }
296
+ function D(t, e) {
297
+ if (e == null) return null;
298
+ let r = t;
299
+ for (const i of e) {
300
+ const n = r.children.find((s) => s.criterionKey === i.criterionKey && s.categoryKey === i.categoryKey);
301
+ if (n == null) return null;
302
+ r = n;
303
+ }
304
+ return r;
305
+ }
306
+ class It {
307
+ constructor(e, r, i = {}) {
308
+ c(this, "layout$");
309
+ c(this, "selectedPath$");
310
+ c(this, "selectedBlock$");
311
+ c(this, "selectedItems$");
312
+ c(this, "layoutEmitter");
313
+ c(this, "selectedBlockEmitter");
314
+ c(this, "selectedItemsEmitter");
315
+ c(this, "releases", []);
316
+ c(this, "disposed", !1);
317
+ this.options = i, this.layoutEmitter = new Bt(e, r, i), this.layout$ = this.layoutEmitter, this.selectedPath$ = new A(null, {
318
+ owner: this,
319
+ purpose: "selected block path",
320
+ equals: qt
321
+ }), this.selectedBlockEmitter = new z(
322
+ [this.layout$, this.selectedPath$],
323
+ ([n, s]) => D(n.root, s),
324
+ { owner: this, purpose: "selected block" }
325
+ ), this.selectedBlock$ = this.selectedBlockEmitter, this.selectedItemsEmitter = new z(
326
+ [this.selectedBlock$],
327
+ ([n]) => (n == null ? void 0 : n.items) ?? Object.freeze([]),
328
+ { owner: this, purpose: "selected block items" }
329
+ ), this.selectedItems$ = this.selectedItemsEmitter, this.releases.push(
330
+ this.layout$.subscribe(() => this.reconcileSelection(), { emitCurrent: !1 }),
331
+ this.selectedPath$.subscribe(() => this.reconcileSelection(), { emitCurrent: !1 })
332
+ );
333
+ }
334
+ select(e, r) {
335
+ this.assertActive();
336
+ const i = tt(e);
337
+ if (D(this.layout$.get().root, i) == null)
338
+ throw new Error("Cannot select a path absent from the current block layout");
339
+ return this.selectedPath$.set(i, r ?? "block selected");
340
+ }
341
+ clear(e) {
342
+ return this.assertActive(), this.selectedPath$.set(null, e ?? "block selection cleared");
343
+ }
344
+ dispose() {
345
+ if (!this.disposed) {
346
+ this.disposed = !0;
347
+ for (const e of this.releases.splice(0)) e();
348
+ this.selectedItemsEmitter.dispose(), this.selectedBlockEmitter.dispose(), this.selectedPath$.dispose(), this.layoutEmitter.dispose();
349
+ }
350
+ }
351
+ reconcileSelection() {
352
+ const e = this.selectedPath$.get();
353
+ e == null || D(this.layout$.get().root, e) != null || this.selectedPath$.set(null, "block selection no longer exists");
354
+ }
355
+ assertActive() {
356
+ if (this.disposed) throw new Error("Block selection model is disposed");
357
+ }
358
+ }
359
+ function ci(t, e, r = {}) {
360
+ return new It(t, e, r);
361
+ }
362
+ class Bt extends xe {
363
+ constructor(r, i, n) {
364
+ super(we([], [], n), {
365
+ purpose: "reactive block layout",
366
+ fetchState: k.Initial
367
+ });
368
+ c(this, "releases", []);
369
+ c(this, "categoryReleases", []);
370
+ this.items$ = r, this.splits$ = i, this.options = n, Ie(r, "Block selection items$"), Ie(i, "Block selection splits$"), this.releases.push(
371
+ r.subscribe(({ event: s }) => this.recompute(s), { emitCurrent: !1 }),
372
+ i.subscribe(({ event: s }) => {
373
+ this.subscribeCategories(), this.recompute(s);
374
+ }, { emitCurrent: !1 })
375
+ ), this.subscribeCategories(), this.recompute(null);
376
+ }
377
+ dispose() {
378
+ for (const r of this.releases.splice(0)) r();
379
+ this.releaseCategories(), super.dispose();
380
+ }
381
+ subscribeCategories() {
382
+ this.releaseCategories(), this.categoryReleases = this.splits$.get().map((r) => r.categories$.subscribe(
383
+ ({ event: i }) => this.recompute(i),
384
+ { emitCurrent: !1 }
385
+ ));
386
+ }
387
+ releaseCategories() {
388
+ for (const r of this.categoryReleases.splice(0)) r();
389
+ }
390
+ recompute(r) {
391
+ const i = this.splits$.get(), n = [
392
+ this.items$,
393
+ this.splits$,
394
+ ...i.map(({ categories$: p }) => p)
395
+ ], s = n.map((p) => p.getFetchState()), o = n.map((p) => p.getError()).filter(Ut);
396
+ let a, l = null;
397
+ try {
398
+ a = we(
399
+ this.items$.get(),
400
+ i.map(Kt),
401
+ this.options
402
+ );
403
+ } catch (p) {
404
+ l = p, a = we([], [], this.options);
405
+ }
406
+ const u = l == null ? o : [...o, l], h = u.length > 0 ? k.Error : Rt(s);
407
+ this.setSnapshot({
408
+ value: a,
409
+ fetchState: h,
410
+ error: u.length === 0 ? null : Object.freeze(u),
411
+ parentEvent: r,
412
+ cause: "block layout source changed"
413
+ });
414
+ }
415
+ }
416
+ function et(t) {
417
+ const {
418
+ items: e,
419
+ splits: r,
420
+ splitIndex: i,
421
+ path: n,
422
+ criterion: s,
423
+ category: o,
424
+ parentCount: a,
425
+ totalShare: l,
426
+ readabilityThreshold: u,
427
+ issues: h,
428
+ rootLabel: p
429
+ } = t, b = r[i], y = b != null && n.length > 0 && l < u, g = b == null || y ? [] : Ft({
430
+ items: e,
431
+ splits: r,
432
+ splitIndex: i,
433
+ path: n,
434
+ criterion: b,
435
+ totalShare: l,
436
+ readabilityThreshold: u,
437
+ issues: h,
438
+ rootLabel: p
439
+ }), f = a === 0 ? 0 : e.length / a;
440
+ return Object.freeze({
441
+ key: _t(n),
442
+ path: n,
443
+ criterionKey: (s == null ? void 0 : s.key) ?? null,
444
+ criterionLabel: (s == null ? void 0 : s.label) ?? null,
445
+ categoryKey: (o == null ? void 0 : o.key) ?? null,
446
+ label: (o == null ? void 0 : o.label) ?? p,
447
+ colors: (o == null ? void 0 : o.colors) ?? null,
448
+ colorKey: (o == null ? void 0 : o.colorKey) ?? null,
449
+ count: e.length,
450
+ share: f,
451
+ totalShare: l,
452
+ depth: n.length - 1,
453
+ items: e,
454
+ children: Object.freeze(g),
455
+ childOrientation: n.length % 2 === 0 ? "horizontal" : "vertical",
456
+ childrenSuppressed: y
457
+ });
458
+ }
459
+ function Ft(t) {
460
+ const { items: e, criterion: r, path: i, issues: n } = t, s = new Map(r.categories.map((l) => [l.key, {
461
+ category: l,
462
+ items: []
463
+ }]));
464
+ let o = !0;
465
+ if (e.forEach((l, u) => {
466
+ const h = r.categories.filter((p) => p.predicate(l));
467
+ if (h.length !== 1) {
468
+ o = !1, n.push(Object.freeze({
469
+ kind: h.length === 0 ? "unmatched" : "multiple-matches",
470
+ criterionKey: r.key,
471
+ criterionLabel: r.label,
472
+ parentPath: i,
473
+ item: l,
474
+ itemIndex: u,
475
+ matchedCategoryKeys: Object.freeze(h.map(({ key: p }) => p))
476
+ }));
477
+ return;
478
+ }
479
+ s.get(h[0].key).items.push(l);
480
+ }), !o) return [];
481
+ let a = [...s.values()].filter((l) => l.items.length > 0);
482
+ return r.allowResorting && (a = a.sort((l, u) => u.items.length - l.items.length || l.category.label.localeCompare(u.category.label) || l.category.key.localeCompare(u.category.key))), a.map(({ category: l, items: u }) => {
483
+ const h = tt([...i, {
484
+ criterionKey: r.key,
485
+ categoryKey: l.key
486
+ }]), p = e.length === 0 ? 0 : u.length / e.length;
487
+ return et({
488
+ ...t,
489
+ items: Object.freeze(u),
490
+ splitIndex: t.splitIndex + 1,
491
+ path: h,
492
+ criterion: r,
493
+ category: l,
494
+ parentCount: e.length,
495
+ totalShare: t.totalShare * p
496
+ });
497
+ });
498
+ }
499
+ function tt(t) {
500
+ if (!Array.isArray(t)) throw new TypeError("Block path must be an array");
501
+ return Object.freeze(t.map((e) => {
502
+ if (e == null || typeof e != "object")
503
+ throw new TypeError("Block path segments must be objects");
504
+ if (typeof e.criterionKey != "string" || e.criterionKey === "" || typeof e.categoryKey != "string" || e.categoryKey === "")
505
+ throw new TypeError("Block path keys must be non-empty strings");
506
+ return Object.freeze({ ...e });
507
+ }));
508
+ }
509
+ function qt(t, e) {
510
+ return t === e || t != null && e != null && t.length === e.length && t.every((r, i) => {
511
+ const n = e[i];
512
+ return r.criterionKey === (n == null ? void 0 : n.criterionKey) && r.categoryKey === n.categoryKey;
513
+ });
514
+ }
515
+ function _t(t) {
516
+ return t.length === 0 ? "root" : t.map(({ criterionKey: e, categoryKey: r }) => `${encodeURIComponent(e)}=${encodeURIComponent(r)}`).join("/");
517
+ }
518
+ function Ut(t) {
519
+ return t != null;
520
+ }
521
+ function Ie(t, e) {
522
+ if (t == null || typeof t != "object" && typeof t != "function" || typeof Reflect.get(t, "get") != "function" || typeof Reflect.get(t, "getFetchState") != "function" || typeof Reflect.get(t, "getError") != "function" || typeof Reflect.get(t, "subscribe") != "function")
523
+ throw new TypeError(`${e} must be a readable emitter`);
524
+ }
525
+ const Be = "data-cap-structural-styles";
526
+ let Ht = 1;
527
+ class rt {
528
+ constructor(e = `runtime-${Ht++}`) {
529
+ c(this, "id");
530
+ c(this, "cssFragments", /* @__PURE__ */ new Map());
531
+ if (typeof e != "string") throw new TypeError("StyleRegistry id must be a string");
532
+ this.id = e;
533
+ }
534
+ registerCSS(e) {
535
+ if (typeof e != "string") throw new TypeError("Component CSS must be a string");
536
+ const r = e.trim();
537
+ return r.length > 0 && this.cssFragments.set(`raw:${r}`, { kind: "raw", css: r }), this;
538
+ }
539
+ /** @internal Collect a host-relative component template without resolving it yet. */
540
+ registerHostCSS(e, r) {
541
+ if (typeof e != "string") throw new TypeError("Component CSS must be a string");
542
+ if (typeof r != "string" || r.trim().length === 0)
543
+ throw new TypeError("Component CSS host must be a non-empty selector");
544
+ const i = e.trim();
545
+ if (i.length === 0) return this;
546
+ if (!i.includes("&")) return this.registerCSS(i);
547
+ const n = `host:${i}`, s = this.cssFragments.get(n);
548
+ return s == null ? this.cssFragments.set(n, {
549
+ kind: "host",
550
+ css: i,
551
+ hosts: /* @__PURE__ */ new Set([r.trim()])
552
+ }) : s.kind === "host" && s.hosts.add(r.trim()), this;
553
+ }
554
+ generateCSS() {
555
+ return [...this.cssFragments.values()].map((e) => e.kind === "raw" ? e.css : it(e.css, [...e.hosts])).join(`
556
+
557
+ `);
558
+ }
559
+ injectAll(e = globalThis.document) {
560
+ if ((e == null ? void 0 : e.head) == null)
561
+ throw new TypeError("StyleRegistry.injectAll requires a document with a head");
562
+ const r = `style[${Be}="${Gt(this.id)}"]`;
563
+ let i = e.head.querySelector(r);
564
+ i == null && (i = e.createElement("style"), i.setAttribute(Be, this.id), e.head.prepend(i));
565
+ const n = this.generateCSS();
566
+ return i.textContent !== n && (i.textContent = n), i;
567
+ }
568
+ reset() {
569
+ this.cssFragments.clear();
570
+ }
571
+ }
572
+ function Vt() {
573
+ return new rt();
574
+ }
575
+ const Yt = new rt("");
576
+ function Gt(t) {
577
+ return t.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
578
+ }
579
+ function it(t, e) {
580
+ let r = "", i = 0;
581
+ for (; i < t.length; ) {
582
+ const n = Zt(t, i);
583
+ if (n < 0) return r + t.slice(i);
584
+ const s = Jt(t, n);
585
+ if (s < 0) return r + t.slice(i);
586
+ const o = t.slice(i, n), a = t.slice(n + 1, s), l = o.trim();
587
+ r += l.startsWith("@") ? `${o}{${it(a, e)}}` : `${Wt(o, e)}{${a}}`, i = s + 1;
588
+ }
589
+ return r;
590
+ }
591
+ function Wt(t, e) {
592
+ var o, a, l;
593
+ if (e.length === 1 || !t.includes("&"))
594
+ return e.length === 1 ? t.replaceAll("&", e[0]) : t;
595
+ const r = ((o = t.match(/^\s*/)) == null ? void 0 : o[0]) ?? "", i = ((a = t.match(/\s*$/)) == null ? void 0 : a[0]) ?? "", n = Xt(t.trim()), s = ((l = r.match(/(?:^|\n)([ \t]*)$/)) == null ? void 0 : l[1]) ?? "";
596
+ return r + n.flatMap((u) => u.includes("&") ? e.map((h) => u.replaceAll("&", h)) : [u]).join(`,
597
+ ${s}`) + i;
598
+ }
599
+ function Xt(t) {
600
+ const e = [];
601
+ let r = 0, i = 0, n = 0, s = null;
602
+ for (let o = 0; o < t.length; o += 1) {
603
+ const a = t[o];
604
+ if (s != null) {
605
+ a === "\\" ? o += 1 : a === s && (s = null);
606
+ continue;
607
+ }
608
+ a === '"' || a === "'" ? s = a : a === "(" ? i += 1 : a === ")" ? i -= 1 : a === "[" ? n += 1 : a === "]" ? n -= 1 : a === "," && i === 0 && n === 0 && (e.push(t.slice(r, o).trim()), r = o + 1);
609
+ }
610
+ return e.push(t.slice(r).trim()), e.filter(Boolean);
611
+ }
612
+ function Zt(t, e) {
613
+ for (let r = e; r < t.length; r += 1) {
614
+ const i = t[r];
615
+ if (i === '"' || i === "'")
616
+ r = nt(t, r);
617
+ else if (i === "/" && t[r + 1] === "*")
618
+ r = st(t, r);
619
+ else if (i === "{")
620
+ return r;
621
+ }
622
+ return -1;
623
+ }
624
+ function Jt(t, e) {
625
+ let r = 1;
626
+ for (let i = e + 1; i < t.length; i += 1) {
627
+ const n = t[i];
628
+ if (n === '"' || n === "'")
629
+ i = nt(t, i);
630
+ else if (n === "/" && t[i + 1] === "*")
631
+ i = st(t, i);
632
+ else if (n === "{")
633
+ r += 1;
634
+ else if (n === "}" && --r === 0)
635
+ return i;
636
+ }
637
+ return -1;
638
+ }
639
+ function nt(t, e) {
640
+ const r = t[e];
641
+ for (let i = e + 1; i < t.length; i += 1)
642
+ if (t[i] === "\\") i += 1;
643
+ else if (t[i] === r) return i;
644
+ return t.length;
645
+ }
646
+ function st(t, e) {
647
+ const r = t.indexOf("*/", e + 2);
648
+ return r < 0 ? t.length : r + 1;
649
+ }
650
+ const Qt = /* @__PURE__ */ new WeakSet(), er = /* @__PURE__ */ new WeakSet();
651
+ class ot {
652
+ constructor(e = []) {
653
+ c(this, "providers", /* @__PURE__ */ new Map());
654
+ c(this, "instances", /* @__PURE__ */ new Map());
655
+ c(this, "creationOrder", []);
656
+ c(this, "resolving", []);
657
+ c(this, "disposed", !1);
658
+ if (!Array.isArray(e))
659
+ throw new TypeError("ServiceScope providers must be an array");
660
+ for (const r of e) {
661
+ if (ir(r), this.providers.has(r.key))
662
+ throw new Error(`Service "${r.key.name}" is registered more than once`);
663
+ this.providers.set(r.key, r);
664
+ }
665
+ }
666
+ get isDisposed() {
667
+ return this.disposed;
668
+ }
669
+ has(e) {
670
+ return this.assertActive(), Fe(e), this.providers.has(e);
671
+ }
672
+ require(e) {
673
+ if (this.assertActive(), Fe(e), this.instances.has(e)) return this.instances.get(e);
674
+ const r = this.providers.get(e);
675
+ if (r == null) throw new Error(`Service "${e.name}" is not registered`);
676
+ const i = this.resolving.indexOf(e);
677
+ if (i >= 0) {
678
+ const n = [...this.resolving.slice(i), e].map((s) => s.name).join(" -> ");
679
+ throw new Error(`Circular service dependency: ${n}`);
680
+ }
681
+ this.resolving.push(e);
682
+ try {
683
+ const n = r.create(this);
684
+ return this.instances.set(e, n), this.creationOrder.push(e), n;
685
+ } finally {
686
+ this.resolving.pop();
687
+ }
688
+ }
689
+ dispose() {
690
+ if (this.disposed) return;
691
+ this.disposed = !0;
692
+ const e = [];
693
+ for (const r of [...this.creationOrder].reverse()) {
694
+ const i = this.instances.get(r);
695
+ try {
696
+ const n = nr(i);
697
+ n != null && n.call(i);
698
+ } catch (n) {
699
+ e.push(n);
700
+ }
701
+ }
702
+ if (this.instances.clear(), this.creationOrder.length = 0, this.resolving.length = 0, e.length === 1) throw e[0];
703
+ if (e.length > 1)
704
+ throw new AggregateError(e, "Several services failed during disposal");
705
+ }
706
+ assertActive() {
707
+ if (this.disposed) throw new Error("ServiceScope has been disposed");
708
+ }
709
+ }
710
+ function tr(t = []) {
711
+ return new ot(t);
712
+ }
713
+ function rr(t) {
714
+ return t != null && (typeof t == "object" || typeof t == "function") && Qt.has(t);
715
+ }
716
+ function Fe(t) {
717
+ if (!rr(t)) throw new TypeError("Expected a service key created by defineService()");
718
+ }
719
+ function ir(t) {
720
+ if (t == null || typeof t != "object" && typeof t != "function" || !er.has(t))
721
+ throw new TypeError("Expected a service provider created by provideService()");
722
+ }
723
+ function nr(t) {
724
+ if (t == null || typeof t != "object" && typeof t != "function") return null;
725
+ const e = Reflect.get(t, "dispose");
726
+ return typeof e == "function" ? e : null;
727
+ }
728
+ const ne = Object.freeze({
729
+ breadcrumbLabel: "Breadcrumb",
730
+ calendarGridLabel: "Choose a date",
731
+ calendarNextMonthLabel: "Next month",
732
+ calendarPreviousMonthLabel: "Previous month",
733
+ checkboxOptionLabel: "Option",
734
+ checkboxStateLabel: (t, e) => `${t}: ${e}`,
735
+ colorOptionGrayLabel: "Gray",
736
+ colorOptionGreenLabel: "Green",
737
+ colorOptionIceBlueLabel: "Ice blue",
738
+ colorOptionOceanLabel: "Ocean",
739
+ colorOptionOrangeLabel: "Orange",
740
+ colorOptionPurpleLabel: "Purple",
741
+ colorOptionRedLabel: "Red",
742
+ colorOptionYellowLabel: "Yellow",
743
+ dataTableEmpty: "No rows",
744
+ dataTableLoadError: "Unable to load rows",
745
+ dataTableLoading: "Loading rows…",
746
+ dataTableRetry: "Retry",
747
+ datePickerDialogLabel: "Choose a date",
748
+ datePickerOpenCalendarLabel: "Open calendar",
749
+ dateTimePickerDateLabel: "Date",
750
+ dateTimePickerTimeLabel: "Time",
751
+ dialogCloseLabel: "Close",
752
+ dropdownLoadError: "Unable to load options",
753
+ dropdownPlaceholder: "Select…",
754
+ filterModeDenyLabel: "deny",
755
+ filterModeNeutralLabel: "neutral",
756
+ filterModePreferLabel: "prefer",
757
+ filterModeRequireLabel: "require",
758
+ filterPanelEmpty: "No filter options",
759
+ filterPanelLabel: "Filter options",
760
+ filterPanelLoadError: "Unable to load filter options",
761
+ filterPanelLoading: "Loading filter options…",
762
+ listViewEmpty: "No items",
763
+ listViewLabel: "Items",
764
+ listViewLoadError: "Unable to load items",
765
+ listViewLoading: "Loading items…",
766
+ progressInProgress: "In progress",
767
+ radioOptionLabel: "Option",
768
+ splitViewSeparatorLabel: "Resize panes",
769
+ tabLineLabel: "Sections",
770
+ tableFilterColumnLabel: (t) => `Filter ${t}`,
771
+ tableSortColumnLabel: (t) => `Sort ${t}`,
772
+ themeOptionJavaLabel: "Java",
773
+ themeOptionMinimalLabel: "Minimal",
774
+ themeOptionShinyLabel: "Shiny",
775
+ timePickerPlaceholder: "Select time…",
776
+ toolbarLabel: "Actions",
777
+ treeViewEmpty: "No tree items",
778
+ treeViewLoadError: "Unable to load tree items",
779
+ treeViewLoading: "Loading tree items…"
780
+ });
781
+ class at {
782
+ constructor(e, r) {
783
+ c(this, "locale");
784
+ c(this, "messages");
785
+ this.locale = e, this.messages = r, Object.freeze(this);
786
+ }
787
+ message(e) {
788
+ return this.messages[e];
789
+ }
790
+ }
791
+ const sr = new at(
792
+ void 0,
793
+ ne
794
+ );
795
+ function or(t) {
796
+ if (t == null) return sr;
797
+ if (typeof t != "object" || Array.isArray(t))
798
+ throw new TypeError("Capillary UI localization must be an object");
799
+ const e = ar(t.locale), r = t.messages;
800
+ if (r != null && (typeof r != "object" || Array.isArray(r)))
801
+ throw new TypeError("Capillary UI localization messages must be an object");
802
+ const i = { ...ne };
803
+ if (r != null)
804
+ for (const n of Object.keys(ne)) {
805
+ const s = r[n];
806
+ if (s === void 0) continue;
807
+ const o = ne[n];
808
+ if (typeof s != typeof o)
809
+ throw new TypeError(`Capillary UI localization message "${n}" has the wrong type`);
810
+ Object.assign(i, { [n]: s });
811
+ }
812
+ return new at(e, Object.freeze(i));
813
+ }
814
+ function ar(t) {
815
+ if (typeof t != "string" || t.trim() === "")
816
+ throw new TypeError("Capillary UI localization locale must be a non-empty BCP 47 language tag");
817
+ try {
818
+ return Intl.getCanonicalLocales(t)[0];
819
+ } catch (e) {
820
+ throw new RangeError(`Invalid Capillary UI localization locale: ${t}`, { cause: e });
821
+ }
822
+ }
823
+ const lr = /* @__PURE__ */ new Set([
824
+ "annotation-xml",
825
+ "color-profile",
826
+ "font-face",
827
+ "font-face-src",
828
+ "font-face-uri",
829
+ "font-face-format",
830
+ "font-face-name",
831
+ "missing-glyph"
832
+ ]);
833
+ class lt {
834
+ constructor(e = {}, r = Vt()) {
835
+ c(this, "styleRegistry");
836
+ c(this, "services");
837
+ c(this, "router");
838
+ c(this, "localization");
839
+ c(this, "routedRoots", /* @__PURE__ */ new WeakSet());
840
+ if (e == null || typeof e != "object" || Array.isArray(e))
841
+ throw new TypeError("CapillaryUiRuntime options must be an object");
842
+ if (Object.hasOwn(e, "elementNames"))
843
+ throw new TypeError("CapillaryUiRuntime no longer supports configurable element names");
844
+ if (this.styleRegistry = r, this.localization = or(e.localization), this.services = e.services ?? tr(), !(this.services instanceof ot))
845
+ throw new TypeError("Capillary UI services must be a ServiceScope");
846
+ if (this.router = e.router ?? null, this.router != null && (typeof this.router != "object" || typeof this.router.openScope != "function" || typeof this.router.completeScope != "function"))
847
+ throw new TypeError("Capillary UI router must be a BrowserRouter");
848
+ }
849
+ /** Resolve a fixed one-hyphen public host name for a built-in component. */
850
+ resolveElementName(e) {
851
+ ct(e, "Capillary UI component host name");
852
+ const r = `cap-${e.replaceAll("-", "")}`;
853
+ return cr(r), r;
854
+ }
855
+ resolveHostSelector(e, r) {
856
+ if (typeof e != "string") throw new TypeError("Host selector must be a string");
857
+ return e.replaceAll("&", this.resolveElementName(r));
858
+ }
859
+ resolveHostCSS(e, r) {
860
+ if (typeof e != "string") throw new TypeError("Host CSS must be a string");
861
+ return e.replaceAll("&", this.resolveElementName(r));
862
+ }
863
+ create(e, ...r) {
864
+ const i = new e(...r);
865
+ return i._setRuntime(this), i;
866
+ }
867
+ mount(e, r, i = null) {
868
+ e._setRuntime(this);
869
+ let n = null;
870
+ this.router != null && !this.routedRoots.has(e) && (this.routedRoots.add(e), n = this.router.openScope(this.router.root, e), e.onCleanup(n));
871
+ try {
872
+ e.mount(r, i), this.router != null && n != null && this.router.completeScope(this.router.root, e);
873
+ } catch (s) {
874
+ throw n == null || n(), s;
875
+ }
876
+ return e;
877
+ }
878
+ registerStyles(e) {
879
+ if (e == null || typeof e.registerStyles != "function")
880
+ throw new TypeError("registerStyles requires a Capillary UI component dependency");
881
+ return e.registerStyles(this), this;
882
+ }
883
+ injectStyles(e = globalThis.document) {
884
+ return this.styleRegistry.injectAll(e);
885
+ }
886
+ }
887
+ const qe = new lt({}, Yt);
888
+ function ct(t, e) {
889
+ if (typeof t != "string" || !/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(t))
890
+ throw new TypeError(`${e} must be a lowercase kebab-case name`);
891
+ }
892
+ function cr(t) {
893
+ if (ct(t, "Capillary UI element name"), !t.includes("-") || lr.has(t))
894
+ throw new TypeError(`Capillary UI element name must be a non-reserved name containing a hyphen: ${t}`);
895
+ }
896
+ const le = Symbol.for("@capillaryjs/capillary-ui.Fragment"), ur = /* @__PURE__ */ new WeakSet(), hr = /* @__PURE__ */ new Set([
897
+ "allowFullScreen",
898
+ "async",
899
+ "autoFocus",
900
+ "autoPlay",
901
+ "checked",
902
+ "controls",
903
+ "default",
904
+ "defer",
905
+ "disabled",
906
+ "formNoValidate",
907
+ "hidden",
908
+ "inert",
909
+ "loop",
910
+ "multiple",
911
+ "muted",
912
+ "noModule",
913
+ "noValidate",
914
+ "open",
915
+ "playsInline",
916
+ "readOnly",
917
+ "required",
918
+ "reversed",
919
+ "selected"
920
+ ]), dr = /* @__PURE__ */ new Set([
921
+ "checked",
922
+ "defaultChecked",
923
+ "defaultValue",
924
+ "disabled",
925
+ "indeterminate",
926
+ "multiple",
927
+ "muted",
928
+ "readOnly",
929
+ "required",
930
+ "selected",
931
+ "selectedIndex",
932
+ "tabIndex",
933
+ "value"
934
+ ]), _e = "data-cap";
935
+ function ce(t, e = null, ...r) {
936
+ const i = e ?? {};
937
+ if (typeof i != "object" || Array.isArray(i))
938
+ throw new TypeError("VNode props must be an object or null");
939
+ const {
940
+ children: n,
941
+ key: s = null,
942
+ ...o
943
+ } = i;
944
+ return {
945
+ type: t,
946
+ key: s,
947
+ props: {
948
+ ...o,
949
+ children: ut([n, r])
950
+ }
951
+ };
952
+ }
953
+ function pr(t, ...e) {
954
+ return t.reduce((r, i, n) => r + i + String(e[n] ?? ""), "");
955
+ }
956
+ const $ = class $ {
957
+ constructor(e = {}) {
958
+ c(this, "props");
959
+ c(this, "dom", null);
960
+ /** @internal */
961
+ c(this, "_rendered", null);
962
+ /** @internal */
963
+ c(this, "_childComponents", /* @__PURE__ */ new Set());
964
+ /** @internal Component ancestry used to enforce structural invariants. */
965
+ c(this, "_parentComponent", null);
966
+ c(this, "initialized", !1);
967
+ c(this, "mounted", !1);
968
+ c(this, "destroyed", !1);
969
+ c(this, "updating", !1);
970
+ c(this, "updateRequested", !1);
971
+ c(this, "cleanupFunctions", /* @__PURE__ */ new Set());
972
+ c(this, "watched", /* @__PURE__ */ new Map());
973
+ c(this, "renderReadSubscriptions", /* @__PURE__ */ new Map());
974
+ c(this, "collectingRenderReads", null);
975
+ /** @internal */
976
+ c(this, "_runtime", qe);
977
+ /** @internal Route lineage inherited by nested routed components. */
978
+ c(this, "_routeContext", null);
979
+ /** JSX component for this instance's runtime-configured custom host. */
980
+ c(this, "Host", ({
981
+ children: e = [],
982
+ ...r
983
+ }) => this.host(r, e));
984
+ if (e == null || typeof e != "object" || Array.isArray(e))
985
+ throw new TypeError(`${this.constructor.name} props must be an object`);
986
+ this.props = e;
987
+ }
988
+ static new(...e) {
989
+ const r = new this(...e);
990
+ if (!(r instanceof $))
991
+ throw new TypeError("Component.new() requires a Component constructor");
992
+ return r.mount();
993
+ }
994
+ static registerStyles(e = qe, r = /* @__PURE__ */ new Set()) {
995
+ if (r.has(this)) return;
996
+ r.add(this);
997
+ const i = this.hostName ?? null, n = Ar(this);
998
+ for (const s of n)
999
+ Object.hasOwn(s, "css") && s.css && (i == null ? e.styleRegistry.registerCSS(s.css) : e.styleRegistry.registerHostCSS(
1000
+ s.css,
1001
+ e.resolveElementName(i)
1002
+ ));
1003
+ for (const s of n)
1004
+ if (Object.hasOwn(s, "dependencies"))
1005
+ for (const o of s.dependencies ?? [])
1006
+ o.registerStyles(e, r);
1007
+ }
1008
+ /** One-time setup hook. Constructors must not subscribe or render. */
1009
+ initialize() {
1010
+ }
1011
+ render() {
1012
+ throw new Error(`${this.constructor.name} must implement render()`);
1013
+ }
1014
+ /** Render this component's configured custom host element. */
1015
+ host(e = null, ...r) {
1016
+ const n = this.constructor.hostName;
1017
+ if (n == null)
1018
+ throw new Error(`${this.constructor.name} does not declare a custom host name`);
1019
+ const {
1020
+ class: s,
1021
+ className: o,
1022
+ ...a
1023
+ } = e ?? {}, l = o ?? s, u = this.props.island === !0 ? Or(l, "island") : l;
1024
+ return ce(this._runtime.resolveElementName(n), {
1025
+ ...a,
1026
+ ...u == null ? {} : { className: u },
1027
+ "data-cap-component": n
1028
+ }, ...r);
1029
+ }
1030
+ /** @internal Assign an immutable application runtime before initialization or mounting. */
1031
+ _setRuntime(e) {
1032
+ var r;
1033
+ if (!(e instanceof lt))
1034
+ throw new TypeError("Component runtime must be a CapillaryUiRuntime");
1035
+ if (e === this._runtime) return this;
1036
+ if (this.initialized || this.mounted || this._rendered != null)
1037
+ throw new Error("Cannot change a component runtime after initialization");
1038
+ return this._runtime = e, this._routeContext == null && (this._routeContext = ((r = e.router) == null ? void 0 : r.root) ?? null), this;
1039
+ }
1040
+ /** @internal Assign contextual route lineage before initialization. */
1041
+ _setRouteContext(e) {
1042
+ if (this.initialized || this.mounted || this._rendered != null)
1043
+ throw new Error("Cannot change a component route context after initialization");
1044
+ return this._routeContext = e, this;
1045
+ }
1046
+ /** @internal Route lineage inherited by component children. */
1047
+ _routeContextForChildren() {
1048
+ return this._routeContext;
1049
+ }
1050
+ /** @internal Assign the renderer-owned component ancestry. */
1051
+ _setParentComponent(e) {
1052
+ if (this._parentComponent != null && this._parentComponent !== e)
1053
+ throw new Error("A component instance cannot move between component owners");
1054
+ return this._parentComponent = e, this.validateIslandAncestry(this.props), this;
1055
+ }
1056
+ mount(e = null, r = null) {
1057
+ if (this.destroyed) throw new Error("Cannot mount a destroyed component");
1058
+ this.validateIslandAncestry(this.props);
1059
+ let i = !1;
1060
+ return this.initialized || (this.validateRequiredServices(), this.initialized = !0, this.initialize()), this.mounted || (this.mounted = !0, this.update(), i = !0), e != null && (Rr(e), je(e, this._rendered, r)), i && this.afterMount(this.dom), this;
1061
+ }
1062
+ attachTo(e) {
1063
+ return this.mount(e), this;
1064
+ }
1065
+ update(e) {
1066
+ if (this.destroyed) return this;
1067
+ if (!this.mounted) return this.mount();
1068
+ if (this.updating)
1069
+ return this.updateRequested = !0, this;
1070
+ this.updating = !0;
1071
+ try {
1072
+ do {
1073
+ this.updateRequested = !1;
1074
+ const r = /* @__PURE__ */ new Set();
1075
+ this.collectingRenderReads = r;
1076
+ let i;
1077
+ try {
1078
+ i = H(this.render());
1079
+ } finally {
1080
+ this.collectingRenderReads = null;
1081
+ }
1082
+ this._rendered = Re(this._rendered, i, this), this.dom = mt(this._rendered), this.reconcileRenderReads(r), this.afterUpdate(this.dom);
1083
+ } while (this.updateRequested && !this.destroyed);
1084
+ } finally {
1085
+ this.updating = !1;
1086
+ }
1087
+ return this;
1088
+ }
1089
+ setProps(e) {
1090
+ if (e == null || typeof e != "object" || Array.isArray(e))
1091
+ throw new TypeError(`${this.constructor.name} props must be an object`);
1092
+ return this.validateIslandAncestry(e), this.props = e, this.mounted && this.update(), this;
1093
+ }
1094
+ afterMount(e) {
1095
+ }
1096
+ afterUpdate(e) {
1097
+ }
1098
+ watch(...e) {
1099
+ for (const r of e) {
1100
+ if (r == null || typeof r.subscribe != "function")
1101
+ throw new TypeError("watch requires emitter-like values");
1102
+ if (this.watched.has(r)) continue;
1103
+ const i = r.subscribe(({ event: n }) => {
1104
+ this.mounted && !this.destroyed && this.update(n);
1105
+ }, { emitCurrent: !1 });
1106
+ this.watched.set(r, i), this.onCleanup(() => {
1107
+ i(), this.watched.delete(r);
1108
+ });
1109
+ }
1110
+ return this;
1111
+ }
1112
+ watchFutureValues(...e) {
1113
+ return this.watch(...e);
1114
+ }
1115
+ /** Read an emitter during render and rerender when that dependency changes. */
1116
+ read(e) {
1117
+ return this.trackRenderRead(e), e.get();
1118
+ }
1119
+ /** Read a Capillary value, fetch state, and error as one tracked render dependency. */
1120
+ snapshot(e) {
1121
+ return this.trackRenderRead(e), Object.freeze({
1122
+ value: e.get(),
1123
+ fetchState: e.getFetchState(),
1124
+ error: e.getError()
1125
+ });
1126
+ }
1127
+ onCleanup(e) {
1128
+ if (typeof e != "function") throw new TypeError("cleanup must be a function");
1129
+ if (this.destroyed)
1130
+ return e(), () => {
1131
+ };
1132
+ this.cleanupFunctions.add(e);
1133
+ let r = !0;
1134
+ return () => {
1135
+ r && (r = !1, this.cleanupFunctions.delete(e), e());
1136
+ };
1137
+ }
1138
+ /** Resolve one explicitly declared application service from this component's runtime. */
1139
+ requireService(e) {
1140
+ if (!this.initialized)
1141
+ throw new Error("Components may resolve services during initialize() or later");
1142
+ const r = this.constructor;
1143
+ if (!r.requiredServices.includes(e))
1144
+ throw new Error(
1145
+ `${r.name} must declare service "${e.name}" in requiredServices`
1146
+ );
1147
+ return this._runtime.services.require(e);
1148
+ }
1149
+ /** Read the immutable Capillary UI localization selected for this component's runtime. */
1150
+ get localization() {
1151
+ return this._runtime.localization;
1152
+ }
1153
+ /** Resolve one Capillary UI-authored message with the runtime's English fallback. */
1154
+ capillaryUiMessage(e) {
1155
+ return this.localization.message(e);
1156
+ }
1157
+ listen(e, r, i, n) {
1158
+ if (e == null || typeof e.addEventListener != "function")
1159
+ throw new TypeError("listen target must be an EventTarget");
1160
+ const s = i;
1161
+ return e.addEventListener(r, s, n), this.onCleanup(() => e.removeEventListener(r, s, n)), this;
1162
+ }
1163
+ registerChild(e) {
1164
+ if (!(e instanceof $))
1165
+ throw new TypeError("registerChild requires a Component");
1166
+ return this._childComponents.add(e), e;
1167
+ }
1168
+ destroy() {
1169
+ if (!this.destroyed) {
1170
+ this.destroyed = !0, this.mounted = !1;
1171
+ for (const e of [...this.cleanupFunctions]) e();
1172
+ this.cleanupFunctions.clear(), this.watched.clear();
1173
+ for (const e of this.renderReadSubscriptions.values()) e();
1174
+ this.renderReadSubscriptions.clear(), this.collectingRenderReads = null, this._rendered && R(this._rendered, !0), this._rendered = null, this.dom = null, this._childComponents.clear(), this.onDestroy();
1175
+ }
1176
+ }
1177
+ validateRequiredServices() {
1178
+ const e = this.constructor;
1179
+ for (const r of e.requiredServices)
1180
+ if (!this._runtime.services.has(r))
1181
+ throw new Error(`${e.name} requires unregistered service "${r.name}"`);
1182
+ }
1183
+ validateIslandAncestry(e) {
1184
+ if (!ke(e)) return;
1185
+ if (this.hasIslandDescendant())
1186
+ throw new Error("An island component cannot contain another island");
1187
+ let r = this._parentComponent;
1188
+ for (; r != null; ) {
1189
+ if (ke(r.props))
1190
+ throw new Error("An island component cannot be nested inside another island");
1191
+ r = r._parentComponent;
1192
+ }
1193
+ }
1194
+ hasIslandDescendant() {
1195
+ for (const e of this._childComponents)
1196
+ if (ke(e.props) || e.hasIslandDescendant()) return !0;
1197
+ return !1;
1198
+ }
1199
+ onDestroy() {
1200
+ }
1201
+ trackRenderRead(e) {
1202
+ if (wt(e, "Component.read"), this.collectingRenderReads == null)
1203
+ throw new Error("Component.read() and snapshot() may only be called during render()");
1204
+ this.collectingRenderReads.add(e);
1205
+ }
1206
+ reconcileRenderReads(e) {
1207
+ for (const [r, i] of this.renderReadSubscriptions)
1208
+ e.has(r) || (i(), this.renderReadSubscriptions.delete(r));
1209
+ for (const r of e) {
1210
+ if (this.watched.has(r) || this.renderReadSubscriptions.has(r)) continue;
1211
+ const i = r.subscribe(({ event: n }) => {
1212
+ this.mounted && !this.destroyed && this.update(n);
1213
+ }, { emitCurrent: !1 });
1214
+ this.renderReadSubscriptions.set(r, i);
1215
+ }
1216
+ }
1217
+ };
1218
+ c($, "dependencies", []), c($, "requiredServices", []), /** Component `live()` bindings are opt-in; subclasses declare their allowlist. */
1219
+ c($, "liveProps", []), c($, "css", pr`
1220
+ .cap-fill-horizontal,
1221
+ .cap-fill-vertical {
1222
+ box-sizing: border-box;
1223
+ background: var(--application-background);
1224
+ color: var(--ui-color);
1225
+ font-family: var(--font-family);
1226
+ font-size: var(--font-size);
1227
+ line-height: var(--line-height);
1228
+ }
1229
+
1230
+ .cap-fill-horizontal {
1231
+ width: 100vw;
1232
+ max-width: 100vw;
1233
+ min-width: 0;
1234
+ overflow-x: auto;
1235
+ }
1236
+
1237
+ .cap-fill-vertical {
1238
+ height: 100vh;
1239
+ max-height: 100vh;
1240
+ min-height: 0;
1241
+ overflow-y: auto;
1242
+ }
1243
+
1244
+ .cap-layout-horizontal,
1245
+ .cap-layout-vertical {
1246
+ display: flex;
1247
+ align-items: stretch;
1248
+ min-inline-size: 0;
1249
+ min-block-size: 0;
1250
+ }
1251
+
1252
+ .cap-layout-horizontal {
1253
+ flex-direction: row;
1254
+ }
1255
+
1256
+ .cap-layout-vertical {
1257
+ flex-direction: column;
1258
+ }
1259
+
1260
+ .cap-size-natural {
1261
+ flex: 0 0 auto;
1262
+ }
1263
+
1264
+ .cap-size-flexible {
1265
+ flex: 1 1 0;
1266
+ min-inline-size: 0;
1267
+ min-block-size: 0;
1268
+ }
1269
+
1270
+ .cap-scroll {
1271
+ overflow: auto;
1272
+ min-inline-size: 0;
1273
+ min-block-size: 0;
1274
+ }
1275
+
1276
+ .colored {
1277
+ --colored-base-bg:
1278
+ linear-gradient(
1279
+ 15deg,
1280
+ var(--c1) 0%,
1281
+ var(--c2) 65%,
1282
+ var(--c2) 65%,
1283
+ var(--c3) 100%
1284
+ );
1285
+
1286
+ background: var(--colored-base-bg);
1287
+ box-shadow: var(--colored-shadow);
1288
+ border-radius: var(--ui-border-radius);
1289
+ }
1290
+
1291
+ .app-footer.island,
1292
+ .island {
1293
+ box-sizing: border-box;
1294
+ min-width: 0;
1295
+ min-height: 0;
1296
+ margin: var(--island-margin);
1297
+ padding: var(--island-padding);
1298
+ background: var(--island-background);
1299
+ border: var(--island-border);
1300
+ border-radius: var(--island-radius);
1301
+ box-shadow: var(--island-shadow);
1302
+ }
1303
+
1304
+ .cap-fill-horizontal.island,
1305
+ .cap-fill-horizontal .island {
1306
+ max-width: calc(100% - (2 * var(--island-margin)));
1307
+ overflow-x: auto;
1308
+ }
1309
+
1310
+ .cap-fill-vertical.island,
1311
+ .cap-fill-vertical .island {
1312
+ max-height: calc(100% - (2 * var(--island-margin)));
1313
+ overflow-y: auto;
1314
+ }
1315
+
1316
+ label[data-cap] {
1317
+ user-select: none;
1318
+ }
1319
+ `), c($, "hostName", null);
1320
+ let C = $;
1321
+ function H(t) {
1322
+ return Array.isArray(t) ? ce(le, null, t) : t == null || typeof t == "boolean" ? ce(le) : t;
1323
+ }
1324
+ function ut(t) {
1325
+ const e = [], r = (i) => {
1326
+ if (Array.isArray(i))
1327
+ for (const n of i) r(n);
1328
+ else i != null && typeof i != "boolean" && e.push(i);
1329
+ };
1330
+ return r(t), e;
1331
+ }
1332
+ function Y(t, e) {
1333
+ if (typeof t == "string" || typeof t == "number")
1334
+ return {
1335
+ kind: "text",
1336
+ key: null,
1337
+ value: t,
1338
+ node: document.createTextNode(String(t)),
1339
+ owner: e
1340
+ };
1341
+ if (fe(t)) {
1342
+ const s = document.createComment("cap-emitter-start"), o = document.createComment("cap-emitter-end"), a = t.get();
1343
+ if (Object.is(a, t))
1344
+ throw new TypeError("A Capillary UI emitter child cannot render itself");
1345
+ const l = document.createDocumentFragment();
1346
+ l.append(s, o);
1347
+ const u = Y(H(a), e);
1348
+ je(l, u, o);
1349
+ const h = {
1350
+ kind: "emitter",
1351
+ key: null,
1352
+ source: t,
1353
+ start: s,
1354
+ end: o,
1355
+ child: u,
1356
+ unsubscribe: () => {
1357
+ },
1358
+ owner: e
1359
+ };
1360
+ return h.unsubscribe = t.subscribe(({ value: p }) => {
1361
+ if (Object.is(p, t))
1362
+ throw new TypeError("A Capillary UI emitter child cannot render itself");
1363
+ h.child = Re(h.child, H(p), e);
1364
+ }, { emitCurrent: !1 }), h;
1365
+ }
1366
+ if (t instanceof C)
1367
+ return t._setRuntime(e._runtime), t._setRouteContext(e._routeContextForChildren()), t._setParentComponent(e), t.mount(), e.registerChild(t), {
1368
+ kind: "component",
1369
+ key: yt(t.props),
1370
+ type: t.constructor,
1371
+ instance: t,
1372
+ prebuilt: !0,
1373
+ props: t.props,
1374
+ liveProps: /* @__PURE__ */ new Map(),
1375
+ owner: e
1376
+ };
1377
+ if (!T(t))
1378
+ throw new TypeError(`Invalid Capillary UI child: ${Ve(t)}`);
1379
+ const { type: r, key: i = null, props: n } = t;
1380
+ if (r === le) {
1381
+ const s = document.createComment("cap-fragment-start"), o = document.createComment("cap-fragment-end"), a = {
1382
+ kind: "fragment",
1383
+ key: i,
1384
+ type: r,
1385
+ start: s,
1386
+ end: o,
1387
+ children: [],
1388
+ owner: e
1389
+ }, l = document.createDocumentFragment();
1390
+ return l.append(s, o), a.children = ue(
1391
+ l,
1392
+ [],
1393
+ n.children,
1394
+ e,
1395
+ o,
1396
+ s
1397
+ ), a;
1398
+ }
1399
+ if (typeof r == "string") {
1400
+ const s = document.createElement(r), o = {
1401
+ kind: "element",
1402
+ key: i,
1403
+ type: r,
1404
+ node: s,
1405
+ props: {},
1406
+ listeners: /* @__PURE__ */ new Map(),
1407
+ liveProps: /* @__PURE__ */ new Map(),
1408
+ nativeBindings: /* @__PURE__ */ new Map(),
1409
+ ref: null,
1410
+ children: [],
1411
+ owner: e
1412
+ };
1413
+ return ft(o, n), o.children = ue(s, [], n.children, e), o;
1414
+ }
1415
+ if (bt(r)) {
1416
+ const s = n;
1417
+ pt(r, s);
1418
+ const o = Ue(s), a = new r(o);
1419
+ a._setRuntime(e._runtime), a._setRouteContext(e._routeContextForChildren()), a._setParentComponent(e);
1420
+ const l = {
1421
+ kind: "component",
1422
+ key: i,
1423
+ type: r,
1424
+ instance: a,
1425
+ prebuilt: !1,
1426
+ props: o,
1427
+ liveProps: /* @__PURE__ */ new Map(),
1428
+ owner: e
1429
+ };
1430
+ return dt(l, s), a.mount(), e.registerChild(a), l;
1431
+ }
1432
+ if (typeof r == "function") {
1433
+ const s = r, o = n, a = Ue(o), l = H(s(a)), u = {
1434
+ kind: "function",
1435
+ key: i,
1436
+ type: s,
1437
+ props: a,
1438
+ sourceProps: o,
1439
+ liveProps: /* @__PURE__ */ new Map(),
1440
+ child: Y(l, e),
1441
+ owner: e
1442
+ };
1443
+ return mr(u), u;
1444
+ }
1445
+ throw new TypeError(`Unsupported vnode type: ${Ve(r)}`);
1446
+ }
1447
+ function Re(t, e, r) {
1448
+ if (t == null) return Y(e, r);
1449
+ if (gt(t, e)) return ht(t, e, r);
1450
+ const i = Y(e, r), n = mt(t), s = (n == null ? void 0 : n.parentNode) ?? null;
1451
+ return s && je(s, i, n), R(t, !0), i;
1452
+ }
1453
+ function ht(t, e, r) {
1454
+ return t.kind === "text" ? (typeof e != "string" && typeof e != "number" || Object.is(t.value, e) || (t.value = e, t.node.data = String(e)), t) : t.kind === "emitter" ? (!fe(e) || t.source !== e, t) : t.kind === "component" ? (e instanceof C || T(e) && fr(t, e.props), t) : T(e) ? t.kind === "function" ? (yr(t, e.props), t) : t.kind === "fragment" ? (t.children = ue(
1455
+ t.start.parentNode,
1456
+ t.children,
1457
+ e.props.children,
1458
+ r,
1459
+ t.end,
1460
+ t.start
1461
+ ), t) : (ft(t, e.props), t.children = ue(
1462
+ t.node,
1463
+ t.children,
1464
+ e.props.children,
1465
+ r
1466
+ ), t) : t;
1467
+ }
1468
+ function Ue(t) {
1469
+ return Object.fromEntries(Object.entries(t).map(([e, r]) => [
1470
+ e,
1471
+ N(r) ? r.emitter.get() : r
1472
+ ]));
1473
+ }
1474
+ function dt(t, e) {
1475
+ Ae(t.liveProps, e, (r, i) => {
1476
+ t.props = { ...t.props, [r]: i }, t.instance.setProps(t.props);
1477
+ }), t.props = Oe(t.liveProps, e), t.instance.setProps(t.props);
1478
+ }
1479
+ function fr(t, e) {
1480
+ pt(t.type, e), dt(t, e);
1481
+ }
1482
+ function pt(t, e) {
1483
+ const r = Reflect.get(t, "liveProps");
1484
+ if (r == null) return;
1485
+ if (!Array.isArray(r) || r.some((n) => typeof n != "string"))
1486
+ throw new TypeError(`${t.name || "Component"}.liveProps must be an array`);
1487
+ const i = new Set(r);
1488
+ for (const [n, s] of Object.entries(e))
1489
+ if (N(s) && !i.has(n))
1490
+ throw new TypeError(
1491
+ `${t.name || "Component"} prop "${n}" does not support live()`
1492
+ );
1493
+ }
1494
+ function mr(t) {
1495
+ Ae(t.liveProps, t.sourceProps, (e, r) => {
1496
+ t.props = { ...t.props, [e]: r }, $e(t);
1497
+ }), t.props = Oe(t.liveProps, t.sourceProps);
1498
+ }
1499
+ function yr(t, e) {
1500
+ t.sourceProps = e, Ae(t.liveProps, e, (r, i) => {
1501
+ t.props = { ...t.props, [r]: i }, $e(t);
1502
+ }), t.props = Oe(t.liveProps, e), $e(t);
1503
+ }
1504
+ function $e(t) {
1505
+ const e = H(t.type(t.props));
1506
+ t.child = Re(t.child, e, t.owner);
1507
+ }
1508
+ function Ae(t, e, r) {
1509
+ for (const [i, n] of t) {
1510
+ const s = e[i];
1511
+ N(s) && s.emitter === n.source || (n.unsubscribe(), t.delete(i));
1512
+ }
1513
+ for (const [i, n] of Object.entries(e)) {
1514
+ if (!N(n) || t.has(i)) continue;
1515
+ const s = {
1516
+ source: n.emitter,
1517
+ value: n.emitter.get(),
1518
+ unsubscribe: () => {
1519
+ }
1520
+ };
1521
+ s.unsubscribe = n.emitter.subscribe(({ value: o }) => {
1522
+ t.get(i) === s && (s.value = o, r(i, o));
1523
+ }, { emitCurrent: !1 }), t.set(i, s);
1524
+ }
1525
+ }
1526
+ function Oe(t, e) {
1527
+ return Object.fromEntries(Object.entries(e).map(([r, i]) => {
1528
+ var n;
1529
+ return [
1530
+ r,
1531
+ N(i) ? ((n = t.get(r)) == null ? void 0 : n.value) ?? i.emitter.get() : i
1532
+ ];
1533
+ }));
1534
+ }
1535
+ function ue(t, e, r, i, n = null, s = null) {
1536
+ if (t == null) throw new Error("Cannot patch a detached fragment range");
1537
+ const o = ut(r), a = /* @__PURE__ */ new Map(), l = [];
1538
+ for (const g of e)
1539
+ g.key == null ? l.push(g) : a.has(g.key) || a.set(g.key, g);
1540
+ const u = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Set(), p = [];
1541
+ let b = 0;
1542
+ for (const g of o) {
1543
+ const f = U(g);
1544
+ if (f != null) {
1545
+ if (u.has(f)) throw new Error(`Duplicate sibling key: ${String(f)}`);
1546
+ u.add(f);
1547
+ }
1548
+ const E = f == null ? l[b++] : a.get(f);
1549
+ E && gt(E, g) ? (h.add(E), p.push(ht(E, g, i))) : p.push(Y(g, i));
1550
+ }
1551
+ for (const g of e)
1552
+ h.has(g) || R(g, !0);
1553
+ let y = s ? s.nextSibling : t.firstChild;
1554
+ for (const g of p)
1555
+ for (const f of O(g))
1556
+ f === y ? y = y.nextSibling : (t.insertBefore(f, y ?? n), y = f.nextSibling);
1557
+ return p;
1558
+ }
1559
+ function ft(t, e) {
1560
+ const r = Object.fromEntries(Object.entries(e).filter(
1561
+ ([s]) => s !== "children" && se(s) !== _e
1562
+ )), i = t.props, n = /* @__PURE__ */ new Set([...Object.keys(i), ...Object.keys(r)]);
1563
+ for (const s of ["value", "checked"])
1564
+ if (Object.hasOwn(r, s) && Object.hasOwn(r, `bind:${s}`))
1565
+ throw new Error(`${s} and bind:${s} cannot be used together`);
1566
+ for (const s of n) {
1567
+ const o = i[s], a = r[s];
1568
+ if (Cr(s))
1569
+ br(t, s, a);
1570
+ else if (s === "ref")
1571
+ o !== a && vr(t, a);
1572
+ else if ($r(s))
1573
+ wr(t, s, a);
1574
+ else if (N(a))
1575
+ gr(t, s, a);
1576
+ else {
1577
+ const l = t.liveProps.get(s);
1578
+ l && (l.unsubscribe(), t.liveProps.delete(s));
1579
+ const u = (l == null ? void 0 : l.value) ?? o;
1580
+ Object.is(u, a) || M(t.node, s, u, a);
1581
+ }
1582
+ }
1583
+ t.node.setAttribute(_e, ""), t.props = { ...r };
1584
+ }
1585
+ function gr(t, e, r) {
1586
+ const i = t.liveProps.get(e);
1587
+ if ((i == null ? void 0 : i.source) === r.emitter) return;
1588
+ i == null || i.unsubscribe();
1589
+ const n = r.emitter.get();
1590
+ M(t.node, e, (i == null ? void 0 : i.value) ?? t.props[e], n);
1591
+ const s = {
1592
+ source: r.emitter,
1593
+ value: n,
1594
+ unsubscribe: () => {
1595
+ }
1596
+ };
1597
+ s.unsubscribe = r.emitter.subscribe(({ value: o }) => {
1598
+ const a = s.value;
1599
+ s.value = o, Object.is(a, o) || M(t.node, e, a, o);
1600
+ }, { emitCurrent: !1 }), t.liveProps.set(e, s);
1601
+ }
1602
+ function br(t, e, r) {
1603
+ const i = e.slice(5), n = t.nativeBindings.get(e);
1604
+ if (r == null) {
1605
+ n && (n.unsubscribe(), t.node.removeEventListener(n.eventName, n.listener), t.nativeBindings.delete(e), M(t.node, i, n.value, void 0));
1606
+ return;
1607
+ }
1608
+ if (xr(r, e), (n == null ? void 0 : n.source) === r) return;
1609
+ n && (n.unsubscribe(), t.node.removeEventListener(n.eventName, n.listener)), Tr(t.node, i);
1610
+ const s = zr(t.node, i), o = r.get();
1611
+ M(t.node, i, n == null ? void 0 : n.value, o);
1612
+ const a = () => {
1613
+ r.set(Reflect.get(t.node, i), `${e} changed`);
1614
+ }, l = {
1615
+ source: r,
1616
+ value: o,
1617
+ eventName: s,
1618
+ listener: a,
1619
+ unsubscribe: () => {
1620
+ }
1621
+ };
1622
+ l.unsubscribe = r.subscribe(({ value: u }) => {
1623
+ const h = l.value;
1624
+ l.value = u, Object.is(h, u) || M(t.node, i, h, u);
1625
+ }, { emitCurrent: !1 }), t.node.addEventListener(s, a), t.nativeBindings.set(e, l);
1626
+ }
1627
+ function wr(t, e, r) {
1628
+ const i = e.slice(2).toLowerCase(), n = t.listeners.get(e);
1629
+ if (n && n !== r && (t.node.removeEventListener(i, n), t.listeners.delete(e)), r != null && typeof r != "function")
1630
+ throw new TypeError(`${e} must be a function or null`);
1631
+ if (typeof r == "function" && n !== r) {
1632
+ const s = r;
1633
+ t.node.addEventListener(i, s), t.listeners.set(e, s);
1634
+ }
1635
+ }
1636
+ function vr(t, e) {
1637
+ if (Ce(t.ref, null), e != null && typeof e != "function" && typeof e != "object")
1638
+ throw new TypeError("ref must be a function, object, or null");
1639
+ t.ref = e, Ce(t.ref, t.node);
1640
+ }
1641
+ function M(t, e, r, i) {
1642
+ if (e === "class" || e === "className") {
1643
+ ve(t, "class", i);
1644
+ return;
1645
+ }
1646
+ if (e === "for" || e === "htmlFor") {
1647
+ ve(t, "for", i);
1648
+ return;
1649
+ }
1650
+ if (e === "dataset") {
1651
+ kr(t, r, i);
1652
+ return;
1653
+ }
1654
+ if (e === "style") {
1655
+ Sr(t, r, i);
1656
+ return;
1657
+ }
1658
+ if (e === "dangerouslySetInnerHTML")
1659
+ throw new Error("dangerouslySetInnerHTML is not supported");
1660
+ const n = Er(e);
1661
+ if (hr.has(n)) {
1662
+ const s = !!i;
1663
+ n in t && Reflect.set(t, n, s), t.toggleAttribute(se(e), s);
1664
+ return;
1665
+ }
1666
+ if (dr.has(n) && n in t) {
1667
+ const s = i ?? (n === "value" ? "" : !1);
1668
+ Object.is(Reflect.get(t, n), s) || Reflect.set(t, n, s), i == null && t.removeAttribute(se(e));
1669
+ return;
1670
+ }
1671
+ ve(t, se(e), i);
1672
+ }
1673
+ function kr(t, e, r) {
1674
+ const i = he(e, "dataset"), n = he(r, "dataset");
1675
+ for (const s of /* @__PURE__ */ new Set([...Object.keys(i), ...Object.keys(n)])) {
1676
+ const o = n[s];
1677
+ o == null ? delete t.dataset[s] : t.dataset[s] = String(o);
1678
+ }
1679
+ }
1680
+ function Sr(t, e, r) {
1681
+ if (typeof r == "string") {
1682
+ t.style.cssText = r;
1683
+ return;
1684
+ }
1685
+ const i = typeof e == "string" ? {} : he(e, "style"), n = he(r, "style");
1686
+ typeof e == "string" && (t.style.cssText = "");
1687
+ for (const s of /* @__PURE__ */ new Set([...Object.keys(i), ...Object.keys(n)])) {
1688
+ const o = n[s];
1689
+ s.startsWith("--") ? o == null ? t.style.removeProperty(s) : t.style.setProperty(s, String(o)) : Reflect.set(t.style, s, o == null ? "" : String(o));
1690
+ }
1691
+ }
1692
+ function he(t, e) {
1693
+ if (t == null) return {};
1694
+ if (typeof t != "object" || Array.isArray(t))
1695
+ throw new TypeError(`${e} must be an object or null`);
1696
+ return t;
1697
+ }
1698
+ function ve(t, e, r) {
1699
+ r == null || r === !1 ? t.removeAttribute(e) : r === !0 ? t.setAttribute(e, "") : t.setAttribute(e, String(r));
1700
+ }
1701
+ function Er(t) {
1702
+ return t === "readonly" ? "readOnly" : t === "autofocus" ? "autoFocus" : t;
1703
+ }
1704
+ function se(t) {
1705
+ return t === "className" ? "class" : t === "htmlFor" ? "for" : t === "minLength" ? "minlength" : t === "maxLength" ? "maxlength" : t === "autoComplete" ? "autocomplete" : t === "inputMode" ? "inputmode" : /^aria[A-Z]/.test(t) || /^data[A-Z]/.test(t) ? He(t) : t.replace(/[A-Z]/g, (e) => `-${e.toLowerCase()}`);
1706
+ }
1707
+ function He(t) {
1708
+ return t.replace(/[A-Z]/g, (e) => `-${e.toLowerCase()}`);
1709
+ }
1710
+ function Ce(t, e) {
1711
+ t != null && (typeof t == "function" ? t(e) : t.current = e);
1712
+ }
1713
+ function R(t, e) {
1714
+ if (t.kind === "emitter") {
1715
+ if (t.unsubscribe(), R(t.child, !1), e)
1716
+ for (const r of O(t)) r.remove();
1717
+ return;
1718
+ }
1719
+ if (t.kind === "component") {
1720
+ for (const r of t.liveProps.values()) r.unsubscribe();
1721
+ t.liveProps.clear(), t.owner._childComponents.delete(t.instance), t.instance.destroy();
1722
+ return;
1723
+ }
1724
+ if (t.kind === "function") {
1725
+ for (const r of t.liveProps.values()) r.unsubscribe();
1726
+ t.liveProps.clear(), R(t.child, e);
1727
+ return;
1728
+ }
1729
+ if (t.kind === "element") {
1730
+ Ce(t.ref, null);
1731
+ for (const [r, i] of t.listeners)
1732
+ t.node.removeEventListener(r.slice(2).toLowerCase(), i);
1733
+ t.listeners.clear();
1734
+ for (const r of t.liveProps.values()) r.unsubscribe();
1735
+ t.liveProps.clear();
1736
+ for (const r of t.nativeBindings.values())
1737
+ r.unsubscribe(), t.node.removeEventListener(r.eventName, r.listener);
1738
+ t.nativeBindings.clear();
1739
+ for (const r of t.children) R(r, !1);
1740
+ e && t.node.remove();
1741
+ return;
1742
+ }
1743
+ if (t.kind === "fragment") {
1744
+ for (const r of t.children) R(r, !1);
1745
+ if (e)
1746
+ for (const r of O(t)) r.remove();
1747
+ return;
1748
+ }
1749
+ e && t.node.remove();
1750
+ }
1751
+ function je(t, e, r = null) {
1752
+ if (e != null)
1753
+ for (const i of O(e)) t.insertBefore(i, r);
1754
+ }
1755
+ function O(t) {
1756
+ if (t == null) return [];
1757
+ if (t.kind === "text" || t.kind === "element") return [t.node];
1758
+ if (t.kind === "component") return O(t.instance._rendered);
1759
+ if (t.kind === "function") return O(t.child);
1760
+ const e = [];
1761
+ let r = t.start;
1762
+ for (; r && (e.push(r), r !== t.end); )
1763
+ r = r.nextSibling;
1764
+ return e;
1765
+ }
1766
+ function mt(t) {
1767
+ return O(t)[0] ?? null;
1768
+ }
1769
+ function U(t) {
1770
+ return t instanceof C ? yt(t.props) : T(t) ? t.key : null;
1771
+ }
1772
+ function yt(t) {
1773
+ const e = t.key;
1774
+ return typeof e == "string" || typeof e == "number" ? e : null;
1775
+ }
1776
+ function gt(t, e) {
1777
+ return t.kind === "text" ? typeof e == "string" || typeof e == "number" : t.kind === "emitter" ? fe(e) && t.source === e : t.kind === "component" ? e instanceof C ? t.instance === e : T(e) && bt(e.type) && t.type === e.type && t.key === U(e) : t.kind === "function" ? T(e) && t.type === e.type && t.key === U(e) : t.kind === "fragment" ? T(e) && e.type === le && t.key === U(e) : T(e) && typeof e.type == "string" && t.type === e.type && t.key === U(e);
1778
+ }
1779
+ function T(t) {
1780
+ return t != null && typeof t == "object" && Object.hasOwn(t, "type");
1781
+ }
1782
+ function bt(t) {
1783
+ return typeof t == "function" && (t === C || t.prototype instanceof C);
1784
+ }
1785
+ function $r(t) {
1786
+ return /^on[A-Z]/.test(t);
1787
+ }
1788
+ function Cr(t) {
1789
+ return t === "bind:value" || t === "bind:checked";
1790
+ }
1791
+ function N(t) {
1792
+ return t != null && typeof t == "object" && ur.has(t);
1793
+ }
1794
+ function fe(t) {
1795
+ return (typeof t != "object" || t == null) && typeof t != "function" ? !1 : typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "getFetchState") == "function" && typeof Reflect.get(t, "getError") == "function" && typeof Reflect.get(t, "subscribe") == "function";
1796
+ }
1797
+ function wt(t, e) {
1798
+ if (!fe(t)) throw new TypeError(`${e} requires a readable emitter`);
1799
+ }
1800
+ function xr(t, e) {
1801
+ if (wt(t, e), typeof Reflect.get(t, "set") != "function")
1802
+ throw new TypeError(`${e} requires a writable emitter`);
1803
+ }
1804
+ function Tr(t, e) {
1805
+ const r = t.localName;
1806
+ if (!(e === "checked" ? r === "input" : r === "input" || r === "textarea" || r === "select")) throw new TypeError(`bind:${e} is not supported on ${r}`);
1807
+ }
1808
+ function zr(t, e) {
1809
+ return e === "value" && t.localName !== "select" ? "input" : "change";
1810
+ }
1811
+ function Rr(t) {
1812
+ if (t == null || typeof t != "object" && typeof t != "function" || typeof Reflect.get(t, "insertBefore") != "function")
1813
+ throw new TypeError("Component parent must be a DOM ParentNode");
1814
+ }
1815
+ function Ve(t) {
1816
+ try {
1817
+ return String(t);
1818
+ } catch {
1819
+ return Object.prototype.toString.call(t);
1820
+ }
1821
+ }
1822
+ function Ar(t) {
1823
+ const e = [];
1824
+ let r = t;
1825
+ for (; r != null && typeof r == "function" && (e.unshift(r), r !== C); )
1826
+ r = Object.getPrototypeOf(r);
1827
+ return e;
1828
+ }
1829
+ function Or(...t) {
1830
+ return [...new Set(t.flatMap((e) => typeof e == "string" ? e.split(/\s+/) : []).filter(Boolean))].join(" ");
1831
+ }
1832
+ function ke(t) {
1833
+ if (t.island === !0) return !0;
1834
+ const e = t.className ?? t.class;
1835
+ return typeof e == "string" && e.split(/\s+/).includes("island");
1836
+ }
1837
+ function d(t, e, r) {
1838
+ const i = e == null ? {} : { ...e };
1839
+ return r !== void 0 && (i.key = r), ce(t, i);
1840
+ }
1841
+ const m = d, jr = [
1842
+ "var(--colored-dark)",
1843
+ "var(--colored-base)",
1844
+ "var(--colored-light)"
1845
+ ];
1846
+ class ee extends Te {
1847
+ render() {
1848
+ var b;
1849
+ const {
1850
+ model: e,
1851
+ label: r = "Block graph",
1852
+ description: i = "Area is proportional to item count.",
1853
+ emptyMessage: n = "No items are available."
1854
+ } = this.props, s = this.snapshot(e.layout$), o = this.read(e.selectedPath$), a = s.value, l = D(a.root, o), u = a.root.children.length === 0 ? [a.root] : a.root.children, h = (b = u[0]) == null ? void 0 : b.key, p = this.Host;
1855
+ return /* @__PURE__ */ m(
1856
+ p,
1857
+ {
1858
+ className: (this.props.className ?? this.props.class ?? "") || null,
1859
+ "aria-label": r,
1860
+ "aria-busy": s.fetchState !== k.Ready ? "true" : null,
1861
+ children: [
1862
+ /* @__PURE__ */ m("header", { children: [
1863
+ /* @__PURE__ */ m("cap-summary", { children: [
1864
+ /* @__PURE__ */ d("h2", { children: r }),
1865
+ /* @__PURE__ */ m("p", { children: [
1866
+ i,
1867
+ " ",
1868
+ a.root.count,
1869
+ " items."
1870
+ ] }),
1871
+ /* @__PURE__ */ m("output", { children: [
1872
+ /* @__PURE__ */ d("strong", { children: "Selection:" }),
1873
+ " ",
1874
+ l == null ? "None" : l.path.length === 0 ? l.label : l.path.map((y, g) => {
1875
+ var E;
1876
+ const f = l.path.slice(0, g + 1);
1877
+ return ((E = D(a.root, f)) == null ? void 0 : E.label) ?? y.categoryKey;
1878
+ }).join(" → ")
1879
+ ] })
1880
+ ] }),
1881
+ /* @__PURE__ */ d(
1882
+ oe,
1883
+ {
1884
+ label: "Clear selection",
1885
+ disabled: o == null,
1886
+ onClick: () => e.clear()
1887
+ }
1888
+ )
1889
+ ] }),
1890
+ s.fetchState === k.Error ? /* @__PURE__ */ d("p", { role: "alert", children: "The block graph could not be calculated." }) : s.fetchState !== k.Ready ? /* @__PURE__ */ d("p", { role: "status", "aria-live": "polite", children: "Loading block graph…" }) : a.valid ? a.root.count === 0 ? /* @__PURE__ */ d("p", { role: "status", children: n }) : /* @__PURE__ */ d(
1891
+ "cap-scroller",
1892
+ {
1893
+ tabIndex: 0,
1894
+ "aria-label": `Scrollable ${r}`,
1895
+ children: /* @__PURE__ */ d(
1896
+ "cap-blocks",
1897
+ {
1898
+ role: "tree",
1899
+ "aria-label": r,
1900
+ className: a.root.childOrientation,
1901
+ onClick: (y) => {
1902
+ y.target === y.currentTarget && e.clear();
1903
+ },
1904
+ children: u.map((y) => this.renderBlock(
1905
+ y,
1906
+ o,
1907
+ (l == null ? void 0 : l.key) ?? h ?? null
1908
+ ))
1909
+ }
1910
+ )
1911
+ }
1912
+ ) : this.renderPartitionError(a.issues)
1913
+ ]
1914
+ }
1915
+ );
1916
+ }
1917
+ renderBlock(e, r, i) {
1918
+ const n = Lr(e.path, r), s = e.colors, o = Xe(s ?? jr);
1919
+ return /* @__PURE__ */ m(
1920
+ "article",
1921
+ {
1922
+ role: "treeitem",
1923
+ className: "colored",
1924
+ tabIndex: n || r == null && e.key === i ? 0 : -1,
1925
+ "aria-level": Math.max(1, e.depth + 1),
1926
+ "aria-selected": n ? "true" : "false",
1927
+ "aria-label": `${e.criterionLabel ?? "Items"}: ${e.label}, ${e.count} ${e.count === 1 ? "item" : "items"}`,
1928
+ "data-block-key": e.key,
1929
+ onClick: (a) => {
1930
+ a.target.closest('[role="treeitem"]') === a.currentTarget && this.props.model.select(e.path);
1931
+ },
1932
+ onKeyDown: (a) => this.blockKeyDown(a, e),
1933
+ style: {
1934
+ flexGrow: e.count,
1935
+ ...o,
1936
+ ...s == null ? {} : {
1937
+ borderColor: s[0]
1938
+ }
1939
+ },
1940
+ children: [
1941
+ /* @__PURE__ */ m("cap-blocklabel", { children: [
1942
+ /* @__PURE__ */ m("cap-blockname", { children: [
1943
+ /* @__PURE__ */ m("small", { children: [
1944
+ e.criterionLabel ?? "Items",
1945
+ ":"
1946
+ ] }),
1947
+ /* @__PURE__ */ d("strong", { children: e.label })
1948
+ ] }),
1949
+ /* @__PURE__ */ d("data", { value: String(e.count), children: e.count })
1950
+ ] }),
1951
+ e.children.length === 0 ? null : /* @__PURE__ */ d(
1952
+ "cap-blockgroup",
1953
+ {
1954
+ role: "group",
1955
+ className: e.childOrientation,
1956
+ children: e.children.map((a) => this.renderBlock(
1957
+ a,
1958
+ r,
1959
+ i
1960
+ ))
1961
+ }
1962
+ )
1963
+ ]
1964
+ },
1965
+ e.key
1966
+ );
1967
+ }
1968
+ renderPartitionError(e) {
1969
+ const r = e[0], i = r == null ? "The selected criteria do not form a complete partition." : r.kind === "unmatched" ? `${r.criterionLabel} has an item with no category.` : `${r.criterionLabel} has an item matching multiple categories.`;
1970
+ return /* @__PURE__ */ m("div", { role: "alert", children: [
1971
+ /* @__PURE__ */ d("strong", { children: "Invalid block partition" }),
1972
+ /* @__PURE__ */ m("p", { children: [
1973
+ i,
1974
+ " ",
1975
+ e.length,
1976
+ " partition issue",
1977
+ e.length === 1 ? "" : "s",
1978
+ " detected."
1979
+ ] })
1980
+ ] });
1981
+ }
1982
+ blockKeyDown(e, r) {
1983
+ if (e.key === "Enter" || e.key === " ") {
1984
+ e.preventDefault(), this.props.model.select(r.path, "block selected by keyboard");
1985
+ return;
1986
+ }
1987
+ if (e.key === "Escape") {
1988
+ e.preventDefault(), this.props.model.clear("block selection cleared by keyboard");
1989
+ return;
1990
+ }
1991
+ const i = this.props.model.layout$.get().root, n = vt(i.children.length === 0 ? [i] : i.children), s = n.findIndex(({ key: a }) => a === r.key);
1992
+ let o;
1993
+ if (e.key === "ArrowDown") o = n[s + 1];
1994
+ else if (e.key === "ArrowUp") o = n[s - 1];
1995
+ else if (e.key === "Home") o = n[0];
1996
+ else if (e.key === "End") o = n.at(-1);
1997
+ else if (e.key === "ArrowRight") o = r.children[0] ?? n[s + 1];
1998
+ else if (e.key === "ArrowLeft")
1999
+ o = r.path.length <= 1 ? n[s - 1] : D(i, r.path.slice(0, -1)) ?? void 0;
2000
+ else return;
2001
+ o != null && (e.preventDefault(), this.focusBlock(o.key));
2002
+ }
2003
+ focusBlock(e) {
2004
+ if (this.dom instanceof Element) {
2005
+ for (const r of this.dom.querySelectorAll('[role="treeitem"]'))
2006
+ if (r.dataset.blockKey === e) {
2007
+ r.focus();
2008
+ return;
2009
+ }
2010
+ }
2011
+ }
2012
+ }
2013
+ c(ee, "liveProps", []), c(ee, "hostName", "block-graph"), c(ee, "dependencies", [oe]), c(ee, "css", G`
2014
+ & {
2015
+ display: flex;
2016
+ min-width: 0;
2017
+ min-height: var(--viz-block-graph-min-height, 24rem);
2018
+ flex-direction: column;
2019
+ padding: var(--viz-space, 0.7rem);
2020
+ overflow: hidden;
2021
+ user-select: none;
2022
+ }
2023
+
2024
+ & > header {
2025
+ display: flex;
2026
+ flex: 0 0 auto;
2027
+ flex-wrap: wrap;
2028
+ justify-content: space-between;
2029
+ gap: 0.5rem;
2030
+ margin-block-end: 0.6rem;
2031
+ }
2032
+
2033
+ & h2,
2034
+ & p {
2035
+ margin: 0;
2036
+ }
2037
+
2038
+ & header output {
2039
+ display: block;
2040
+ margin-block-start: 0.25rem;
2041
+ }
2042
+
2043
+ & > cap-scroller {
2044
+ flex: 1;
2045
+ min-width: 0;
2046
+ min-height: 20rem;
2047
+ overflow: auto;
2048
+ }
2049
+
2050
+ & cap-blocks,
2051
+ & cap-blockgroup {
2052
+ display: flex;
2053
+ min-width: 0;
2054
+ min-height: 0;
2055
+ align-items: stretch;
2056
+ }
2057
+
2058
+ & cap-blocks {
2059
+ width: 100%;
2060
+ min-width: 34rem;
2061
+ height: 100%;
2062
+ min-height: 24rem;
2063
+ }
2064
+
2065
+ & .horizontal {
2066
+ flex-direction: row;
2067
+ }
2068
+
2069
+ & .vertical {
2070
+ flex-direction: column;
2071
+ }
2072
+
2073
+ & [role="treeitem"] {
2074
+ position: relative;
2075
+ display: flex;
2076
+ min-width: 0;
2077
+ min-height: 0;
2078
+ flex-basis: 0;
2079
+ flex-direction: column;
2080
+ overflow: hidden;
2081
+ border: var(--block-graph-block-border, 1px solid var(--c1, var(--colored-dark)));
2082
+ border-radius: var(--block-graph-block-radius, 0.25em);
2083
+ box-shadow: var(--block-graph-block-shadow, none);
2084
+ color: var(--colored-contrast);
2085
+ }
2086
+
2087
+ & [role="treeitem"] > cap-blocklabel {
2088
+ position: absolute;
2089
+ z-index: 1;
2090
+ inset-block-start: 0;
2091
+ inset-inline-start: 0;
2092
+ box-sizing: border-box;
2093
+ display: grid;
2094
+ grid-template-columns: minmax(0, 1fr) auto;
2095
+ grid-template-areas: "label count";
2096
+ align-items: center;
2097
+ gap: 0 0.35rem;
2098
+ width: 100%;
2099
+ padding: 0.25rem 0.4rem;
2100
+ overflow: hidden;
2101
+ text-align: start;
2102
+ border: 0;
2103
+ cursor: pointer;
2104
+ }
2105
+
2106
+ & [role="treeitem"][aria-selected="true"] {
2107
+ z-index: 3;
2108
+ outline: 3px solid var(--viz-selection-color, var(--colored-contrast, Highlight));
2109
+ outline-offset: -3px;
2110
+ }
2111
+
2112
+ & [role="treeitem"]:focus-visible {
2113
+ z-index: 2;
2114
+ outline: 3px solid var(--viz-focus-color, Highlight);
2115
+ outline-offset: -3px;
2116
+ }
2117
+
2118
+ & cap-blocklabel > cap-blockname {
2119
+ grid-area: label;
2120
+ display: grid;
2121
+ grid-template-columns: auto minmax(0, 1fr);
2122
+ align-items: baseline;
2123
+ gap: 0.2rem;
2124
+ min-width: 0;
2125
+ overflow: hidden;
2126
+ white-space: nowrap;
2127
+ }
2128
+
2129
+ & cap-blockname > small {
2130
+ overflow: hidden;
2131
+ font-size: 0.68rem;
2132
+ opacity: 0.82;
2133
+ text-overflow: ellipsis;
2134
+ white-space: nowrap;
2135
+ }
2136
+
2137
+ & cap-blockname > strong {
2138
+ min-width: 0;
2139
+ overflow: hidden;
2140
+ text-overflow: ellipsis;
2141
+ white-space: nowrap;
2142
+ }
2143
+
2144
+ & cap-blocklabel > data {
2145
+ grid-area: count;
2146
+ align-self: center;
2147
+ font-weight: 750;
2148
+ }
2149
+
2150
+ & cap-blockgroup {
2151
+ position: relative;
2152
+ z-index: 1;
2153
+ box-sizing: border-box;
2154
+ flex: 1;
2155
+ padding: var(--viz-block-graph-child-inset, 1.6em);
2156
+ }
2157
+
2158
+ & [role="treeitem"]:hover:not(:has([role="treeitem"]:hover)) {
2159
+ filter: saturate(1.35) brightness(1.15);
2160
+ }
2161
+
2162
+ @media (forced-colors: active) {
2163
+ & [role="treeitem"] {
2164
+ color: CanvasText;
2165
+ background: Canvas;
2166
+ border-color: CanvasText;
2167
+ forced-color-adjust: auto;
2168
+ }
2169
+
2170
+ & [role="treeitem"] > cap-blocklabel {
2171
+ color: ButtonText;
2172
+ background: ButtonFace;
2173
+ }
2174
+ }
2175
+ `);
2176
+ function vt(t) {
2177
+ return t.flatMap((e) => [e, ...vt(e.children)]);
2178
+ }
2179
+ function Lr(t, e) {
2180
+ return e != null && t.length === e.length && t.every((r, i) => {
2181
+ var n, s;
2182
+ return r.criterionKey === ((n = e[i]) == null ? void 0 : n.criterionKey) && r.categoryKey === ((s = e[i]) == null ? void 0 : s.categoryKey);
2183
+ });
2184
+ }
2185
+ class de extends At {
2186
+ constructor(r) {
2187
+ super(r);
2188
+ c(this, "contentId");
2189
+ c(this, "collapsed");
2190
+ this.collapsed = r.collapsed ?? !1, this.contentId = `${this.groupId}-content`;
2191
+ }
2192
+ render() {
2193
+ if (this.props.headerEnd != null)
2194
+ throw new Error(
2195
+ "CollapsibleOptionGroup trailing header content must use a direct OptionGroupHeaderEnd child"
2196
+ );
2197
+ const { content: r, regions: i } = Ot(
2198
+ "CollapsibleOptionGroup",
2199
+ this.props.children,
2200
+ { headerEnd: jt }
2201
+ );
2202
+ return this.renderOptionGroup(r, i.headerEnd ?? null);
2203
+ }
2204
+ toggle() {
2205
+ this.collapsed = !this.collapsed, this.update();
2206
+ }
2207
+ renderOptionGroup(r, i) {
2208
+ const n = this.Host, {
2209
+ label: s,
2210
+ ariaLabel: o,
2211
+ disabled: a = !1,
2212
+ required: l = !1,
2213
+ busy: u = !1,
2214
+ error: h = null
2215
+ } = this.props;
2216
+ return /* @__PURE__ */ m(n, { className: this.props.className ?? this.props.class ?? null, children: [
2217
+ /* @__PURE__ */ m(
2218
+ "fieldset",
2219
+ {
2220
+ id: this.groupId,
2221
+ disabled: a,
2222
+ "aria-label": s == null ? o : null,
2223
+ "aria-required": l ? "true" : null,
2224
+ "aria-busy": u ? "true" : null,
2225
+ "aria-invalid": h == null ? null : "true",
2226
+ "aria-describedby": h == null ? null : this.errorId,
2227
+ children: [
2228
+ /* @__PURE__ */ m("legend", { children: [
2229
+ /* @__PURE__ */ d(
2230
+ "button",
2231
+ {
2232
+ type: "button",
2233
+ className: "cap-collapse-toggle",
2234
+ "aria-expanded": !this.collapsed,
2235
+ "aria-controls": this.contentId,
2236
+ onClick: () => this.toggle(),
2237
+ children: this.collapsed ? "▸" : "▾"
2238
+ }
2239
+ ),
2240
+ s != null ? /* @__PURE__ */ d("span", { children: s }) : null,
2241
+ i
2242
+ ] }),
2243
+ /* @__PURE__ */ d("div", { id: this.contentId, hidden: this.collapsed, children: r })
2244
+ ]
2245
+ }
2246
+ ),
2247
+ this.renderOptionGroupError(h)
2248
+ ] });
2249
+ }
2250
+ }
2251
+ c(de, "hostName", "collapsible-option-group"), c(de, "css", G`
2252
+ & > fieldset > legend > button.cap-collapse-toggle {
2253
+ display: inline-flex;
2254
+ align-items: center;
2255
+ justify-content: center;
2256
+ width: 1.2em;
2257
+ height: 1.2em;
2258
+ padding: 0;
2259
+ border: 0;
2260
+ border-radius: var(--ui-border-radius);
2261
+ background: transparent;
2262
+ color: inherit;
2263
+ font: inherit;
2264
+ cursor: pointer;
2265
+ flex: 0 0 auto;
2266
+ user-select: none;
2267
+ }
2268
+
2269
+ & > fieldset > legend > button.cap-collapse-toggle:hover {
2270
+ background: var(--button-background-hover, rgba(0, 0, 0, 0.05));
2271
+ }
2272
+
2273
+ & > fieldset > legend > button.cap-collapse-toggle:focus-visible {
2274
+ outline: 2px solid var(--focus-color, var(--ui-accent-color));
2275
+ outline-offset: 1px;
2276
+ }
2277
+
2278
+ & > fieldset > div {
2279
+ display: contents;
2280
+ }
2281
+
2282
+ & > fieldset > div[hidden] {
2283
+ display: none;
2284
+ }
2285
+ `);
2286
+ const Dr = [
2287
+ ["☐", "hidden"],
2288
+ ["✓", "visible"]
2289
+ ];
2290
+ class te extends Lt {
2291
+ render() {
2292
+ const {
2293
+ criteria: e,
2294
+ label: r = "Show or hide categories",
2295
+ description: i = ""
2296
+ } = this.props, n = this.snapshot(this.props.items$), s = Array.isArray(n.value) ? n.value : [];
2297
+ return this.renderGroupBox(
2298
+ r,
2299
+ /* @__PURE__ */ m("cap-categoryhidecontent", { children: [
2300
+ /* @__PURE__ */ d("p", { children: i }),
2301
+ n.fetchState === k.Error ? /* @__PURE__ */ d("p", { role: "alert", children: "Category counts are unavailable." }) : null,
2302
+ /* @__PURE__ */ d("cap-criteriongroups", { children: e.map((o) => {
2303
+ const a = this.snapshot(o.categories$), l = Array.isArray(a.value) ? a.value : [];
2304
+ return /* @__PURE__ */ m(
2305
+ de,
2306
+ {
2307
+ label: o.label,
2308
+ children: [
2309
+ a.fetchState === k.Error ? /* @__PURE__ */ m("p", { role: "alert", children: [
2310
+ o.label,
2311
+ " categories are unavailable."
2312
+ ] }) : null,
2313
+ a.fetchState !== k.Ready ? /* @__PURE__ */ m("p", { role: "status", "aria-live": "polite", children: [
2314
+ "Loading ",
2315
+ o.label,
2316
+ "…"
2317
+ ] }) : null,
2318
+ /* @__PURE__ */ d("cap-categories", { children: l.map((u) => {
2319
+ const h = Mr(s, u.predicate);
2320
+ return /* @__PURE__ */ m(
2321
+ "cap-categoryoption",
2322
+ {
2323
+ style: { ...Xe(u.colors) },
2324
+ children: [
2325
+ /* @__PURE__ */ d("cap-categoryswatch", { "aria-hidden": "true" }),
2326
+ /* @__PURE__ */ d(
2327
+ ae,
2328
+ {
2329
+ symbols: Dr,
2330
+ label: `${u.label} (${h})`,
2331
+ valueEmitter: o.visibility(u.key)
2332
+ }
2333
+ )
2334
+ ]
2335
+ },
2336
+ u.key
2337
+ );
2338
+ }) })
2339
+ ]
2340
+ },
2341
+ o.key
2342
+ );
2343
+ }) })
2344
+ ] })
2345
+ );
2346
+ }
2347
+ }
2348
+ c(te, "liveProps", []), c(te, "hostName", "category-hide-panel"), c(te, "dependencies", [ae, de]), c(te, "css", G`
2349
+ & {
2350
+ flex: 0 0 auto;
2351
+ min-width: 0;
2352
+ user-select: none;
2353
+ }
2354
+
2355
+ & > cap-content > cap-categoryhidecontent {
2356
+ display: grid;
2357
+ align-content: start;
2358
+ gap: var(--viz-space, 0.6rem);
2359
+ min-width: 0;
2360
+ }
2361
+
2362
+ & > cap-content > cap-categoryhidecontent > p {
2363
+ margin: 0;
2364
+ color: var(--viz-muted-color, var(--ui-muted-text-color, currentColor));
2365
+ font-size: 0.875em;
2366
+ }
2367
+
2368
+ & > cap-content > cap-categoryhidecontent > cap-criteriongroups {
2369
+ display: grid;
2370
+ gap: 1em;
2371
+ min-width: 0;
2372
+ }
2373
+
2374
+ & cap-collapsible-option-group > fieldset > legend small {
2375
+ white-space: nowrap;
2376
+ }
2377
+
2378
+ & cap-categories {
2379
+ display: flex;
2380
+ box-sizing: border-box;
2381
+ gap: .31em;
2382
+ min-width: 0;
2383
+ flex-flow: column;
2384
+ padding: 0;
2385
+ overflow: visible;
2386
+ }
2387
+
2388
+ & cap-categoryoption {
2389
+ display: flex;
2390
+ flex-flow: row nowrap;
2391
+ align-items: center;
2392
+ gap: 0.45rem;
2393
+ min-width: 0;
2394
+ max-height: 1em;
2395
+ }
2396
+
2397
+ & cap-categoryswatch {
2398
+ display: block;
2399
+ width: 1rem;
2400
+ height: 1rem;
2401
+ border: 1px solid var(--c1);
2402
+ border-radius: 0.2rem;
2403
+ background: linear-gradient(15deg, var(--c1) 0%, var(--c2) 65%, var(--c2) 65%, var(--c3) 100%);
2404
+ }
2405
+
2406
+ & cap-categoryoption:has(input:not(:checked)) > cap-categoryswatch {
2407
+ opacity: 0.22;
2408
+ }
2409
+
2410
+ & cap-categoryoption > cap-checkbox,
2411
+ & cap-categoryoption > cap-checkbox > label {
2412
+ min-width: 0;
2413
+ width: 100%;
2414
+ height: unset;
2415
+ }
2416
+
2417
+ & cap-categoryoption > cap-checkbox > label {
2418
+ justify-content: flex-start;
2419
+ text-align: start;
2420
+ white-space: nowrap;
2421
+ }
2422
+ `);
2423
+ function Mr(t, e) {
2424
+ let r = 0;
2425
+ for (const i of t)
2426
+ e(i) && (r += 1);
2427
+ return r;
2428
+ }
2429
+ const kt = 864e5, Pr = /^(\d{4})-(\d{2})-(\d{2})$/;
2430
+ function S(t) {
2431
+ const e = Pr.exec(t);
2432
+ if (e == null) throw new TypeError(`Invalid civil date "${t}"; expected YYYY-MM-DD`);
2433
+ const r = Number(e[1]), i = Number(e[2]), n = Number(e[3]), s = Date.UTC(r, i - 1, n), o = new Date(s);
2434
+ if (o.getUTCFullYear() !== r || o.getUTCMonth() !== i - 1 || o.getUTCDate() !== n)
2435
+ throw new TypeError(`Invalid civil date "${t}"`);
2436
+ return Math.floor(s / kt);
2437
+ }
2438
+ function K(t) {
2439
+ if (!Number.isInteger(t)) throw new TypeError("Civil day must be an integer");
2440
+ return new Date(t * kt).toISOString().slice(0, 10);
2441
+ }
2442
+ function Nr(t, e) {
2443
+ if (!Number.isInteger(e)) throw new TypeError("Civil date offset must be an integer");
2444
+ return K(S(t) + e);
2445
+ }
2446
+ function Kr(t = /* @__PURE__ */ new Date()) {
2447
+ if (!(t instanceof Date) || Number.isNaN(t.getTime()))
2448
+ throw new TypeError("todayCivilDate requires a valid Date");
2449
+ return `${String(t.getUTCFullYear()).padStart(4, "0")}-${String(
2450
+ t.getUTCMonth() + 1
2451
+ ).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`;
2452
+ }
2453
+ function Ir(t, e) {
2454
+ return S(t) - S(e);
2455
+ }
2456
+ function Br(t, e = {}) {
2457
+ var Me, Pe, Ne, Ke;
2458
+ Vr(t);
2459
+ const r = Ye(e.width ?? 960, "Chart width"), i = Ye(e.height ?? 420, "Chart height"), n = Math.min(72, r * 0.18), s = 24, o = Math.max(1, r - n - 24), a = Math.max(1, i - s - 58), l = t.flatMap((w) => Object.keys(w.values)), u = e.today ?? Kr(), h = ((Me = e.range) == null ? void 0 : Me.minX) ?? Yr(l) ?? u, p = ((Pe = e.range) == null ? void 0 : Pe.maxX) ?? u, b = S(h), y = S(p);
2460
+ if (b > y) throw new RangeError("Line graph minX must not be after maxX");
2461
+ const g = Ur(t, b, y), f = e.stacked ?? !1, E = t.map((w) => ({
2462
+ shape: w,
2463
+ values: g.map((F) => Et(w, F))
2464
+ }));
2465
+ let B = ((Ne = e.range) == null ? void 0 : Ne.minY) ?? 0, X = B;
2466
+ const Le = Array.from({ length: g.length }, () => 0), $t = E.map(({ shape: w, values: F }) => {
2467
+ const q = F.map((Z, L) => {
2468
+ const J = f ? Le[L] : 0, Q = J + Z;
2469
+ return f && (Le[L] = Q), B = Math.min(B, J, Q), X = Math.max(X, J, Q), { value: Z, baseValue: J, displayValue: Q };
2470
+ });
2471
+ return { shape: w, entries: q };
2472
+ }), Ct = Math.max(1, X - B), j = X + Ct * 0.05, me = ((Ke = e.range) == null ? void 0 : Ke.minY) ?? B, ye = Math.max(1, j - me), De = Math.max(1, y - b), xt = $t.map(({ shape: w, entries: F }) => ({
2473
+ key: w.key,
2474
+ label: w.label,
2475
+ color: w.color,
2476
+ ...w.colorKey === void 0 ? {} : { colorKey: w.colorKey },
2477
+ shape: w,
2478
+ points: Object.freeze(F.map((q, Z) => {
2479
+ const L = g[Z];
2480
+ return Object.freeze({
2481
+ date: K(L),
2482
+ day: L,
2483
+ ...q,
2484
+ x: n + (L - b) / De * o,
2485
+ y: s + (j - q.displayValue) / ye * a,
2486
+ baseY: s + (j - q.baseValue) / ye * a
2487
+ });
2488
+ }))
2489
+ }));
2490
+ return Object.freeze({
2491
+ minDate: h,
2492
+ maxDate: p,
2493
+ minDay: b,
2494
+ maxDay: y,
2495
+ minY: me,
2496
+ maxY: j,
2497
+ width: r,
2498
+ height: i,
2499
+ plotLeft: n,
2500
+ plotTop: s,
2501
+ plotWidth: o,
2502
+ plotHeight: a,
2503
+ stacked: f,
2504
+ series: Object.freeze(xt),
2505
+ dateMarks: Object.freeze(Hr(b, y, e.maxDateMarks ?? 8).map((w) => ({
2506
+ date: K(w),
2507
+ day: w,
2508
+ x: n + (w - b) / De * o
2509
+ }))),
2510
+ valueTicks: Object.freeze(_r(me, j).map((w) => ({
2511
+ value: w,
2512
+ y: s + (j - w) / ye * a
2513
+ })))
2514
+ });
2515
+ }
2516
+ function Fr(t, e) {
2517
+ return Et(t, S(e));
2518
+ }
2519
+ function St(t, e) {
2520
+ const r = t[0];
2521
+ if (r == null) return "";
2522
+ let i = `M ${v(r.x)} ${v(r.y)}`;
2523
+ for (let n = 1; n < t.length; n += 1) {
2524
+ const s = t[n - 1], o = t[n];
2525
+ if (e) {
2526
+ const a = (s.x + o.x) / 2;
2527
+ i += ` C ${v(a)} ${v(s.y)}, ${v(a)} ${v(o.y)}, ${v(o.x)} ${v(o.y)}`;
2528
+ } else
2529
+ i += ` H ${v(o.x)} V ${v(o.y)}`;
2530
+ }
2531
+ return i;
2532
+ }
2533
+ function qr(t, e) {
2534
+ if (t.length === 0) return "";
2535
+ const r = St(t, e), i = [...t].reverse();
2536
+ let n = "";
2537
+ for (let s = 0; s < i.length; s += 1) {
2538
+ const o = i[s];
2539
+ if (s === 0) n += ` L ${v(o.x)} ${v(o.baseY)}`;
2540
+ else if (e) {
2541
+ const a = i[s - 1], l = (a.x + o.x) / 2;
2542
+ n += ` C ${v(l)} ${v(a.baseY)}, ${v(l)} ${v(o.baseY)}, ${v(o.x)} ${v(o.baseY)}`;
2543
+ } else
2544
+ n += ` H ${v(o.x)} V ${v(o.baseY)}`;
2545
+ }
2546
+ return `${r}${n} Z`;
2547
+ }
2548
+ function _r(t, e, r = 6) {
2549
+ if (!Number.isFinite(t) || !Number.isFinite(e) || t > e)
2550
+ throw new RangeError("Tick range must contain finite ascending values");
2551
+ if (!Number.isInteger(r) || r < 2) throw new RangeError("Tick target must be at least two");
2552
+ const n = Math.max(1, e - t) / (r - 1), s = 10 ** Math.floor(Math.log10(n)), o = n / s, a = o <= 1 ? 1 : o <= 2 ? 2 : o <= 5 ? 5 : 10, l = Math.max(1, a * s), u = Math.ceil(t / l) * l, h = [];
2553
+ for (let p = u; p <= e + l / 1e3; p += l)
2554
+ h.push(Number(p.toFixed(10)));
2555
+ return h.length === 0 && h.push(Math.ceil(t)), h;
2556
+ }
2557
+ function Ur(t, e, r) {
2558
+ const i = /* @__PURE__ */ new Set([e, r]);
2559
+ for (const n of t)
2560
+ for (const s of Object.keys(n.values)) {
2561
+ const o = S(s);
2562
+ o >= e && o <= r && i.add(o);
2563
+ }
2564
+ return [...i].sort((n, s) => n - s);
2565
+ }
2566
+ function Et(t, e) {
2567
+ const r = t.values[K(e)];
2568
+ if (r !== void 0) return r;
2569
+ if (t.carryForward !== !0) return 0;
2570
+ let i = Number.NEGATIVE_INFINITY, n = 0;
2571
+ for (const [s, o] of Object.entries(t.values)) {
2572
+ const a = S(s);
2573
+ a <= e && a > i && (i = a, n = o);
2574
+ }
2575
+ return n;
2576
+ }
2577
+ function Hr(t, e, r) {
2578
+ if (!Number.isInteger(r) || r < 2)
2579
+ throw new RangeError("Maximum date marks must be at least two");
2580
+ const i = Math.max(0, e - t), n = i <= 62 ? 7 : i <= 730 ? 30 : 365, s = Math.max(n, Math.ceil(Math.max(1, i) / (r - 1))), o = [t];
2581
+ for (let a = t + s; a < e; a += s) o.push(a);
2582
+ return e !== t && o.push(e), o;
2583
+ }
2584
+ function Vr(t) {
2585
+ if (!Array.isArray(t)) throw new TypeError("History shapes must be an array");
2586
+ const e = /* @__PURE__ */ new Set();
2587
+ for (const r of t) {
2588
+ if (r == null || typeof r != "object") throw new TypeError("History shape must be an object");
2589
+ if (typeof r.key != "string" || r.key.trim() === "" || e.has(r.key))
2590
+ throw new Error("History shape keys must be non-empty and unique");
2591
+ if (e.add(r.key), typeof r.label != "string" || r.label.trim() === "")
2592
+ throw new TypeError("History shape label must be a non-empty string");
2593
+ if (typeof r.color != "string" || r.color.trim() === "")
2594
+ throw new TypeError("History shape color must be a non-empty CSS value");
2595
+ for (const [i, n] of Object.entries(r.values))
2596
+ if (S(i), !Number.isFinite(n)) throw new TypeError("History shape values must be finite");
2597
+ }
2598
+ }
2599
+ function Yr(t) {
2600
+ return t.length === 0 ? void 0 : t.reduce((e, r) => S(e) <= S(r) ? e : r);
2601
+ }
2602
+ function Ye(t, e) {
2603
+ if (!Number.isFinite(t) || t <= 0) throw new RangeError(`${e} must be positive`);
2604
+ return t;
2605
+ }
2606
+ function v(t) {
2607
+ return Number(t.toFixed(3)).toString();
2608
+ }
2609
+ class Se extends Te {
2610
+ constructor(r) {
2611
+ super(r);
2612
+ c(this, "cursorDate$", new A(null, {
2613
+ owner: this,
2614
+ purpose: "line graph cursor date"
2615
+ }));
2616
+ c(this, "shapes$");
2617
+ c(this, "stacked$");
2618
+ c(this, "smooth$");
2619
+ c(this, "range$");
2620
+ c(this, "ownedSources", []);
2621
+ c(this, "chartHost", null);
2622
+ c(this, "observedWidth", 960);
2623
+ c(this, "currentModel", null);
2624
+ c(this, "resizeObserver", null);
2625
+ this.shapes$ = this.source(r.shapes$, "line graph shapes"), this.stacked$ = this.source(r.stacked$, "line graph stacked state"), this.smooth$ = this.source(r.smooth$, "line graph smooth state"), this.range$ = this.source(r.range$, "line graph range");
2626
+ }
2627
+ render() {
2628
+ const r = this.snapshot(this.shapes$), i = this.snapshot(this.stacked$), n = this.snapshot(this.smooth$), s = this.snapshot(this.range$), o = this.read(this.cursorDate$), a = this.props.label ?? "History chart", l = [r, i, n, s].some(({ fetchState: f }) => f === k.Error) ? k.Error : [r, i, n, s].some(({ fetchState: f }) => f !== k.Ready) ? k.Loading : k.Ready;
2629
+ let u = null;
2630
+ if (this.currentModel = null, l === k.Ready)
2631
+ try {
2632
+ this.currentModel = Br(r.value, {
2633
+ stacked: i.value,
2634
+ range: s.value,
2635
+ width: Math.max(480, this.observedWidth),
2636
+ maxDateMarks: this.observedWidth < 640 ? 5 : 9
2637
+ });
2638
+ } catch (f) {
2639
+ u = f;
2640
+ }
2641
+ const h = this.currentModel, p = h == null ? null : o ?? h.maxDate, b = this.props.formatDate ?? ((f) => f), y = this.props.formatValue ?? ((f) => String(f)), g = this.Host;
2642
+ return /* @__PURE__ */ m(
2643
+ g,
2644
+ {
2645
+ className: (this.props.className ?? this.props.class ?? "") || null,
2646
+ "aria-label": a,
2647
+ "aria-busy": l !== k.Ready ? "true" : null,
2648
+ children: [
2649
+ /* @__PURE__ */ m("header", { children: [
2650
+ /* @__PURE__ */ d("h2", { children: a }),
2651
+ /* @__PURE__ */ m("p", { children: [
2652
+ i.value ? "Stacked area" : "Individual line",
2653
+ " chart;",
2654
+ " ",
2655
+ n.value ? "smooth" : "step",
2656
+ " rendering."
2657
+ ] })
2658
+ ] }),
2659
+ l === k.Error || u != null ? /* @__PURE__ */ d("p", { role: "alert", children: "The history chart could not be calculated." }) : l !== k.Ready ? /* @__PURE__ */ d("p", { role: "status", "aria-live": "polite", children: "Loading history chart…" }) : r.value.length === 0 ? /* @__PURE__ */ d("p", { role: "status", children: this.props.emptyMessage ?? "No history values are available." }) : /* @__PURE__ */ d(
2660
+ "cap-chart",
2661
+ {
2662
+ tabIndex: 0,
2663
+ role: "group",
2664
+ "aria-label": `${a}. Use Left and Right Arrow to move by day; hold Shift to move by week.`,
2665
+ onPointerMove: (f) => this.pointerMove(f),
2666
+ onKeyDown: (f) => this.cursorKeyDown(f),
2667
+ ref: (f) => this.chartHost = f
2668
+ }
2669
+ ),
2670
+ h == null || p == null ? null : /* @__PURE__ */ m("cap-readout", { children: [
2671
+ /* @__PURE__ */ d("p", { "aria-live": "polite", children: /* @__PURE__ */ d("strong", { children: b(p) }) }),
2672
+ /* @__PURE__ */ d("ul", { children: h.series.map(({ shape: f }) => /* @__PURE__ */ m("li", { children: [
2673
+ /* @__PURE__ */ d(
2674
+ "cap-swatch",
2675
+ {
2676
+ style: { "--colored-base": f.color },
2677
+ "aria-hidden": "true"
2678
+ }
2679
+ ),
2680
+ /* @__PURE__ */ d("span", { children: f.label }),
2681
+ /* @__PURE__ */ d("strong", { children: y(Fr(f, p)) })
2682
+ ] }, f.key)) })
2683
+ ] })
2684
+ ]
2685
+ }
2686
+ );
2687
+ }
2688
+ afterMount() {
2689
+ this.observeSize(), this.drawChart();
2690
+ }
2691
+ afterUpdate() {
2692
+ this.drawChart();
2693
+ }
2694
+ onDestroy() {
2695
+ var r;
2696
+ (r = this.resizeObserver) == null || r.disconnect(), this.resizeObserver = null, this.chartHost = null, this.cursorDate$.dispose();
2697
+ for (const i of this.ownedSources) i.dispose();
2698
+ this.ownedSources.length = 0;
2699
+ }
2700
+ observeSize() {
2701
+ this.chartHost == null || typeof globalThis.ResizeObserver != "function" || (this.resizeObserver = new ResizeObserver((r) => {
2702
+ var n;
2703
+ const i = (n = r[0]) == null ? void 0 : n.contentRect.width;
2704
+ i == null || i <= 0 || Math.abs(i - this.observedWidth) < 1 || (this.observedWidth = i, this.update());
2705
+ }), this.resizeObserver.observe(this.chartHost));
2706
+ }
2707
+ source(r, i) {
2708
+ if (Gr(r)) return r;
2709
+ const n = new A(r, { owner: this, purpose: i });
2710
+ return this.ownedSources.push(n), n;
2711
+ }
2712
+ pointerMove(r) {
2713
+ const i = this.currentModel, n = this.chartHost;
2714
+ if (i == null || n == null) return;
2715
+ const s = n.getBoundingClientRect();
2716
+ if (s.width <= 0) return;
2717
+ const o = (r.clientX - s.left) / s.width * i.width, a = Math.max(0, Math.min(1, (o - i.plotLeft) / i.plotWidth)), l = Math.round(i.minDay + a * (i.maxDay - i.minDay));
2718
+ this.cursorDate$.set(K(l), "line graph pointer moved");
2719
+ }
2720
+ cursorKeyDown(r) {
2721
+ const i = this.currentModel;
2722
+ if (i == null) return;
2723
+ let n = S(this.cursorDate$.get() ?? i.maxDate);
2724
+ if (r.key === "ArrowLeft") n -= r.shiftKey ? 7 : 1;
2725
+ else if (r.key === "ArrowRight") n += r.shiftKey ? 7 : 1;
2726
+ else if (r.key === "Home") n = i.minDay;
2727
+ else if (r.key === "End") n = i.maxDay;
2728
+ else if (r.key === "Escape") {
2729
+ r.preventDefault(), this.cursorDate$.set(null, "line graph cursor cleared");
2730
+ return;
2731
+ } else return;
2732
+ r.preventDefault();
2733
+ const s = K(Math.max(i.minDay, Math.min(i.maxDay, n)));
2734
+ this.cursorDate$.set(s, "line graph cursor moved by keyboard");
2735
+ }
2736
+ drawChart() {
2737
+ const r = this.chartHost, i = this.currentModel;
2738
+ if (r == null || i == null) return;
2739
+ const n = this.smooth$.get(), s = x("svg");
2740
+ s.setAttribute("viewBox", `0 0 ${i.width} ${i.height}`), s.setAttribute("role", "img"), s.setAttribute("aria-label", this.props.label ?? "History chart");
2741
+ for (const a of i.valueTicks) {
2742
+ const l = x("line");
2743
+ l.classList.add("gridline"), _(l, {
2744
+ x1: i.plotLeft,
2745
+ x2: i.plotLeft + i.plotWidth,
2746
+ y1: a.y,
2747
+ y2: a.y
2748
+ }), s.append(l);
2749
+ const u = x("text");
2750
+ u.classList.add("axismark"), _(u, { x: i.plotLeft - 8, y: a.y + 4, "text-anchor": "end" }), u.textContent = String(a.value), s.append(u);
2751
+ }
2752
+ for (const a of i.dateMarks) {
2753
+ const l = x("line");
2754
+ l.classList.add("gridline"), _(l, {
2755
+ x1: a.x,
2756
+ x2: a.x,
2757
+ y1: i.plotTop,
2758
+ y2: i.plotTop + i.plotHeight
2759
+ }), s.append(l);
2760
+ const u = x("text");
2761
+ u.classList.add("axismark"), _(u, {
2762
+ x: a.x,
2763
+ y: i.plotTop + i.plotHeight + 22,
2764
+ "text-anchor": "middle"
2765
+ }), u.textContent = a.date, s.append(u);
2766
+ }
2767
+ for (const a of i.series) {
2768
+ if (i.stacked) {
2769
+ const u = x("path");
2770
+ u.classList.add("seriesarea"), u.setAttribute("fill", a.color), u.setAttribute("d", qr(a.points, n)), s.append(u);
2771
+ }
2772
+ const l = x("path");
2773
+ l.classList.add("seriesline"), l.setAttribute("stroke", a.color), l.setAttribute("d", St(a.points, n)), s.append(l);
2774
+ }
2775
+ const o = this.cursorDate$.get();
2776
+ if (o != null) {
2777
+ const a = S(o), l = i.plotLeft + (a - i.minDay) / Math.max(1, i.maxDay - i.minDay) * i.plotWidth, u = x("line");
2778
+ u.classList.add("cursor"), _(u, {
2779
+ x1: l,
2780
+ x2: l,
2781
+ y1: i.plotTop,
2782
+ y2: i.plotTop + i.plotHeight
2783
+ }), s.append(u);
2784
+ }
2785
+ r.replaceChildren(s);
2786
+ }
2787
+ }
2788
+ c(Se, "liveProps", []), c(Se, "hostName", "line-graph"), c(Se, "css", G`
2789
+ & {
2790
+ display: flex;
2791
+ min-width: 0;
2792
+ min-height: var(--viz-line-graph-min-height, 24rem);
2793
+ flex-direction: column;
2794
+ padding: var(--viz-space, 0.7rem);
2795
+ user-select: none;
2796
+ }
2797
+
2798
+ & h2,
2799
+ & p,
2800
+ & ul {
2801
+ margin: 0;
2802
+ }
2803
+
2804
+ & > cap-chart {
2805
+ flex: 1;
2806
+ min-height: 20rem;
2807
+ margin-block: 0.6rem;
2808
+ overflow: auto;
2809
+ }
2810
+
2811
+ & svg {
2812
+ display: block;
2813
+ width: 100%;
2814
+ min-width: 30rem;
2815
+ height: auto;
2816
+ }
2817
+
2818
+ & .gridline {
2819
+ stroke: var(--viz-grid-color, var(--ui-border-color));
2820
+ stroke-width: 1;
2821
+ vector-effect: non-scaling-stroke;
2822
+ }
2823
+
2824
+ & .axismark {
2825
+ fill: var(--viz-color, var(--ui-text-color));
2826
+ font: 12px system-ui, sans-serif;
2827
+ }
2828
+
2829
+ & .seriesline {
2830
+ fill: none;
2831
+ stroke-width: 3;
2832
+ stroke-linecap: round;
2833
+ stroke-linejoin: round;
2834
+ vector-effect: non-scaling-stroke;
2835
+ }
2836
+
2837
+ & .seriesarea {
2838
+ opacity: var(--viz-area-opacity, 0.25);
2839
+ }
2840
+
2841
+ & .cursor {
2842
+ stroke: var(--viz-cursor-color, var(--ui-text-color));
2843
+ stroke-width: 2;
2844
+ stroke-dasharray: 4 3;
2845
+ vector-effect: non-scaling-stroke;
2846
+ }
2847
+
2848
+ & > cap-readout {
2849
+ padding-block-start: 0.4rem;
2850
+ border-block-start: 1px solid var(--viz-border-color, var(--ui-border-color));
2851
+ }
2852
+
2853
+ & > cap-readout ul {
2854
+ display: flex;
2855
+ flex-wrap: wrap;
2856
+ gap: 0.4rem 1rem;
2857
+ padding: 0;
2858
+ list-style: none;
2859
+ }
2860
+
2861
+ & > cap-readout li {
2862
+ display: inline-flex;
2863
+ align-items: center;
2864
+ gap: 0.35rem;
2865
+ }
2866
+
2867
+ & cap-swatch {
2868
+ display: block;
2869
+ width: 0.8rem;
2870
+ height: 0.8rem;
2871
+ border-radius: 50%;
2872
+ background: var(--colored-base);
2873
+ }
2874
+
2875
+ @media (forced-colors: active) {
2876
+ & .seriesline,
2877
+ & .cursor,
2878
+ & .gridline {
2879
+ stroke: CanvasText;
2880
+ forced-color-adjust: auto;
2881
+ }
2882
+
2883
+ & .seriesarea {
2884
+ fill: Canvas;
2885
+ stroke: CanvasText;
2886
+ }
2887
+ }
2888
+ `);
2889
+ function Gr(t) {
2890
+ return t != null && (typeof t == "object" || typeof t == "function") && typeof Reflect.get(t, "get") == "function" && typeof Reflect.get(t, "subscribe") == "function";
2891
+ }
2892
+ const Wr = "http://www.w3.org/2000/svg";
2893
+ function x(t) {
2894
+ return document.createElementNS(Wr, t);
2895
+ }
2896
+ function _(t, e) {
2897
+ for (const [r, i] of Object.entries(e))
2898
+ t.setAttribute(r, String(i));
2899
+ }
2900
+ class Xr {
2901
+ constructor(e, r = {}) {
2902
+ c(this, "criteria");
2903
+ c(this, "presets");
2904
+ c(this, "order$");
2905
+ c(this, "activeSplits$");
2906
+ c(this, "activePreset$");
2907
+ c(this, "byKey");
2908
+ c(this, "state$");
2909
+ c(this, "orderEmitter");
2910
+ c(this, "activeSplitsEmitter");
2911
+ c(this, "activeEmitters", /* @__PURE__ */ new Map());
2912
+ c(this, "disposed", !1);
2913
+ if (!Array.isArray(e) || e.some((o) => !(o instanceof I)))
2914
+ throw new TypeError("Split criteria must contain GroupingCriterion instances");
2915
+ const i = new Map(
2916
+ e.map((o) => [o.key, o])
2917
+ );
2918
+ if (i.size !== e.length) throw new Error("Split criteria keys must be unique");
2919
+ this.criteria = Object.freeze([...e]), this.byKey = i, this.presets = Jr(r.presets ?? [], i);
2920
+ const n = this.criteria.map(({ key: o }) => o), s = r.active ?? n;
2921
+ V(s, i, "Active split keys"), this.state$ = new A(re(n, new Set(s)), {
2922
+ owner: this,
2923
+ purpose: "split selection state",
2924
+ equals: Qr
2925
+ }), this.orderEmitter = new z(
2926
+ [this.state$],
2927
+ ([o]) => Object.freeze(
2928
+ o.order.map((a) => Ge(i, a))
2929
+ ),
2930
+ { owner: this, purpose: "ordered visualization criteria" }
2931
+ ), this.order$ = this.orderEmitter, this.activeSplitsEmitter = new z(
2932
+ [this.state$],
2933
+ ([o]) => Object.freeze(o.order.filter((a) => o.active.has(a)).map((a) => Ge(i, a))),
2934
+ { owner: this, purpose: "active ordered visualization splits" }
2935
+ ), this.activeSplits$ = this.activeSplitsEmitter, this.activePreset$ = new A(null, {
2936
+ owner: this,
2937
+ purpose: "active visualization split preset"
2938
+ });
2939
+ }
2940
+ activeState(e) {
2941
+ this.assertActive();
2942
+ const r = this.requireKey(e);
2943
+ let i = this.activeEmitters.get(r);
2944
+ return i == null && (i = new Zr(this, r), this.activeEmitters.set(r, i)), i;
2945
+ }
2946
+ isActive(e) {
2947
+ return this.state$.get().active.has(this.requireKey(e));
2948
+ }
2949
+ toggle(e, r) {
2950
+ this.assertActive();
2951
+ const i = this.requireKey(e), n = this.state$.get(), s = new Set(n.active);
2952
+ return s.has(i) ? s.delete(i) : s.add(i), this.activePreset$.set(null, "split selection customized"), this.state$.set(
2953
+ re(n.order, s),
2954
+ r ?? `${i} split toggled`
2955
+ );
2956
+ }
2957
+ move(e, r, i) {
2958
+ this.assertActive();
2959
+ const n = this.requireKey(e);
2960
+ if (!Number.isInteger(r)) throw new TypeError("Split target index must be an integer");
2961
+ const s = this.state$.get(), o = s.order.indexOf(n), a = Math.max(0, Math.min(r, s.order.length - 1));
2962
+ if (o === a) return !1;
2963
+ const l = [...s.order];
2964
+ return l.splice(o, 1), l.splice(a, 0, n), this.activePreset$.set(null, "split order customized"), this.state$.set(
2965
+ re(l, s.active),
2966
+ i ?? `${n} split moved`
2967
+ );
2968
+ }
2969
+ moveBy(e, r, i) {
2970
+ if (!Number.isInteger(r)) throw new TypeError("Split move offset must be an integer");
2971
+ const n = this.requireKey(e);
2972
+ return this.move(
2973
+ n,
2974
+ this.state$.get().order.indexOf(n) + r,
2975
+ i
2976
+ );
2977
+ }
2978
+ setSplits(e, r, i) {
2979
+ this.assertActive(), V(e, this.byKey, "Active split keys");
2980
+ const n = new Set(e), s = r ?? this.state$.get().order.filter((a) => !n.has(a));
2981
+ V(s, this.byKey, "Inactive split keys");
2982
+ const o = [...e, ...s];
2983
+ if (new Set(o).size !== this.criteria.length || o.length !== this.criteria.length)
2984
+ throw new Error("Active and inactive split keys must cover every criterion exactly once");
2985
+ return this.activePreset$.set(null, "split selection replaced"), this.state$.set(
2986
+ re(o, n),
2987
+ i ?? "split selection replaced"
2988
+ );
2989
+ }
2990
+ applyPreset(e) {
2991
+ this.assertActive();
2992
+ const r = this.presets.find(({ key: n }) => n === e);
2993
+ if (r == null) throw new Error(`Unknown split preset "${e}"`);
2994
+ const i = this.setSplits(r.active, r.inactive, `${r.key} preset applied`);
2995
+ return this.activePreset$.set(r.key, `${r.key} preset applied`), i;
2996
+ }
2997
+ dispose() {
2998
+ if (!this.disposed) {
2999
+ this.disposed = !0;
3000
+ for (const e of this.activeEmitters.values()) e.dispose();
3001
+ this.activeEmitters.clear(), this.activePreset$.dispose(), this.activeSplitsEmitter.dispose(), this.orderEmitter.dispose(), this.state$.dispose();
3002
+ }
3003
+ }
3004
+ requireKey(e) {
3005
+ if (typeof e != "string" || !this.byKey.has(e))
3006
+ throw new Error(`Unknown criterion key "${String(e)}"`);
3007
+ return e;
3008
+ }
3009
+ assertActive() {
3010
+ if (this.disposed) throw new Error("Split selection model is disposed");
3011
+ }
3012
+ }
3013
+ function ui(t, e = {}) {
3014
+ return new Xr(t, e);
3015
+ }
3016
+ class Zr extends xe {
3017
+ constructor(r, i) {
3018
+ super(r.isActive(i) ? "visible" : "hidden", {
3019
+ owner: r,
3020
+ purpose: `${i} split enabled`,
3021
+ fetchState: r.activeSplits$.getFetchState(),
3022
+ error: r.activeSplits$.getError()
3023
+ });
3024
+ c(this, "release");
3025
+ this.model = r, this.criterionKey = i, this.release = r.activeSplits$.subscribe(
3026
+ (n) => this.updateFromSource(n),
3027
+ { emitCurrent: !1 }
3028
+ );
3029
+ }
3030
+ set(r, i) {
3031
+ if (r !== "hidden" && r !== "visible")
3032
+ throw new TypeError("Split state must be hidden or visible");
3033
+ return r === "visible" === this.model.isActive(this.criterionKey) ? !1 : this.model.toggle(this.criterionKey, i);
3034
+ }
3035
+ dispose() {
3036
+ this.release(), super.dispose();
3037
+ }
3038
+ updateFromSource(r) {
3039
+ this.setSnapshot({
3040
+ value: r.value.some(({ key: i }) => i === this.criterionKey) ? "visible" : "hidden",
3041
+ fetchState: r.fetchState,
3042
+ error: r.error,
3043
+ parentEvent: r.event,
3044
+ cause: "active split membership changed"
3045
+ });
3046
+ }
3047
+ }
3048
+ function Jr(t, e) {
3049
+ if (!Array.isArray(t)) throw new TypeError("Split presets must be an array");
3050
+ const r = /* @__PURE__ */ new Set();
3051
+ return Object.freeze(t.map((i) => {
3052
+ if (i == null || typeof i != "object" || Array.isArray(i))
3053
+ throw new TypeError("Split preset must be an object");
3054
+ if (typeof i.key != "string" || i.key.trim() === "" || r.has(i.key))
3055
+ throw new Error("Split preset keys must be non-empty and unique");
3056
+ if (typeof i.label != "string" || i.label.trim() === "")
3057
+ throw new TypeError("Split preset label must be a non-empty string");
3058
+ r.add(i.key), V(i.active, e, `${i.key} active keys`);
3059
+ const n = Object.freeze([...i.active]), s = i.inactive == null ? Object.freeze([...e.keys()].filter((o) => !n.includes(o))) : Object.freeze([...i.inactive]);
3060
+ if (V(s, e, `${i.key} inactive keys`), (/* @__PURE__ */ new Set([...n, ...s])).size !== e.size || n.length + s.length !== e.size)
3061
+ throw new Error(`Split preset "${i.key}" must cover every criterion exactly once`);
3062
+ return Object.freeze({ ...i, active: n, inactive: s });
3063
+ }));
3064
+ }
3065
+ function V(t, e, r) {
3066
+ if (!Array.isArray(t)) throw new TypeError(`${r} must be an array`);
3067
+ if (new Set(t).size !== t.length) throw new Error(`${r} must be unique`);
3068
+ for (const n of t)
3069
+ if (!e.has(n)) throw new Error(`${r} contains unknown criterion "${n}"`);
3070
+ }
3071
+ function Ge(t, e) {
3072
+ const r = t.get(e);
3073
+ if (r == null) throw new Error(`Missing criterion "${e}"`);
3074
+ return r;
3075
+ }
3076
+ function re(t, e) {
3077
+ return Object.freeze({ order: Object.freeze([...t]), active: new Set(e) });
3078
+ }
3079
+ function Qr(t, e) {
3080
+ return t.order.length === e.order.length && t.order.every((r, i) => r === e.order[i]) && t.active.size === e.active.size && [...t.active].every((r) => e.active.has(r));
3081
+ }
3082
+ const ei = [
3083
+ ["☐", "hidden"],
3084
+ ["✓", "visible"]
3085
+ ];
3086
+ class ie extends Te {
3087
+ constructor() {
3088
+ super(...arguments);
3089
+ c(this, "draggingKey", null);
3090
+ c(this, "pendingDrag", null);
3091
+ c(this, "suppressClick", !1);
3092
+ c(this, "suppressClickTimer", null);
3093
+ c(this, "announcement", "");
3094
+ }
3095
+ initialize() {
3096
+ this.listen(document, "pointermove", (r) => this.pointerMove(r)), this.listen(document, "pointerup", () => this.stopDragging()), this.listen(document, "pointercancel", () => this.stopDragging());
3097
+ }
3098
+ render() {
3099
+ const {
3100
+ model: r,
3101
+ label: i = "Select and order splits",
3102
+ description: n = "",
3103
+ presetsLabel: s = "Split presets"
3104
+ } = this.props, o = this.read(r.order$);
3105
+ this.read(r.activeSplits$);
3106
+ const a = this.read(r.activePreset$), l = this.Host;
3107
+ return /* @__PURE__ */ m(l, { children: [
3108
+ r.presets.length === 0 ? null : /* @__PURE__ */ d(ge, { header: s, children: /* @__PURE__ */ d("cap-presets", { children: r.presets.map((u) => /* @__PURE__ */ d(
3109
+ oe,
3110
+ {
3111
+ label: u.label,
3112
+ pressed: a === u.key,
3113
+ onClick: () => {
3114
+ r.applyPreset(u.key), this.announce(`${u.label} split preset applied`);
3115
+ }
3116
+ },
3117
+ u.key
3118
+ )) }) }),
3119
+ /* @__PURE__ */ m(ge, { header: i, children: [
3120
+ /* @__PURE__ */ d("p", { children: n }),
3121
+ /* @__PURE__ */ d("ol", { children: o.map((u) => /* @__PURE__ */ m(
3122
+ "li",
3123
+ {
3124
+ className: this.draggingKey === u.key ? "dragging" : void 0,
3125
+ "data-split-key": u.key,
3126
+ onPointerDown: (h) => this.startDragging(u.key, h),
3127
+ onClick: (h) => this.suppressDraggedClick(h),
3128
+ children: [
3129
+ /* @__PURE__ */ d(
3130
+ ae,
3131
+ {
3132
+ symbols: ei,
3133
+ label: u.label,
3134
+ valueEmitter: r.activeState(u.key)
3135
+ }
3136
+ ),
3137
+ /* @__PURE__ */ d(
3138
+ "cap-draghandle",
3139
+ {
3140
+ role: "button",
3141
+ tabIndex: 0,
3142
+ "aria-label": `Reorder ${u.label}`,
3143
+ title: "Drag to reorder; use Alt+Arrow keys from the keyboard",
3144
+ onKeyDown: (h) => {
3145
+ if (!h.altKey || h.key !== "ArrowUp" && h.key !== "ArrowDown")
3146
+ return;
3147
+ h.preventDefault();
3148
+ const p = h.key === "ArrowUp" ? -1 : 1;
3149
+ if (r.moveBy(u.key, p, "split reordered by keyboard")) {
3150
+ const b = r.order$.get().findIndex(({ key: y }) => y === u.key) + 1;
3151
+ this.announce(`${u.label} moved to position ${b}`), queueMicrotask(() => this.focusHandle(u.key));
3152
+ }
3153
+ }
3154
+ }
3155
+ )
3156
+ ]
3157
+ },
3158
+ u.key
3159
+ )) }),
3160
+ /* @__PURE__ */ d("p", { role: "status", "aria-live": "polite", "aria-atomic": "true", children: this.announcement })
3161
+ ] })
3162
+ ] });
3163
+ }
3164
+ pointerMove(r) {
3165
+ var a;
3166
+ if (this.draggingKey == null && this.pendingDrag != null) {
3167
+ const { clientX: l, clientY: u, key: h } = this.pendingDrag;
3168
+ if (Math.hypot(r.clientX - l, r.clientY - u) < 4) return;
3169
+ this.draggingKey = h, this.pendingDrag = null, this.update();
3170
+ }
3171
+ if (this.draggingKey == null || typeof document.elementFromPoint != "function") return;
3172
+ const i = (a = document.elementFromPoint(r.clientX, r.clientY)) == null ? void 0 : a.closest("[data-split-key]");
3173
+ if (i == null) return;
3174
+ const n = i.dataset.splitKey;
3175
+ if (n == null) return;
3176
+ const s = this.props.model.order$.get().findIndex(({ key: l }) => l === n);
3177
+ if (s < 0 || !this.props.model.move(
3178
+ this.draggingKey,
3179
+ s,
3180
+ "split reordered by pointer"
3181
+ )) return;
3182
+ const o = this.props.model.criteria.find(({ key: l }) => l === this.draggingKey);
3183
+ this.announce(`${(o == null ? void 0 : o.label) ?? this.draggingKey} moved to position ${s + 1}`);
3184
+ }
3185
+ stopDragging() {
3186
+ if (this.draggingKey == null && this.pendingDrag == null) return;
3187
+ const r = this.draggingKey, i = r != null;
3188
+ this.draggingKey = null, this.pendingDrag = null, i && (this.suppressClick = !0, this.suppressClickTimer != null && clearTimeout(this.suppressClickTimer), this.suppressClickTimer = setTimeout(() => {
3189
+ this.suppressClick = !1, this.suppressClickTimer = null;
3190
+ }, 0), this.update(), queueMicrotask(() => this.focusHandle(r)));
3191
+ }
3192
+ startDragging(r, i) {
3193
+ i.button === 0 && (this.pendingDrag = { key: r, clientX: i.clientX, clientY: i.clientY });
3194
+ }
3195
+ suppressDraggedClick(r) {
3196
+ this.suppressClick && (this.suppressClick = !1, this.suppressClickTimer != null && clearTimeout(this.suppressClickTimer), this.suppressClickTimer = null, r.preventDefault(), r.stopPropagation());
3197
+ }
3198
+ announce(r) {
3199
+ this.announcement = r, this.update();
3200
+ }
3201
+ focusHandle(r) {
3202
+ var n;
3203
+ const i = this.dom instanceof Element ? this.dom.querySelectorAll("[data-split-key] cap-draghandle") : [];
3204
+ for (const s of i)
3205
+ if (((n = s.closest("[data-split-key]")) == null ? void 0 : n.dataset.splitKey) === r) {
3206
+ s.focus();
3207
+ return;
3208
+ }
3209
+ }
3210
+ }
3211
+ c(ie, "liveProps", []), c(ie, "hostName", "split-selection-panel"), c(ie, "dependencies", [oe, ae, ge]), c(ie, "css", G`
3212
+ & {
3213
+ display: grid;
3214
+ gap: var(--viz-space, 0.6rem);
3215
+ min-width: 0;
3216
+ user-select: none;
3217
+ }
3218
+
3219
+ & > cap-groupbox {
3220
+ min-width: 0;
3221
+ }
3222
+
3223
+ & > cap-groupbox > cap-content {
3224
+ display: flex;
3225
+ flex-flow: column;
3226
+ padding: .25em;
3227
+ flex: 1 1 0;
3228
+ }
3229
+
3230
+ & > cap-groupbox > cap-content > p,
3231
+ & > cap-groupbox > cap-content > ol {
3232
+ margin: 0;
3233
+ }
3234
+
3235
+ & > cap-groupbox > cap-content > p:first-child {
3236
+ color: var(--viz-muted-color, var(--ui-muted-text-color, currentColor));
3237
+ font-size: 0.875em;
3238
+ }
3239
+
3240
+ & > cap-groupbox > cap-content > cap-presets {
3241
+ display: grid;
3242
+ gap: 0.35rem;
3243
+ align-content: stretch;
3244
+ justify-content: stretch;
3245
+ }
3246
+
3247
+ & > cap-groupbox > cap-content > cap-presets > cap-button {
3248
+ display: flex;
3249
+ flex-flow: column;
3250
+ align-content: stretch;
3251
+ }
3252
+
3253
+ & ol {
3254
+ display: grid;
3255
+ gap: 0.25rem;
3256
+ padding: 0;
3257
+ list-style: none;
3258
+ }
3259
+
3260
+ & li {
3261
+ display: flex;
3262
+ flex-flow: row nowrap;
3263
+ align-items: center;
3264
+ justify-content: space-between;
3265
+ gap: 0.35rem;
3266
+ min-width: 0;
3267
+ padding: 0 .35rem;
3268
+ border-radius: var(--ui-border-radius);
3269
+ box-shadow: var(--box-shadow);
3270
+ }
3271
+
3272
+ & li:has(input[type="checkbox"]:not(:checked)) {
3273
+ color: var(--viz-muted-color, var(--ui-muted-text-color, currentColor));
3274
+ }
3275
+
3276
+ & li.dragging {
3277
+ outline: 2px solid var(--focus-color, var(--ui-accent-color));
3278
+ }
3279
+
3280
+ & cap-draghandle {
3281
+ display: block;
3282
+ width: 1.1rem;
3283
+ height: .9rem;
3284
+ min-height: .9rem;
3285
+ padding: 0;
3286
+ border: 0;
3287
+ border-radius: 0;
3288
+ color: inherit;
3289
+ background-color: transparent;
3290
+ background-image: radial-gradient(currentColor 0.75px, transparent 0.9px);
3291
+ background-position: center;
3292
+ background-size: 3px 3px;
3293
+ cursor: grab;
3294
+ touch-action: none;
3295
+ }
3296
+
3297
+ & cap-draghandle:focus-visible {
3298
+ outline: 2px solid var(--focus-color, var(--ui-accent-color));
3299
+ outline-offset: 1px;
3300
+ }
3301
+
3302
+ & li > :has(> [role="checkbox"]),
3303
+ & [role="checkbox"] {
3304
+
3305
+ justify-content: center;
3306
+ align-items: center;
3307
+ justify-items: center;
3308
+ align-content: center;
3309
+ }
3310
+
3311
+ & > cap-groupbox > cap-content > p[role="status"][aria-live="polite"][aria-atomic="true"] {
3312
+ position: absolute;
3313
+ width: 1px;
3314
+ height: 1px;
3315
+ padding: 0;
3316
+ overflow: hidden;
3317
+ clip: rect(0, 0, 0, 0);
3318
+ white-space: nowrap;
3319
+ border: 0;
3320
+ }
3321
+ `);
3322
+ class hi {
3323
+ constructor(e) {
3324
+ c(this, "categories");
3325
+ c(this, "byKey");
3326
+ c(this, "deltas", /* @__PURE__ */ new Map());
3327
+ if (!Array.isArray(e)) throw new TypeError("Series categories must be an array");
3328
+ const r = e.map((n) => ti(n)), i = new Map(r.map((n) => [n.key, n]));
3329
+ if (i.size !== r.length) throw new Error("Series category keys must be unique");
3330
+ this.categories = Object.freeze(r), this.byKey = i;
3331
+ }
3332
+ addOne(e, r) {
3333
+ return this.add(e, r, 1);
3334
+ }
3335
+ removeOne(e, r) {
3336
+ return this.add(e, r, -1);
3337
+ }
3338
+ add(e, r, i) {
3339
+ if (S(e), !Number.isFinite(i)) throw new TypeError("Series delta must be finite");
3340
+ if (!this.byKey.has(r))
3341
+ throw new Error(`Unknown series category "${r}"`);
3342
+ const n = this.deltas.get(r) ?? /* @__PURE__ */ new Map();
3343
+ return n.set(e, (n.get(e) ?? 0) + i), this.deltas.set(r, n), this;
3344
+ }
3345
+ build() {
3346
+ const e = this.allDates();
3347
+ return this.categories.map((r) => We(r, Object.fromEntries(e.map((i) => {
3348
+ var n;
3349
+ return [
3350
+ i,
3351
+ ((n = this.deltas.get(r.key)) == null ? void 0 : n.get(i)) ?? 0
3352
+ ];
3353
+ })), !1)).filter((r) => Object.values(r.values).some((i) => i !== 0));
3354
+ }
3355
+ buildCumulative() {
3356
+ const e = this.allDates();
3357
+ if (e.length === 0) return Object.freeze([]);
3358
+ const r = [Nr(e[0], -1), ...e];
3359
+ return this.categories.map((i) => {
3360
+ var o;
3361
+ let n = 0;
3362
+ const s = { [r[0]]: 0 };
3363
+ for (const a of e)
3364
+ n += ((o = this.deltas.get(i.key)) == null ? void 0 : o.get(a)) ?? 0, s[a] = n;
3365
+ return We(i, s, !0);
3366
+ }).filter((i) => Object.values(i.values).some((n) => n !== 0));
3367
+ }
3368
+ allDates() {
3369
+ return [...new Set([...this.deltas.values()].flatMap((e) => [...e.keys()]))].sort(Ir);
3370
+ }
3371
+ }
3372
+ function ti(t) {
3373
+ if (t == null || typeof t != "object")
3374
+ throw new TypeError("Series category must be an object");
3375
+ if (typeof t.key != "string" || t.key.trim() === "")
3376
+ throw new TypeError("Series category key must be a non-empty string");
3377
+ if (typeof t.label != "string" || t.label.trim() === "")
3378
+ throw new TypeError("Series category label must be a non-empty string");
3379
+ const e = "color" in t ? t.color : t.colors[1];
3380
+ if (typeof e != "string" || e.trim() === "")
3381
+ throw new TypeError("Series category color must be a non-empty CSS value");
3382
+ const r = t.colorKey === void 0 ? { key: t.key, label: t.label, color: e } : { key: t.key, label: t.label, color: e, colorKey: t.colorKey };
3383
+ return Object.freeze(r);
3384
+ }
3385
+ function We(t, e, r) {
3386
+ return Object.freeze({
3387
+ ...t,
3388
+ values: Object.freeze(e),
3389
+ carryForward: r
3390
+ });
3391
+ }
3392
+ export {
3393
+ ee as BlockGraph,
3394
+ It as BlockSelectionModel,
3395
+ te as CategoryHidePanel,
3396
+ de as CollapsibleOptionGroup,
3397
+ I as GroupingCriterion,
3398
+ Se as LineGraph,
3399
+ hi as SeriesBuilder,
3400
+ Xr as SplitSelectionModel,
3401
+ ie as SplitSelectionPanel,
3402
+ Nr as addCivilDays,
3403
+ qr as areaPath,
3404
+ we as buildBlockLayout,
3405
+ _r as buildIntegerTicks,
3406
+ Br as buildLineChartModel,
3407
+ Xe as categoryColorVariables,
3408
+ li as categoryCounts,
3409
+ S as civilDateToDay,
3410
+ Ir as compareCivilDates,
3411
+ ci as createBlockSelection,
3412
+ ui as createSplitSelection,
3413
+ Kt as criterionSnapshot,
3414
+ K as dayToCivilDate,
3415
+ Dt as deriveCategories,
3416
+ oi as derivedCriterion,
3417
+ ai as filterByHidden,
3418
+ D as findBlock,
3419
+ vt as flattenBlocks,
3420
+ St as linePath,
3421
+ Mt as setsEqual,
3422
+ si as staticCriterion,
3423
+ Kr as todayCivilDate,
3424
+ Fr as valueAtDate
3425
+ };
3426
+ //# sourceMappingURL=index.js.map