@jant/core 0.2.4 → 0.2.6

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.
@@ -0,0 +1,3434 @@
1
+ function ze(t) {
2
+ return t instanceof HTMLElement || t instanceof SVGElement ? t : null;
3
+ }
4
+ function ue() {
5
+ throw new Error("Cycle detected");
6
+ }
7
+ function Et() {
8
+ throw new Error("Computed cannot have side-effects");
9
+ }
10
+ const _t = Symbol.for("preact-signals"), O = 1, B = 2, Y = 4, W = 8, J = 16, H = 32;
11
+ function fe() {
12
+ G++;
13
+ }
14
+ function de() {
15
+ if (G > 1) {
16
+ G--;
17
+ return;
18
+ }
19
+ let t, e = false;
20
+ for (; K !== void 0; ) {
21
+ let s = K;
22
+ for (K = void 0, we++; s !== void 0; ) {
23
+ const n = s._nextBatchedEffect;
24
+ if (s._nextBatchedEffect = void 0, s._flags &= ~B, !(s._flags & W) && Qe(s))
25
+ try {
26
+ s._callback();
27
+ } catch (r) {
28
+ e || (t = r, e = true);
29
+ }
30
+ s = n;
31
+ }
32
+ }
33
+ if (we = 0, G--, e)
34
+ throw t;
35
+ }
36
+ function St(t) {
37
+ if (G > 0)
38
+ return t();
39
+ fe();
40
+ try {
41
+ return t();
42
+ } finally {
43
+ de();
44
+ }
45
+ }
46
+ let _, K, G = 0, we = 0, le = 0;
47
+ function Ze(t) {
48
+ if (_ === void 0)
49
+ return;
50
+ let e = t._node;
51
+ if (e === void 0 || e._target !== _)
52
+ return e = {
53
+ _version: 0,
54
+ _source: t,
55
+ _prevSource: _._sources,
56
+ _nextSource: void 0,
57
+ _target: _,
58
+ _prevTarget: void 0,
59
+ _nextTarget: void 0,
60
+ _rollbackNode: e
61
+ }, _._sources !== void 0 && (_._sources._nextSource = e), _._sources = e, t._node = e, _._flags & H && t._subscribe(e), e;
62
+ if (e._version === -1)
63
+ return e._version = 0, e._nextSource !== void 0 && (e._nextSource._prevSource = e._prevSource, e._prevSource !== void 0 && (e._prevSource._nextSource = e._nextSource), e._prevSource = _._sources, e._nextSource = void 0, _._sources._nextSource = e, _._sources = e), e;
64
+ }
65
+ function T(t) {
66
+ this._value = t, this._version = 0, this._node = void 0, this._targets = void 0;
67
+ }
68
+ T.prototype.brand = _t;
69
+ T.prototype._refresh = function() {
70
+ return true;
71
+ };
72
+ T.prototype._subscribe = function(t) {
73
+ this._targets !== t && t._prevTarget === void 0 && (t._nextTarget = this._targets, this._targets !== void 0 && (this._targets._prevTarget = t), this._targets = t);
74
+ };
75
+ T.prototype._unsubscribe = function(t) {
76
+ if (this._targets !== void 0) {
77
+ const e = t._prevTarget, s = t._nextTarget;
78
+ e !== void 0 && (e._nextTarget = s, t._prevTarget = void 0), s !== void 0 && (s._prevTarget = e, t._nextTarget = void 0), t === this._targets && (this._targets = s);
79
+ }
80
+ };
81
+ T.prototype.subscribe = function(t) {
82
+ const e = this;
83
+ return nt(function() {
84
+ const s = e.value, n = this._flags & H;
85
+ this._flags &= ~H;
86
+ try {
87
+ t(s);
88
+ } finally {
89
+ this._flags |= n;
90
+ }
91
+ });
92
+ };
93
+ T.prototype.valueOf = function() {
94
+ return this.value;
95
+ };
96
+ T.prototype.toString = function() {
97
+ return this.value + "";
98
+ };
99
+ T.prototype.toJSON = function() {
100
+ return this.value;
101
+ };
102
+ T.prototype.peek = function() {
103
+ return this._value;
104
+ };
105
+ Object.defineProperty(T.prototype, "value", {
106
+ get() {
107
+ const t = Ze(this);
108
+ return t !== void 0 && (t._version = this._version), this._value;
109
+ },
110
+ set(t) {
111
+ if (_ instanceof R && Et(), t !== this._value) {
112
+ we > 100 && ue(), this._value = t, this._version++, le++, fe();
113
+ try {
114
+ for (let e = this._targets; e !== void 0; e = e._nextTarget)
115
+ e._target._notify();
116
+ } finally {
117
+ de();
118
+ }
119
+ }
120
+ }
121
+ });
122
+ function Xe(t) {
123
+ return new T(t);
124
+ }
125
+ function Qe(t) {
126
+ for (let e = t._sources; e !== void 0; e = e._nextSource)
127
+ if (e._source._version !== e._version || !e._source._refresh() || e._source._version !== e._version)
128
+ return true;
129
+ return false;
130
+ }
131
+ function et(t) {
132
+ for (let e = t._sources; e !== void 0; e = e._nextSource) {
133
+ const s = e._source._node;
134
+ if (s !== void 0 && (e._rollbackNode = s), e._source._node = e, e._version = -1, e._nextSource === void 0) {
135
+ t._sources = e;
136
+ break;
137
+ }
138
+ }
139
+ }
140
+ function tt(t) {
141
+ let e = t._sources, s;
142
+ for (; e !== void 0; ) {
143
+ const n = e._prevSource;
144
+ e._version === -1 ? (e._source._unsubscribe(e), n !== void 0 && (n._nextSource = e._nextSource), e._nextSource !== void 0 && (e._nextSource._prevSource = n)) : s = e, e._source._node = e._rollbackNode, e._rollbackNode !== void 0 && (e._rollbackNode = void 0), e = n;
145
+ }
146
+ t._sources = s;
147
+ }
148
+ function R(t) {
149
+ T.call(this, void 0), this._compute = t, this._sources = void 0, this._globalVersion = le - 1, this._flags = Y;
150
+ }
151
+ R.prototype = new T();
152
+ R.prototype._refresh = function() {
153
+ if (this._flags &= ~B, this._flags & O)
154
+ return false;
155
+ if ((this._flags & (Y | H)) === H || (this._flags &= ~Y, this._globalVersion === le))
156
+ return true;
157
+ if (this._globalVersion = le, this._flags |= O, this._version > 0 && !Qe(this))
158
+ return this._flags &= ~O, true;
159
+ const t = _;
160
+ try {
161
+ et(this), _ = this;
162
+ const e = this._compute();
163
+ (this._flags & J || this._value !== e || this._version === 0) && (this._value = e, this._flags &= ~J, this._version++);
164
+ } catch (e) {
165
+ this._value = e, this._flags |= J, this._version++;
166
+ }
167
+ return _ = t, tt(this), this._flags &= ~O, true;
168
+ };
169
+ R.prototype._subscribe = function(t) {
170
+ if (this._targets === void 0) {
171
+ this._flags |= Y | H;
172
+ for (let e = this._sources; e !== void 0; e = e._nextSource)
173
+ e._source._subscribe(e);
174
+ }
175
+ T.prototype._subscribe.call(this, t);
176
+ };
177
+ R.prototype._unsubscribe = function(t) {
178
+ if (this._targets !== void 0 && (T.prototype._unsubscribe.call(this, t), this._targets === void 0)) {
179
+ this._flags &= ~H;
180
+ for (let e = this._sources; e !== void 0; e = e._nextSource)
181
+ e._source._unsubscribe(e);
182
+ }
183
+ };
184
+ R.prototype._notify = function() {
185
+ if (!(this._flags & B)) {
186
+ this._flags |= Y | B;
187
+ for (let t = this._targets; t !== void 0; t = t._nextTarget)
188
+ t._target._notify();
189
+ }
190
+ };
191
+ R.prototype.peek = function() {
192
+ if (this._refresh() || ue(), this._flags & J)
193
+ throw this._value;
194
+ return this._value;
195
+ };
196
+ Object.defineProperty(R.prototype, "value", {
197
+ get() {
198
+ this._flags & O && ue();
199
+ const t = Ze(this);
200
+ if (this._refresh(), t !== void 0 && (t._version = this._version), this._flags & J)
201
+ throw this._value;
202
+ return this._value;
203
+ }
204
+ });
205
+ function Tt(t) {
206
+ return new R(t);
207
+ }
208
+ function st(t) {
209
+ const e = t._cleanup;
210
+ if (t._cleanup = void 0, typeof e == "function") {
211
+ fe();
212
+ const s = _;
213
+ _ = void 0;
214
+ try {
215
+ e();
216
+ } catch (n) {
217
+ throw t._flags &= ~O, t._flags |= W, Ne(t), n;
218
+ } finally {
219
+ _ = s, de();
220
+ }
221
+ }
222
+ }
223
+ function Ne(t) {
224
+ for (let e = t._sources; e !== void 0; e = e._nextSource)
225
+ e._source._unsubscribe(e);
226
+ t._compute = void 0, t._sources = void 0, st(t);
227
+ }
228
+ function At(t) {
229
+ if (_ !== this)
230
+ throw new Error("Out-of-order effect");
231
+ tt(this), _ = t, this._flags &= ~O, this._flags & W && Ne(this), de();
232
+ }
233
+ function X(t) {
234
+ this._compute = t, this._cleanup = void 0, this._sources = void 0, this._nextBatchedEffect = void 0, this._flags = H;
235
+ }
236
+ X.prototype._callback = function() {
237
+ const t = this._start();
238
+ try {
239
+ if (this._flags & W || this._compute === void 0)
240
+ return;
241
+ const e = this._compute();
242
+ typeof e == "function" && (this._cleanup = e);
243
+ } finally {
244
+ t();
245
+ }
246
+ };
247
+ X.prototype._start = function() {
248
+ this._flags & O && ue(), this._flags |= O, this._flags &= ~W, st(this), et(this), fe();
249
+ const t = _;
250
+ return _ = this, At.bind(this, t);
251
+ };
252
+ X.prototype._notify = function() {
253
+ this._flags & B || (this._flags |= B, this._nextBatchedEffect = K, K = this);
254
+ };
255
+ X.prototype._dispose = function() {
256
+ this._flags |= W, this._flags & O || Ne(this);
257
+ };
258
+ function nt(t) {
259
+ const e = new X(t);
260
+ try {
261
+ e._callback();
262
+ } catch (s) {
263
+ throw e._dispose(), s;
264
+ }
265
+ return e._dispose.bind(e);
266
+ }
267
+ class rt {
268
+ get value() {
269
+ return Ee(this);
270
+ }
271
+ set value(e) {
272
+ St(() => Nt(this, e));
273
+ }
274
+ peek() {
275
+ return Ee(this, { peek: true });
276
+ }
277
+ }
278
+ const oe = (t) => Object.assign(
279
+ new rt(),
280
+ Object.entries(t).reduce(
281
+ (e, [s, n]) => {
282
+ if (["value", "peek"].some((r) => r === s))
283
+ throw new Error(`${s} is a reserved property name`);
284
+ return typeof n != "object" || n === null || Array.isArray(n) ? e[s] = Xe(n) : e[s] = oe(n), e;
285
+ },
286
+ {}
287
+ )
288
+ ), Nt = (t, e) => Object.keys(e).forEach((s) => t[s].value = e[s]), Ee = (t, { peek: e = false } = {}) => Object.entries(t).reduce(
289
+ (s, [n, r]) => (r instanceof T ? s[n] = e ? r.peek() : r.value : r instanceof rt && (s[n] = Ee(r, { peek: e })), s),
290
+ {}
291
+ );
292
+ function ot(t, e) {
293
+ if (typeof e != "object" || Array.isArray(e) || !e)
294
+ return e;
295
+ if (typeof e == "object" && e.toJSON !== void 0 && typeof e.toJSON == "function")
296
+ return e.toJSON();
297
+ let s = t;
298
+ return typeof t != "object" && (s = { ...e }), Object.keys(e).forEach((n) => {
299
+ s.hasOwnProperty(n) || (s[n] = e[n]), e[n] === null ? delete s[n] : s[n] = ot(s[n], e[n]);
300
+ }), s;
301
+ }
302
+ const q = "datastar-event", it = "[a-zA-Z_$]+", Lt = it + "[0-9a-zA-Z_$.]*";
303
+ function Le(t, e, s, n = true) {
304
+ const r = n ? Lt : it;
305
+ return new RegExp(`(?<whole>\\${t}(?<${e}>${r})${s})`, "g");
306
+ }
307
+ const kt = {
308
+ regexp: Le("$", "signal", "(?<method>\\([^\\)]*\\))?"),
309
+ replacer: (t) => {
310
+ const { signal: e, method: s } = t, n = "ctx.store()";
311
+ if (!s?.length)
312
+ return `${n}.${e}.value`;
313
+ const r = e.split("."), o = r.pop(), i = r.join(".");
314
+ return `${n}.${i}.value.${o}${s}`;
315
+ }
316
+ }, Mt = {
317
+ regexp: Le("$\\$", "action", "(?<call>\\((?<args>.*)\\))?"),
318
+ replacer: ({ action: t, args: e }) => {
319
+ const s = ["ctx"];
320
+ e && s.push(...e.split(",").map((r) => r.trim()));
321
+ const n = s.join(",");
322
+ return `ctx.actions.${t}(${n})`;
323
+ }
324
+ }, Pt = {
325
+ regexp: Le("~", "ref", "", false),
326
+ replacer({ ref: t }) {
327
+ return `document.querySelector(ctx.store()._dsPlugins.refs.${t})`;
328
+ }
329
+ }, $t = [Mt, kt, Pt], Ot = {
330
+ prefix: "store",
331
+ removeNewLines: true,
332
+ preprocessors: {
333
+ pre: [
334
+ {
335
+ regexp: /(?<whole>.+)/g,
336
+ replacer: (t) => {
337
+ const { whole: e } = t;
338
+ return `Object.assign({...ctx.store()}, ${e})`;
339
+ }
340
+ }
341
+ ]
342
+ },
343
+ allowedModifiers: /* @__PURE__ */ new Set(["local", "session", "ifmissing"]),
344
+ onLoad: (t) => {
345
+ let e = "";
346
+ const s = (l) => {
347
+ const g = t.store(), c = JSON.stringify(g);
348
+ c !== e && (window.localStorage.setItem(U, c), e = c);
349
+ }, n = t.modifiers.has("local");
350
+ if (n) {
351
+ window.addEventListener(q, s);
352
+ const l = window.localStorage.getItem(U) || "{}", g = JSON.parse(l);
353
+ t.mergeStore(g);
354
+ }
355
+ const r = t.modifiers.has("session"), o = (l) => {
356
+ const g = t.store(), c = JSON.stringify(g);
357
+ window.sessionStorage.setItem(U, c);
358
+ };
359
+ if (r) {
360
+ window.addEventListener(q, o);
361
+ const l = window.sessionStorage.getItem(U) || "{}", g = JSON.parse(l);
362
+ t.mergeStore(g);
363
+ }
364
+ const i = t.expressionFn(t), f = lt(t.store(), i, t.modifiers.has("ifmissing"));
365
+ return t.mergeStore(f), delete t.el.dataset[t.rawKey], () => {
366
+ n && window.removeEventListener(q, s), r && window.removeEventListener(q, o);
367
+ };
368
+ }
369
+ }, It = {
370
+ prefix: "computed",
371
+ mustNotEmptyKey: true,
372
+ onLoad: (t) => {
373
+ const e = t.store();
374
+ return e[t.key] = t.reactivity.computed(() => t.expressionFn(t)), () => {
375
+ const s = t.store();
376
+ delete s[t.key];
377
+ };
378
+ }
379
+ }, Rt = {
380
+ prefix: "ref",
381
+ mustHaveEmptyKey: true,
382
+ mustNotEmptyExpression: true,
383
+ bypassExpressionFunctionCreation: () => true,
384
+ onLoad: (t) => {
385
+ t.upsertIfMissingFromStore("_dsPlugins.refs", {});
386
+ const { el: e, expression: s } = t, r = {
387
+ _dsPlugins: {
388
+ refs: {
389
+ ...t.store()._dsPlugins.refs.value,
390
+ [s]: at(e)
391
+ }
392
+ }
393
+ };
394
+ return t.mergeStore(r), () => {
395
+ const o = t.store(), i = { ...o._dsPlugins.refs.value };
396
+ delete i[s], o._dsPlugins.refs = i;
397
+ };
398
+ }
399
+ }, Ct = [Ot, It, Rt];
400
+ function at(t) {
401
+ if (!t)
402
+ return "null";
403
+ if (typeof t == "string")
404
+ return t;
405
+ if (t instanceof Window)
406
+ return "Window";
407
+ if (t instanceof Document)
408
+ return "Document";
409
+ if (t.tagName === "BODY")
410
+ return "BODY";
411
+ const e = [];
412
+ for (; t.parentElement && t.tagName !== "BODY"; ) {
413
+ if (t.id) {
414
+ e.unshift("#" + t.getAttribute("id"));
415
+ break;
416
+ } else {
417
+ let s = 1, n = t;
418
+ for (; n.previousElementSibling; n = n.previousElementSibling, s++)
419
+ ;
420
+ e.unshift(t.tagName + ":nth-child(" + s + ")");
421
+ }
422
+ t = t.parentElement;
423
+ }
424
+ return e.join(">");
425
+ }
426
+ function lt(t, e, s) {
427
+ const n = {};
428
+ if (!s)
429
+ Object.assign(n, e);
430
+ else
431
+ for (const r in e) {
432
+ const o = t[r]?.value;
433
+ o == null && (n[r] = e[r]);
434
+ }
435
+ return n;
436
+ }
437
+ const U = "datastar", k = `${U}-`;
438
+ class Dt {
439
+ constructor(e = {}, ...s) {
440
+ if (this.plugins = [], this.store = oe({ _dsPlugins: {} }), this.actions = {}, this.refs = {}, this.reactivity = {
441
+ signal: Xe,
442
+ computed: Tt,
443
+ effect: nt
444
+ }, this.parentID = "", this.missingIDNext = 0, this.removals = /* @__PURE__ */ new Map(), this.mergeRemovals = new Array(), this.actions = Object.assign(this.actions, e), s = [...Ct, ...s], !s.length)
445
+ throw new Error("No plugins provided");
446
+ const n = /* @__PURE__ */ new Set();
447
+ for (const r of s) {
448
+ if (r.requiredPluginPrefixes) {
449
+ for (const o of r.requiredPluginPrefixes)
450
+ if (!n.has(o))
451
+ throw new Error(`${r.prefix} requires ${o}`);
452
+ }
453
+ this.plugins.push(r), n.add(r.prefix);
454
+ }
455
+ }
456
+ run() {
457
+ new MutationObserver((s, n) => {
458
+ N("core", "dom", "mutation", document.body, document.body.outerHTML);
459
+ }).observe(document.body, {
460
+ attributes: true,
461
+ childList: true,
462
+ subtree: true
463
+ }), this.plugins.forEach((s) => {
464
+ s.onGlobalInit && (s.onGlobalInit({
465
+ actions: this.actions,
466
+ reactivity: this.reactivity,
467
+ mergeStore: this.mergeStore.bind(this),
468
+ store: this.store
469
+ }), N("core", "plugins", "registration", "BODY", `On prefix ${s.prefix}`));
470
+ }), this.applyPlugins(document.body);
471
+ }
472
+ cleanupElementRemovals(e) {
473
+ const s = this.removals.get(e);
474
+ if (s) {
475
+ for (const n of s.set)
476
+ n();
477
+ this.removals.delete(e);
478
+ }
479
+ }
480
+ mergeStore(e) {
481
+ this.mergeRemovals.forEach((n) => n()), this.mergeRemovals = this.mergeRemovals.slice(0);
482
+ const s = ot(this.store.value, e);
483
+ this.store = oe(s), this.mergeRemovals.push(
484
+ this.reactivity.effect(() => {
485
+ N("core", "store", "merged", "STORE", JSON.stringify(this.store.value));
486
+ })
487
+ );
488
+ }
489
+ removeFromStore(...e) {
490
+ const s = { ...this.store.value };
491
+ for (const n of e) {
492
+ const r = n.split(".");
493
+ let o = r[0], i = s;
494
+ for (let f = 1; f < r.length; f++) {
495
+ const l = r[f];
496
+ i[o] || (i[o] = {}), i = i[o], o = l;
497
+ }
498
+ delete i[o];
499
+ }
500
+ this.store = oe(s), this.applyPlugins(document.body);
501
+ }
502
+ upsertIfMissingFromStore(e, s) {
503
+ const n = e.split(".");
504
+ let r = this.store;
505
+ for (let i = 0; i < n.length - 1; i++) {
506
+ const f = n[i];
507
+ r[f] || (r[f] = {}), r = r[f];
508
+ }
509
+ const o = n[n.length - 1];
510
+ r[o] || (r[o] = this.reactivity.signal(s), N("core", "store", "upsert", e, s));
511
+ }
512
+ signalByName(e) {
513
+ return this.store[e];
514
+ }
515
+ applyPlugins(e) {
516
+ const s = /* @__PURE__ */ new Set();
517
+ this.plugins.forEach((n, r) => {
518
+ this.walkDownDOM(e, (o) => {
519
+ r || this.cleanupElementRemovals(o);
520
+ for (const i in o.dataset) {
521
+ const f = o.dataset[i] || "";
522
+ let l = f;
523
+ if (!i.startsWith(n.prefix))
524
+ continue;
525
+ if (o.id.length === 0 && (o.id = `ds-${this.parentID}-${this.missingIDNext++}`), s.clear(), n.allowedTagRegexps) {
526
+ const a = o.tagName.toLowerCase();
527
+ if (![...n.allowedTagRegexps].some((w) => a.match(w)))
528
+ throw new Error(
529
+ `'${o.tagName}' not allowed for '${i}', allowed ${[
530
+ [...n.allowedTagRegexps].map((w) => `'${w}'`)
531
+ ].join(", ")}`
532
+ );
533
+ }
534
+ let g = i.slice(n.prefix.length), [c, ...d] = g.split(".");
535
+ if (n.mustHaveEmptyKey && c.length > 0)
536
+ throw new Error(`'${i}' must have empty key`);
537
+ if (n.mustNotEmptyKey && c.length === 0)
538
+ throw new Error(`'${i}' must have non-empty key`);
539
+ c.length && (c = c[0].toLowerCase() + c.slice(1));
540
+ const v = d.map((a) => {
541
+ const [b, ...w] = a.split("_");
542
+ return { label: b, args: w };
543
+ });
544
+ if (n.allowedModifiers) {
545
+ for (const a of v)
546
+ if (!n.allowedModifiers.has(a.label))
547
+ throw new Error(`'${a.label}' is not allowed`);
548
+ }
549
+ const u = /* @__PURE__ */ new Map();
550
+ for (const a of v)
551
+ u.set(a.label, a.args);
552
+ if (n.mustHaveEmptyExpression && l.length)
553
+ throw new Error(`'${i}' must have empty expression`);
554
+ if (n.mustNotEmptyExpression && !l.length)
555
+ throw new Error(`'${i}' must have non-empty expression`);
556
+ const E = /;|\n/;
557
+ n.removeNewLines && (l = l.split(`
558
+ `).map((a) => a.trim()).join(" "));
559
+ const y = [...n.preprocessors?.pre || [], ...$t, ...n.preprocessors?.post || []];
560
+ for (const a of y) {
561
+ if (s.has(a))
562
+ continue;
563
+ s.add(a);
564
+ const b = l.split(E), w = [];
565
+ b.forEach((m) => {
566
+ let S = m;
567
+ const P = [...S.matchAll(a.regexp)];
568
+ if (P.length)
569
+ for (const C of P) {
570
+ if (!C.groups)
571
+ continue;
572
+ const { groups: D } = C, { whole: V } = D;
573
+ S = S.replace(V, a.replacer(D));
574
+ }
575
+ w.push(S);
576
+ }), l = w.join("; ");
577
+ }
578
+ const h = {
579
+ store: () => this.store,
580
+ mergeStore: this.mergeStore.bind(this),
581
+ upsertIfMissingFromStore: this.upsertIfMissingFromStore.bind(this),
582
+ removeFromStore: this.removeFromStore.bind(this),
583
+ applyPlugins: this.applyPlugins.bind(this),
584
+ cleanupElementRemovals: this.cleanupElementRemovals.bind(this),
585
+ walkSignals: this.walkSignals.bind(this),
586
+ actions: this.actions,
587
+ reactivity: this.reactivity,
588
+ el: o,
589
+ rawKey: i,
590
+ key: c,
591
+ rawExpression: f,
592
+ expression: l,
593
+ expressionFn: () => {
594
+ throw new Error("Expression function not created");
595
+ },
596
+ modifiers: u,
597
+ sendDatastarEvent: N
598
+ };
599
+ if (!n.bypassExpressionFunctionCreation?.(h) && !n.mustHaveEmptyExpression && l.length) {
600
+ const a = l.split(E).map((m) => m.trim()).filter((m) => m.length);
601
+ a[a.length - 1] = `return ${a[a.length - 1]}`;
602
+ const b = a.map((m) => ` ${m}`).join(`;
603
+ `), w = `
604
+ try {
605
+ const _datastarExpression = () => {
606
+ ${b}
607
+ }
608
+ const _datastarReturnVal = _datastarExpression()
609
+ ctx.sendDatastarEvent('core', 'attributes', 'expr_eval', ctx.el, '${i} equals ' + JSON.stringify(_datastarReturnVal))
610
+ return _datastarReturnVal
611
+ } catch (e) {
612
+ const msg = \`
613
+ Error evaluating Datastar expression:
614
+ ${b.replaceAll("`", "\\`")}
615
+
616
+ Error: \${e.message}
617
+
618
+ Check if the expression is valid before raising an issue.
619
+ \`.trim()
620
+ ctx.sendDatastarEvent('core', 'attributes', 'expr_eval_err', ctx.el, msg)
621
+ console.error(msg)
622
+ debugger
623
+ }
624
+ `;
625
+ try {
626
+ const m = n.argumentNames || [], S = new Function("ctx", ...m, w);
627
+ h.expressionFn = S;
628
+ } catch (m) {
629
+ const S = new Error(`Error creating expression function for '${w}', error: ${m}`);
630
+ N("core", "attributes", "expr_construction_err", h.el, String(S)), console.error(S);
631
+ debugger;
632
+ }
633
+ }
634
+ const p = n.onLoad(h);
635
+ p && (this.removals.has(o) || this.removals.set(o, { id: o.id, set: /* @__PURE__ */ new Set() }), this.removals.get(o).set.add(p));
636
+ }
637
+ });
638
+ });
639
+ }
640
+ walkSignalsStore(e, s) {
641
+ const n = Object.keys(e);
642
+ for (let r = 0; r < n.length; r++) {
643
+ const o = n[r], i = e[o], f = i instanceof T, l = typeof i == "object" && Object.keys(i).length > 0;
644
+ if (f) {
645
+ s(o, i);
646
+ continue;
647
+ }
648
+ l && this.walkSignalsStore(i, s);
649
+ }
650
+ }
651
+ walkSignals(e) {
652
+ this.walkSignalsStore(this.store, e);
653
+ }
654
+ walkDownDOM(e, s, n = 0) {
655
+ if (!e)
656
+ return;
657
+ const r = ze(e);
658
+ if (r)
659
+ for (s(r), n = 0, e = e.firstElementChild; e; )
660
+ this.walkDownDOM(e, s, n++), e = e.nextElementSibling;
661
+ }
662
+ }
663
+ const ct = (t) => t.replace(/[A-Z]+(?![a-z])|[A-Z]/g, (e, s) => (s ? "-" : "") + e.toLowerCase()), Ft = {
664
+ prefix: "bind",
665
+ mustNotEmptyKey: true,
666
+ mustNotEmptyExpression: true,
667
+ onLoad: (t) => t.reactivity.effect(async () => {
668
+ const e = ct(t.key), s = t.expressionFn(t);
669
+ let n;
670
+ typeof s == "string" ? n = s : n = JSON.stringify(s), !n || n === "false" || n === "null" || n === "undefined" ? t.el.removeAttribute(e) : t.el.setAttribute(e, n);
671
+ })
672
+ }, Ht = /^data:(?<mime>[^;]+);base64,(?<contents>.*)$/, te = ["change", "input", "keydown"], Vt = {
673
+ prefix: "model",
674
+ mustHaveEmptyKey: true,
675
+ preprocessors: {
676
+ post: [
677
+ {
678
+ regexp: /(?<whole>.+)/g,
679
+ replacer: (t) => {
680
+ const { whole: e } = t;
681
+ return `ctx.store().${e}`;
682
+ }
683
+ }
684
+ ]
685
+ },
686
+ // bypassExpressionFunctionCreation: () => true,
687
+ onLoad: (t) => {
688
+ const { el: e, expression: s } = t, n = t.expressionFn(t), r = e.tagName.toLowerCase();
689
+ if (s.startsWith("ctx.store().ctx.store()"))
690
+ throw new Error(`Model attribute on #${e.id} must have a signal name, you probably prefixed with $ by accident`);
691
+ const o = r.includes("input"), i = e.getAttribute("type"), f = r.includes("checkbox") || o && i === "checkbox", l = r.includes("select"), g = r.includes("radio") || o && i === "radio", c = o && i === "file", d = s.replaceAll("ctx.store().", "");
692
+ g && (e.getAttribute("name")?.length || e.setAttribute("name", d));
693
+ const v = () => {
694
+ if (!n)
695
+ throw new Error(`Signal ${d} not found`);
696
+ const p = "value" in e, a = n.value;
697
+ if (f || g) {
698
+ const b = e;
699
+ f ? b.checked = a : g && (b.checked = `${a}` === b.value);
700
+ } else if (!c)
701
+ if (l) {
702
+ const b = e;
703
+ if (b.multiple) {
704
+ const w = n.value;
705
+ Array.from(b.options).forEach((m) => {
706
+ m?.disabled || (m.selected = w.includes(m.value));
707
+ });
708
+ } else
709
+ b.value = `${a}`;
710
+ } else
711
+ p ? e.value = `${a}` : e.setAttribute("value", `${a}`);
712
+ }, u = t.reactivity.effect(v), E = async () => {
713
+ if (c) {
714
+ const b = [...e?.files || []], w = [], m = [], S = [];
715
+ await Promise.all(
716
+ b.map((V) => new Promise((Q) => {
717
+ const $ = new FileReader();
718
+ $.onload = () => {
719
+ if (typeof $.result != "string")
720
+ throw new Error(`Invalid result type: ${typeof $.result}`);
721
+ const j = $.result.match(Ht);
722
+ if (!j?.groups)
723
+ throw new Error(`Invalid data URI: ${$.result}`);
724
+ w.push(j.groups.contents), m.push(j.groups.mime), S.push(V.name);
725
+ }, $.onloadend = () => Q(void 0), $.readAsDataURL(V);
726
+ }))
727
+ ), n.value = w;
728
+ const P = t.store(), C = `${d}Mimes`, D = `${d}Names`;
729
+ C in P && (P[`${C}`].value = m), D in P && (P[`${D}`].value = S);
730
+ return;
731
+ }
732
+ const p = n.value, a = e || e;
733
+ if (typeof p == "number")
734
+ n.value = Number(a.value || a.getAttribute("value"));
735
+ else if (typeof p == "string")
736
+ n.value = a.value || a.getAttribute("value") || "";
737
+ else if (typeof p == "boolean")
738
+ f ? n.value = a.checked || a.getAttribute("checked") === "true" : n.value = !!(a.value || a.getAttribute("value"));
739
+ else if (!(typeof p > "u"))
740
+ if (typeof p == "bigint")
741
+ n.value = BigInt(a.value || a.getAttribute("value") || "0");
742
+ else if (Array.isArray(p)) {
743
+ if (l) {
744
+ const m = [...e.selectedOptions].map((S) => S.value);
745
+ n.value = m;
746
+ } else
747
+ n.value = JSON.parse(a.value).split(",");
748
+ console.log(a.value);
749
+ } else
750
+ throw console.log(typeof p), new Error(`Unsupported type ${typeof p} for signal ${d}`);
751
+ }, y = e.tagName.split("-");
752
+ if (y.length > 1) {
753
+ const p = y[0].toLowerCase();
754
+ te.forEach((a) => {
755
+ te.push(`${p}-${a}`);
756
+ });
757
+ }
758
+ return te.forEach((p) => e.addEventListener(p, E)), () => {
759
+ u(), te.forEach((p) => e.removeEventListener(p, E));
760
+ };
761
+ }
762
+ }, xt = {
763
+ prefix: "text",
764
+ mustHaveEmptyKey: true,
765
+ onLoad: (t) => {
766
+ const { el: e, expressionFn: s } = t;
767
+ if (!(e instanceof HTMLElement))
768
+ throw new Error("Element is not HTMLElement");
769
+ return t.reactivity.effect(() => {
770
+ const n = s(t);
771
+ e.textContent = `${n}`;
772
+ });
773
+ }
774
+ };
775
+ let $e = "";
776
+ const jt = /* @__PURE__ */ new Set(["window", "once", "passive", "capture", "debounce", "throttle", "remote", "outside"]), Ut = {
777
+ prefix: "on",
778
+ mustNotEmptyKey: true,
779
+ mustNotEmptyExpression: true,
780
+ argumentNames: ["evt"],
781
+ onLoad: (t) => {
782
+ const { el: e, key: s, expressionFn: n } = t;
783
+ let r = t.el;
784
+ t.modifiers.get("window") && (r = window);
785
+ let o = (d) => {
786
+ N("plugin", "event", s, r, "triggered"), n(t, d);
787
+ };
788
+ const i = t.modifiers.get("debounce");
789
+ if (i) {
790
+ const d = _e(i), v = se(i, "leading", false), u = se(i, "noTrail", true);
791
+ o = Jt(o, d, v, u);
792
+ }
793
+ const f = t.modifiers.get("throttle");
794
+ if (f) {
795
+ const d = _e(f), v = se(f, "noLead", true), u = se(f, "noTrail", false);
796
+ o = Kt(o, d, v, u);
797
+ }
798
+ const l = {
799
+ capture: true,
800
+ passive: false,
801
+ once: false
802
+ };
803
+ t.modifiers.has("capture") || (l.capture = false), t.modifiers.has("passive") && (l.passive = true), t.modifiers.has("once") && (l.once = true), [...t.modifiers.keys()].filter((d) => !jt.has(d)).forEach((d) => {
804
+ const v = t.modifiers.get(d) || [], u = o;
805
+ o = () => {
806
+ const y = event, h = y[d];
807
+ let p;
808
+ if (typeof h == "function")
809
+ p = h(...v);
810
+ else if (typeof h == "boolean")
811
+ p = h;
812
+ else if (typeof h == "string") {
813
+ const a = h.toLowerCase().trim(), b = v.join("").toLowerCase().trim();
814
+ p = a === b;
815
+ } else {
816
+ const a = `Invalid value for ${d} modifier on ${s} on ${e}`;
817
+ console.error(a);
818
+ debugger;
819
+ throw new Error(a);
820
+ }
821
+ p && u(y);
822
+ };
823
+ });
824
+ const c = ct(s).toLowerCase();
825
+ switch (c) {
826
+ case "load":
827
+ return o(), delete t.el.dataset.onLoad, () => {
828
+ };
829
+ case "raf":
830
+ let d;
831
+ const v = () => {
832
+ o(), d = requestAnimationFrame(v);
833
+ };
834
+ return d = requestAnimationFrame(v), () => {
835
+ d && cancelAnimationFrame(d);
836
+ };
837
+ case "store-change":
838
+ return t.reactivity.effect(() => {
839
+ let y = t.store().value;
840
+ t.modifiers.has("remote") && (y = he(y));
841
+ const h = JSON.stringify(y);
842
+ $e !== h && ($e = h, o());
843
+ });
844
+ default:
845
+ if (t.modifiers.has("outside")) {
846
+ r = document;
847
+ const E = o;
848
+ let y = false;
849
+ o = (p) => {
850
+ const a = p?.target;
851
+ if (!a)
852
+ return;
853
+ const b = e.id === a.id;
854
+ b && y && (y = false), !b && !y && (E(p), y = true);
855
+ };
856
+ }
857
+ return r.addEventListener(c, o, l), () => {
858
+ r.removeEventListener(c, o);
859
+ };
860
+ }
861
+ }
862
+ };
863
+ function he(t) {
864
+ const e = {};
865
+ for (const [s, n] of Object.entries(t))
866
+ s.startsWith("_") || (typeof n == "object" && !Array.isArray(n) ? e[s] = he(n) : e[s] = n);
867
+ return e;
868
+ }
869
+ const Bt = {
870
+ prefix: "class",
871
+ mustHaveEmptyKey: true,
872
+ mustNotEmptyExpression: true,
873
+ onLoad: (t) => t.reactivity.effect(() => {
874
+ const e = t.expressionFn(t);
875
+ for (const [s, n] of Object.entries(e))
876
+ n ? t.el.classList.add(s) : t.el.classList.remove(s);
877
+ return () => {
878
+ t.el.classList.remove(...Object.keys(e));
879
+ };
880
+ })
881
+ }, Wt = [
882
+ Ft,
883
+ Vt,
884
+ xt,
885
+ Ut,
886
+ Bt
887
+ ], qt = {
888
+ remote: async (t) => he(t.store().value)
889
+ };
890
+ function _e(t) {
891
+ if (!t || t?.length === 0)
892
+ return 0;
893
+ for (const e of t) {
894
+ if (e.endsWith("ms"))
895
+ return Number(e.replace("ms", ""));
896
+ if (e.endsWith("s"))
897
+ return Number(e.replace("s", "")) * 1e3;
898
+ try {
899
+ return parseFloat(e);
900
+ } catch {
901
+ }
902
+ }
903
+ return 0;
904
+ }
905
+ function se(t, e, s = false) {
906
+ return t ? t.includes(e) || s : false;
907
+ }
908
+ function Jt(t, e, s = false, n = true) {
909
+ let r;
910
+ const o = () => r && clearTimeout(r);
911
+ return function(...f) {
912
+ o(), s && !r && t(...f), r = setTimeout(() => {
913
+ n && t(...f), o();
914
+ }, e);
915
+ };
916
+ }
917
+ function Kt(t, e, s = true, n = false) {
918
+ let r = false;
919
+ return function(...i) {
920
+ r || (s && t(...i), r = true, setTimeout(() => {
921
+ r = false, n && t(...i);
922
+ }, e));
923
+ };
924
+ }
925
+ function Gt(t, {
926
+ signal: e,
927
+ headers: s,
928
+ onopen: n,
929
+ onmessage: r,
930
+ onclose: o,
931
+ onerror: i,
932
+ openWhenHidden: f,
933
+ ...l
934
+ }) {
935
+ return new Promise((g, c) => {
936
+ let d = 0;
937
+ const v = { ...s };
938
+ v.accept || (v.accept = Se);
939
+ let u;
940
+ function E() {
941
+ u.abort(), document.hidden || b();
942
+ }
943
+ f || document.addEventListener("visibilitychange", E);
944
+ let y = Oe, h = 0;
945
+ function p() {
946
+ document.removeEventListener("visibilitychange", E), window.clearTimeout(h), u.abort();
947
+ }
948
+ e?.addEventListener("abort", () => {
949
+ p(), g();
950
+ });
951
+ const a = n ?? Zt;
952
+ async function b() {
953
+ u = new AbortController();
954
+ try {
955
+ const w = await fetch(t, {
956
+ ...l,
957
+ headers: v,
958
+ signal: u.signal
959
+ });
960
+ await a(w), await Xt(
961
+ w.body,
962
+ Qt(
963
+ es(
964
+ (m) => {
965
+ m ? v[Ie] = m : delete v[Ie];
966
+ },
967
+ (m) => {
968
+ y = m;
969
+ },
970
+ r
971
+ )
972
+ )
973
+ ), o?.(), p(), g();
974
+ } catch (w) {
975
+ if (!u.signal.aborted)
976
+ try {
977
+ const m = i?.(w) ?? y;
978
+ window.clearTimeout(h), h = window.setTimeout(b, m), y *= 1.5, y = Math.min(y, Yt), d++, d >= zt ? (p(), c(new Error("Max retries hit, check your server or network connection."))) : console.error(`Error fetching event source, retrying in ${m}ms`);
979
+ } catch (m) {
980
+ p(), c(m);
981
+ }
982
+ }
983
+ }
984
+ y = Oe, b();
985
+ });
986
+ }
987
+ const Se = "text/event-stream", Oe = 100, Yt = 1e4, zt = 10, Ie = "last-event-id";
988
+ function Zt(t) {
989
+ const e = t.headers.get("content-type");
990
+ if (!e?.startsWith(Se))
991
+ throw new Error(`Expected content-type to be ${Se}, Actual: ${e}`);
992
+ }
993
+ async function Xt(t, e) {
994
+ const s = t.getReader();
995
+ for (; ; ) {
996
+ const n = await s.read();
997
+ if (n.done)
998
+ break;
999
+ e(n.value);
1000
+ }
1001
+ }
1002
+ function Qt(t) {
1003
+ let e, s, n, r = false;
1004
+ return function(i) {
1005
+ e === void 0 ? (e = i, s = 0, n = -1) : e = ts(e, i);
1006
+ const f = e.length;
1007
+ let l = 0;
1008
+ for (; s < f; ) {
1009
+ r && (e[s] === 10 && (l = ++s), r = false);
1010
+ let g = -1;
1011
+ for (; s < f && g === -1; ++s)
1012
+ switch (e[s]) {
1013
+ case 58:
1014
+ n === -1 && (n = s - l);
1015
+ break;
1016
+ case 13:
1017
+ r = true;
1018
+ case 10:
1019
+ g = s;
1020
+ break;
1021
+ }
1022
+ if (g === -1)
1023
+ break;
1024
+ t(e.subarray(l, g), n), l = s, n = -1;
1025
+ }
1026
+ l === f ? e = void 0 : l !== 0 && (e = e.subarray(l), s -= l);
1027
+ };
1028
+ }
1029
+ function es(t, e, s) {
1030
+ let n = Re();
1031
+ const r = new TextDecoder();
1032
+ return function(i, f) {
1033
+ if (i.length === 0)
1034
+ s?.(n), n = Re();
1035
+ else if (f > 0) {
1036
+ const l = r.decode(i.subarray(0, f)), g = f + (i[f + 1] === 32 ? 2 : 1), c = r.decode(i.subarray(g));
1037
+ switch (l) {
1038
+ case "data":
1039
+ n.data = n.data ? n.data + `
1040
+ ` + c : c;
1041
+ break;
1042
+ case "event":
1043
+ n.event = c;
1044
+ break;
1045
+ case "id":
1046
+ t(n.id = c);
1047
+ break;
1048
+ case "retry":
1049
+ const d = parseInt(c, 10);
1050
+ isNaN(d) || e(n.retry = d);
1051
+ break;
1052
+ }
1053
+ }
1054
+ };
1055
+ }
1056
+ function ts(t, e) {
1057
+ const s = new Uint8Array(t.length + e.length);
1058
+ return s.set(t), s.set(e, t.length), s;
1059
+ }
1060
+ function Re() {
1061
+ return {
1062
+ data: "",
1063
+ event: "",
1064
+ id: "",
1065
+ retry: void 0
1066
+ };
1067
+ }
1068
+ const ie = /* @__PURE__ */ new WeakSet();
1069
+ function ss(t, e, s = {}) {
1070
+ t instanceof Document && (t = t.documentElement);
1071
+ let n;
1072
+ typeof e == "string" ? n = as(e) : n = e;
1073
+ const r = ls(n), o = rs(t, r, s);
1074
+ return ut(t, r, o);
1075
+ }
1076
+ function ut(t, e, s) {
1077
+ if (s.head.block) {
1078
+ const n = t.querySelector("head"), r = e.querySelector("head");
1079
+ if (n && r) {
1080
+ const o = dt(r, n, s);
1081
+ Promise.all(o).then(() => {
1082
+ ut(
1083
+ t,
1084
+ e,
1085
+ Object.assign(s, {
1086
+ head: {
1087
+ block: false,
1088
+ ignore: true
1089
+ }
1090
+ })
1091
+ );
1092
+ });
1093
+ return;
1094
+ }
1095
+ }
1096
+ if (s.morphStyle === "innerHTML")
1097
+ return ft(e, t, s), t.children;
1098
+ if (s.morphStyle === "outerHTML" || s.morphStyle == null) {
1099
+ const n = us(e, t, s);
1100
+ if (!n)
1101
+ throw new Error("Could not find best match");
1102
+ const r = n?.previousSibling, o = n?.nextSibling, i = ae(t, n, s);
1103
+ return n ? cs(r, i, o) : [];
1104
+ } else
1105
+ throw "Do not understand how to morph style " + s.morphStyle;
1106
+ }
1107
+ function ae(t, e, s) {
1108
+ if (!(s.ignoreActive && t === document.activeElement))
1109
+ if (e == null) {
1110
+ if (s.callbacks.beforeNodeRemoved(t) === false)
1111
+ return;
1112
+ t.remove(), s.callbacks.afterNodeRemoved(t);
1113
+ return;
1114
+ } else {
1115
+ if (ce(t, e))
1116
+ return s.callbacks.beforeNodeMorphed(t, e) === false ? void 0 : (t instanceof HTMLHeadElement && s.head.ignore || (e instanceof HTMLHeadElement && t instanceof HTMLHeadElement && s.head.style !== "morph" ? dt(e, t, s) : (ns(e, t), ft(e, t, s))), s.callbacks.afterNodeMorphed(t, e), t);
1117
+ if (s.callbacks.beforeNodeRemoved(t) === false || s.callbacks.beforeNodeAdded(e) === false)
1118
+ return;
1119
+ if (!t.parentElement)
1120
+ throw new Error("oldNode has no parentElement");
1121
+ return t.parentElement.replaceChild(e, t), s.callbacks.afterNodeAdded(e), s.callbacks.afterNodeRemoved(t), e;
1122
+ }
1123
+ }
1124
+ function ft(t, e, s) {
1125
+ let n = t.firstChild, r = e.firstChild, o;
1126
+ for (; n; ) {
1127
+ if (o = n, n = o.nextSibling, r == null) {
1128
+ if (s.callbacks.beforeNodeAdded(o) === false)
1129
+ return;
1130
+ e.appendChild(o), s.callbacks.afterNodeAdded(o), x(s, o);
1131
+ continue;
1132
+ }
1133
+ if (ht(o, r, s)) {
1134
+ ae(r, o, s), r = r.nextSibling, x(s, o);
1135
+ continue;
1136
+ }
1137
+ let i = os(t, e, o, r, s);
1138
+ if (i) {
1139
+ r = Ce(r, i, s), ae(i, o, s), x(s, o);
1140
+ continue;
1141
+ }
1142
+ let f = is(t, o, r, s);
1143
+ if (f) {
1144
+ r = Ce(r, f, s), ae(f, o, s), x(s, o);
1145
+ continue;
1146
+ }
1147
+ if (s.callbacks.beforeNodeAdded(o) === false)
1148
+ return;
1149
+ e.insertBefore(o, r), s.callbacks.afterNodeAdded(o), x(s, o);
1150
+ }
1151
+ for (; r !== null; ) {
1152
+ let i = r;
1153
+ r = r.nextSibling, pt(i, s);
1154
+ }
1155
+ }
1156
+ function ns(t, e) {
1157
+ let s = t.nodeType;
1158
+ if (s === 1) {
1159
+ for (const n of t.attributes)
1160
+ e.getAttribute(n.name) !== n.value && e.setAttribute(n.name, n.value);
1161
+ for (const n of e.attributes)
1162
+ t.hasAttribute(n.name) || e.removeAttribute(n.name);
1163
+ }
1164
+ if ((s === Node.COMMENT_NODE || s === Node.TEXT_NODE) && e.nodeValue !== t.nodeValue && (e.nodeValue = t.nodeValue), t instanceof HTMLInputElement && e instanceof HTMLInputElement && t.type !== "file")
1165
+ e.value = t.value || "", ne(t, e, "value"), ne(t, e, "checked"), ne(t, e, "disabled");
1166
+ else if (t instanceof HTMLOptionElement)
1167
+ ne(t, e, "selected");
1168
+ else if (t instanceof HTMLTextAreaElement && e instanceof HTMLTextAreaElement) {
1169
+ const n = t.value, r = e.value;
1170
+ n !== r && (e.value = n), e.firstChild && e.firstChild.nodeValue !== n && (e.firstChild.nodeValue = n);
1171
+ }
1172
+ }
1173
+ function ne(t, e, s) {
1174
+ const n = t.getAttribute(s), r = e.getAttribute(s);
1175
+ n !== r && (n ? e.setAttribute(s, n) : e.removeAttribute(s));
1176
+ }
1177
+ function dt(t, e, s) {
1178
+ const n = [], r = [], o = [], i = [], f = s.head.style, l = /* @__PURE__ */ new Map();
1179
+ for (const c of t.children)
1180
+ l.set(c.outerHTML, c);
1181
+ for (const c of e.children) {
1182
+ let d = l.has(c.outerHTML), v = s.head.shouldReAppend(c), u = s.head.shouldPreserve(c);
1183
+ d || u ? v ? r.push(c) : (l.delete(c.outerHTML), o.push(c)) : f === "append" ? v && (r.push(c), i.push(c)) : s.head.shouldRemove(c) !== false && r.push(c);
1184
+ }
1185
+ i.push(...l.values());
1186
+ const g = [];
1187
+ for (const c of i) {
1188
+ const d = document.createRange().createContextualFragment(c.outerHTML).firstChild;
1189
+ if (!d)
1190
+ throw new Error("could not create new element from: " + c.outerHTML);
1191
+ if (s.callbacks.beforeNodeAdded(d)) {
1192
+ if (d.hasAttribute("href") || d.hasAttribute("src")) {
1193
+ let v;
1194
+ const u = new Promise((E) => {
1195
+ v = E;
1196
+ });
1197
+ d.addEventListener("load", function() {
1198
+ v(void 0);
1199
+ }), g.push(u);
1200
+ }
1201
+ e.appendChild(d), s.callbacks.afterNodeAdded(d), n.push(d);
1202
+ }
1203
+ }
1204
+ for (const c of r)
1205
+ s.callbacks.beforeNodeRemoved(c) !== false && (e.removeChild(c), s.callbacks.afterNodeRemoved(c));
1206
+ return s.head.afterHeadMorphed(e, {
1207
+ added: n,
1208
+ kept: o,
1209
+ removed: r
1210
+ }), g;
1211
+ }
1212
+ function F() {
1213
+ }
1214
+ function rs(t, e, s) {
1215
+ return {
1216
+ target: t,
1217
+ newContent: e,
1218
+ config: s,
1219
+ morphStyle: s.morphStyle,
1220
+ ignoreActive: s.ignoreActive,
1221
+ idMap: ps(t, e),
1222
+ deadIds: /* @__PURE__ */ new Set(),
1223
+ callbacks: Object.assign(
1224
+ {
1225
+ beforeNodeAdded: F,
1226
+ afterNodeAdded: F,
1227
+ beforeNodeMorphed: F,
1228
+ afterNodeMorphed: F,
1229
+ beforeNodeRemoved: F,
1230
+ afterNodeRemoved: F
1231
+ },
1232
+ s.callbacks
1233
+ ),
1234
+ head: Object.assign(
1235
+ {
1236
+ style: "merge",
1237
+ shouldPreserve: (n) => n.getAttribute("im-preserve") === "true",
1238
+ shouldReAppend: (n) => n.getAttribute("im-re-append") === "true",
1239
+ shouldRemove: F,
1240
+ afterHeadMorphed: F
1241
+ },
1242
+ s.head
1243
+ )
1244
+ };
1245
+ }
1246
+ function ht(t, e, s) {
1247
+ return !t || !e ? false : t.nodeType === e.nodeType && t.tagName === e.tagName ? t?.id?.length && t.id === e.id ? true : z(s, t, e) > 0 : false;
1248
+ }
1249
+ function ce(t, e) {
1250
+ return !t || !e ? false : t.nodeType === e.nodeType && t.tagName === e.tagName;
1251
+ }
1252
+ function Ce(t, e, s) {
1253
+ for (; t !== e; ) {
1254
+ const n = t;
1255
+ if (t = t?.nextSibling, !n)
1256
+ throw new Error("tempNode is null");
1257
+ pt(n, s);
1258
+ }
1259
+ return x(s, e), e.nextSibling;
1260
+ }
1261
+ function os(t, e, s, n, r) {
1262
+ const o = z(r, s, e);
1263
+ let i = null;
1264
+ if (o > 0) {
1265
+ i = n;
1266
+ let f = 0;
1267
+ for (; i != null; ) {
1268
+ if (ht(s, i, r))
1269
+ return i;
1270
+ if (f += z(r, i, t), f > o)
1271
+ return null;
1272
+ i = i.nextSibling;
1273
+ }
1274
+ }
1275
+ return i;
1276
+ }
1277
+ function is(t, e, s, n) {
1278
+ let r = s, o = e.nextSibling, i = 0;
1279
+ for (; r && o; ) {
1280
+ if (z(n, r, t) > 0)
1281
+ return null;
1282
+ if (ce(e, r))
1283
+ return r;
1284
+ if (ce(o, r) && (i++, o = o.nextSibling, i >= 2))
1285
+ return null;
1286
+ r = r.nextSibling;
1287
+ }
1288
+ return r;
1289
+ }
1290
+ const De = new DOMParser();
1291
+ function as(t) {
1292
+ const e = t.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, "");
1293
+ if (e.match(/<\/html>/) || e.match(/<\/head>/) || e.match(/<\/body>/)) {
1294
+ const s = De.parseFromString(t, "text/html");
1295
+ if (e.match(/<\/html>/))
1296
+ return ie.add(s), s;
1297
+ {
1298
+ let n = s.firstChild;
1299
+ return n ? (ie.add(n), n) : null;
1300
+ }
1301
+ } else {
1302
+ const n = De.parseFromString(`<body><template>${t}</template></body>`, "text/html").body.querySelector("template")?.content;
1303
+ if (!n)
1304
+ throw new Error("content is null");
1305
+ return ie.add(n), n;
1306
+ }
1307
+ }
1308
+ function ls(t) {
1309
+ if (t == null)
1310
+ return document.createElement("div");
1311
+ if (ie.has(t))
1312
+ return t;
1313
+ if (t instanceof Node) {
1314
+ const e = document.createElement("div");
1315
+ return e.append(t), e;
1316
+ } else {
1317
+ const e = document.createElement("div");
1318
+ for (const s of [...t])
1319
+ e.append(s);
1320
+ return e;
1321
+ }
1322
+ }
1323
+ function cs(t, e, s) {
1324
+ const n = [], r = [];
1325
+ for (; t; )
1326
+ n.push(t), t = t.previousSibling;
1327
+ for (; n.length > 0; ) {
1328
+ const o = n.pop();
1329
+ r.push(o), e?.parentElement?.insertBefore(o, e);
1330
+ }
1331
+ for (r.push(e); s; )
1332
+ n.push(s), r.push(s), s = s.nextSibling;
1333
+ for (; n.length; )
1334
+ e?.parentElement?.insertBefore(n.pop(), e.nextSibling);
1335
+ return r;
1336
+ }
1337
+ function us(t, e, s) {
1338
+ let n = t.firstChild, r = n, o = 0;
1339
+ for (; n; ) {
1340
+ let i = fs(n, e, s);
1341
+ i > o && (r = n, o = i), n = n.nextSibling;
1342
+ }
1343
+ return r;
1344
+ }
1345
+ function fs(t, e, s) {
1346
+ return ce(t, e) ? 0.5 + z(s, t, e) : 0;
1347
+ }
1348
+ function pt(t, e) {
1349
+ x(e, t), e.callbacks.beforeNodeRemoved(t) !== false && (t.remove(), e.callbacks.afterNodeRemoved(t));
1350
+ }
1351
+ function ds(t, e) {
1352
+ return !t.deadIds.has(e);
1353
+ }
1354
+ function hs(t, e, s) {
1355
+ return t.idMap.get(s)?.has(e) || false;
1356
+ }
1357
+ function x(t, e) {
1358
+ const s = t.idMap.get(e);
1359
+ if (s)
1360
+ for (const n of s)
1361
+ t.deadIds.add(n);
1362
+ }
1363
+ function z(t, e, s) {
1364
+ const n = t.idMap.get(e);
1365
+ if (!n)
1366
+ return 0;
1367
+ let r = 0;
1368
+ for (const o of n)
1369
+ ds(t, o) && hs(t, o, s) && ++r;
1370
+ return r;
1371
+ }
1372
+ function Fe(t, e) {
1373
+ const s = t.parentElement, n = t.querySelectorAll("[id]");
1374
+ for (const r of n) {
1375
+ let o = r;
1376
+ for (; o !== s && o; ) {
1377
+ let i = e.get(o);
1378
+ i == null && (i = /* @__PURE__ */ new Set(), e.set(o, i)), i.add(r.id), o = o.parentElement;
1379
+ }
1380
+ }
1381
+ }
1382
+ function ps(t, e) {
1383
+ const s = /* @__PURE__ */ new Map();
1384
+ return Fe(t, s), Fe(e, s), s;
1385
+ }
1386
+ const ge = "display", He = "none", ve = "important", Ve = "duration", ms = "show", be = `${k}showing`, ye = `${k}hiding`, xe = `${k}show-transition-style`, gs = {
1387
+ prefix: ms,
1388
+ allowedModifiers: /* @__PURE__ */ new Set([ve, Ve]),
1389
+ onLoad: (t) => {
1390
+ const { el: e, modifiers: s, expressionFn: n, reactivity: r } = t, i = s.has(ve) ? ve : void 0;
1391
+ let f, l;
1392
+ const g = t.modifiers.get(Ve);
1393
+ if (g) {
1394
+ let c = document.getElementById(xe);
1395
+ if (!c) {
1396
+ c = document.createElement("style"), c.id = xe, document.head.appendChild(c);
1397
+ const v = _e(g) || "300";
1398
+ c.innerHTML = `
1399
+ .${be} {
1400
+ visibility: visible;
1401
+ transition: opacity ${v}ms linear;
1402
+ }
1403
+ .${ye} {
1404
+ visibility: hidden;
1405
+ transition: visibility 0s ${v}ms, opacity ${v}ms linear;
1406
+ }
1407
+ `;
1408
+ }
1409
+ const d = (v) => (u) => {
1410
+ u.target === e && (e.classList.remove(v), e.removeEventListener("transitionend", d(v)));
1411
+ };
1412
+ f = () => {
1413
+ e.addEventListener("transitionend", d(be)), e.classList.add(be), requestAnimationFrame(() => {
1414
+ e.style.setProperty("opacity", "1", i);
1415
+ });
1416
+ }, l = () => {
1417
+ e.addEventListener("transitionend", d(ye)), e.classList.add(ye), requestAnimationFrame(() => {
1418
+ e.style.setProperty("opacity", "0", i);
1419
+ });
1420
+ };
1421
+ } else
1422
+ f = () => {
1423
+ e.style.length === 1 && e.style.display === He ? e.style.removeProperty(ge) : e.style.setProperty(ge, "", i);
1424
+ }, l = () => {
1425
+ e.style.setProperty(ge, He, i);
1426
+ };
1427
+ return r.effect(async () => {
1428
+ !!await n(t) ? f() : l();
1429
+ });
1430
+ }
1431
+ }, vs = "intersects", je = "once", Ue = "half", Be = "full", bs = {
1432
+ prefix: vs,
1433
+ allowedModifiers: /* @__PURE__ */ new Set([je, Ue, Be]),
1434
+ mustHaveEmptyKey: true,
1435
+ onLoad: (t) => {
1436
+ const { modifiers: e } = t, s = { threshold: 0 };
1437
+ e.has(Be) ? s.threshold = 1 : e.has(Ue) && (s.threshold = 0.5);
1438
+ const n = new IntersectionObserver((r) => {
1439
+ r.forEach((o) => {
1440
+ o.isIntersecting && (t.expressionFn(t), e.has(je) && (n.disconnect(), delete t.el.dataset[t.rawKey]));
1441
+ });
1442
+ }, s);
1443
+ return n.observe(t.el), () => n.disconnect();
1444
+ }
1445
+ }, We = "prepend", qe = "append", Je = new Error("Target element must have a parent if using prepend or append"), ys = {
1446
+ prefix: "teleport",
1447
+ allowedModifiers: /* @__PURE__ */ new Set([We, qe]),
1448
+ allowedTagRegexps: /* @__PURE__ */ new Set(["template"]),
1449
+ bypassExpressionFunctionCreation: () => true,
1450
+ onLoad: (t) => {
1451
+ const { el: e, modifiers: s, expression: n } = t;
1452
+ if (!(e instanceof HTMLTemplateElement))
1453
+ throw new Error("el must be a template element");
1454
+ const r = document.querySelector(n);
1455
+ if (!r)
1456
+ throw new Error(`Target element not found: ${n}`);
1457
+ if (!e.content)
1458
+ throw new Error("Template element must have content");
1459
+ const o = e.content.cloneNode(true);
1460
+ if (ze(o)?.firstElementChild)
1461
+ throw new Error("Empty template");
1462
+ if (s.has(We)) {
1463
+ if (!r.parentNode)
1464
+ throw Je;
1465
+ r.parentNode.insertBefore(o, r);
1466
+ } else if (s.has(qe)) {
1467
+ if (!r.parentNode)
1468
+ throw Je;
1469
+ r.parentNode.insertBefore(o, r.nextSibling);
1470
+ } else
1471
+ r.appendChild(o);
1472
+ }
1473
+ }, ws = {
1474
+ prefix: "scrollIntoView",
1475
+ mustHaveEmptyKey: true,
1476
+ mustHaveEmptyExpression: true,
1477
+ allowedModifiers: /* @__PURE__ */ new Set([
1478
+ "smooth",
1479
+ "instant",
1480
+ "auto",
1481
+ "hstart",
1482
+ "hcenter",
1483
+ "hend",
1484
+ "hnearest",
1485
+ "vstart",
1486
+ "vcenter",
1487
+ "vend",
1488
+ "vnearest",
1489
+ "focus"
1490
+ ]),
1491
+ onLoad: ({ el: t, modifiers: e, rawKey: s }) => {
1492
+ t.tabIndex || t.setAttribute("tabindex", "0");
1493
+ const n = {
1494
+ behavior: "smooth",
1495
+ block: "center",
1496
+ inline: "center"
1497
+ };
1498
+ return e.has("smooth") && (n.behavior = "smooth"), e.has("instant") && (n.behavior = "instant"), e.has("auto") && (n.behavior = "auto"), e.has("hstart") && (n.inline = "start"), e.has("hcenter") && (n.inline = "center"), e.has("hend") && (n.inline = "end"), e.has("hnearest") && (n.inline = "nearest"), e.has("vstart") && (n.block = "start"), e.has("vcenter") && (n.block = "center"), e.has("vend") && (n.block = "end"), e.has("vnearest") && (n.block = "nearest"), vt(t, n, e.has("focus")), delete t.dataset[s], () => {
1499
+ };
1500
+ }
1501
+ }, mt = document, gt = !!mt.startViewTransition, Es = {
1502
+ prefix: "viewTransition",
1503
+ onGlobalInit() {
1504
+ let t = false;
1505
+ if (document.head.childNodes.forEach((e) => {
1506
+ e instanceof HTMLMetaElement && e.name === "view-transition" && (t = true);
1507
+ }), !t) {
1508
+ const e = document.createElement("meta");
1509
+ e.name = "view-transition", e.content = "same-origin", document.head.appendChild(e);
1510
+ }
1511
+ },
1512
+ onLoad: (t) => {
1513
+ if (!gt) {
1514
+ console.error("Browser does not support view transitions");
1515
+ return;
1516
+ }
1517
+ return t.reactivity.effect(() => {
1518
+ const { el: e, expressionFn: s } = t;
1519
+ let n = s(t);
1520
+ if (!n)
1521
+ return;
1522
+ const r = e.style;
1523
+ r.viewTransitionName = n;
1524
+ });
1525
+ }
1526
+ }, _s = [
1527
+ gs,
1528
+ bs,
1529
+ ys,
1530
+ ws,
1531
+ Es
1532
+ ], Ss = {
1533
+ scroll: async (t, e, s) => {
1534
+ const n = Object.assign(
1535
+ { behavior: "smooth", vertical: "center", horizontal: "center", shouldFocus: true },
1536
+ s
1537
+ ), r = document.querySelector(e);
1538
+ vt(r, n);
1539
+ }
1540
+ };
1541
+ function vt(t, e, s = true) {
1542
+ if (!(t instanceof HTMLElement || t instanceof SVGElement))
1543
+ throw new Error("Element not found");
1544
+ t.tabIndex || t.setAttribute("tabindex", "0"), t.scrollIntoView(e), s && t.focus();
1545
+ }
1546
+ const Ts = 500, As = true, Ns = "morph", Ls = "Content-Type", ks = `${U}-request`, Ms = "application/json", Ps = "true", $s = `${k}fragment`, Os = `${k}signal`, Is = `${k}delete`, Rs = `${k}redirect`, Cs = `${k}console`, Z = `${k}indicator`, Te = `${Z}-loading`, Ke = `${k}settling`, re = `${k}swapping`, Ds = "self", Fs = "get", Hs = "post", Vs = "put", xs = "patch", js = "delete", I = {
1547
+ MorphElement: "morph",
1548
+ InnerElement: "inner",
1549
+ OuterElement: "outer",
1550
+ PrependElement: "prepend",
1551
+ AppendElement: "append",
1552
+ BeforeElement: "before",
1553
+ AfterElement: "after",
1554
+ UpsertAttributes: "upsert_attributes"
1555
+ }, Us = {
1556
+ prefix: "fetchIndicator",
1557
+ mustHaveEmptyKey: true,
1558
+ mustNotEmptyExpression: true,
1559
+ onGlobalInit: () => {
1560
+ const t = document.createElement("style");
1561
+ t.innerHTML = `
1562
+ .${Z}{
1563
+ opacity:0;
1564
+ transition: opacity 300ms ease-out;
1565
+ }
1566
+ .${Te} {
1567
+ opacity:1;
1568
+ transition: opacity 300ms ease-in;
1569
+ }
1570
+ `, document.head.appendChild(t);
1571
+ },
1572
+ onLoad: (t) => t.reactivity.effect(() => {
1573
+ t.upsertIfMissingFromStore("_dsPlugins.fetch.indicatorElements", {}), t.upsertIfMissingFromStore("_dsPlugins.fetch.indicatorsVisible", []);
1574
+ const e = t.reactivity.computed(() => `${t.expressionFn(t)}`), s = t.store(), n = document.querySelectorAll(e.value);
1575
+ if (n.length === 0)
1576
+ throw new Error("No indicator found");
1577
+ return n.forEach((r) => {
1578
+ r.classList.add(Z);
1579
+ }), s._dsPlugins.fetch.indicatorElements[t.el.id] = t.reactivity.signal(n), () => {
1580
+ delete s._dsPlugins.fetch.indicatorElements[t.el.id];
1581
+ };
1582
+ })
1583
+ }, Bs = {
1584
+ prefix: "header",
1585
+ mustNotEmptyKey: true,
1586
+ mustNotEmptyExpression: true,
1587
+ preprocessors: {
1588
+ post: [
1589
+ {
1590
+ regexp: /(?<whole>.+)/g,
1591
+ replacer: (t) => {
1592
+ const { whole: e } = t;
1593
+ return `'${e}'`;
1594
+ }
1595
+ }
1596
+ ]
1597
+ },
1598
+ onLoad: (t) => {
1599
+ t.upsertIfMissingFromStore("_dsPlugins.fetch.headers", {});
1600
+ const e = t.key.replace(/([a-z](?=[A-Z]))/g, "$1-").toUpperCase(), s = t.expressionFn(t);
1601
+ return t.store()._dsPlugins.fetch.headers[e] = s, () => {
1602
+ delete t.store()._dsPlugins.fetch.headers[e];
1603
+ };
1604
+ }
1605
+ }, Ws = [Us, Bs];
1606
+ async function qs(t, e, s, n = true) {
1607
+ const r = s.store();
1608
+ if (!e)
1609
+ throw new Error(`No signal for ${t} on ${e}`);
1610
+ let o = { ...r.value };
1611
+ n && (o = he(o));
1612
+ const i = JSON.stringify(o), f = s.el;
1613
+ N(
1614
+ "plugin",
1615
+ "backend",
1616
+ "fetch_start",
1617
+ f,
1618
+ JSON.stringify({ method: t, urlExpression: e, onlyRemote: n, storeJSON: i })
1619
+ );
1620
+ const l = r?._dsPlugins?.fetch?.indicatorElements ? r._dsPlugins.fetch.indicatorElements[f.id]?.value || [] : [], g = r?._dsPlugins.fetch?.indicatorsVisible;
1621
+ l?.forEach && l.forEach((u) => {
1622
+ if (!u || !g)
1623
+ return;
1624
+ const E = g.value.findIndex((y) => y ? u.isSameNode(y.el) : false);
1625
+ if (E > -1) {
1626
+ const y = g.value[E], h = [...g.value];
1627
+ delete h[E], g.value = [
1628
+ ...h.filter((p) => !!p),
1629
+ { el: u, count: y.count + 1 }
1630
+ ];
1631
+ } else
1632
+ u.classList.remove(Z), u.classList.add(Te), g.value = [
1633
+ ...g.value,
1634
+ {
1635
+ el: u,
1636
+ count: 1
1637
+ }
1638
+ ];
1639
+ });
1640
+ const c = new URL(e, window.location.origin);
1641
+ t = t.toUpperCase();
1642
+ const d = {
1643
+ method: t,
1644
+ headers: {
1645
+ [Ls]: Ms,
1646
+ [ks]: Ps
1647
+ },
1648
+ onmessage: (u) => {
1649
+ if (u.event) {
1650
+ if (!u.event.startsWith(k)) {
1651
+ console.log(`Unknown event: ${u.event}`);
1652
+ debugger;
1653
+ }
1654
+ } else
1655
+ return;
1656
+ switch (u.event) {
1657
+ case $s:
1658
+ const E = u.data.trim().split(`
1659
+ `), y = ["selector", "merge", "settle", "fragment", "vt"];
1660
+ let h = "", p = Ns, a = Ts, b = As, w = false, m = "", S = "";
1661
+ for (let L = 0; L < E.length; L++) {
1662
+ let A = E[L];
1663
+ if (!A?.length)
1664
+ continue;
1665
+ const M = A.split(" ", 1)[0];
1666
+ if (y.includes(M) && M !== S)
1667
+ switch (S = M, A = A.slice(M.length + 1), S) {
1668
+ case "selector":
1669
+ m = A;
1670
+ break;
1671
+ case "merge":
1672
+ if (p = A, w = Object.values(I).includes(p), !w)
1673
+ throw new Error(`Unknown merge option: ${p}`);
1674
+ break;
1675
+ case "settle":
1676
+ a = parseInt(A);
1677
+ break;
1678
+ case "fragment":
1679
+ break;
1680
+ case "vt":
1681
+ b = A === "true";
1682
+ break;
1683
+ default:
1684
+ throw new Error("Unknown data type");
1685
+ }
1686
+ S === "fragment" && (h += A + `
1687
+ `);
1688
+ }
1689
+ h?.length || (h = "<div></div>"), Js(s, m, p, h, a, b), N(
1690
+ "plugin",
1691
+ "backend",
1692
+ "merge",
1693
+ m,
1694
+ JSON.stringify({ fragment: h, settleTime: a, useViewTransition: b })
1695
+ );
1696
+ break;
1697
+ case Os:
1698
+ let P = false, C = "";
1699
+ const D = u.data.trim().split(`
1700
+ `);
1701
+ for (let L = 0; L < D.length; L++) {
1702
+ const A = D[L], [M, ...ee] = A.split(" "), me = ee.join(" ");
1703
+ switch (M) {
1704
+ case "onlyIfMissing":
1705
+ P = me.trim() === "true";
1706
+ break;
1707
+ case "store":
1708
+ C += `${me}
1709
+ `;
1710
+ break;
1711
+ default:
1712
+ throw new Error(`Unknown signal type: ${M}`);
1713
+ }
1714
+ }
1715
+ const V = ` return Object.assign({...ctx.store()}, ${C})`;
1716
+ try {
1717
+ const A = new Function("ctx", V)(s), M = lt(s.store(), A, P);
1718
+ s.mergeStore(M), s.applyPlugins(document.body);
1719
+ } catch (L) {
1720
+ console.log(V), console.error(L);
1721
+ debugger;
1722
+ }
1723
+ break;
1724
+ case Is:
1725
+ const [Q, ...$] = u.data.trim().split(" ");
1726
+ switch (Q) {
1727
+ case "selector":
1728
+ const L = $.join(" ");
1729
+ document.querySelectorAll(L).forEach((ee) => ee.remove());
1730
+ break;
1731
+ case "paths":
1732
+ const M = $.join(" ").split(" ");
1733
+ s.removeFromStore(...M);
1734
+ break;
1735
+ default:
1736
+ throw new Error(`Unknown delete prefix: ${Q}`);
1737
+ }
1738
+ break;
1739
+ case Rs:
1740
+ const [j, ...yt] = u.data.trim().split(" ");
1741
+ if (j !== "url")
1742
+ throw new Error(`Unknown redirect selector: ${j}`);
1743
+ const Me = yt.join(" ");
1744
+ N("plugin", "backend", "redirect", "WINDOW", Me), window.location.href = Me;
1745
+ break;
1746
+ case Cs:
1747
+ const [pe, ...wt] = u.data.trim().split(" "), Pe = wt.join(" ");
1748
+ switch (pe) {
1749
+ case "debug":
1750
+ case "error":
1751
+ case "info":
1752
+ case "group":
1753
+ case "groupEnd":
1754
+ case "log":
1755
+ case "warn":
1756
+ console[pe](Pe);
1757
+ break;
1758
+ default:
1759
+ throw new Error(`Unknown console mode: '${pe}', message: '${Pe}'`);
1760
+ }
1761
+ }
1762
+ },
1763
+ onerror: (u) => {
1764
+ console.error(u);
1765
+ },
1766
+ onclose: () => {
1767
+ try {
1768
+ const u = s.store(), E = u?._dsPlugins?.fetch?.indicatorsVisible || [], y = u?._dsPlugins?.fetch?.indicatorElements ? u._dsPlugins.fetch.indicatorElements[f.id]?.value || [] : [], h = [];
1769
+ y?.forEach && y.forEach((p) => {
1770
+ if (!p || !E)
1771
+ return;
1772
+ const a = E.value, b = a.findIndex((m) => m ? p.isSameNode(m.el) : !1), w = a[b];
1773
+ w && (w.count < 2 ? (h.push(
1774
+ new Promise(
1775
+ () => setTimeout(() => {
1776
+ p.classList.remove(Te), p.classList.add(Z);
1777
+ }, 300)
1778
+ )
1779
+ ), delete a[b]) : b > -1 && (a[b].count = a[b].count - 1), E.value = a.filter((m) => !!m));
1780
+ }), Promise.all(h);
1781
+ } catch (u) {
1782
+ console.error(u);
1783
+ debugger;
1784
+ } finally {
1785
+ N("plugin", "backend", "fetch_end", f, JSON.stringify({ method: t, urlExpression: e }));
1786
+ }
1787
+ }
1788
+ };
1789
+ if (t === "GET") {
1790
+ const u = new URLSearchParams(c.search);
1791
+ u.append("datastar", i), c.search = u.toString();
1792
+ } else
1793
+ d.body = i;
1794
+ const v = r?._dsPlugins?.fetch?.headers || {};
1795
+ if (d.headers)
1796
+ for (const [u, E] of Object.entries(v))
1797
+ u.startsWith("_") || (d.headers[u] = `${E}`);
1798
+ Gt(c, d);
1799
+ }
1800
+ const Ge = document.createElement("template");
1801
+ function Js(t, e, s, n, r, o) {
1802
+ const { el: i } = t;
1803
+ Ge.innerHTML = n.trim(), [...Ge.content.children].forEach((l) => {
1804
+ if (!(l instanceof Element))
1805
+ throw new Error("No fragment found");
1806
+ const g = (u) => {
1807
+ for (const E of u) {
1808
+ E.classList.add(re);
1809
+ const y = E.outerHTML;
1810
+ let h = E;
1811
+ switch (s) {
1812
+ case I.MorphElement:
1813
+ const a = ss(h, l, {
1814
+ callbacks: {
1815
+ beforeNodeRemoved: (w, m) => (t.cleanupElementRemovals(w), true)
1816
+ }
1817
+ });
1818
+ if (!a?.length)
1819
+ throw new Error("No morph result");
1820
+ h = a[0];
1821
+ break;
1822
+ case I.InnerElement:
1823
+ h.innerHTML = l.innerHTML;
1824
+ break;
1825
+ case I.OuterElement:
1826
+ h.replaceWith(l);
1827
+ break;
1828
+ case I.PrependElement:
1829
+ h.prepend(l);
1830
+ break;
1831
+ case I.AppendElement:
1832
+ h.append(l);
1833
+ break;
1834
+ case I.BeforeElement:
1835
+ h.before(l);
1836
+ break;
1837
+ case I.AfterElement:
1838
+ h.after(l);
1839
+ break;
1840
+ case I.UpsertAttributes:
1841
+ l.getAttributeNames().forEach((w) => {
1842
+ const m = l.getAttribute(w);
1843
+ h.setAttribute(w, m);
1844
+ });
1845
+ break;
1846
+ default:
1847
+ throw new Error(`Unknown merge type: ${s}`);
1848
+ }
1849
+ t.cleanupElementRemovals(h), h.classList.add(re), t.applyPlugins(document.body), setTimeout(() => {
1850
+ E.classList.remove(re), h.classList.remove(re);
1851
+ }, r);
1852
+ const p = h.outerHTML;
1853
+ y !== p && (h.classList.add(Ke), setTimeout(() => {
1854
+ h.classList.remove(Ke);
1855
+ }, r));
1856
+ }
1857
+ }, c = e === Ds;
1858
+ let d;
1859
+ if (c)
1860
+ d = [i];
1861
+ else {
1862
+ const u = e || `#${l.getAttribute("id")}`;
1863
+ if (d = document.querySelectorAll(u) || [], !d)
1864
+ throw new Error(`No targets found for ${u}`);
1865
+ }
1866
+ const v = [...d];
1867
+ if (!v.length)
1868
+ throw new Error(`No targets found for ${e}`);
1869
+ gt && o ? mt.startViewTransition(() => g(v)) : g(v);
1870
+ });
1871
+ }
1872
+ const Ks = [Fs, Hs, Vs, xs, js].reduce(
1873
+ (t, e) => (t[e] = (s, n, r) => {
1874
+ const o = ["true", true, void 0].includes(r);
1875
+ qs(e, n, s, o);
1876
+ }, t),
1877
+ {
1878
+ isFetching: (t, e) => {
1879
+ const s = [...document.querySelectorAll(e)], r = t.store()?._dsPlugins?.fetch.indicatorsVisible?.value || [];
1880
+ return s.length ? s.some((o) => r.filter((i) => !!i).some((i) => i.el.isSameNode(o) && i.count > 0)) : false;
1881
+ }
1882
+ }
1883
+ ), Ye = "0.19.9", ke = (t, e, s, n, r, o) => (e - s) / (n - s) * (o - r) + r, Gs = (t, e, s, n, r, o) => Math.round(ke(t, e, s, n, r, o)), bt = (t, e, s, n, r, o) => Math.max(r, Math.min(o, ke(t, e, s, n, r, o))), Ys = (t, e, s, n, r, o) => Math.round(bt(t, e, s, n, r, o)), zs = {
1884
+ setAll: (t, e, s) => {
1885
+ const n = new RegExp(e);
1886
+ t.walkSignals((r, o) => n.test(r) && (o.value = s));
1887
+ },
1888
+ toggleAll: (t, e) => {
1889
+ const s = new RegExp(e);
1890
+ t.walkSignals((n, r) => s.test(n) && (r.value = !r.value));
1891
+ },
1892
+ clipboard: (t, e) => {
1893
+ if (!navigator.clipboard)
1894
+ throw new Error("Clipboard API not available");
1895
+ navigator.clipboard.writeText(e);
1896
+ },
1897
+ fit: ke,
1898
+ fitInt: Gs,
1899
+ clampFit: bt,
1900
+ clampFitInt: Ys
1901
+ };
1902
+ function Zs(t = {}, ...e) {
1903
+ const s = new Dt(t, ...e);
1904
+ return s.run(), s;
1905
+ }
1906
+ function Xs(t = {}, ...e) {
1907
+ const s = Object.assign(
1908
+ {},
1909
+ zs,
1910
+ qt,
1911
+ Ks,
1912
+ Ss,
1913
+ t
1914
+ ), n = [...Ws, ..._s, ...Wt, ...e];
1915
+ return Zs(s, ...n);
1916
+ }
1917
+ const Qs = {
1918
+ bubbles: true,
1919
+ cancelable: true,
1920
+ composed: true
1921
+ }, Ae = window, N = (t, e, s, n, r, o = Qs) => {
1922
+ Ae.dispatchEvent(
1923
+ new CustomEvent(
1924
+ q,
1925
+ Object.assign(
1926
+ {
1927
+ detail: {
1928
+ time: /* @__PURE__ */ new Date(),
1929
+ category: t,
1930
+ subcategory: e,
1931
+ type: s,
1932
+ target: at(n),
1933
+ message: r
1934
+ }
1935
+ },
1936
+ o
1937
+ )
1938
+ )
1939
+ );
1940
+ };
1941
+ Ae.ds || setTimeout(() => {
1942
+ N("core", "init", "start", document.body, `Datastar v${Ye} loading`);
1943
+ const t = performance.now();
1944
+ Ae.ds = Xs();
1945
+ const e = performance.now();
1946
+ N(
1947
+ "core",
1948
+ "init",
1949
+ "end",
1950
+ document.body,
1951
+ `Datastar v${Ye} loaded and attached to all DOM elements in ${(e - t).toFixed(2)}ms`
1952
+ );
1953
+ const s = document.createElement("style");
1954
+ s.innerHTML = `
1955
+ .datastar-inspector-highlight {
1956
+ border: 2px solid blue;
1957
+ }
1958
+ `, document.head.appendChild(s), window.addEventListener("datastar-inspector-event", (n) => {
1959
+ if ("detail" in n && typeof n.detail == "object" && n.detail) {
1960
+ const { detail: r } = n;
1961
+ if ("script" in r && typeof r.script == "string")
1962
+ try {
1963
+ new Function(r.script)();
1964
+ } catch (o) {
1965
+ console.error(o);
1966
+ }
1967
+ }
1968
+ });
1969
+ }, 0);
1970
+
1971
+ (() => {
1972
+ const componentRegistry = {};
1973
+ let observer = null;
1974
+
1975
+ const registerComponent = (name, selector, initFunction) => {
1976
+ componentRegistry[name] = {
1977
+ selector,
1978
+ init: initFunction
1979
+ };
1980
+ };
1981
+
1982
+ const initAllComponents = () => {
1983
+ Object.entries(componentRegistry).forEach(([name, { selector, init }]) => {
1984
+ document.querySelectorAll(selector).forEach(init);
1985
+ });
1986
+ };
1987
+
1988
+ const initNewComponents = (node) => {
1989
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
1990
+
1991
+ Object.entries(componentRegistry).forEach(([name, { selector, init }]) => {
1992
+ if (node.matches(selector)) {
1993
+ init(node);
1994
+ }
1995
+ node.querySelectorAll(selector).forEach(init);
1996
+ });
1997
+ };
1998
+
1999
+ const startObserver = () => {
2000
+ if (observer) return;
2001
+
2002
+ observer = new MutationObserver((mutations) => {
2003
+ mutations.forEach((mutation) => {
2004
+ mutation.addedNodes.forEach(initNewComponents);
2005
+ });
2006
+ });
2007
+
2008
+ observer.observe(document.body, { childList: true, subtree: true });
2009
+ };
2010
+
2011
+ const stopObserver = () => {
2012
+ if (observer) {
2013
+ observer.disconnect();
2014
+ observer = null;
2015
+ }
2016
+ };
2017
+
2018
+ const reinitComponent = (componentName) => {
2019
+ const component = componentRegistry[componentName];
2020
+ if (!component) {
2021
+ console.warn(`Component '${componentName}' not found in registry`);
2022
+ return;
2023
+ }
2024
+
2025
+ // Clear initialization flag for this component
2026
+ const flag = `data-${componentName}-initialized`;
2027
+ document.querySelectorAll(`[${flag}]`).forEach(el => {
2028
+ el.removeAttribute(flag);
2029
+ });
2030
+
2031
+ document.querySelectorAll(component.selector).forEach(component.init);
2032
+ };
2033
+
2034
+ const reinitAll = () => {
2035
+ // Clear all initialization flags using the registry
2036
+ Object.entries(componentRegistry).forEach(([name, { selector }]) => {
2037
+ const flag = `data-${name}-initialized`;
2038
+ document.querySelectorAll(`[${flag}]`).forEach(el => {
2039
+ el.removeAttribute(flag);
2040
+ });
2041
+ });
2042
+
2043
+ initAllComponents();
2044
+ };
2045
+
2046
+ window.basecoat = {
2047
+ register: registerComponent,
2048
+ init: reinitComponent,
2049
+ initAll: reinitAll,
2050
+ start: startObserver,
2051
+ stop: stopObserver
2052
+ };
2053
+
2054
+ document.addEventListener('DOMContentLoaded', () => {
2055
+ initAllComponents();
2056
+ startObserver();
2057
+ });
2058
+ })();
2059
+ (() => {
2060
+ const initCommand = (container) => {
2061
+ const input = container.querySelector('header input');
2062
+ const menu = container.querySelector('[role="menu"]');
2063
+
2064
+ if (!input || !menu) {
2065
+ const missing = [];
2066
+ if (!input) missing.push('input');
2067
+ if (!menu) missing.push('menu');
2068
+ console.error(`Command component initialization failed. Missing element(s): ${missing.join(', ')}`, container);
2069
+ return;
2070
+ }
2071
+
2072
+ const allMenuItems = Array.from(menu.querySelectorAll('[role="menuitem"]'));
2073
+ const menuItems = allMenuItems.filter(item =>
2074
+ !item.hasAttribute('disabled') &&
2075
+ item.getAttribute('aria-disabled') !== 'true'
2076
+ );
2077
+ let visibleMenuItems = [...menuItems];
2078
+ let activeIndex = -1;
2079
+
2080
+ const setActiveItem = (index) => {
2081
+ if (activeIndex > -1 && menuItems[activeIndex]) {
2082
+ menuItems[activeIndex].classList.remove('active');
2083
+ }
2084
+
2085
+ activeIndex = index;
2086
+
2087
+ if (activeIndex > -1) {
2088
+ const activeItem = menuItems[activeIndex];
2089
+ activeItem.classList.add('active');
2090
+ if (activeItem.id) {
2091
+ input.setAttribute('aria-activedescendant', activeItem.id);
2092
+ } else {
2093
+ input.removeAttribute('aria-activedescendant');
2094
+ }
2095
+ } else {
2096
+ input.removeAttribute('aria-activedescendant');
2097
+ }
2098
+ };
2099
+
2100
+ const filterMenuItems = () => {
2101
+ const searchTerm = input.value.trim().toLowerCase();
2102
+
2103
+ setActiveItem(-1);
2104
+
2105
+ visibleMenuItems = [];
2106
+ allMenuItems.forEach(item => {
2107
+ if (item.hasAttribute('data-force')) {
2108
+ item.setAttribute('aria-hidden', 'false');
2109
+ if (menuItems.includes(item)) {
2110
+ visibleMenuItems.push(item);
2111
+ }
2112
+ return;
2113
+ }
2114
+
2115
+ const itemText = (item.dataset.filter || item.textContent).trim().toLowerCase();
2116
+ const keywordList = (item.dataset.keywords || '')
2117
+ .toLowerCase()
2118
+ .split(/[\s,]+/)
2119
+ .filter(Boolean);
2120
+ const matchesKeyword = keywordList.some(keyword => keyword.includes(searchTerm));
2121
+ const matches = itemText.includes(searchTerm) || matchesKeyword;
2122
+ item.setAttribute('aria-hidden', String(!matches));
2123
+ if (matches && menuItems.includes(item)) {
2124
+ visibleMenuItems.push(item);
2125
+ }
2126
+ });
2127
+
2128
+ if (visibleMenuItems.length > 0) {
2129
+ setActiveItem(menuItems.indexOf(visibleMenuItems[0]));
2130
+ visibleMenuItems[0].scrollIntoView({ block: 'nearest' });
2131
+ }
2132
+ };
2133
+
2134
+ input.addEventListener('input', filterMenuItems);
2135
+
2136
+ const handleKeyNavigation = (event) => {
2137
+ if (!['ArrowDown', 'ArrowUp', 'Enter', 'Home', 'End'].includes(event.key)) {
2138
+ return;
2139
+ }
2140
+
2141
+ if (event.key === 'Enter') {
2142
+ event.preventDefault();
2143
+ if (activeIndex > -1) {
2144
+ menuItems[activeIndex]?.click();
2145
+ }
2146
+ return;
2147
+ }
2148
+
2149
+ if (visibleMenuItems.length === 0) return;
2150
+
2151
+ event.preventDefault();
2152
+
2153
+ const currentVisibleIndex = activeIndex > -1 ? visibleMenuItems.indexOf(menuItems[activeIndex]) : -1;
2154
+ let nextVisibleIndex = currentVisibleIndex;
2155
+
2156
+ switch (event.key) {
2157
+ case 'ArrowDown':
2158
+ if (currentVisibleIndex < visibleMenuItems.length - 1) {
2159
+ nextVisibleIndex = currentVisibleIndex + 1;
2160
+ }
2161
+ break;
2162
+ case 'ArrowUp':
2163
+ if (currentVisibleIndex > 0) {
2164
+ nextVisibleIndex = currentVisibleIndex - 1;
2165
+ } else if (currentVisibleIndex === -1) {
2166
+ nextVisibleIndex = 0;
2167
+ }
2168
+ break;
2169
+ case 'Home':
2170
+ nextVisibleIndex = 0;
2171
+ break;
2172
+ case 'End':
2173
+ nextVisibleIndex = visibleMenuItems.length - 1;
2174
+ break;
2175
+ }
2176
+
2177
+ if (nextVisibleIndex !== currentVisibleIndex) {
2178
+ const newActiveItem = visibleMenuItems[nextVisibleIndex];
2179
+ setActiveItem(menuItems.indexOf(newActiveItem));
2180
+ newActiveItem.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
2181
+ }
2182
+ };
2183
+
2184
+ menu.addEventListener('mousemove', (event) => {
2185
+ const menuItem = event.target.closest('[role="menuitem"]');
2186
+ if (menuItem && visibleMenuItems.includes(menuItem)) {
2187
+ const index = menuItems.indexOf(menuItem);
2188
+ if (index !== activeIndex) {
2189
+ setActiveItem(index);
2190
+ }
2191
+ }
2192
+ });
2193
+
2194
+ menu.addEventListener('click', (event) => {
2195
+ const clickedItem = event.target.closest('[role="menuitem"]');
2196
+ if (clickedItem && visibleMenuItems.includes(clickedItem)) {
2197
+ const dialog = container.closest('dialog.command-dialog');
2198
+ if (dialog && !clickedItem.hasAttribute('data-keep-command-open')) {
2199
+ dialog.close();
2200
+ }
2201
+ }
2202
+ });
2203
+
2204
+ input.addEventListener('keydown', handleKeyNavigation);
2205
+
2206
+ if (visibleMenuItems.length > 0) {
2207
+ setActiveItem(menuItems.indexOf(visibleMenuItems[0]));
2208
+ visibleMenuItems[0].scrollIntoView({ block: 'nearest' });
2209
+ }
2210
+
2211
+ container.dataset.commandInitialized = true;
2212
+ container.dispatchEvent(new CustomEvent('basecoat:initialized'));
2213
+ };
2214
+
2215
+ if (window.basecoat) {
2216
+ window.basecoat.register('command', '.command:not([data-command-initialized])', initCommand);
2217
+ }
2218
+ })();
2219
+
2220
+ (() => {
2221
+ const initDropdownMenu = (dropdownMenuComponent) => {
2222
+ const trigger = dropdownMenuComponent.querySelector(':scope > button');
2223
+ const popover = dropdownMenuComponent.querySelector(':scope > [data-popover]');
2224
+ const menu = popover.querySelector('[role="menu"]');
2225
+
2226
+ if (!trigger || !menu || !popover) {
2227
+ const missing = [];
2228
+ if (!trigger) missing.push('trigger');
2229
+ if (!menu) missing.push('menu');
2230
+ if (!popover) missing.push('popover');
2231
+ console.error(`Dropdown menu initialisation failed. Missing element(s): ${missing.join(', ')}`, dropdownMenuComponent);
2232
+ return;
2233
+ }
2234
+
2235
+ let menuItems = [];
2236
+ let activeIndex = -1;
2237
+
2238
+ const closePopover = (focusOnTrigger = true) => {
2239
+ if (trigger.getAttribute('aria-expanded') === 'false') return;
2240
+ trigger.setAttribute('aria-expanded', 'false');
2241
+ trigger.removeAttribute('aria-activedescendant');
2242
+ popover.setAttribute('aria-hidden', 'true');
2243
+
2244
+ if (focusOnTrigger) {
2245
+ trigger.focus();
2246
+ }
2247
+
2248
+ setActiveItem(-1);
2249
+ };
2250
+
2251
+ const openPopover = (initialSelection = false) => {
2252
+ document.dispatchEvent(new CustomEvent('basecoat:popover', {
2253
+ detail: { source: dropdownMenuComponent }
2254
+ }));
2255
+
2256
+ trigger.setAttribute('aria-expanded', 'true');
2257
+ popover.setAttribute('aria-hidden', 'false');
2258
+ menuItems = Array.from(menu.querySelectorAll('[role^="menuitem"]')).filter(item =>
2259
+ !item.hasAttribute('disabled') &&
2260
+ item.getAttribute('aria-disabled') !== 'true'
2261
+ );
2262
+
2263
+ if (menuItems.length > 0 && initialSelection) {
2264
+ if (initialSelection === 'first') {
2265
+ setActiveItem(0);
2266
+ } else if (initialSelection === 'last') {
2267
+ setActiveItem(menuItems.length - 1);
2268
+ }
2269
+ }
2270
+ };
2271
+
2272
+ const setActiveItem = (index) => {
2273
+ if (activeIndex > -1 && menuItems[activeIndex]) {
2274
+ menuItems[activeIndex].classList.remove('active');
2275
+ }
2276
+ activeIndex = index;
2277
+ if (activeIndex > -1 && menuItems[activeIndex]) {
2278
+ const activeItem = menuItems[activeIndex];
2279
+ activeItem.classList.add('active');
2280
+ trigger.setAttribute('aria-activedescendant', activeItem.id);
2281
+ } else {
2282
+ trigger.removeAttribute('aria-activedescendant');
2283
+ }
2284
+ };
2285
+
2286
+ trigger.addEventListener('click', () => {
2287
+ const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
2288
+ if (isExpanded) {
2289
+ closePopover();
2290
+ } else {
2291
+ openPopover(false);
2292
+ }
2293
+ });
2294
+
2295
+ dropdownMenuComponent.addEventListener('keydown', (event) => {
2296
+ const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
2297
+
2298
+ if (event.key === 'Escape') {
2299
+ if (isExpanded) closePopover();
2300
+ return;
2301
+ }
2302
+
2303
+ if (!isExpanded) {
2304
+ if (['Enter', ' '].includes(event.key)) {
2305
+ event.preventDefault();
2306
+ openPopover(false);
2307
+ } else if (event.key === 'ArrowDown') {
2308
+ event.preventDefault();
2309
+ openPopover('first');
2310
+ } else if (event.key === 'ArrowUp') {
2311
+ event.preventDefault();
2312
+ openPopover('last');
2313
+ }
2314
+ return;
2315
+ }
2316
+
2317
+ if (menuItems.length === 0) return;
2318
+
2319
+ let nextIndex = activeIndex;
2320
+
2321
+ switch (event.key) {
2322
+ case 'ArrowDown':
2323
+ event.preventDefault();
2324
+ nextIndex = activeIndex === -1 ? 0 : Math.min(activeIndex + 1, menuItems.length - 1);
2325
+ break;
2326
+ case 'ArrowUp':
2327
+ event.preventDefault();
2328
+ nextIndex = activeIndex === -1 ? menuItems.length - 1 : Math.max(activeIndex - 1, 0);
2329
+ break;
2330
+ case 'Home':
2331
+ event.preventDefault();
2332
+ nextIndex = 0;
2333
+ break;
2334
+ case 'End':
2335
+ event.preventDefault();
2336
+ nextIndex = menuItems.length - 1;
2337
+ break;
2338
+ case 'Enter':
2339
+ case ' ':
2340
+ event.preventDefault();
2341
+ menuItems[activeIndex]?.click();
2342
+ closePopover();
2343
+ return;
2344
+ }
2345
+
2346
+ if (nextIndex !== activeIndex) {
2347
+ setActiveItem(nextIndex);
2348
+ }
2349
+ });
2350
+
2351
+ menu.addEventListener('mousemove', (event) => {
2352
+ const menuItem = event.target.closest('[role^="menuitem"]');
2353
+ if (menuItem && menuItems.includes(menuItem)) {
2354
+ const index = menuItems.indexOf(menuItem);
2355
+ if (index !== activeIndex) {
2356
+ setActiveItem(index);
2357
+ }
2358
+ }
2359
+ });
2360
+
2361
+ menu.addEventListener('mouseleave', () => {
2362
+ setActiveItem(-1);
2363
+ });
2364
+
2365
+ menu.addEventListener('click', (event) => {
2366
+ if (event.target.closest('[role^="menuitem"]')) {
2367
+ closePopover();
2368
+ }
2369
+ });
2370
+
2371
+ document.addEventListener('click', (event) => {
2372
+ if (!dropdownMenuComponent.contains(event.target)) {
2373
+ closePopover();
2374
+ }
2375
+ });
2376
+
2377
+ document.addEventListener('basecoat:popover', (event) => {
2378
+ if (event.detail.source !== dropdownMenuComponent) {
2379
+ closePopover(false);
2380
+ }
2381
+ });
2382
+
2383
+ dropdownMenuComponent.dataset.dropdownMenuInitialized = true;
2384
+ dropdownMenuComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
2385
+ };
2386
+
2387
+ if (window.basecoat) {
2388
+ window.basecoat.register('dropdown-menu', '.dropdown-menu:not([data-dropdown-menu-initialized])', initDropdownMenu);
2389
+ }
2390
+ })();
2391
+ (() => {
2392
+ const initPopover = (popoverComponent) => {
2393
+ const trigger = popoverComponent.querySelector(':scope > button');
2394
+ const content = popoverComponent.querySelector(':scope > [data-popover]');
2395
+
2396
+ if (!trigger || !content) {
2397
+ const missing = [];
2398
+ if (!trigger) missing.push('trigger');
2399
+ if (!content) missing.push('content');
2400
+ console.error(`Popover initialisation failed. Missing element(s): ${missing.join(', ')}`, popoverComponent);
2401
+ return;
2402
+ }
2403
+
2404
+ const closePopover = (focusOnTrigger = true) => {
2405
+ if (trigger.getAttribute('aria-expanded') === 'false') return;
2406
+ trigger.setAttribute('aria-expanded', 'false');
2407
+ content.setAttribute('aria-hidden', 'true');
2408
+ if (focusOnTrigger) {
2409
+ trigger.focus();
2410
+ }
2411
+ };
2412
+
2413
+ const openPopover = () => {
2414
+ document.dispatchEvent(new CustomEvent('basecoat:popover', {
2415
+ detail: { source: popoverComponent }
2416
+ }));
2417
+
2418
+ const elementToFocus = content.querySelector('[autofocus]');
2419
+ if (elementToFocus) {
2420
+ content.addEventListener('transitionend', () => {
2421
+ elementToFocus.focus();
2422
+ }, { once: true });
2423
+ }
2424
+
2425
+ trigger.setAttribute('aria-expanded', 'true');
2426
+ content.setAttribute('aria-hidden', 'false');
2427
+ };
2428
+
2429
+ trigger.addEventListener('click', () => {
2430
+ const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
2431
+ if (isExpanded) {
2432
+ closePopover();
2433
+ } else {
2434
+ openPopover();
2435
+ }
2436
+ });
2437
+
2438
+ popoverComponent.addEventListener('keydown', (event) => {
2439
+ if (event.key === 'Escape') {
2440
+ closePopover();
2441
+ }
2442
+ });
2443
+
2444
+ document.addEventListener('click', (event) => {
2445
+ if (!popoverComponent.contains(event.target)) {
2446
+ closePopover();
2447
+ }
2448
+ });
2449
+
2450
+ document.addEventListener('basecoat:popover', (event) => {
2451
+ if (event.detail.source !== popoverComponent) {
2452
+ closePopover(false);
2453
+ }
2454
+ });
2455
+
2456
+ popoverComponent.dataset.popoverInitialized = true;
2457
+ popoverComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
2458
+ };
2459
+
2460
+ if (window.basecoat) {
2461
+ window.basecoat.register('popover', '.popover:not([data-popover-initialized])', initPopover);
2462
+ }
2463
+ })();
2464
+
2465
+ (() => {
2466
+ const initSelect = (selectComponent) => {
2467
+ const trigger = selectComponent.querySelector(':scope > button');
2468
+ const selectedLabel = trigger.querySelector(':scope > span');
2469
+ const popover = selectComponent.querySelector(':scope > [data-popover]');
2470
+ const listbox = popover ? popover.querySelector('[role="listbox"]') : null;
2471
+ const input = selectComponent.querySelector(':scope > input[type="hidden"]');
2472
+ const filter = selectComponent.querySelector('header input[type="text"]');
2473
+
2474
+ if (!trigger || !popover || !listbox || !input) {
2475
+ const missing = [];
2476
+ if (!trigger) missing.push('trigger');
2477
+ if (!popover) missing.push('popover');
2478
+ if (!listbox) missing.push('listbox');
2479
+ if (!input) missing.push('input');
2480
+ console.error(`Select component initialisation failed. Missing element(s): ${missing.join(', ')}`, selectComponent);
2481
+ return;
2482
+ }
2483
+
2484
+ const allOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
2485
+ const options = allOptions.filter(opt => opt.getAttribute('aria-disabled') !== 'true');
2486
+ let visibleOptions = [...options];
2487
+ let activeIndex = -1;
2488
+ const isMultiple = listbox.getAttribute('aria-multiselectable') === 'true';
2489
+ const selectedOptions = isMultiple ? new Set() : null;
2490
+ const placeholder = isMultiple ? (selectComponent.dataset.placeholder || '') : null;
2491
+ const closeOnSelect = selectComponent.dataset.closeOnSelect === 'true';
2492
+
2493
+ const getValue = (opt) => opt.dataset.value ?? opt.textContent.trim();
2494
+
2495
+ const setActiveOption = (index) => {
2496
+ if (activeIndex > -1 && options[activeIndex]) {
2497
+ options[activeIndex].classList.remove('active');
2498
+ }
2499
+
2500
+ activeIndex = index;
2501
+
2502
+ if (activeIndex > -1) {
2503
+ const activeOption = options[activeIndex];
2504
+ activeOption.classList.add('active');
2505
+ if (activeOption.id) {
2506
+ trigger.setAttribute('aria-activedescendant', activeOption.id);
2507
+ } else {
2508
+ trigger.removeAttribute('aria-activedescendant');
2509
+ }
2510
+ } else {
2511
+ trigger.removeAttribute('aria-activedescendant');
2512
+ }
2513
+ };
2514
+
2515
+ const hasTransition = () => {
2516
+ const style = getComputedStyle(popover);
2517
+ return parseFloat(style.transitionDuration) > 0 || parseFloat(style.transitionDelay) > 0;
2518
+ };
2519
+
2520
+ const updateValue = (optionOrOptions, triggerEvent = true) => {
2521
+ let value;
2522
+
2523
+ if (isMultiple) {
2524
+ const opts = Array.isArray(optionOrOptions) ? optionOrOptions : [];
2525
+ selectedOptions.clear();
2526
+ opts.forEach(opt => selectedOptions.add(opt));
2527
+
2528
+ // Get selected options in DOM order
2529
+ const selected = options.filter(opt => selectedOptions.has(opt));
2530
+ if (selected.length === 0) {
2531
+ selectedLabel.textContent = placeholder;
2532
+ selectedLabel.classList.add('text-muted-foreground');
2533
+ } else {
2534
+ selectedLabel.textContent = selected.map(opt => opt.dataset.label || opt.textContent.trim()).join(', ');
2535
+ selectedLabel.classList.remove('text-muted-foreground');
2536
+ }
2537
+
2538
+ value = selected.map(getValue);
2539
+ input.value = JSON.stringify(value);
2540
+ } else {
2541
+ const option = optionOrOptions;
2542
+ if (!option) return;
2543
+ selectedLabel.innerHTML = option.innerHTML;
2544
+ value = getValue(option);
2545
+ input.value = value;
2546
+ }
2547
+
2548
+ options.forEach(opt => {
2549
+ const isSelected = isMultiple ? selectedOptions.has(opt) : opt === optionOrOptions;
2550
+ if (isSelected) {
2551
+ opt.setAttribute('aria-selected', 'true');
2552
+ } else {
2553
+ opt.removeAttribute('aria-selected');
2554
+ }
2555
+ });
2556
+
2557
+ if (triggerEvent) {
2558
+ selectComponent.dispatchEvent(new CustomEvent('change', {
2559
+ detail: { value },
2560
+ bubbles: true
2561
+ }));
2562
+ }
2563
+ };
2564
+
2565
+ const closePopover = (focusOnTrigger = true) => {
2566
+ if (popover.getAttribute('aria-hidden') === 'true') return;
2567
+
2568
+ if (filter) {
2569
+ const resetFilter = () => {
2570
+ filter.value = '';
2571
+ visibleOptions = [...options];
2572
+ allOptions.forEach(opt => opt.setAttribute('aria-hidden', 'false'));
2573
+ };
2574
+
2575
+ if (hasTransition()) {
2576
+ popover.addEventListener('transitionend', resetFilter, { once: true });
2577
+ } else {
2578
+ resetFilter();
2579
+ }
2580
+ }
2581
+
2582
+ if (focusOnTrigger) trigger.focus();
2583
+ popover.setAttribute('aria-hidden', 'true');
2584
+ trigger.setAttribute('aria-expanded', 'false');
2585
+ setActiveOption(-1);
2586
+ };
2587
+
2588
+ const toggleMultipleValue = (option) => {
2589
+ if (selectedOptions.has(option)) {
2590
+ selectedOptions.delete(option);
2591
+ } else {
2592
+ selectedOptions.add(option);
2593
+ }
2594
+ updateValue(options.filter(opt => selectedOptions.has(opt)));
2595
+ };
2596
+
2597
+ const select = (value) => {
2598
+ if (isMultiple) {
2599
+ const option = options.find(opt => getValue(opt) === value && !selectedOptions.has(opt));
2600
+ if (!option) return;
2601
+ selectedOptions.add(option);
2602
+ updateValue(options.filter(opt => selectedOptions.has(opt)));
2603
+ } else {
2604
+ const option = options.find(opt => getValue(opt) === value);
2605
+ if (!option) return;
2606
+ if (input.value !== value) {
2607
+ updateValue(option);
2608
+ }
2609
+ closePopover();
2610
+ }
2611
+ };
2612
+
2613
+ const deselect = (value) => {
2614
+ if (!isMultiple) return;
2615
+ const option = options.find(opt => getValue(opt) === value && selectedOptions.has(opt));
2616
+ if (!option) return;
2617
+ selectedOptions.delete(option);
2618
+ updateValue(options.filter(opt => selectedOptions.has(opt)));
2619
+ };
2620
+
2621
+ const toggle = (value) => {
2622
+ if (!isMultiple) return;
2623
+ const option = options.find(opt => getValue(opt) === value);
2624
+ if (!option) return;
2625
+ toggleMultipleValue(option);
2626
+ };
2627
+
2628
+ if (filter) {
2629
+ const filterOptions = () => {
2630
+ const searchTerm = filter.value.trim().toLowerCase();
2631
+
2632
+ setActiveOption(-1);
2633
+
2634
+ visibleOptions = [];
2635
+ allOptions.forEach(option => {
2636
+ if (option.hasAttribute('data-force')) {
2637
+ option.setAttribute('aria-hidden', 'false');
2638
+ if (options.includes(option)) {
2639
+ visibleOptions.push(option);
2640
+ }
2641
+ return;
2642
+ }
2643
+
2644
+ const optionText = (option.dataset.filter || option.textContent).trim().toLowerCase();
2645
+ const keywordList = (option.dataset.keywords || '')
2646
+ .toLowerCase()
2647
+ .split(/[\s,]+/)
2648
+ .filter(Boolean);
2649
+ const matchesKeyword = keywordList.some(keyword => keyword.includes(searchTerm));
2650
+ const matches = optionText.includes(searchTerm) || matchesKeyword;
2651
+ option.setAttribute('aria-hidden', String(!matches));
2652
+ if (matches && options.includes(option)) {
2653
+ visibleOptions.push(option);
2654
+ }
2655
+ });
2656
+ };
2657
+
2658
+ filter.addEventListener('input', filterOptions);
2659
+ }
2660
+
2661
+ // Initialization
2662
+ if (isMultiple) {
2663
+ const ariaSelected = options.filter(opt => opt.getAttribute('aria-selected') === 'true');
2664
+ try {
2665
+ const parsed = JSON.parse(input.value || '[]');
2666
+ const validValues = new Set(options.map(getValue));
2667
+ const initialValues = Array.isArray(parsed) ? parsed.filter(v => validValues.has(v)) : [];
2668
+
2669
+ const initialOptions = [];
2670
+ if (initialValues.length > 0) {
2671
+ // Match values to options in order, allowing duplicates
2672
+ initialValues.forEach(val => {
2673
+ const opt = options.find(o => getValue(o) === val && !initialOptions.includes(o));
2674
+ if (opt) initialOptions.push(opt);
2675
+ });
2676
+ } else {
2677
+ initialOptions.push(...ariaSelected);
2678
+ }
2679
+
2680
+ updateValue(initialOptions, false);
2681
+ } catch (e) {
2682
+ updateValue(ariaSelected, false);
2683
+ }
2684
+ } else {
2685
+ const initialOption = options.find(opt => getValue(opt) === input.value) || options[0];
2686
+ if (initialOption) updateValue(initialOption, false);
2687
+ }
2688
+
2689
+ const handleKeyNavigation = (event) => {
2690
+ const isPopoverOpen = popover.getAttribute('aria-hidden') === 'false';
2691
+
2692
+ if (!['ArrowDown', 'ArrowUp', 'Enter', 'Home', 'End', 'Escape'].includes(event.key)) {
2693
+ return;
2694
+ }
2695
+
2696
+ if (!isPopoverOpen) {
2697
+ if (event.key !== 'Enter' && event.key !== 'Escape') {
2698
+ event.preventDefault();
2699
+ trigger.click();
2700
+ }
2701
+ return;
2702
+ }
2703
+
2704
+ event.preventDefault();
2705
+
2706
+ if (event.key === 'Escape') {
2707
+ closePopover();
2708
+ return;
2709
+ }
2710
+
2711
+ if (event.key === 'Enter') {
2712
+ if (activeIndex > -1) {
2713
+ const option = options[activeIndex];
2714
+ if (isMultiple) {
2715
+ toggleMultipleValue(option);
2716
+ if (closeOnSelect) {
2717
+ closePopover();
2718
+ }
2719
+ } else {
2720
+ if (input.value !== getValue(option)) {
2721
+ updateValue(option);
2722
+ }
2723
+ closePopover();
2724
+ }
2725
+ }
2726
+ return;
2727
+ }
2728
+
2729
+ if (visibleOptions.length === 0) return;
2730
+
2731
+ const currentVisibleIndex = activeIndex > -1 ? visibleOptions.indexOf(options[activeIndex]) : -1;
2732
+ let nextVisibleIndex = currentVisibleIndex;
2733
+
2734
+ switch (event.key) {
2735
+ case 'ArrowDown':
2736
+ if (currentVisibleIndex < visibleOptions.length - 1) {
2737
+ nextVisibleIndex = currentVisibleIndex + 1;
2738
+ }
2739
+ break;
2740
+ case 'ArrowUp':
2741
+ if (currentVisibleIndex > 0) {
2742
+ nextVisibleIndex = currentVisibleIndex - 1;
2743
+ } else if (currentVisibleIndex === -1) {
2744
+ nextVisibleIndex = 0;
2745
+ }
2746
+ break;
2747
+ case 'Home':
2748
+ nextVisibleIndex = 0;
2749
+ break;
2750
+ case 'End':
2751
+ nextVisibleIndex = visibleOptions.length - 1;
2752
+ break;
2753
+ }
2754
+
2755
+ if (nextVisibleIndex !== currentVisibleIndex) {
2756
+ const newActiveOption = visibleOptions[nextVisibleIndex];
2757
+ setActiveOption(options.indexOf(newActiveOption));
2758
+ newActiveOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
2759
+ }
2760
+ };
2761
+
2762
+ listbox.addEventListener('mousemove', (event) => {
2763
+ const option = event.target.closest('[role="option"]');
2764
+ if (option && visibleOptions.includes(option)) {
2765
+ const index = options.indexOf(option);
2766
+ if (index !== activeIndex) {
2767
+ setActiveOption(index);
2768
+ }
2769
+ }
2770
+ });
2771
+
2772
+ listbox.addEventListener('mouseleave', () => {
2773
+ const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
2774
+ if (selectedOption) {
2775
+ setActiveOption(options.indexOf(selectedOption));
2776
+ } else {
2777
+ setActiveOption(-1);
2778
+ }
2779
+ });
2780
+
2781
+ trigger.addEventListener('keydown', handleKeyNavigation);
2782
+ if (filter) {
2783
+ filter.addEventListener('keydown', handleKeyNavigation);
2784
+ }
2785
+
2786
+ const openPopover = () => {
2787
+ document.dispatchEvent(new CustomEvent('basecoat:popover', {
2788
+ detail: { source: selectComponent }
2789
+ }));
2790
+
2791
+ if (filter) {
2792
+ if (hasTransition()) {
2793
+ popover.addEventListener('transitionend', () => {
2794
+ filter.focus();
2795
+ }, { once: true });
2796
+ } else {
2797
+ filter.focus();
2798
+ }
2799
+ }
2800
+
2801
+ popover.setAttribute('aria-hidden', 'false');
2802
+ trigger.setAttribute('aria-expanded', 'true');
2803
+
2804
+ const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
2805
+ if (selectedOption) {
2806
+ setActiveOption(options.indexOf(selectedOption));
2807
+ selectedOption.scrollIntoView({ block: 'nearest' });
2808
+ }
2809
+ };
2810
+
2811
+ trigger.addEventListener('click', () => {
2812
+ const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
2813
+ if (isExpanded) {
2814
+ closePopover();
2815
+ } else {
2816
+ openPopover();
2817
+ }
2818
+ });
2819
+
2820
+ listbox.addEventListener('click', (event) => {
2821
+ const clickedOption = event.target.closest('[role="option"]');
2822
+ if (!clickedOption) return;
2823
+
2824
+ const option = options.find(opt => opt === clickedOption);
2825
+ if (!option) return;
2826
+
2827
+ if (isMultiple) {
2828
+ toggleMultipleValue(option);
2829
+ if (closeOnSelect) {
2830
+ closePopover();
2831
+ } else {
2832
+ setActiveOption(options.indexOf(option));
2833
+ if (filter) {
2834
+ filter.focus();
2835
+ } else {
2836
+ trigger.focus();
2837
+ }
2838
+ }
2839
+ } else {
2840
+ if (input.value !== getValue(option)) {
2841
+ updateValue(option);
2842
+ }
2843
+ closePopover();
2844
+ }
2845
+ });
2846
+
2847
+ document.addEventListener('click', (event) => {
2848
+ if (!selectComponent.contains(event.target)) {
2849
+ closePopover(false);
2850
+ }
2851
+ });
2852
+
2853
+ document.addEventListener('basecoat:popover', (event) => {
2854
+ if (event.detail.source !== selectComponent) {
2855
+ closePopover(false);
2856
+ }
2857
+ });
2858
+
2859
+ popover.setAttribute('aria-hidden', 'true');
2860
+
2861
+ // Public API
2862
+ Object.defineProperty(selectComponent, 'value', {
2863
+ get: () => {
2864
+ if (isMultiple) {
2865
+ return options.filter(opt => selectedOptions.has(opt)).map(getValue);
2866
+ } else {
2867
+ return input.value;
2868
+ }
2869
+ },
2870
+ set: (val) => {
2871
+ if (isMultiple) {
2872
+ const values = Array.isArray(val) ? val : (val != null ? [val] : []);
2873
+ const opts = [];
2874
+ values.forEach(v => {
2875
+ const opt = options.find(o => getValue(o) === v && !opts.includes(o));
2876
+ if (opt) opts.push(opt);
2877
+ });
2878
+ updateValue(opts);
2879
+ } else {
2880
+ const option = options.find(opt => getValue(opt) === val);
2881
+ if (option) {
2882
+ updateValue(option);
2883
+ closePopover();
2884
+ }
2885
+ }
2886
+ }
2887
+ });
2888
+
2889
+ selectComponent.select = select;
2890
+ selectComponent.selectByValue = select; // Backward compatibility alias
2891
+ if (isMultiple) {
2892
+ selectComponent.deselect = deselect;
2893
+ selectComponent.toggle = toggle;
2894
+ selectComponent.selectAll = () => updateValue(options);
2895
+ selectComponent.selectNone = () => updateValue([]);
2896
+ }
2897
+ selectComponent.dataset.selectInitialized = true;
2898
+ selectComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
2899
+ };
2900
+
2901
+ if (window.basecoat) {
2902
+ window.basecoat.register('select', 'div.select:not([data-select-initialized])', initSelect);
2903
+ }
2904
+ })();
2905
+
2906
+ (() => {
2907
+ // Monkey patching the history API to detect client-side navigation
2908
+ if (!window.history.__basecoatPatched) {
2909
+ const originalPushState = window.history.pushState;
2910
+ window.history.pushState = function(...args) {
2911
+ originalPushState.apply(this, args);
2912
+ window.dispatchEvent(new Event('basecoat:locationchange'));
2913
+ };
2914
+
2915
+ const originalReplaceState = window.history.replaceState;
2916
+ window.history.replaceState = function(...args) {
2917
+ originalReplaceState.apply(this, args);
2918
+ window.dispatchEvent(new Event('basecoat:locationchange'));
2919
+ };
2920
+
2921
+ window.history.__basecoatPatched = true;
2922
+ }
2923
+
2924
+ const initSidebar = (sidebarComponent) => {
2925
+ const initialOpen = sidebarComponent.dataset.initialOpen !== 'false';
2926
+ const initialMobileOpen = sidebarComponent.dataset.initialMobileOpen === 'true';
2927
+ const breakpoint = parseInt(sidebarComponent.dataset.breakpoint) || 768;
2928
+
2929
+ let open = breakpoint > 0
2930
+ ? (window.innerWidth >= breakpoint ? initialOpen : initialMobileOpen)
2931
+ : initialOpen;
2932
+
2933
+ const updateCurrentPageLinks = () => {
2934
+ const currentPath = window.location.pathname.replace(/\/$/, '');
2935
+ sidebarComponent.querySelectorAll('a').forEach(link => {
2936
+ if (link.hasAttribute('data-ignore-current')) return;
2937
+
2938
+ const linkPath = new URL(link.href).pathname.replace(/\/$/, '');
2939
+ if (linkPath === currentPath) {
2940
+ link.setAttribute('aria-current', 'page');
2941
+ } else {
2942
+ link.removeAttribute('aria-current');
2943
+ }
2944
+ });
2945
+ };
2946
+
2947
+ const updateState = () => {
2948
+ sidebarComponent.setAttribute('aria-hidden', !open);
2949
+ if (open) {
2950
+ sidebarComponent.removeAttribute('inert');
2951
+ } else {
2952
+ sidebarComponent.setAttribute('inert', '');
2953
+ }
2954
+ };
2955
+
2956
+ const setState = (state) => {
2957
+ open = state;
2958
+ updateState();
2959
+ };
2960
+
2961
+ const sidebarId = sidebarComponent.id;
2962
+
2963
+ document.addEventListener('basecoat:sidebar', (event) => {
2964
+ if (event.detail?.id && event.detail.id !== sidebarId) return;
2965
+
2966
+ switch (event.detail?.action) {
2967
+ case 'open':
2968
+ setState(true);
2969
+ break;
2970
+ case 'close':
2971
+ setState(false);
2972
+ break;
2973
+ default:
2974
+ setState(!open);
2975
+ break;
2976
+ }
2977
+ });
2978
+
2979
+ sidebarComponent.addEventListener('click', (event) => {
2980
+ const target = event.target;
2981
+ const nav = sidebarComponent.querySelector('nav');
2982
+
2983
+ const isMobile = window.innerWidth < breakpoint;
2984
+
2985
+ if (isMobile && (target.closest('a, button') && !target.closest('[data-keep-mobile-sidebar-open]'))) {
2986
+ if (document.activeElement) document.activeElement.blur();
2987
+ setState(false);
2988
+ return;
2989
+ }
2990
+
2991
+ if (target === sidebarComponent || (nav && !nav.contains(target))) {
2992
+ if (document.activeElement) document.activeElement.blur();
2993
+ setState(false);
2994
+ }
2995
+ });
2996
+
2997
+ window.addEventListener('popstate', updateCurrentPageLinks);
2998
+ window.addEventListener('basecoat:locationchange', updateCurrentPageLinks);
2999
+
3000
+ updateState();
3001
+ updateCurrentPageLinks();
3002
+ sidebarComponent.dataset.sidebarInitialized = true;
3003
+ sidebarComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
3004
+ };
3005
+
3006
+ if (window.basecoat) {
3007
+ window.basecoat.register('sidebar', '.sidebar:not([data-sidebar-initialized])', initSidebar);
3008
+ }
3009
+ })();
3010
+ (() => {
3011
+ const initTabs = (tabsComponent) => {
3012
+ const tablist = tabsComponent.querySelector('[role="tablist"]');
3013
+ if (!tablist) return;
3014
+
3015
+ const tabs = Array.from(tablist.querySelectorAll('[role="tab"]'));
3016
+ const panels = tabs.map(tab => document.getElementById(tab.getAttribute('aria-controls'))).filter(Boolean);
3017
+
3018
+ const selectTab = (tabToSelect) => {
3019
+ tabs.forEach((tab, index) => {
3020
+ tab.setAttribute('aria-selected', 'false');
3021
+ tab.setAttribute('tabindex', '-1');
3022
+ if (panels[index]) panels[index].hidden = true;
3023
+ });
3024
+
3025
+ tabToSelect.setAttribute('aria-selected', 'true');
3026
+ tabToSelect.setAttribute('tabindex', '0');
3027
+ const activePanel = document.getElementById(tabToSelect.getAttribute('aria-controls'));
3028
+ if (activePanel) activePanel.hidden = false;
3029
+ };
3030
+
3031
+ tablist.addEventListener('click', (event) => {
3032
+ const clickedTab = event.target.closest('[role="tab"]');
3033
+ if (clickedTab) selectTab(clickedTab);
3034
+ });
3035
+
3036
+ tablist.addEventListener('keydown', (event) => {
3037
+ const currentTab = event.target;
3038
+ if (!tabs.includes(currentTab)) return;
3039
+
3040
+ let nextTab;
3041
+ const currentIndex = tabs.indexOf(currentTab);
3042
+
3043
+ switch (event.key) {
3044
+ case 'ArrowRight':
3045
+ nextTab = tabs[(currentIndex + 1) % tabs.length];
3046
+ break;
3047
+ case 'ArrowLeft':
3048
+ nextTab = tabs[(currentIndex - 1 + tabs.length) % tabs.length];
3049
+ break;
3050
+ case 'Home':
3051
+ nextTab = tabs[0];
3052
+ break;
3053
+ case 'End':
3054
+ nextTab = tabs[tabs.length - 1];
3055
+ break;
3056
+ default:
3057
+ return;
3058
+ }
3059
+
3060
+ event.preventDefault();
3061
+ selectTab(nextTab);
3062
+ nextTab.focus();
3063
+ });
3064
+
3065
+ tabsComponent.dataset.tabsInitialized = true;
3066
+ tabsComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
3067
+ };
3068
+
3069
+ if (window.basecoat) {
3070
+ window.basecoat.register('tabs', '.tabs:not([data-tabs-initialized])', initTabs);
3071
+ }
3072
+ })();
3073
+ (() => {
3074
+ let toaster;
3075
+ const toasts = new WeakMap();
3076
+ let isPaused = false;
3077
+ const ICONS = {
3078
+ success: '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',
3079
+ error: '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',
3080
+ info: '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',
3081
+ warning: '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'
3082
+ };
3083
+
3084
+ function initToaster(toasterElement) {
3085
+ if (toasterElement.dataset.toasterInitialized) return;
3086
+ toaster = toasterElement;
3087
+
3088
+ toaster.addEventListener('mouseenter', pauseAllTimeouts);
3089
+ toaster.addEventListener('mouseleave', resumeAllTimeouts);
3090
+ toaster.addEventListener('click', (event) => {
3091
+ const actionLink = event.target.closest('.toast footer a');
3092
+ const actionButton = event.target.closest('.toast footer button');
3093
+ if (actionLink || actionButton) {
3094
+ closeToast(event.target.closest('.toast'));
3095
+ }
3096
+ });
3097
+
3098
+ toaster.querySelectorAll('.toast:not([data-toast-initialized])').forEach(initToast);
3099
+ toaster.dataset.toasterInitialized = 'true';
3100
+ toaster.dispatchEvent(new CustomEvent('basecoat:initialized'));
3101
+ }
3102
+
3103
+ function initToast(element) {
3104
+ if (element.dataset.toastInitialized) return;
3105
+
3106
+ const duration = parseInt(element.dataset.duration);
3107
+ const timeoutDuration = duration !== -1
3108
+ ? duration || (element.dataset.category === 'error' ? 5000 : 3000)
3109
+ : -1;
3110
+
3111
+ const state = {
3112
+ remainingTime: timeoutDuration,
3113
+ timeoutId: null,
3114
+ startTime: null,
3115
+ };
3116
+
3117
+ if (timeoutDuration !== -1) {
3118
+ if (isPaused) {
3119
+ state.timeoutId = null;
3120
+ } else {
3121
+ state.startTime = Date.now();
3122
+ state.timeoutId = setTimeout(() => closeToast(element), timeoutDuration);
3123
+ }
3124
+ }
3125
+ toasts.set(element, state);
3126
+
3127
+ element.dataset.toastInitialized = 'true';
3128
+ }
3129
+
3130
+ function pauseAllTimeouts() {
3131
+ if (isPaused) return;
3132
+
3133
+ isPaused = true;
3134
+
3135
+ toaster.querySelectorAll('.toast:not([aria-hidden="true"])').forEach(element => {
3136
+ if (!toasts.has(element)) return;
3137
+
3138
+ const state = toasts.get(element);
3139
+ if (state.timeoutId) {
3140
+ clearTimeout(state.timeoutId);
3141
+ state.timeoutId = null;
3142
+ state.remainingTime -= Date.now() - state.startTime;
3143
+ }
3144
+ });
3145
+ }
3146
+
3147
+ function resumeAllTimeouts() {
3148
+ if (!isPaused) return;
3149
+
3150
+ isPaused = false;
3151
+
3152
+ toaster.querySelectorAll('.toast:not([aria-hidden="true"])').forEach(element => {
3153
+ if (!toasts.has(element)) return;
3154
+
3155
+ const state = toasts.get(element);
3156
+ if (state.remainingTime !== -1 && !state.timeoutId) {
3157
+ if (state.remainingTime > 0) {
3158
+ state.startTime = Date.now();
3159
+ state.timeoutId = setTimeout(() => closeToast(element), state.remainingTime);
3160
+ } else {
3161
+ closeToast(element);
3162
+ }
3163
+ }
3164
+ });
3165
+ }
3166
+
3167
+ function closeToast(element) {
3168
+ if (!toasts.has(element)) return;
3169
+
3170
+ const state = toasts.get(element);
3171
+ clearTimeout(state.timeoutId);
3172
+ toasts.delete(element);
3173
+
3174
+ if (element.contains(document.activeElement)) document.activeElement.blur();
3175
+ element.setAttribute('aria-hidden', 'true');
3176
+ element.addEventListener('transitionend', () => element.remove(), { once: true });
3177
+ }
3178
+
3179
+ function createToast(config) {
3180
+ const {
3181
+ category = 'info',
3182
+ title,
3183
+ description,
3184
+ action,
3185
+ cancel,
3186
+ duration,
3187
+ icon,
3188
+ } = config;
3189
+
3190
+ const iconHtml = icon || (category && ICONS[category]) || '';
3191
+ const titleHtml = title ? `<h2>${title}</h2>` : '';
3192
+ const descriptionHtml = description ? `<p>${description}</p>` : '';
3193
+ const actionHtml = action?.href
3194
+ ? `<a href="${action.href}" class="btn" data-toast-action>${action.label}</a>`
3195
+ : action?.onclick
3196
+ ? `<button type="button" class="btn" data-toast-action onclick="${action.onclick}">${action.label}</button>`
3197
+ : '';
3198
+ const cancelHtml = cancel
3199
+ ? `<button type="button" class="btn-outline h-6 text-xs px-2.5 rounded-sm" data-toast-cancel onclick="${cancel?.onclick}">${cancel.label}</button>`
3200
+ : '';
3201
+
3202
+ const footerHtml = actionHtml || cancelHtml ? `<footer>${actionHtml}${cancelHtml}</footer>` : '';
3203
+
3204
+ const html = `
3205
+ <div
3206
+ class="toast"
3207
+ role="${category === 'error' ? 'alert' : 'status'}"
3208
+ aria-atomic="true"
3209
+ ${category ? `data-category="${category}"` : ''}
3210
+ ${duration !== undefined ? `data-duration="${duration}"` : ''}
3211
+ >
3212
+ <div class="toast-content">
3213
+ ${iconHtml}
3214
+ <section>
3215
+ ${titleHtml}
3216
+ ${descriptionHtml}
3217
+ </section>
3218
+ ${footerHtml}
3219
+ </div>
3220
+ </div>
3221
+ </div>
3222
+ `;
3223
+ const template = document.createElement('template');
3224
+ template.innerHTML = html.trim();
3225
+ return template.content.firstChild;
3226
+ }
3227
+
3228
+ document.addEventListener('basecoat:toast', (event) => {
3229
+ if (!toaster) {
3230
+ console.error('Cannot create toast: toaster container not found on page.');
3231
+ return;
3232
+ }
3233
+ const config = event.detail?.config || {};
3234
+ const toastElement = createToast(config);
3235
+ toaster.appendChild(toastElement);
3236
+ });
3237
+
3238
+ if (window.basecoat) {
3239
+ window.basecoat.register('toaster', '#toaster:not([data-toaster-initialized])', initToaster);
3240
+ window.basecoat.register('toast', '.toast:not([data-toast-initialized])', initToast);
3241
+ }
3242
+ })();
3243
+
3244
+ /**
3245
+ * Client-side Image Processor
3246
+ *
3247
+ * Processes images before upload:
3248
+ * - Corrects EXIF orientation
3249
+ * - Resizes to max dimensions
3250
+ * - Strips all metadata (privacy)
3251
+ * - Converts to WebP format
3252
+ */ const DEFAULT_OPTIONS = {
3253
+ maxWidth: 1920,
3254
+ maxHeight: 1920,
3255
+ quality: 0.85,
3256
+ mimeType: "image/webp"
3257
+ };
3258
+ /**
3259
+ * EXIF Orientation values and their transformations
3260
+ */ const ORIENTATIONS = {
3261
+ 1: {
3262
+ rotate: 0,
3263
+ flip: false
3264
+ },
3265
+ 2: {
3266
+ rotate: 0,
3267
+ flip: true
3268
+ },
3269
+ 3: {
3270
+ rotate: 180,
3271
+ flip: false
3272
+ },
3273
+ 4: {
3274
+ rotate: 180,
3275
+ flip: true
3276
+ },
3277
+ 5: {
3278
+ rotate: 90,
3279
+ flip: true
3280
+ },
3281
+ 6: {
3282
+ rotate: 90,
3283
+ flip: false
3284
+ },
3285
+ 7: {
3286
+ rotate: 270,
3287
+ flip: true
3288
+ },
3289
+ 8: {
3290
+ rotate: 270,
3291
+ flip: false
3292
+ }
3293
+ };
3294
+ /**
3295
+ * Read EXIF orientation from JPEG file
3296
+ */ function readExifOrientation(buffer) {
3297
+ const view = new DataView(buffer);
3298
+ // Check for JPEG SOI marker
3299
+ if (view.getUint16(0) !== 0xffd8) return 1;
3300
+ let offset = 2;
3301
+ const length = view.byteLength;
3302
+ while(offset < length){
3303
+ if (view.getUint8(offset) !== 0xff) return 1;
3304
+ const marker = view.getUint8(offset + 1);
3305
+ // APP1 marker (EXIF)
3306
+ if (marker === 0xe1) {
3307
+ const exifOffset = offset + 4;
3308
+ // Check for "Exif\0\0"
3309
+ if (view.getUint32(exifOffset) !== 0x45786966 || view.getUint16(exifOffset + 4) !== 0x0000) {
3310
+ return 1;
3311
+ }
3312
+ const tiffOffset = exifOffset + 6;
3313
+ const littleEndian = view.getUint16(tiffOffset) === 0x4949;
3314
+ // Validate TIFF header
3315
+ if (view.getUint16(tiffOffset + 2, littleEndian) !== 0x002a) return 1;
3316
+ const ifdOffset = view.getUint32(tiffOffset + 4, littleEndian);
3317
+ const numEntries = view.getUint16(tiffOffset + ifdOffset, littleEndian);
3318
+ // Search for orientation tag (0x0112)
3319
+ for(let i = 0; i < numEntries; i++){
3320
+ const entryOffset = tiffOffset + ifdOffset + 2 + i * 12;
3321
+ const tag = view.getUint16(entryOffset, littleEndian);
3322
+ if (tag === 0x0112) {
3323
+ return view.getUint16(entryOffset + 8, littleEndian);
3324
+ }
3325
+ }
3326
+ return 1;
3327
+ }
3328
+ // Skip to next marker
3329
+ if (marker === 0xd8 || marker === 0xd9) {
3330
+ offset += 2;
3331
+ } else {
3332
+ offset += 2 + view.getUint16(offset + 2);
3333
+ }
3334
+ }
3335
+ return 1;
3336
+ }
3337
+ /**
3338
+ * Load image from file
3339
+ */ function loadImage(file) {
3340
+ return new Promise((resolve, reject)=>{
3341
+ const img = new Image();
3342
+ img.onload = ()=>{
3343
+ URL.revokeObjectURL(img.src);
3344
+ resolve(img);
3345
+ };
3346
+ img.onerror = ()=>reject(new Error("Failed to load image"));
3347
+ img.src = URL.createObjectURL(file);
3348
+ });
3349
+ }
3350
+ /**
3351
+ * Calculate output dimensions maintaining aspect ratio
3352
+ */ function calculateDimensions(width, height, maxWidth, maxHeight) {
3353
+ if (width <= maxWidth && height <= maxHeight) {
3354
+ return {
3355
+ width,
3356
+ height
3357
+ };
3358
+ }
3359
+ const ratio = Math.min(maxWidth / width, maxHeight / height);
3360
+ return {
3361
+ width: Math.round(width * ratio),
3362
+ height: Math.round(height * ratio)
3363
+ };
3364
+ }
3365
+ /**
3366
+ * Process image file
3367
+ */ async function process(file, options = {}) {
3368
+ const opts = {
3369
+ ...DEFAULT_OPTIONS,
3370
+ ...options
3371
+ };
3372
+ // Read file buffer for EXIF
3373
+ const buffer = await file.arrayBuffer();
3374
+ const orientation = readExifOrientation(buffer);
3375
+ const transform = ORIENTATIONS[orientation] || ORIENTATIONS[1];
3376
+ // Load image
3377
+ const img = await loadImage(file);
3378
+ // For 90° or 270° rotation, swap dimensions
3379
+ const isRotated = transform.rotate === 90 || transform.rotate === 270;
3380
+ const srcWidth = isRotated ? img.height : img.width;
3381
+ const srcHeight = isRotated ? img.width : img.height;
3382
+ // Calculate output size
3383
+ const { width, height } = calculateDimensions(srcWidth, srcHeight, opts.maxWidth, opts.maxHeight);
3384
+ // Create canvas
3385
+ const canvas = document.createElement("canvas");
3386
+ canvas.width = width;
3387
+ canvas.height = height;
3388
+ const ctx = canvas.getContext("2d");
3389
+ if (!ctx) throw new Error("Failed to get canvas context");
3390
+ // Apply transformations
3391
+ ctx.save();
3392
+ ctx.translate(width / 2, height / 2);
3393
+ if (transform.rotate) {
3394
+ ctx.rotate(transform.rotate * Math.PI / 180);
3395
+ }
3396
+ if (transform.flip) {
3397
+ ctx.scale(-1, 1);
3398
+ }
3399
+ const drawWidth = isRotated ? height : width;
3400
+ const drawHeight = isRotated ? width : height;
3401
+ ctx.drawImage(img, -drawWidth / 2, -drawHeight / 2, drawWidth, drawHeight);
3402
+ ctx.restore();
3403
+ // Export as WebP
3404
+ return new Promise((resolve, reject)=>{
3405
+ canvas.toBlob((blob)=>{
3406
+ if (blob) {
3407
+ resolve(blob);
3408
+ } else {
3409
+ reject(new Error("Failed to create blob"));
3410
+ }
3411
+ }, opts.mimeType, opts.quality);
3412
+ });
3413
+ }
3414
+ /**
3415
+ * Process file and create a new File object
3416
+ */ async function processToFile(file, options = {}) {
3417
+ const blob = await process(file, options);
3418
+ // Generate new filename with .webp extension
3419
+ const originalName = file.name.replace(/\.[^.]+$/, "");
3420
+ const newName = `${originalName}.webp`;
3421
+ return new File([
3422
+ blob
3423
+ ], newName, {
3424
+ type: "image/webp"
3425
+ });
3426
+ }
3427
+ const ImageProcessor = {
3428
+ process,
3429
+ processToFile
3430
+ };
3431
+ // Expose globally for inline scripts
3432
+ if (typeof window !== "undefined") {
3433
+ window.ImageProcessor = ImageProcessor;
3434
+ }