umwelt-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1867 @@
1
+ import { createComponent as g, template as A, use as xt, delegateEvents as We, insert as k, effect as q, setAttribute as Re, memo as le, className as _t, render as Nt } from "solid-js/web";
2
+ import { createContext as W, createSignal as C, useContext as Z, createEffect as F, onCleanup as J, createMemo as _, Switch as Pt, Match as Ie, For as ee, onMount as Ze, Show as Qe } from "solid-js";
3
+ import { isMultiSpec as Le, olliVis as Ft } from "olli";
4
+ import { VegaLiteAdapter as Ot } from "olli/adapters";
5
+ import fe from "moize";
6
+ import { getDomain as Vt, fetchAndParse as Ct, typeCoerceData as Rt, getBins as It, serializeValue as Lt } from "@umwelt-data/umwelt-utils/data";
7
+ import { compile as et } from "vega-lite";
8
+ import { evaluateVegaData as jt, extractOutputDatasets as qt, computeGuideTicks as Mt } from "@umwelt-data/umwelt-utils/vega";
9
+ import be from "lodash.clonedeep";
10
+ import { withExternalStateParam as Bt, selectionStoreToSelection as zt, EXTERNAL_STATE_STORE as je, predicateToSelectionStore as Gt } from "@umwelt-data/umwelt-utils/vl-bridge";
11
+ import "lz-string";
12
+ import { parse as Kt, View as Ht } from "vega";
13
+ import { debounce as Jt } from "@solid-primitives/scheduled";
14
+ import "olli/styles.css";
15
+ import { createStore as me } from "solid-js/store";
16
+ import { makeCommaSeparatedString as Te, fmtValue as Yt, describeField as H } from "@umwelt-data/umwelt-utils/description";
17
+ import { testDatum as Xt } from "@umwelt-data/umwelt-utils/predicate";
18
+ import * as V from "tone";
19
+ import { Storage as Wt } from "versioned-storage";
20
+ import { scaleTime as Zt, scaleLinear as Qt, scaleOrdinal as en } from "d3-scale";
21
+ import tn from "fast-cartesian";
22
+ import { styled as x } from "solid-styled-components";
23
+ const nn = "_Viewer_1uzho_29", rn = {
24
+ Viewer: nn
25
+ }, an = ["mean", "median", "min", "max", "sum", "count"];
26
+ function tt(e) {
27
+ return an.includes(e);
28
+ }
29
+ function sn(e) {
30
+ return e && (typeof e.name == "string" || e.name === void 0) && Array.isArray(e.values);
31
+ }
32
+ function nt(e) {
33
+ return e && (typeof e.name == "string" || e.name === void 0) && typeof e.url == "string";
34
+ }
35
+ const on = ["x", "y", "color", "shape", "size", "opacity", "order", "facet"];
36
+ function it(e) {
37
+ return on.includes(e);
38
+ }
39
+ const rt = "None", cn = "", Y = (e, n) => `${n}_${e}`, M = (e) => [`${e}_bin_start`, `${e}_bin_end`], X = (e, n) => `${n}_${e}`, pe = (e) => {
40
+ const n = xe([e]);
41
+ let t = e.field;
42
+ for (const i of n)
43
+ if ("aggregate" in i)
44
+ for (const r of i.aggregate)
45
+ tt(r.op) && (t = Y(t, r.op));
46
+ else "bin" in i && !e.aggregate ? t = M(t)[0] : "timeUnit" in i && !e.aggregate && (t = X(t, i.timeUnit));
47
+ return t;
48
+ }, at = (e) => {
49
+ const n = xe([e]);
50
+ let t = e.field;
51
+ for (const i of n)
52
+ if ("aggregate" in i)
53
+ for (const r of i.aggregate)
54
+ tt(r.op) && (typeof t == "string" ? t = Y(t, r.op) : t = [Y(t[0], r.op), Y(t[1], r.op)]);
55
+ else "bin" in i && !e.aggregate ? typeof t == "string" ? t = M(t) : t = [M(t[0])[0], M(t[1])[1]] : "timeUnit" in i && !e.aggregate && (typeof t == "string" ? t = X(t, i.timeUnit) : t = [X(t[0], i.timeUnit), X(t[1], i.timeUnit)]);
56
+ if (typeof t == "string")
57
+ throw new Error("Expected derived field name to be a tuple");
58
+ return t;
59
+ }, ke = (e, n, t) => {
60
+ const i = new Set(n.filter((s) => s.bin && t?.[s.field]?.length).map((s) => s.field));
61
+ let r = e;
62
+ i.size && (r = e.map((s) => {
63
+ const c = { ...s };
64
+ for (const o of i) {
65
+ const [d, l] = M(o), f = ln(s[o], t[o]);
66
+ c[d] = f ? f[0] : null, c[l] = f ? f[1] : null;
67
+ }
68
+ return c;
69
+ }));
70
+ const a = xe(n, i);
71
+ return st(r, a);
72
+ }, ln = (e, n) => {
73
+ if (e == null) return;
74
+ const t = Number(e);
75
+ if (!isNaN(t))
76
+ for (let i = 0; i < n.length; i++) {
77
+ const [r, a] = n[i];
78
+ if (t >= r && (t < a || i === n.length - 1 && t <= a))
79
+ return n[i];
80
+ }
81
+ }, xe = (e, n) => {
82
+ const t = [], i = [], r = [], a = /* @__PURE__ */ new Set();
83
+ for (const u of e) {
84
+ const { field: s, timeUnit: c, bin: o, aggregate: d } = u;
85
+ d || (c && a.add(X(s, c)), o && M(s).forEach((l) => a.add(l)), !c && !o && a.add(s));
86
+ }
87
+ for (const u of e) {
88
+ const { field: s, timeUnit: c, bin: o, aggregate: d } = u;
89
+ if (o && !n?.has(s)) {
90
+ const l = M(s);
91
+ i.push({
92
+ bin: !0,
93
+ field: s,
94
+ as: l
95
+ });
96
+ }
97
+ if (c) {
98
+ const l = o ? M(s)[0] : X(s, c);
99
+ t.push({
100
+ timeUnit: c,
101
+ field: s,
102
+ as: l
103
+ });
104
+ }
105
+ if (d) {
106
+ const l = o ? M(s)[0] : s, f = r.find((p) => p.groupby?.length === a.size && p.groupby?.every((h) => a.has(h)));
107
+ f ? f.aggregate.push({
108
+ op: d,
109
+ field: l,
110
+ as: Y(s, d)
111
+ }) : r.push({
112
+ aggregate: [
113
+ {
114
+ op: d,
115
+ field: l,
116
+ as: Y(s, d)
117
+ }
118
+ ],
119
+ groupby: Array.from(a)
120
+ });
121
+ }
122
+ }
123
+ return [...i, ...t, ...r];
124
+ };
125
+ function st(e, n) {
126
+ const r = et({
127
+ data: { values: e },
128
+ transform: n,
129
+ mark: "point"
130
+ }).spec.data ?? [], a = jt(r), u = qt(r, a);
131
+ return u[u.length - 1] ?? [];
132
+ }
133
+ const te = fe((e, n, t) => {
134
+ const i = t ? pe(e) : e.field;
135
+ return Vt({ field: i, type: e.type, timeUnit: e.timeUnit }, n);
136
+ }), un = fe((e, n) => {
137
+ if (e.bin) {
138
+ const t = at(e);
139
+ return n.map((i) => {
140
+ const r = i[t[0]], a = i[t[1]];
141
+ return [r, a];
142
+ }).sort((i, r) => typeof i[0] == "number" && typeof r[0] == "number" ? i[0] - r[0] : i[0] instanceof Date && r[0] instanceof Date ? i[0].getTime() - r[0].getTime() : typeof i[0] == "string" && typeof r[0] == "string" ? i[0].localeCompare(r[0]) : 0);
143
+ }
144
+ return [];
145
+ }), de = "dataset", dn = "https://raw.githubusercontent.com/vega/vega-datasets/master/data/", fn = Object.fromEntries(
146
+ ["stocks.csv", "cars.json", "weather.csv", "seattle-weather.csv", "penguins.json", "driving.json", "barley.json", "disasters.csv", "gapminder.json"].map((e) => [e, `${dn}${e}`])
147
+ );
148
+ async function mn(e) {
149
+ if (sn(e)) {
150
+ const n = e.name || de;
151
+ return e.values.length ? { name: n, data: e.values } : void 0;
152
+ }
153
+ if (nt(e)) {
154
+ const n = e.name || e.url.split("/").pop() || de, t = await qe(e.url);
155
+ return t.length ? { name: n, data: t, sourceUrl: e.url } : void 0;
156
+ }
157
+ if (e.name) {
158
+ const n = fn[e.name];
159
+ if (!n) {
160
+ console.error(`Unknown example dataset "${e.name}". A name-only data source must reference a built-in example dataset, or provide a url or values.`);
161
+ return;
162
+ }
163
+ const t = await qe(n);
164
+ return t.length ? { name: e.name, data: t, sourceUrl: n } : void 0;
165
+ }
166
+ }
167
+ const qe = fe.promise(async (e) => {
168
+ try {
169
+ const n = await Ct(e);
170
+ return Array.isArray(n) ? n : [];
171
+ } catch (n) {
172
+ return console.warn(`Failed to load data from ${e}
173
+ ${n}`), [];
174
+ }
175
+ });
176
+ fe.promise(async (e, n) => {
177
+ try {
178
+ return st(e, n);
179
+ } catch (t) {
180
+ return console.warn(`Failed to evaluate transforms
181
+ ${t}`), [];
182
+ }
183
+ });
184
+ function pn(e, n) {
185
+ const t = n.map((i) => ({ name: i.name, type: i.type }));
186
+ return Rt(e, t);
187
+ }
188
+ function gn(e, n) {
189
+ return e.filter((t) => Object.entries(t).every(([i, r]) => n.find((a) => a.name === i) ? r != null : !0));
190
+ }
191
+ function $(e, n) {
192
+ return e.fields.find((t) => t.name === n);
193
+ }
194
+ function N(e, n) {
195
+ const { active: t, name: i, encodings: r, ...a } = e, u = n ? {
196
+ ...a,
197
+ ...n
198
+ } : { field: i, ...a };
199
+ return Object.fromEntries(Object.entries(u).filter(([s, c]) => c !== rt));
200
+ }
201
+ function _e(e, n) {
202
+ const i = [...Object.values(n.encoding), ...n.traversal].flatMap((a) => {
203
+ const u = $(e, a.field);
204
+ return u ? [N(u, a)] : [];
205
+ }), r = /* @__PURE__ */ new Set();
206
+ return i.filter((a) => {
207
+ const u = JSON.stringify(a);
208
+ return r.has(u) ? !1 : (r.add(u), !0);
209
+ });
210
+ }
211
+ async function vn(e, n, t) {
212
+ if (!e.data || !(e.fields && e.fields.length))
213
+ return;
214
+ const i = e.data.name;
215
+ if (i && n[i]?.data?.length)
216
+ return Me(e);
217
+ const r = await mn(e.data);
218
+ if (!r)
219
+ return;
220
+ const a = Me(e), u = pn(r.data, a.fields), s = gn(u, a.fields);
221
+ if (s.length)
222
+ return t(r.name, s, r.sourceUrl), a;
223
+ }
224
+ function Me(e) {
225
+ const n = e.fields.map((i) => {
226
+ const r = [];
227
+ return e.visual.units.forEach((a) => {
228
+ Object.entries(a.encoding).forEach(([u, s]) => {
229
+ it(u) && s.field === i.name && r.push({ unit: a.name, property: u });
230
+ });
231
+ }), e.audio.units.forEach((a) => {
232
+ Object.entries(a.encoding).forEach(([u, s]) => {
233
+ u === "pitch" && s.field === i.name && r.push({ unit: a.name, property: u });
234
+ });
235
+ }), { ...i, active: !0, encodings: r };
236
+ });
237
+ return {
238
+ ...e,
239
+ data: {
240
+ name: e.data.name || (nt(e.data) ? e.data.url.split("/").pop() : de) || de
241
+ },
242
+ fields: n,
243
+ visual: { units: e.visual.units, composition: e.visual.composition || "layer" },
244
+ audio: { units: e.audio.units, composition: e.audio.composition || "concat" },
245
+ // regenerate node ids on import so a serialized id can never collide with one
246
+ // this session's counter later mints
247
+ text: {
248
+ structures: e.text?.structures ? Object.fromEntries(Object.entries(e.text.structures).map(([i, r]) => [i, r.map(ct)])) : {}
249
+ }
250
+ };
251
+ }
252
+ function ot(e, n) {
253
+ if (e.visual.units.length === 0 || e.visual.units.map((c) => Object.values(c.encoding).length).reduce((c, o) => c + o, 0) === 0) return;
254
+ const i = [
255
+ {
256
+ name: "brush",
257
+ select: "interval"
258
+ }
259
+ ];
260
+ function r(c) {
261
+ const o = c.visual.units;
262
+ if (o.length === 1) {
263
+ const d = o[0], l = be(d.encoding);
264
+ return l && Object.keys(l).forEach((f) => {
265
+ if (it(f)) {
266
+ const p = l[f];
267
+ if (p) {
268
+ const h = $(c, p.field);
269
+ if (h) {
270
+ const w = N(h, p);
271
+ if (l[f] = {
272
+ ...w
273
+ }, f === "facet") {
274
+ const E = te(w, n);
275
+ l[f] = {
276
+ ...w,
277
+ columns: E.length === 3 ? 3 : 2
278
+ // TODO do something better
279
+ };
280
+ }
281
+ d.mark === "point" && (f === "x" || f === "y") && w.type === "quantitative" && (l[f] = {
282
+ ...w,
283
+ scale: {
284
+ ...w.scale,
285
+ zero: !1
286
+ }
287
+ });
288
+ }
289
+ }
290
+ }
291
+ }), {
292
+ mark: d.mark,
293
+ encoding: {
294
+ ...l,
295
+ color: {
296
+ ...a({ ...l.color || { value: "navy" }, scale: d.mark === "area" ? { scheme: "category20b" } : void 0 }, "brush", "grey")
297
+ }
298
+ }
299
+ };
300
+ } else if (o.length > 1) {
301
+ const d = c.visual.composition || "layer";
302
+ return {
303
+ columns: d === "concat" ? o.length < 3 ? 1 : 2 : void 0,
304
+ [d]: o.map((l, f) => {
305
+ const p = r({
306
+ ...c,
307
+ visual: {
308
+ units: [l],
309
+ composition: d
310
+ }
311
+ });
312
+ return f === 0 && (p.params = i), p;
313
+ })
314
+ };
315
+ }
316
+ }
317
+ if (e.visual.units[0].mark === "line" || e.visual.units[0].mark === "bar") {
318
+ const c = e.visual.units[0], o = c.encoding.y?.field, d = c.encoding.x?.field, l = $(e, o), f = $(e, d);
319
+ l?.type === "quantitative" && f?.type !== "quantitative" ? i[0].select = { type: "interval", encodings: ["x"] } : f?.type === "quantitative" && l?.type !== "quantitative" && (i[0].select = { type: "interval", encodings: ["y"] });
320
+ }
321
+ const a = (c, o, d, l) => ({
322
+ condition: { param: o, empty: l || !0, ...c },
323
+ value: d
324
+ }), u = r(e);
325
+ let s;
326
+ return "mark" in u ? s = be({
327
+ data: { values: n },
328
+ params: i,
329
+ ...u
330
+ }) : s = be({
331
+ data: { values: n },
332
+ ...u
333
+ }), Bt(s);
334
+ }
335
+ async function hn(e, n) {
336
+ let t;
337
+ const i = e.text.structures, r = e.visual.units.map((c) => c.name);
338
+ JSON.stringify(i);
339
+ const a = new Map(e.fields.map((c) => [c.name, c.type])), u = ot(e, n);
340
+ if (u ? t = await Ot(u) : t = {
341
+ data: n,
342
+ fields: []
343
+ }, Le(t) ? t.units.forEach((c) => {
344
+ s(c, e);
345
+ }) : s(t, e), u)
346
+ (Le(t) ? t.units : [t]).forEach((o, d) => {
347
+ const l = i[r[d]];
348
+ l?.length && ze(o, l, a);
349
+ });
350
+ else {
351
+ const c = i[cn];
352
+ c?.length && ze(t, c, a);
353
+ }
354
+ function s(c, o) {
355
+ c.fields?.length === 0 && (delete c.mark, delete c.axes, delete c.legends), c.fields && o.fields.filter((d) => d.active).forEach((d) => {
356
+ c.fields?.find((l) => l.field === d.name) || c.fields?.push({
357
+ ...d,
358
+ field: d.name,
359
+ timeUnit: d.timeUnit
360
+ });
361
+ });
362
+ }
363
+ return t;
364
+ }
365
+ let yn = 0;
366
+ function Sn() {
367
+ return `text_node_${yn++}`;
368
+ }
369
+ function ct(e) {
370
+ return { ...e, id: Sn(), children: e.children.map(ct) };
371
+ }
372
+ function ue(e, n) {
373
+ if (!e || typeof e != "object") return e;
374
+ if ("and" in e) return { and: e.and.map((t) => ue(t, n)) };
375
+ if ("or" in e) return { or: e.or.map((t) => ue(t, n)) };
376
+ if ("not" in e) return { not: ue(e.not, n) };
377
+ if ("field" in e && n.get(e.field) === "temporal") {
378
+ const t = (r) => r instanceof Date || r == null ? r : new Date(r), i = { ...e };
379
+ for (const r of ["equal", "lt", "lte", "gt", "gte"])
380
+ r in i && (i[r] = t(i[r]));
381
+ return "range" in i && Array.isArray(i.range) && (i.range = i.range.map(t)), "oneOf" in i && Array.isArray(i.oneOf) && (i.oneOf = i.oneOf.map(t)), i;
382
+ }
383
+ return e;
384
+ }
385
+ function lt(e, n, t) {
386
+ const i = e.children.map((r) => lt(r, n, t));
387
+ if (e.nodeType === "group") {
388
+ const r = e.groupby.map(t);
389
+ return { groupby: r.length === 1 ? r[0] : r, ...i.length ? { children: i } : {} };
390
+ }
391
+ return {
392
+ predicate: ue(e.predicate, n),
393
+ ...e.name ? { name: e.name } : {},
394
+ ...e.reasoning ? { reasoning: e.reasoning } : {},
395
+ ...i.length ? { children: i } : {}
396
+ };
397
+ }
398
+ function Be(e, n) {
399
+ return {
400
+ type: e.type ?? n?.type,
401
+ timeUnit: e.timeUnit === rt ? void 0 : e.timeUnit ?? n?.timeUnit,
402
+ bin: e.bin !== void 0 ? e.bin : !!n?.bin
403
+ };
404
+ }
405
+ const Ee = (e) => `${e.type ?? ""}|${e.timeUnit ?? ""}|${e.bin ? "bin" : ""}`;
406
+ function ze(e, n, t) {
407
+ const i = e.fields ?? (e.fields = []), r = e.data ?? [], a = (d) => i.find((l) => l.field === d), u = /* @__PURE__ */ new Map(), s = (d) => d.forEach((l) => {
408
+ l.nodeType === "group" && l.groupby.forEach((f) => {
409
+ const p = Be(f, a(f.field)), h = u.get(f.field) ?? /* @__PURE__ */ new Map();
410
+ h.set(Ee(p), p), u.set(f.field, h);
411
+ }), s(l.children);
412
+ });
413
+ s(n);
414
+ const c = /* @__PURE__ */ new Map();
415
+ u.forEach((d, l) => {
416
+ const f = a(l), p = f ? Ee({ type: f.type, timeUnit: f.timeUnit, bin: !!f.bin }) : void 0, h = [...d.keys()], w = p && d.has(p) ? p : h[0];
417
+ d.forEach((E, L) => {
418
+ if (L === w)
419
+ f && (E.type && (f.type = E.type), f.timeUnit = E.timeUnit, f.bin = E.bin || void 0), c.set(`${l}|${L}`, l);
420
+ else {
421
+ const R = [E.type, E.timeUnit, E.bin ? "bin" : ""].filter(Boolean), P = `${l}__${R.join("_") || "raw"}`;
422
+ c.set(`${l}|${L}`, P), i.find((I) => I.field === P) || i.push({ field: P, label: l, type: E.type ?? t.get(l), timeUnit: E.timeUnit, bin: E.bin || void 0 }), r.forEach((I) => {
423
+ l in I && !(P in I) && (I[P] = I[l]);
424
+ });
425
+ }
426
+ });
427
+ });
428
+ const o = (d) => c.get(`${d.field}|${Ee(Be(d, a(d.field)))}`) ?? d.field;
429
+ e.structure = n.map((d) => lt(d, t, o));
430
+ }
431
+ function bn(e, n) {
432
+ const t = et(e).spec, i = Kt(t), r = new Ht(i, {
433
+ renderer: "canvas",
434
+ container: n,
435
+ hover: !0
436
+ });
437
+ return r.runAsync(), r;
438
+ }
439
+ const ut = W();
440
+ function En(e) {
441
+ const [n, t] = C(void 0), i = {
442
+ setSelection: (r) => {
443
+ r && r.predicate && "and" in r.predicate && r.predicate.and.length === 0 && (r.predicate = void 0), t(r);
444
+ }
445
+ };
446
+ return g(ut.Provider, {
447
+ value: [n, i],
448
+ get children() {
449
+ return e.children;
450
+ }
451
+ });
452
+ }
453
+ function ie() {
454
+ const e = Z(ut);
455
+ if (e === void 0)
456
+ throw new Error("useUmweltSelection must be used within a UmweltSelectionProvider");
457
+ return e;
458
+ }
459
+ var wn = /* @__PURE__ */ A("<div id=vl-container>");
460
+ function Dn(e) {
461
+ const [n, t] = ie(), [i, r] = C(!1), [a, u] = C(null), s = Jt((c) => {
462
+ if (i()) {
463
+ const o = zt(c);
464
+ t.setSelection({
465
+ source: "visualization",
466
+ predicate: o
467
+ });
468
+ }
469
+ }, 250);
470
+ return F(() => {
471
+ const c = n(), o = a();
472
+ if (!c) {
473
+ o && o.data(je, []).run();
474
+ return;
475
+ }
476
+ if (o && (c.source === "sonification" || c.source === "text-navigation")) {
477
+ const d = Gt(c.predicate);
478
+ o.data(je, d ? [d] : []).run();
479
+ }
480
+ }), F(() => {
481
+ const c = ot(e.spec, e.data);
482
+ if (c)
483
+ try {
484
+ const o = bn(c, "#vl-container");
485
+ o.addDataListener("brush_store", (d, l) => {
486
+ s(l);
487
+ }), u(o);
488
+ } catch (o) {
489
+ console.error(o);
490
+ }
491
+ J(() => {
492
+ a()?.finalize(), u(null), document.getElementById("vl-container").innerHTML = "";
493
+ });
494
+ }), (() => {
495
+ var c = wn();
496
+ return c.addEventListener("mouseleave", () => r(!1)), c.addEventListener("mouseenter", () => r(!0)), c;
497
+ })();
498
+ }
499
+ var Un = /* @__PURE__ */ A("<div id=olli-container>");
500
+ function An(e) {
501
+ const [n, t] = ie(), [i, r] = C(null), [a, u] = C(null);
502
+ let s = !1;
503
+ return F(() => {
504
+ let c = !1;
505
+ J(() => {
506
+ c = !0;
507
+ }), hn(e.spec, e.data).then((o) => {
508
+ const d = i();
509
+ if (c || !o || !d) return;
510
+ a()?.destroy(), d.innerHTML = "";
511
+ const l = Ft(o, d);
512
+ l.onFocusChange((f) => {
513
+ if (s) return;
514
+ const p = l.fullPredicate(f);
515
+ "and" in p && p.and.length > 0 ? t.setSelection({
516
+ source: "text-navigation",
517
+ predicate: p
518
+ }) : t.setSelection({
519
+ source: "text-navigation",
520
+ predicate: void 0
521
+ });
522
+ }), l.onSelectionChange((f) => {
523
+ t.setSelection({
524
+ source: "text-filter",
525
+ predicate: f
526
+ });
527
+ }), u(l);
528
+ });
529
+ }), F(() => {
530
+ const c = n(), o = a();
531
+ c && o && c.source === "visualization" && (s = !0, o.setSelection(c.predicate ?? {
532
+ and: []
533
+ }), queueMicrotask(() => {
534
+ s = !1;
535
+ }));
536
+ }), J(() => {
537
+ a()?.destroy();
538
+ }), (() => {
539
+ var c = Un();
540
+ return xt(r, c), c;
541
+ })();
542
+ }
543
+ const dt = W();
544
+ function $n(e) {
545
+ const [n] = ie(), t = () => ({
546
+ activeUnitName: void 0,
547
+ selection: void 0
548
+ }), [i, r] = me(t());
549
+ let a = null;
550
+ F(() => {
551
+ const s = n();
552
+ s && s.source !== "sonification" && u.setSelection(s.predicate);
553
+ });
554
+ const u = {
555
+ setActiveUnit: (s) => {
556
+ r("activeUnitName", s);
557
+ },
558
+ setSelection: (s) => {
559
+ r("selection", s);
560
+ },
561
+ registerPlayCallback: (s, c = !1) => {
562
+ (c || a === null) && (a = s);
563
+ },
564
+ triggerPlay: () => {
565
+ a?.();
566
+ }
567
+ };
568
+ return g(dt.Provider, {
569
+ value: [i, u],
570
+ get children() {
571
+ return e.children;
572
+ }
573
+ });
574
+ }
575
+ function ge() {
576
+ const e = Z(dt);
577
+ if (e === void 0)
578
+ throw new Error("useSonificationRuntime must be used within a SonificationRuntimeProvider");
579
+ return e;
580
+ }
581
+ const G = (e, n) => Array.isArray(e) ? e.length === 2 && (n.type === "quantitative" || n.type === "temporal") ? e.map((t) => G(t, n)).join("–") : Te(e.map((t) => G(t, n))) : Yt(e, n);
582
+ function Ne(e, n) {
583
+ return e.filter((t) => Xt(t, n));
584
+ }
585
+ const Tn = "umwelt", kn = 1, xn = {
586
+ muted: !1,
587
+ speakAxisTicks: !0,
588
+ speechRate: 50,
589
+ playbackRate: 1
590
+ }, ft = () => new Wt(Tn, kn), mt = () => ft().read(), ce = (e) => {
591
+ const n = mt() ?? xn;
592
+ ft().write({
593
+ ...n,
594
+ ...e
595
+ });
596
+ }, Ge = (e, n, t) => Math.min(Math.max(e, n), t), Ke = ["triangle", "sawtooth", "square", "sine"], _n = (e) => Ke[e % Ke.length], we = "default", De = 0.1, ne = 120, pt = W();
597
+ function Nn(e) {
598
+ const n = /* @__PURE__ */ new Map(), t = {
599
+ attack: 0.01,
600
+ decay: 0,
601
+ sustain: 1,
602
+ release: 0.01
603
+ }, i = (o, d = "triangle") => {
604
+ let l = n.get(o);
605
+ if (!l) {
606
+ const f = new V.Synth({
607
+ oscillator: {
608
+ type: d
609
+ },
610
+ envelope: t
611
+ }).toDestination(), p = new V.NoiseSynth({
612
+ noise: {
613
+ type: "pink"
614
+ },
615
+ envelope: t
616
+ }), h = new V.Gain(0.3).toDestination();
617
+ p.connect(h), l = {
618
+ synth: f,
619
+ noiseSynth: p,
620
+ noiseGain: h,
621
+ isSynthPlaying: !1,
622
+ isNoisePlaying: !1
623
+ }, n.set(o, l);
624
+ }
625
+ return l;
626
+ }, r = (o) => {
627
+ o.synth.triggerRelease(), o.noiseSynth.triggerRelease(), o.isSynthPlaying = !1, o.isNoisePlaying = !1;
628
+ };
629
+ F(() => {
630
+ const o = () => {
631
+ document.hidden && c.stopTransport();
632
+ };
633
+ document.addEventListener("visibilitychange", o), J(() => {
634
+ document.removeEventListener("visibilitychange", o), n.forEach((d) => {
635
+ d.synth.dispose(), d.noiseSynth.dispose(), d.noiseGain.dispose();
636
+ }), n.clear(), V.getTransport().cancel(), V.getTransport().stop();
637
+ });
638
+ });
639
+ const a = () => {
640
+ const o = mt();
641
+ return {
642
+ transport: V.getTransport(),
643
+ muted: o?.muted ?? !1,
644
+ speakAxisTicks: o?.speakAxisTicks ?? !0,
645
+ speechRate: o?.speechRate ?? 50,
646
+ playbackRate: o?.playbackRate ?? 1,
647
+ pauseBetweenSections: 0.25,
648
+ isPlaying: !1
649
+ };
650
+ }, [u, s] = me(a());
651
+ F(() => {
652
+ u.transport.bpm.value = ne * u.playbackRate;
653
+ });
654
+ const c = {
655
+ startAudioContext: async () => {
656
+ await V.start(), i(we);
657
+ },
658
+ ensureVoice: (o, d) => {
659
+ i(o, d);
660
+ },
661
+ setMuted: (o) => {
662
+ ce({
663
+ muted: o
664
+ }), s((d) => ({
665
+ ...d,
666
+ muted: o
667
+ })), V.getDestination().mute = o;
668
+ },
669
+ setSpeakAxisTicks: (o) => {
670
+ ce({
671
+ speakAxisTicks: o
672
+ }), s((d) => ({
673
+ ...d,
674
+ speakAxisTicks: o
675
+ })), o || (speechSynthesis.cancel(), u.isPlaying && V.getTransport().start());
676
+ },
677
+ setSpeechRate: (o) => {
678
+ const d = Ge(o, 1, 100);
679
+ ce({
680
+ speechRate: o
681
+ }), s((l) => ({
682
+ ...l,
683
+ speechRate: d
684
+ }));
685
+ },
686
+ setPlaybackRate: (o) => {
687
+ const d = Ge(o, 0.1, 4);
688
+ ce({
689
+ playbackRate: d
690
+ }), s((l) => ({
691
+ ...l,
692
+ playbackRate: d
693
+ }));
694
+ },
695
+ startTransport: async () => {
696
+ s((o) => ({
697
+ ...o,
698
+ isPlaying: !0
699
+ })), V.getTransport().start();
700
+ },
701
+ stopTransport: () => {
702
+ s((o) => ({
703
+ ...o,
704
+ isPlaying: !1
705
+ })), speechSynthesis.cancel(), V.getTransport().pause(), c.releaseSynth();
706
+ },
707
+ playNote: (o, d = we) => {
708
+ const l = i(d);
709
+ if (l.noiseSynth.triggerRelease(), l.synth.triggerRelease(), l.isSynthPlaying = !1, l.isNoisePlaying = !1, !o.rest)
710
+ if (o.pitch) {
711
+ l.synth.volume.value = o.volume;
712
+ const f = V.Frequency(o.pitch, "midi").toFrequency();
713
+ l.synth.triggerAttackRelease(f, o.duration);
714
+ } else
715
+ l.noiseSynth.volume.value = o.volume, l.noiseSynth.triggerAttackRelease(o.duration);
716
+ },
717
+ startOrRampSynth: (o, d = we) => {
718
+ const l = i(d);
719
+ if (o.rest) {
720
+ r(l);
721
+ return;
722
+ }
723
+ if (o.pitch) {
724
+ l.noiseSynth.triggerRelease(), l.isNoisePlaying = !1;
725
+ const f = V.Frequency(o.pitch, "midi").toFrequency();
726
+ l.isSynthPlaying ? (l.synth.volume.rampTo(o.volume, De), l.synth.frequency.rampTo(f, De)) : (l.synth.volume.value = o.volume, l.isSynthPlaying = !0, l.synth.triggerAttack(f));
727
+ } else
728
+ l.synth.triggerRelease(), l.isSynthPlaying = !1, l.isNoisePlaying ? l.noiseSynth.volume.rampTo(o.volume, De) : (l.noiseSynth.volume.value = o.volume, l.isNoisePlaying = !0, l.noiseSynth.triggerAttack());
729
+ },
730
+ releaseSynth: (o) => {
731
+ if (o !== void 0) {
732
+ const d = n.get(o);
733
+ d && r(d);
734
+ } else
735
+ n.forEach(r);
736
+ }
737
+ };
738
+ return g(pt.Provider, {
739
+ value: [u, c],
740
+ get children() {
741
+ return e.children;
742
+ }
743
+ });
744
+ }
745
+ function Q() {
746
+ const e = Z(pt);
747
+ if (e === void 0)
748
+ throw new Error("useSonificationRuntime must be used within a SonificationRuntimeProvider");
749
+ return e;
750
+ }
751
+ function gt(e, n, t) {
752
+ const i = $(e, t);
753
+ if (!i) return;
754
+ const r = i.encodings.find((l) => l.property === "x" || l.property === "y");
755
+ if (!r) return;
756
+ const a = e.visual.units.find((l) => l.name === r.unit), u = a?.encoding[r.property];
757
+ if (!a || !u) return;
758
+ const s = N(i, u), c = a.mark === "point" && s.type === "quantitative" ? !1 : s.scale?.zero, o = Array.isArray(s.scale?.domain) ? s.scale?.domain : void 0, d = {
759
+ field: t,
760
+ type: s.type,
761
+ bin: !!s.bin,
762
+ timeUnit: s.timeUnit,
763
+ scaleZero: c,
764
+ scaleDomain: o,
765
+ // vega-lite sorts discrete scales ascending unless told otherwise
766
+ sort: s.sort === void 0 ? "ascending" : s.sort
767
+ };
768
+ return Mt(n, d);
769
+ }
770
+ function Pe(e, n, t, i) {
771
+ const r = {};
772
+ for (const a of i)
773
+ if (a.bin && a.type === "quantitative" && !(a.field in r)) {
774
+ const u = { field: a.field, type: a.type };
775
+ let s = It(u, t, gt(e, n, a.field));
776
+ if (s.length === 0) {
777
+ let c = 1 / 0, o = -1 / 0;
778
+ for (const d of t) {
779
+ const l = d[a.field];
780
+ if (l == null) continue;
781
+ const f = Number(l);
782
+ isNaN(f) || (f < c && (c = f), f > o && (o = f));
783
+ }
784
+ c <= o && (s = [[c, o]]);
785
+ }
786
+ r[a.field] = s;
787
+ }
788
+ return r;
789
+ }
790
+ const vt = W(), Pn = {
791
+ pitch: [48, 84],
792
+ // in MIDI. Three octaves from C3 to C6
793
+ duration: [0.25, 1],
794
+ // in seconds
795
+ volume: [-20, 0]
796
+ // in decibels
797
+ }, He = {
798
+ pitch: 60,
799
+ // MIDI C4 middle C. We encode in MIDI because linear interpolations in Hz are not perceptually linear
800
+ duration: 0.2,
801
+ // seconds
802
+ volume: -10
803
+ // dB
804
+ };
805
+ function Ue(e, n, t, i) {
806
+ const r = t.encoding[i];
807
+ if (!r)
808
+ return () => He[i];
809
+ const a = $(e, r.field);
810
+ if (!a)
811
+ return console.warn(`Field ${r.field} not found in spec`), () => He[i];
812
+ const u = N(a, r);
813
+ let s = u.scale?.domain;
814
+ if (!s) {
815
+ const o = u.aggregate === "count" || u.aggregate === "sum", d = _e(e, t), l = o ? ke(n, d, Pe(e, n, n, d)) : n;
816
+ switch (a.type) {
817
+ case "ordinal":
818
+ case "nominal":
819
+ s = te(u, l, o);
820
+ break;
821
+ case "quantitative":
822
+ case "temporal":
823
+ s = te(u, l, o), s = [s[0], s[s.length - 1]];
824
+ break;
825
+ default:
826
+ throw new Error(`Unsupported field type ${u.type}`);
827
+ }
828
+ }
829
+ const c = u.scale?.range || Pn[i];
830
+ switch (u.type) {
831
+ case "ordinal":
832
+ case "nominal":
833
+ return en().domain(s).range(c);
834
+ case "quantitative":
835
+ return Qt().domain(s).range(c);
836
+ case "temporal":
837
+ return Zt().domain(s).range(c);
838
+ default:
839
+ throw new Error(`Unsupported field type ${u.type}`);
840
+ }
841
+ }
842
+ function ht(e, n, t) {
843
+ return {
844
+ pitch: Ue(e, n, t, "pitch"),
845
+ duration: Ue(e, n, t, "duration"),
846
+ volume: Ue(e, n, t, "volume")
847
+ };
848
+ }
849
+ function yt(e, n, t) {
850
+ return gt(e, n, t) ?? [];
851
+ }
852
+ function Fn(e) {
853
+ const n = (r) => yt(e.spec, e.data, r.field), t = ht(e.spec, e.data, e.audioUnitSpec), i = {
854
+ getAxisTicks: n
855
+ };
856
+ return g(vt.Provider, {
857
+ value: [t, i],
858
+ get children() {
859
+ return e.children;
860
+ }
861
+ });
862
+ }
863
+ function On() {
864
+ const e = Z(vt);
865
+ if (e === void 0)
866
+ throw new Error("useSonificationRuntime must be used within a SonificationRuntimeProvider");
867
+ return e;
868
+ }
869
+ const Je = {
870
+ pitch: 60,
871
+ // MIDI C4 middle C. We encode in MIDI because linear interpolations in Hz are not perceptually linear
872
+ duration: 0.2,
873
+ // seconds
874
+ volume: -15
875
+ // dB
876
+ };
877
+ function Ae(e, n, t, i, r) {
878
+ if (!t)
879
+ return Je[e];
880
+ const a = $(n, t.field);
881
+ if (!a)
882
+ return Je[e];
883
+ const u = N(a, t), s = pe(u);
884
+ return i(r[0][s]);
885
+ }
886
+ const Fe = (e, n) => e.audioUnitSpec.traversal.find((t) => t.field === n);
887
+ function ve(e, n, t) {
888
+ const i = $(e.spec, n), r = N(i, Fe(e, n)), a = e.fieldDomains[n];
889
+ if (r.bin && !r.aggregate) {
890
+ const [u, s] = at(r), c = a[t], o = e.derivedData.find((d) => d[u] === c)?.[s] ?? null;
891
+ return [c, o];
892
+ } else
893
+ return a[t];
894
+ }
895
+ function St(e, n) {
896
+ return {
897
+ and: Object.entries(n).map(([t, i]) => {
898
+ const r = ve(e, t, i), a = e.fieldDomains[t].length - 1;
899
+ return Array.isArray(r) ? {
900
+ field: t,
901
+ range: r,
902
+ inclusiveLeft: !0,
903
+ inclusiveRight: i === a
904
+ } : {
905
+ field: t,
906
+ equal: r
907
+ };
908
+ })
909
+ };
910
+ }
911
+ function $e(e, n) {
912
+ const t = {
913
+ and: Object.entries(n).map(([i, r]) => {
914
+ const a = e.fieldDomains[i][r], u = $(e.spec, i);
915
+ if (!u)
916
+ return { field: i, equal: a };
917
+ const s = N(u, Fe(e, i));
918
+ return {
919
+ field: pe(s),
920
+ equal: Lt(a, u)
921
+ };
922
+ })
923
+ };
924
+ return Ne(e.derivedData, t);
925
+ }
926
+ function Vn(e, n) {
927
+ const t = e.audioUnitSpec.encoding;
928
+ return {
929
+ pitch: n.length ? Ae("pitch", e.spec, t.pitch, e.scales.pitch, n) : void 0,
930
+ volume: Ae("volume", e.spec, t.volume, e.scales.volume, n),
931
+ duration: Ae("duration", e.spec, t.duration, e.scales.duration, n)
932
+ };
933
+ }
934
+ function Cn(e, n) {
935
+ const t = Object.entries(n).map(([r, a]) => a === e.fieldDomains[r].length - 1 ? 1 : 0).reverse();
936
+ let i = 0;
937
+ for (let r of t)
938
+ if (r)
939
+ i++;
940
+ else break;
941
+ return i;
942
+ }
943
+ function Rn(e) {
944
+ if (e.audioUnitSpec.traversal.length === 0)
945
+ return !1;
946
+ const n = e.audioUnitSpec.traversal[e.audioUnitSpec.traversal.length - 1].field, t = $(e.spec, n);
947
+ return t?.type === "quantitative" || t?.type === "temporal";
948
+ }
949
+ function In(e) {
950
+ const n = e.audioUnitSpec.traversal.map((r) => r.field), t = n.map((r) => Array.from({ length: e.fieldDomains[r].length }, (a, u) => u));
951
+ return tn(t).map((r) => {
952
+ const a = {};
953
+ return r.forEach((u, s) => {
954
+ a[n[s]] = u;
955
+ }), a;
956
+ });
957
+ }
958
+ function Ln(e, n, t, i) {
959
+ if (!t)
960
+ return !0;
961
+ if (i.bin || i.type === "nominal" || i.type === "ordinal")
962
+ return n[i.field] !== t[i.field];
963
+ const r = e.axisTicks[i.field] ?? [], a = $e(e, n), u = $e(e, t);
964
+ if (a.length && u.length) {
965
+ const s = pe(i), c = a[0][s], o = u[0][s];
966
+ if (c && o) {
967
+ const d = r.findIndex((f, p) => {
968
+ const h = f instanceof Date ? f.getTime() : f, w = r[p + 1], E = w instanceof Date ? w.getTime() : w;
969
+ return h && c >= h && c < (E || 1 / 0);
970
+ }), l = r.findIndex((f, p) => {
971
+ const h = f instanceof Date ? f.getTime() : f, w = r[p + 1], E = w instanceof Date ? w.getTime() : w;
972
+ return h && o >= h && o < (E || 1 / 0);
973
+ });
974
+ return d !== l;
975
+ }
976
+ }
977
+ return !1;
978
+ }
979
+ function jn(e, n, t) {
980
+ const i = [];
981
+ return Object.entries(n).forEach(([r]) => {
982
+ if (!e.fieldDomains[r].length) return;
983
+ const u = $(e.spec, r), s = N(u, Fe(e, r));
984
+ Ln(e, n, t, s) && i.push(G(ve(e, r, n[r]), s));
985
+ }), i.join(", ");
986
+ }
987
+ function bt(e) {
988
+ let n = 0;
989
+ const t = [], i = In(e), r = Rn(e);
990
+ let a;
991
+ return i.forEach((u) => {
992
+ const s = $e(e, u), c = Vn(e, s), o = Cn(e, u), d = e.pauseBetweenSections * o;
993
+ t.push({
994
+ ...c,
995
+ time: n,
996
+ pauseAfter: d,
997
+ ramp: r,
998
+ rest: s.length === 0,
999
+ state: u,
1000
+ speakBefore: jn(e, u, a)
1001
+ }), n += c.duration + d, a = u;
1002
+ }), t;
1003
+ }
1004
+ function qn(e) {
1005
+ if (!e.length) return [];
1006
+ const n = e[0].notes.length, t = [];
1007
+ let i = 0;
1008
+ for (let r = 0; r < n; r++) {
1009
+ const a = e.map((o) => ({ voiceId: o.voiceId, note: o.notes[r] })), u = Math.max(...a.map((o) => o.note.duration)), s = e[0].notes[r], c = s.pauseAfter ?? 0;
1010
+ t.push({
1011
+ state: s.state,
1012
+ time: i,
1013
+ slotDuration: u,
1014
+ pauseAfter: c,
1015
+ speakBefore: s.speakBefore,
1016
+ ramp: s.ramp,
1017
+ notes: a
1018
+ }), i += u + c;
1019
+ }
1020
+ return t;
1021
+ }
1022
+ function Et(e) {
1023
+ return Te(
1024
+ Object.entries(e.audioUnitSpec.encoding).map(([n, t]) => t ? `${H(N($(e.spec, t.field), t))} as ${n}` : "").filter((n) => n)
1025
+ );
1026
+ }
1027
+ function wt(e) {
1028
+ if (!e.audioUnitSpec.traversal.length)
1029
+ return "";
1030
+ const n = e.audioUnitSpec.traversal[e.audioUnitSpec.traversal.length - 1], t = $(e.spec, n.field), i = N(t, n);
1031
+ let r;
1032
+ i.bin ? r = un(i, e.derivedData) : r = e.fieldDomains[n.field];
1033
+ let a = "";
1034
+ r.length > 1 ? a = `${H(i)} from ${G(r[0], i)} to ${G(r[r.length - 1], i)}` : r.length === 1 ? a = `${H(i)} equals ${G(r[0], i)}` : a = H(i);
1035
+ const u = e.audioUnitSpec.traversal.slice(0, -1).map((s) => {
1036
+ const c = $(e.spec, s.field);
1037
+ return H(N(c, s));
1038
+ });
1039
+ return u.length && (a += ` for each ${Te(u)}`), a;
1040
+ }
1041
+ const Oe = W();
1042
+ function Mn(e) {
1043
+ const [n, t] = ie(), [i, r] = On(), [a, u] = ge(), [s, c] = Q(), [o, d] = C(), l = () => {
1044
+ const b = speechSynthesis.getVoices(), S = b.find((m) => m.name === "Samantha"), T = b.find((m) => m.localService && m.default), D = b.find((m) => m.default);
1045
+ d(S ?? T ?? D);
1046
+ };
1047
+ l(), speechSynthesis.addEventListener("voiceschanged", l), J(() => speechSynthesis.removeEventListener("voiceschanged", l));
1048
+ const f = () => ({
1049
+ traversalState: Object.fromEntries(e.audioUnitSpec.traversal.map((b) => [b.field, 0]))
1050
+ }), [p, h] = me(f()), w = _(() => _e(e.spec, e.audioUnitSpec)), E = _(() => a.selection ? Ne(e.data, a.selection) : e.data), L = _(() => Pe(e.spec, e.data, E(), w())), R = _(() => ke(E(), w(), L())), P = _(() => Object.fromEntries(e.audioUnitSpec.traversal.map((b) => {
1051
+ const S = $(e.spec, b.field), T = N(S, b), D = te(T, R(), !0);
1052
+ return [b.field, D];
1053
+ }))), I = _(() => Object.fromEntries(e.audioUnitSpec.traversal.map((b) => {
1054
+ const S = $(e.spec, b.field), T = N(S, b);
1055
+ return [b.field, r.getAxisTicks(T)];
1056
+ }))), B = _(() => ({
1057
+ spec: e.spec,
1058
+ audioUnitSpec: e.audioUnitSpec,
1059
+ derivedData: R(),
1060
+ fieldDomains: P(),
1061
+ axisTicks: I(),
1062
+ scales: i,
1063
+ pauseBetweenSections: s.pauseBetweenSections
1064
+ })), re = _(() => bt(B())), ae = (b, S) => ve(B(), b, S), se = _(() => St(B(), p.traversalState)), ye = (b) => re().find((S) => Object.entries(b).every(([T, D]) => S.state[T] === D));
1065
+ F(() => {
1066
+ if (s.isPlaying) {
1067
+ const b = se();
1068
+ t.setSelection({
1069
+ source: "sonification",
1070
+ predicate: b
1071
+ });
1072
+ }
1073
+ }), F((b) => {
1074
+ const S = P(), T = {
1075
+ ...p.traversalState
1076
+ };
1077
+ let D = !1;
1078
+ const m = {
1079
+ ...T
1080
+ };
1081
+ return Object.entries(S).forEach(([v, y]) => {
1082
+ const U = T[v], j = (b?.[v] ?? y)[U];
1083
+ if (j !== void 0) {
1084
+ const z = y.findIndex((oe) => oe === j);
1085
+ z !== U && (m[v] = z !== -1 ? z : 0, D = !0);
1086
+ }
1087
+ }), D && (h((v) => ({
1088
+ ...v,
1089
+ traversalState: m
1090
+ })), a.activeUnitName === e.audioUnitSpec.name && K.setupTransportSequence()), S;
1091
+ }), F((b) => (b !== e.audioUnitSpec && K.setupTransportSequence(), e.audioUnitSpec));
1092
+ const K = {
1093
+ setTraversalIndex: (b, S) => {
1094
+ c.stopTransport(), h((m) => ({
1095
+ ...m,
1096
+ traversalState: {
1097
+ ...m.traversalState,
1098
+ [b]: S
1099
+ }
1100
+ })), a.activeUnitName === e.audioUnitSpec.name && (u.setActiveUnit(e.audioUnitSpec.name), K.setupTransportSequence());
1101
+ const T = se();
1102
+ t.setSelection({
1103
+ source: "sonification",
1104
+ predicate: T
1105
+ });
1106
+ const D = ye(p.traversalState);
1107
+ D && (s.transport.seconds = D.time, c.playNote(D));
1108
+ },
1109
+ getTraversalIndex: (b) => p.traversalState[b],
1110
+ setupTransportSequence: () => {
1111
+ s.transport.cancel(), s.transport.bpm.value = ne;
1112
+ const b = re();
1113
+ b.forEach((S, T) => {
1114
+ Object.entries(S.state).every(([D, m]) => p.traversalState[D] === m) && (s.transport.seconds = S.time), s.transport.schedule(() => {
1115
+ if (s.isPlaying)
1116
+ if (h((D) => ({
1117
+ ...D,
1118
+ traversalState: S.state
1119
+ })), S.speakBefore && s.speakAxisTicks && !s.muted) {
1120
+ s.transport.pause(), c.releaseSynth(), speechSynthesis.cancel();
1121
+ const D = new SpeechSynthesisUtterance(S.speakBefore);
1122
+ D.voice = o() ?? null, D.rate = s.speechRate / 25, D.onend = () => {
1123
+ s.isPlaying && (S.ramp ? c.startOrRampSynth(S) : c.playNote(S), s.transport.start());
1124
+ }, speechSynthesis.speak(D);
1125
+ } else
1126
+ S.ramp ? c.startOrRampSynth(S) : c.playNote(S);
1127
+ }, S.time), S.pauseAfter && s.transport.schedule(() => {
1128
+ c.releaseSynth();
1129
+ }, S.time + S.duration), T === b.length - 1 && s.transport.schedule(() => {
1130
+ c.stopTransport();
1131
+ }, S.time + S.duration);
1132
+ }), s.transport.bpm.value = ne * s.playbackRate;
1133
+ },
1134
+ getFieldDomains: P,
1135
+ getDerivedData: R,
1136
+ resetTraversalIfEnd: () => {
1137
+ const b = e.audioUnitSpec.traversal.map((D) => D.field), S = p.traversalState;
1138
+ b.every((D) => S[D] === P()[D].length - 1) && (h(f()), s.transport.seconds = 0);
1139
+ },
1140
+ getDomainValue: ae,
1141
+ describeEncodings: () => Et(B()),
1142
+ describePlaybackOrder: () => wt(B())
1143
+ };
1144
+ return g(Oe.Provider, {
1145
+ value: [p, K],
1146
+ get children() {
1147
+ return e.children;
1148
+ }
1149
+ });
1150
+ }
1151
+ function he() {
1152
+ const e = Z(Oe);
1153
+ if (e === void 0)
1154
+ throw new Error("useAudioUnitState must be used within a AudioUnitStateProvider");
1155
+ return e;
1156
+ }
1157
+ const Dt = x("div")`
1158
+ margin-bottom: 3px;
1159
+
1160
+ label {
1161
+ display: grid;
1162
+ grid-template-columns: 25% auto;
1163
+ align-items: center;
1164
+ gap: 1rem;
1165
+ }
1166
+
1167
+ label > * {
1168
+ justify-self: start;
1169
+ }
1170
+ `, Ve = `
1171
+ font-family: monospace;
1172
+ `, Ut = x("div")`
1173
+ border-left: 1px solid #ccc;
1174
+ padding-left: 1rem;
1175
+ `;
1176
+ x("form")`
1177
+ display: flex;
1178
+ gap: 8px;
1179
+ margin-bottom: 8px;
1180
+ `;
1181
+ x("input")`
1182
+ flex: 1;
1183
+ `;
1184
+ x("div")`
1185
+ color: red;
1186
+ font-size: 14px;
1187
+ `;
1188
+ x("div")`
1189
+ margin-top: 0.5rem;
1190
+ display: grid;
1191
+ grid-template-columns: 25% auto;
1192
+ gap: 1rem;
1193
+
1194
+ h5 {
1195
+ margin: 0;
1196
+ }
1197
+ `;
1198
+ x("div")`
1199
+ > * {
1200
+ margin-bottom: 3px;
1201
+ }
1202
+ `;
1203
+ x("div")`
1204
+ display: flex;
1205
+ gap: 3px;
1206
+ `;
1207
+ x("div")`
1208
+ margin-top: 1em;
1209
+ `;
1210
+ x("h4")`
1211
+ ${Ve}
1212
+ `;
1213
+ x("div")`
1214
+ ${Ve}
1215
+ `;
1216
+ x("table")`
1217
+ border: 1px solid #ccc;
1218
+ ${Ve}
1219
+ `;
1220
+ x("button")`
1221
+ margin-top: 1rem;
1222
+ `;
1223
+ x("div")`
1224
+ display: flex;
1225
+ align-items: center;
1226
+ gap: 8px;
1227
+ `;
1228
+ var Bn = /* @__PURE__ */ A("<select>"), zn = /* @__PURE__ */ A("<div><input aria-live=assertive type=range min=0><span>"), Gn = /* @__PURE__ */ A("<label><span>"), Kn = /* @__PURE__ */ A("<option>");
1229
+ function At(e) {
1230
+ const [n, t] = he(), [i, r] = Q(), a = () => $(e.spec, e.traversalFieldDef.field), u = () => N(a(), e.traversalFieldDef), s = () => t.getTraversalIndex(e.traversalFieldDef.field), c = (l) => {
1231
+ r.startAudioContext(), t.setTraversalIndex(e.traversalFieldDef.field, l);
1232
+ }, o = () => t.getFieldDomains()[e.traversalFieldDef.field], d = () => t.getDomainValue(e.traversalFieldDef.field, s());
1233
+ return g(Dt, {
1234
+ get children() {
1235
+ var l = Gn(), f = l.firstChild;
1236
+ return k(f, () => H(u())), k(l, g(Pt, {
1237
+ get children() {
1238
+ return [g(Ie, {
1239
+ get when() {
1240
+ return u().type === "nominal";
1241
+ },
1242
+ get children() {
1243
+ var p = Bn();
1244
+ return p.$$mousedown = () => r.stopTransport(), p.addEventListener("change", (h) => c(h.target.selectedIndex)), k(p, g(ee, {
1245
+ get each() {
1246
+ return o();
1247
+ },
1248
+ children: (h) => (() => {
1249
+ var w = Kn();
1250
+ return k(w, () => String(h)), q(() => w.value = String(h)), w;
1251
+ })()
1252
+ })), q(() => p.value = String(d())), p;
1253
+ }
1254
+ }), g(Ie, {
1255
+ get when() {
1256
+ return u().type !== "nominal";
1257
+ },
1258
+ get children() {
1259
+ var p = zn(), h = p.firstChild, w = h.nextSibling;
1260
+ return h.$$mousedown = () => r.stopTransport(), h.$$input = (E) => c(E.currentTarget.valueAsNumber), k(w, () => G(d(), u())), q((E) => {
1261
+ var L = G(d(), u()), R = o().length - 1;
1262
+ return L !== E.e && Re(h, "aria-valuetext", E.e = L), R !== E.t && Re(h, "max", E.t = R), E;
1263
+ }, {
1264
+ e: void 0,
1265
+ t: void 0
1266
+ }), q(() => h.value = s()), p;
1267
+ }
1268
+ })];
1269
+ }
1270
+ }), null), l;
1271
+ }
1272
+ });
1273
+ }
1274
+ We(["mousedown", "input"]);
1275
+ var Hn = /* @__PURE__ */ A("<button>Pause"), Jn = /* @__PURE__ */ A("<div>"), Yn = /* @__PURE__ */ A("<button>Play");
1276
+ function $t(e) {
1277
+ const [n, t] = he(), [i, r] = Q(), [a, u] = ge();
1278
+ function s() {
1279
+ r.startAudioContext(), a.activeUnitName !== e.unitName && (u.setActiveUnit(e.unitName), t.setupTransportSequence()), t.resetTraversalIfEnd(), r.startTransport();
1280
+ }
1281
+ return Ze(() => u.registerPlayCallback(s)), F(() => {
1282
+ a.activeUnitName === e.unitName && u.registerPlayCallback(s, !0);
1283
+ }), (() => {
1284
+ var c = Jn();
1285
+ return k(c, g(Qe, {
1286
+ get when() {
1287
+ return le(() => !!i.isPlaying)() && a.activeUnitName === e.unitName;
1288
+ },
1289
+ get fallback() {
1290
+ return (() => {
1291
+ var o = Yn();
1292
+ return o.$$click = () => s(), o;
1293
+ })();
1294
+ },
1295
+ get children() {
1296
+ var o = Hn();
1297
+ return o.$$click = () => r.stopTransport(), o;
1298
+ }
1299
+ })), c;
1300
+ })();
1301
+ }
1302
+ We(["click"]);
1303
+ var Xn = /* @__PURE__ */ A("<label> <input readonly>"), Wn = /* @__PURE__ */ A("<p><br>playing ");
1304
+ const Zn = x.div`
1305
+ margin-bottom: 1em;
1306
+ `;
1307
+ function Qn(e) {
1308
+ function n() {
1309
+ return g(Zn, {
1310
+ get children() {
1311
+ return g(ee, {
1312
+ get each() {
1313
+ return Object.entries(e.audioUnitSpec.encoding);
1314
+ },
1315
+ children: ([i, r]) => {
1316
+ if (r) {
1317
+ const a = $(e.spec, r.field);
1318
+ if (a) {
1319
+ const u = N(a, r);
1320
+ return g(Dt, {
1321
+ get children() {
1322
+ var s = Xn(), c = s.firstChild, o = c.nextSibling;
1323
+ return k(s, i, c), q(() => o.value = H(u)), s;
1324
+ }
1325
+ });
1326
+ }
1327
+ }
1328
+ }
1329
+ });
1330
+ }
1331
+ });
1332
+ }
1333
+ function t() {
1334
+ const [i, r] = he();
1335
+ return (() => {
1336
+ var a = Wn(), u = a.firstChild;
1337
+ return u.nextSibling, k(a, () => r.describeEncodings(), u), k(a, () => r.describePlaybackOrder(), null), a;
1338
+ })();
1339
+ }
1340
+ return Object.keys(e.audioUnitSpec.encoding).length === 0 ? null : g(Ut, {
1341
+ get children() {
1342
+ return g(Fn, {
1343
+ get spec() {
1344
+ return e.spec;
1345
+ },
1346
+ get data() {
1347
+ return e.data;
1348
+ },
1349
+ get audioUnitSpec() {
1350
+ return e.audioUnitSpec;
1351
+ },
1352
+ get children() {
1353
+ return g(Mn, {
1354
+ get spec() {
1355
+ return e.spec;
1356
+ },
1357
+ get data() {
1358
+ return e.data;
1359
+ },
1360
+ get audioUnitSpec() {
1361
+ return e.audioUnitSpec;
1362
+ },
1363
+ get children() {
1364
+ return [g(t, {}), g(n, {}), g(ee, {
1365
+ get each() {
1366
+ return e.audioUnitSpec.traversal;
1367
+ },
1368
+ children: (i) => g(At, {
1369
+ get spec() {
1370
+ return e.spec;
1371
+ },
1372
+ traversalFieldDef: i
1373
+ })
1374
+ }), g($t, {
1375
+ get unitName() {
1376
+ return e.audioUnitSpec.name;
1377
+ }
1378
+ })];
1379
+ }
1380
+ });
1381
+ }
1382
+ });
1383
+ }
1384
+ });
1385
+ }
1386
+ function ei(e) {
1387
+ const [n, t] = ie(), [i, r] = ge(), [a, u] = Q(), [s, c] = C(), o = () => {
1388
+ const m = speechSynthesis.getVoices(), v = m.find((O) => O.name === "Samantha"), y = m.find((O) => O.localService && O.default), U = m.find((O) => O.default);
1389
+ c(v ?? y ?? U);
1390
+ };
1391
+ o(), speechSynthesis.addEventListener("voiceschanged", o), J(() => speechSynthesis.removeEventListener("voiceschanged", o));
1392
+ const d = () => e.units[0], l = () => d().traversal, f = () => ({
1393
+ traversalState: Object.fromEntries(l().map((m) => [m.field, 0]))
1394
+ }), [p, h] = me(f()), w = _(() => {
1395
+ const m = i.selection;
1396
+ return e.units.map((v) => {
1397
+ const y = _e(e.spec, v), U = m ? Ne(e.data, m) : e.data, O = Pe(e.spec, e.data, U, y), j = ke(U, y, O), z = ht(e.spec, e.data, v);
1398
+ return {
1399
+ unit: v,
1400
+ derivedData: j,
1401
+ scales: z
1402
+ };
1403
+ });
1404
+ }), E = _(() => {
1405
+ const m = w().flatMap((v) => v.derivedData);
1406
+ return Object.fromEntries(l().map((v) => {
1407
+ const y = $(e.spec, v.field), U = N(y, v);
1408
+ return [v.field, te(U, m, !0)];
1409
+ }));
1410
+ }), L = _(() => Object.fromEntries(l().map((m) => [m.field, yt(e.spec, e.data, m.field)]))), R = (m, v, y) => ({
1411
+ spec: e.spec,
1412
+ audioUnitSpec: m,
1413
+ derivedData: v,
1414
+ fieldDomains: E(),
1415
+ axisTicks: L(),
1416
+ scales: y,
1417
+ pauseBetweenSections: a.pauseBetweenSections
1418
+ }), P = _(() => {
1419
+ const m = w()[0];
1420
+ return R(m.unit, m.derivedData, m.scales);
1421
+ }), I = _(() => w().map((m, v) => ({
1422
+ voiceId: m.unit.name,
1423
+ oscType: _n(v),
1424
+ notes: bt(R(m.unit, m.derivedData, m.scales))
1425
+ }))), B = _(() => qn(I().map((m) => ({
1426
+ voiceId: m.voiceId,
1427
+ notes: m.notes
1428
+ })))), re = (m) => B().find((v) => Object.entries(m).every(([y, U]) => v.state[y] === U)), ae = _(() => St(P(), p.traversalState)), se = () => E(), ye = (m, v) => ve(P(), m, v), K = () => i.activeUnitName === e.groupName;
1429
+ F(() => {
1430
+ a.isPlaying && t.setSelection({
1431
+ source: "sonification",
1432
+ predicate: ae()
1433
+ });
1434
+ }), F((m) => {
1435
+ const v = E(), y = {
1436
+ ...p.traversalState
1437
+ };
1438
+ let U = !1;
1439
+ const O = {
1440
+ ...y
1441
+ };
1442
+ return Object.entries(v).forEach(([j, z]) => {
1443
+ const oe = y[j], Ce = (m?.[j] ?? z)[oe];
1444
+ if (Ce !== void 0) {
1445
+ const Se = z.findIndex((kt) => kt === Ce);
1446
+ Se !== oe && (O[j] = Se !== -1 ? Se : 0, U = !0);
1447
+ }
1448
+ }), U && (h((j) => ({
1449
+ ...j,
1450
+ traversalState: O
1451
+ })), K() && D.setupTransportSequence()), v;
1452
+ }), F((m) => (m !== e.units && D.setupTransportSequence(), e.units));
1453
+ const b = () => I().forEach(({
1454
+ voiceId: m,
1455
+ oscType: v
1456
+ }) => u.ensureVoice(m, v)), S = (m) => {
1457
+ m.notes.forEach(({
1458
+ voiceId: v,
1459
+ note: y
1460
+ }) => {
1461
+ m.ramp ? u.startOrRampSynth(y, v) : u.playNote(y, v);
1462
+ });
1463
+ }, T = (m) => {
1464
+ m.notes.forEach(({
1465
+ voiceId: v,
1466
+ note: y
1467
+ }) => u.playNote(y, v));
1468
+ }, D = {
1469
+ setTraversalIndex: (m, v) => {
1470
+ u.stopTransport(), h((U) => ({
1471
+ ...U,
1472
+ traversalState: {
1473
+ ...U.traversalState,
1474
+ [m]: v
1475
+ }
1476
+ })), K() && (r.setActiveUnit(e.groupName), D.setupTransportSequence()), t.setSelection({
1477
+ source: "sonification",
1478
+ predicate: ae()
1479
+ }), b();
1480
+ const y = re(p.traversalState);
1481
+ y && (a.transport.seconds = y.time, T(y));
1482
+ },
1483
+ getTraversalIndex: (m) => p.traversalState[m],
1484
+ getFieldDomains: se,
1485
+ getDerivedData: () => P().derivedData,
1486
+ getDomainValue: ye,
1487
+ setupTransportSequence: () => {
1488
+ a.transport.cancel(), a.transport.bpm.value = ne, b();
1489
+ const m = B();
1490
+ m.forEach((y) => {
1491
+ Object.entries(y.state).every(([U, O]) => p.traversalState[U] === O) && (a.transport.seconds = y.time), a.transport.schedule(() => {
1492
+ if (a.isPlaying)
1493
+ if (h((U) => ({
1494
+ ...U,
1495
+ traversalState: y.state
1496
+ })), y.speakBefore && a.speakAxisTicks && !a.muted) {
1497
+ a.transport.pause(), u.releaseSynth(), speechSynthesis.cancel();
1498
+ const U = new SpeechSynthesisUtterance(y.speakBefore);
1499
+ U.voice = s() ?? null, U.rate = a.speechRate / 25, U.onend = () => {
1500
+ a.isPlaying && (S(y), a.transport.start());
1501
+ }, speechSynthesis.speak(U);
1502
+ } else
1503
+ S(y);
1504
+ }, y.time), y.pauseAfter && a.transport.schedule(() => u.releaseSynth(), y.time + y.slotDuration);
1505
+ });
1506
+ const v = m[m.length - 1];
1507
+ v && a.transport.schedule(() => u.stopTransport(), v.time + v.slotDuration), a.transport.bpm.value = ne * a.playbackRate;
1508
+ },
1509
+ resetTraversalIfEnd: () => {
1510
+ const m = E();
1511
+ l().every((y) => p.traversalState[y.field] === m[y.field].length - 1) && (h(f()), a.transport.seconds = 0);
1512
+ },
1513
+ describeEncodings: () => e.units.map((m, v) => `layer ${v + 1}: ${Et(R(m, w()[v].derivedData, w()[v].scales))}`).join("; "),
1514
+ describePlaybackOrder: () => wt(P())
1515
+ };
1516
+ return g(Oe.Provider, {
1517
+ value: [p, D],
1518
+ get children() {
1519
+ return e.children;
1520
+ }
1521
+ });
1522
+ }
1523
+ var ti = /* @__PURE__ */ A("<p><br>playing ");
1524
+ const Ye = "layer-group";
1525
+ function ni() {
1526
+ const [e, n] = he();
1527
+ return (() => {
1528
+ var t = ti(), i = t.firstChild;
1529
+ return i.nextSibling, k(t, () => n.describeEncodings(), i), k(t, () => n.describePlaybackOrder(), null), t;
1530
+ })();
1531
+ }
1532
+ function ii(e) {
1533
+ const n = () => e.units.filter((i) => Object.keys(i.encoding).length > 0);
1534
+ if (n().length === 0)
1535
+ return null;
1536
+ const t = () => n()[0].traversal;
1537
+ return g(Ut, {
1538
+ get children() {
1539
+ return g(ei, {
1540
+ get spec() {
1541
+ return e.spec;
1542
+ },
1543
+ get data() {
1544
+ return e.data;
1545
+ },
1546
+ get units() {
1547
+ return n();
1548
+ },
1549
+ groupName: Ye,
1550
+ get children() {
1551
+ return [g(ni, {}), g(ee, {
1552
+ get each() {
1553
+ return t();
1554
+ },
1555
+ children: (i) => g(At, {
1556
+ get spec() {
1557
+ return e.spec;
1558
+ },
1559
+ traversalFieldDef: i
1560
+ })
1561
+ }), g($t, {
1562
+ unitName: Ye
1563
+ })];
1564
+ }
1565
+ });
1566
+ }
1567
+ });
1568
+ }
1569
+ var ri = /* @__PURE__ */ A("<div><label>Playback rate <input type=number min=0.1 max=4 step=0.1 id=rate>x"), ai = /* @__PURE__ */ A("<label><input type=checkbox>Speak axis ticks"), si = /* @__PURE__ */ A("<label><input type=number min=1 max=100 step=10 id=speechRate>speech rate"), oi = /* @__PURE__ */ A("<div><label><input type=checkbox aria-live=polite>");
1570
+ const ci = x.div`
1571
+ margin-top: 1rem;
1572
+ `, li = x.div`
1573
+ display: flex;
1574
+ gap: 3px;
1575
+ `;
1576
+ function ui(e) {
1577
+ const [n, t] = Q();
1578
+ return g(ci, {
1579
+ get children() {
1580
+ return [(() => {
1581
+ var i = ri(), r = i.firstChild, a = r.firstChild, u = a.nextSibling;
1582
+ return u.addEventListener("change", (s) => t.setPlaybackRate(Number(s.target.value))), q(() => u.value = n.playbackRate), i;
1583
+ })(), g(li, {
1584
+ get children() {
1585
+ return [(() => {
1586
+ var i = ai(), r = i.firstChild;
1587
+ return r.addEventListener("change", (a) => t.setSpeakAxisTicks(a.target.checked)), q(() => r.checked = n.speakAxisTicks), i;
1588
+ })(), (() => {
1589
+ var i = si(), r = i.firstChild;
1590
+ return r.addEventListener("change", (a) => t.setSpeechRate(Number(a.target.value))), q(() => r.value = n.speechRate), i;
1591
+ })()];
1592
+ }
1593
+ }), (() => {
1594
+ var i = oi(), r = i.firstChild, a = r.firstChild;
1595
+ return a.addEventListener("change", (u) => t.setMuted(u.target.checked)), k(r, () => n.muted ? "Muted" : "Unmuted", null), q(() => a.checked = n.muted), i;
1596
+ })()];
1597
+ }
1598
+ });
1599
+ }
1600
+ function di() {
1601
+ const e = document.activeElement;
1602
+ if (!e) return !1;
1603
+ const n = e.tagName.toLowerCase();
1604
+ return n === "input" || n === "select" || n === "textarea" || e.isContentEditable;
1605
+ }
1606
+ function fi(e) {
1607
+ const n = (t) => {
1608
+ if (di()) return;
1609
+ const i = e[t.key];
1610
+ i && (t.preventDefault(), i());
1611
+ };
1612
+ Ze(() => document.addEventListener("keydown", n)), J(() => document.removeEventListener("keydown", n));
1613
+ }
1614
+ function mi() {
1615
+ const [e, n] = Q(), [t, i] = ge();
1616
+ return fi({
1617
+ p: () => {
1618
+ e.isPlaying ? n.stopTransport() : i.triggerPlay();
1619
+ }
1620
+ }), null;
1621
+ }
1622
+ function pi(e) {
1623
+ const n = () => e.spec.audio.composition === "layer" && e.spec.audio.units.length > 1;
1624
+ return g($n, {
1625
+ get children() {
1626
+ return g(Nn, {
1627
+ get children() {
1628
+ return [g(mi, {}), g(Qe, {
1629
+ get when() {
1630
+ return n();
1631
+ },
1632
+ get fallback() {
1633
+ return g(ee, {
1634
+ get each() {
1635
+ return e.spec.audio.units;
1636
+ },
1637
+ children: (t) => g(Qn, {
1638
+ get spec() {
1639
+ return e.spec;
1640
+ },
1641
+ get data() {
1642
+ return e.data;
1643
+ },
1644
+ audioUnitSpec: t
1645
+ })
1646
+ });
1647
+ },
1648
+ get children() {
1649
+ return g(ii, {
1650
+ get spec() {
1651
+ return e.spec;
1652
+ },
1653
+ get data() {
1654
+ return e.data;
1655
+ },
1656
+ get units() {
1657
+ return e.spec.audio.units;
1658
+ }
1659
+ });
1660
+ }
1661
+ }), g(ui, {})];
1662
+ }
1663
+ });
1664
+ }
1665
+ });
1666
+ }
1667
+ var gi = /* @__PURE__ */ A("<h2>Visualization"), vi = /* @__PURE__ */ A("<h2>Description"), hi = /* @__PURE__ */ A("<h2>Sonification"), yi = /* @__PURE__ */ A('<div><div class=uw-viewer role=region aria-label="Umwelt Viewer">');
1668
+ function Si(e) {
1669
+ return (() => {
1670
+ var n = yi(), t = n.firstChild;
1671
+ return k(t, g(En, {
1672
+ get children() {
1673
+ return [gi(), g(Dn, {
1674
+ get spec() {
1675
+ return e.spec;
1676
+ },
1677
+ get data() {
1678
+ return e.data;
1679
+ }
1680
+ }), vi(), g(An, {
1681
+ get spec() {
1682
+ return e.spec;
1683
+ },
1684
+ get data() {
1685
+ return e.data;
1686
+ }
1687
+ }), hi(), g(pi, {
1688
+ get spec() {
1689
+ return e.spec;
1690
+ },
1691
+ get data() {
1692
+ return e.data;
1693
+ }
1694
+ })];
1695
+ }
1696
+ })), q(() => _t(n, rn.Viewer)), n;
1697
+ })();
1698
+ }
1699
+ function Xe(e, n, t = localStorage) {
1700
+ const i = t.getItem(e) ? JSON.parse(t.getItem(e)) : n, [r, a] = C(i);
1701
+ return [r, ((s) => {
1702
+ if (s) {
1703
+ const c = a(s);
1704
+ return t.setItem(e, JSON.stringify(c)), c;
1705
+ }
1706
+ })];
1707
+ }
1708
+ const Tt = W();
1709
+ function bi(e) {
1710
+ const n = e.persist !== !1, [t, i] = n ? Xe("umweltDatastore", {}) : C({}), [r, a] = n ? Xe("umweltSessionDatastore", {}, sessionStorage) : C({}), u = () => ({
1711
+ ...t(),
1712
+ ...r()
1713
+ }), s = {
1714
+ setDataset: (c, o, d, l) => {
1715
+ l?.session ? a((f) => ({
1716
+ ...f,
1717
+ [c]: {
1718
+ data: o,
1719
+ sourceUrl: d
1720
+ }
1721
+ })) : i((f) => ({
1722
+ ...f,
1723
+ [c]: {
1724
+ data: o,
1725
+ sourceUrl: f[c]?.sourceUrl || d
1726
+ }
1727
+ }));
1728
+ },
1729
+ removeDataset: (c) => {
1730
+ i((o) => {
1731
+ const d = {
1732
+ ...o
1733
+ };
1734
+ return delete d[c], d;
1735
+ }), s.removeSessionDataset(c);
1736
+ },
1737
+ removeSessionDataset: (c) => {
1738
+ a((o) => {
1739
+ const d = {
1740
+ ...o
1741
+ };
1742
+ return delete d[c], d;
1743
+ });
1744
+ }
1745
+ };
1746
+ return g(Tt.Provider, {
1747
+ value: [u, s],
1748
+ get children() {
1749
+ return e.children;
1750
+ }
1751
+ });
1752
+ }
1753
+ function Ei() {
1754
+ const e = Z(Tt);
1755
+ if (e === void 0)
1756
+ throw new Error("useUmweltDatastore must be used within a UmweltDatastoreProvider");
1757
+ return e;
1758
+ }
1759
+ var wi = /* @__PURE__ */ A("<div>"), Di = /* @__PURE__ */ A("<div>Loading..."), Ui = /* @__PURE__ */ A("<div role=alert>");
1760
+ function Ai(e) {
1761
+ const [n, t] = Ei(), [i, r] = C(), [a, u] = C(!0), [s, c] = C(), o = () => {
1762
+ const d = i();
1763
+ return d ? n()[d.data.name]?.data || [] : [];
1764
+ };
1765
+ return F(async () => {
1766
+ const d = e.exportableSpec;
1767
+ u(!0), c(void 0);
1768
+ try {
1769
+ const l = await vn(d, n(), t.setDataset);
1770
+ l ? r(l) : c("Failed to load Umwelt spec: the spec is invalid or its data source could not be resolved.");
1771
+ } catch (l) {
1772
+ console.error("Error loading spec:", l), c(`Failed to load Umwelt spec: ${l}`);
1773
+ } finally {
1774
+ u(!1);
1775
+ }
1776
+ }), (() => {
1777
+ var d = wi();
1778
+ return k(d, (() => {
1779
+ var l = le(() => !!a());
1780
+ return () => l() && Di();
1781
+ })(), null), k(d, (() => {
1782
+ var l = le(() => !!(!a() && s()));
1783
+ return () => l() && (() => {
1784
+ var f = Ui();
1785
+ return k(f, s), f;
1786
+ })();
1787
+ })(), null), k(d, (() => {
1788
+ var l = le(() => !!(!a() && !s() && i()));
1789
+ return () => l() && g(Si, {
1790
+ get spec() {
1791
+ return i();
1792
+ },
1793
+ get data() {
1794
+ return o();
1795
+ }
1796
+ });
1797
+ })(), null), d;
1798
+ })();
1799
+ }
1800
+ function $i(e) {
1801
+ return g(bi, {
1802
+ persist: !1,
1803
+ get children() {
1804
+ return g(Ai, {
1805
+ get exportableSpec() {
1806
+ return e.exportableSpec;
1807
+ }
1808
+ });
1809
+ }
1810
+ });
1811
+ }
1812
+ class Ti {
1813
+ constructor(n) {
1814
+ this.options = n, this.mount();
1815
+ }
1816
+ disposal;
1817
+ isDestroyed = !1;
1818
+ mount() {
1819
+ if (this.isDestroyed)
1820
+ throw new Error("Cannot mount a destroyed UmweltViewer. Create a new instance.");
1821
+ this.disposal = Nt(() => $i({ exportableSpec: this.options.spec }), this.options.container);
1822
+ }
1823
+ /**
1824
+ * Update the viewer with a new specification.
1825
+ * This will re-render the entire viewer with the new data and configuration.
1826
+ */
1827
+ updateSpec(n) {
1828
+ if (this.isDestroyed)
1829
+ throw new Error("Cannot update a destroyed UmweltViewer.");
1830
+ this.cleanup(), this.options.spec = n, this.mount();
1831
+ }
1832
+ /**
1833
+ * Get the current specification.
1834
+ */
1835
+ getSpec() {
1836
+ return this.options.spec;
1837
+ }
1838
+ /**
1839
+ * Get the container element.
1840
+ */
1841
+ getContainer() {
1842
+ return this.options.container;
1843
+ }
1844
+ cleanup() {
1845
+ this.disposal && (this.disposal(), this.disposal = void 0);
1846
+ }
1847
+ /**
1848
+ * Destroy the viewer and clean up all resources.
1849
+ * The viewer cannot be used after calling this method.
1850
+ */
1851
+ destroy() {
1852
+ this.cleanup(), this.isDestroyed = !0;
1853
+ }
1854
+ /**
1855
+ * Check if the viewer has been destroyed.
1856
+ */
1857
+ getIsDestroyed() {
1858
+ return this.isDestroyed;
1859
+ }
1860
+ }
1861
+ function Xi(e, n) {
1862
+ return new Ti({ spec: e, container: n });
1863
+ }
1864
+ export {
1865
+ Ti as UmweltViewer,
1866
+ Xi as createViewer
1867
+ };