panelset 1.0.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1119 @@
1
+ //#region src/js/functions/core.ts
2
+ var e = class {
3
+ constructor() {
4
+ this._controller = new AbortController();
5
+ }
6
+ get signal() {
7
+ return this._controller.signal;
8
+ }
9
+ start() {
10
+ return this._controller.abort(), this._controller = new AbortController(), this._controller.signal;
11
+ }
12
+ static waitForTransition(e, t) {
13
+ return new Promise((n) => {
14
+ let r = getComputedStyle(e), i = (parseFloat(r.transitionDuration) || 0) + (parseFloat(r.transitionDelay) || 0);
15
+ if (i === 0) return n();
16
+ let a = !1, o = () => {
17
+ a || (a = !0, e.removeEventListener("transitionend", s), n());
18
+ }, s = (n) => {
19
+ n.target === e && (t && n.propertyName !== t || o());
20
+ };
21
+ e.addEventListener("transitionend", s), setTimeout(o, (i + .05) * 1e3);
22
+ });
23
+ }
24
+ };
25
+ //#endregion
26
+ //#region src/js/functions/focus.ts
27
+ function t(e, t, n) {
28
+ if (!t || t !== "input" && n && !(n.type.startsWith("key") || n instanceof MouseEvent && n.detail === 0)) return;
29
+ let r = (e) => {
30
+ setTimeout(() => e.focus(), 100);
31
+ };
32
+ if (t === !0) e.hasAttribute("tabindex") || e.setAttribute("tabindex", "-1"), r(e);
33
+ else if (t === "heading") {
34
+ let t = e.querySelector("h1, h2, h3, h4, h5, h6");
35
+ t && (t.hasAttribute("tabindex") || t.setAttribute("tabindex", "-1"), r(t));
36
+ } else if (t === "first") {
37
+ let t = e.querySelector("a,button,input,select,textarea,[tabindex]:not([tabindex=\"-1\"])");
38
+ t && r(t);
39
+ } else if (t === "input") {
40
+ let t = e.querySelector("input:not([type=hidden]):not([disabled]),select:not([disabled]),textarea:not([disabled])");
41
+ t && r(t);
42
+ } else typeof t == "function" && setTimeout(() => t(e), 100);
43
+ }
44
+ //#endregion
45
+ //#region src/js/functions/persist.ts
46
+ var n = () => {
47
+ let e = new URLSearchParams(location.search).get("panel");
48
+ return e ? e.split(",").filter(Boolean) : [];
49
+ }, r = (e) => {
50
+ let t = new URL(location.href);
51
+ if (t.searchParams.delete("panel"), e.length) {
52
+ let n = t.search ? "&" : "?";
53
+ history.replaceState(null, "", `${t}${n}panel=${e.join(",")}`);
54
+ } else history.replaceState(null, "", t);
55
+ }, i = (e) => `${location.pathname}::${e}`, a = (e) => localStorage.getItem(i(e)), o = (e, t) => localStorage.setItem(i(e), t);
56
+ //#endregion
57
+ //#region src/js/functions/config.ts
58
+ function s(e, t) {
59
+ switch (t) {
60
+ case "string": return e;
61
+ case "boolean": return e !== "false";
62
+ case "number": return parseInt(e, 10);
63
+ case "json": try {
64
+ return JSON.parse(e);
65
+ } catch {
66
+ return e !== "false";
67
+ }
68
+ }
69
+ }
70
+ function c(e, t) {
71
+ let n = {};
72
+ for (let [r, i] of Object.entries(t)) {
73
+ let [t, a] = i, o = e[t];
74
+ o !== void 0 && (n[r] = s(o, a));
75
+ }
76
+ return n;
77
+ }
78
+ function l(e, t) {
79
+ let n = {};
80
+ for (let [r, i] of Object.entries(t)) {
81
+ let [t, a] = i, o = t.replace(/([A-Z])/g, "-$1").toLowerCase(), c = e.getAttribute(o);
82
+ c !== null && (n[r] = s(c, a));
83
+ }
84
+ return n;
85
+ }
86
+ //#endregion
87
+ //#region src/js/functions/utils.ts
88
+ function u(e, t, n, r) {
89
+ n && console.log(`[${e}] "${t.id || "no id"}" -`, r);
90
+ }
91
+ function d(e, t, n) {
92
+ let r = t.split(/\s+/).filter(Boolean);
93
+ if (!r.length) return;
94
+ let i = (e.getAttribute("aria-describedby") || "").split(/\s+/).filter(Boolean), a = !1;
95
+ for (let e of r) {
96
+ let t = i.includes(e);
97
+ n && !t ? (i.push(e), a = !0) : !n && t && (i.splice(i.indexOf(e), 1), a = !0);
98
+ }
99
+ a && (i.length ? e.setAttribute("aria-describedby", i.join(" ")) : e.removeAttribute("aria-describedby"));
100
+ }
101
+ var f = !1;
102
+ function p(e) {
103
+ !e || f || (f = !0, console.log("[Panel/PanelSet] Browser supports 'interpolate-size', which will be used for opening and closing."));
104
+ }
105
+ function m(e) {
106
+ e.waitUntil = (t) => {
107
+ e.promise = e.promise ? Promise.all([e.promise, t]) : t;
108
+ };
109
+ }
110
+ function h(e, t, n, r, i = {}) {
111
+ let a = i.once === !0;
112
+ e.addEventListener(t, (e) => {
113
+ let t = e, i = n(t.detail), { signal: o } = t.detail;
114
+ if (a && i.dataset.loaded === "true") return;
115
+ let s = r(i, o);
116
+ s && typeof s.then == "function" && t.detail.waitUntil(s.then(() => {
117
+ a && (i.dataset.loaded = "true");
118
+ }));
119
+ });
120
+ }
121
+ //#endregion
122
+ //#region src/js/panelset.ts
123
+ var g, _ = class i {
124
+ static init(e = {}, t = {}) {
125
+ let n, r;
126
+ typeof e == "string" ? (n = e, r = t) : (r = e, n = r.selector || "[data-panelset]");
127
+ let a = document.querySelectorAll(n), o = [];
128
+ return a.forEach((e) => {
129
+ try {
130
+ i._validateElement(e);
131
+ } catch (e) {
132
+ console.error(e.message);
133
+ return;
134
+ }
135
+ if (e.panelSet) {
136
+ o.push(e.panelSet);
137
+ return;
138
+ }
139
+ let t = new i(e, r);
140
+ o.push(t);
141
+ }), o;
142
+ }
143
+ constructor(t, s = {}) {
144
+ this.hasAsyncContent = !1, this._animShow = new e(), this._animOpenClose = new e(), this._isLoadingAsync = !1, this._activating = !1, this._switchDirection = null, this._returnFocusTarget = null, this._heightObserver = null, this._verbController = new AbortController(), this._parsePanelParam = () => {
145
+ let e = n();
146
+ return this.panels.find((t) => t.id && e.includes(t.id))?.id ?? null;
147
+ }, this._persistState = (e) => {
148
+ if (this.config.persist && this.element.id && o(`ps:${this.element.id}`, e), this.config.deepLink) this._updatePanelParam(e);
149
+ else {
150
+ let e = new Set(this.panels.map((e) => e.id).filter(Boolean)), t = n();
151
+ t.some((t) => e.has(t)) && r(t.filter((t) => !e.has(t)));
152
+ }
153
+ }, this._updatePanelParam = (e) => {
154
+ let t = new Set(this.panels.map((e) => e.id).filter(Boolean));
155
+ r([...n().filter((e) => !t.has(e)), e].filter(Boolean));
156
+ }, this._resolveInitialPanel = () => {
157
+ let e = this._parsePanelParam();
158
+ if (e) return e;
159
+ if (this.config.persist) {
160
+ let { id: e } = this.element;
161
+ if (!e) return null;
162
+ let t = a(`ps:${e}`);
163
+ return t && this.panels.some((e) => e.id === t) ? t : null;
164
+ }
165
+ return null;
166
+ }, this._onActivationEdge = (e) => {
167
+ let { atStart: t, atEnd: n } = e.detail;
168
+ this._reflectVerbEndState(t, n);
169
+ };
170
+ let l;
171
+ if (typeof t == "string") {
172
+ if (l = document.querySelector(t), !l) throw Error(`PanelSet: No element found for selector "${t}"`);
173
+ } else l = t;
174
+ if (this.element = l, i._validateElement(l), l.panelSet) return console.warn("PanelSet: already initialized"), l.panelSet;
175
+ l.panelSet = this, i._installVerbDelegation();
176
+ let u = c(l.dataset, i.attrs);
177
+ if (this.config = {
178
+ ...i.defaults,
179
+ ...s,
180
+ ...u
181
+ }, this.panels = this._collectPanels(), this.panels.length === 0) {
182
+ this.panelWrapper = this.element.querySelector(":scope > .panel-wrapper") || this._autoWrapPanels(), this._log("Initialized empty (0 panels) — ready for addPanel()"), this._dispatch("ps:ready", {
183
+ container: this.element,
184
+ instance: this
185
+ }), this._initVerbButtons(), this._observeTrackHeight();
186
+ return;
187
+ }
188
+ let d = this._resolveInitialPanel();
189
+ this.activePanel = (d ? this.panels.find((e) => e.id === d) : null) ?? this.panels.find((e) => e.classList.contains("active")) ?? this.panels[0], this.panelWrapper = this.element.querySelector(":scope > .panel-wrapper") || this._autoWrapPanels(), this.pendingPanel = this.activePanel, this.config.align !== "start" && (this.element.dataset.panelsetAlign = this.config.align), this.config.closable && !this.element.classList.contains("is-open") && this.element.setAttribute("inert", ""), i._nativeInterpolateSize && p(this.config.debug), this._log(`Initialized (${this.panels.length} panels)`), this._dispatch("ps:ready", {
190
+ container: this.element,
191
+ instance: this
192
+ }), this._internalInit(), this._initVerbButtons(), this._observeTrackHeight();
193
+ }
194
+ _observeTrackHeight() {
195
+ let e = this.element.closest("[data-panelset-trackheight]");
196
+ if (!e || typeof ResizeObserver > "u") return;
197
+ let t = e.clientWidth, n = 0;
198
+ this._heightObserver = new ResizeObserver(() => {
199
+ let r = e.clientWidth;
200
+ r !== t && (t = r, cancelAnimationFrame(n), n = requestAnimationFrame(() => this._updateHighestPanel()));
201
+ }), this._heightObserver.observe(e);
202
+ }
203
+ _log(e) {
204
+ u("PanelSet", this.element, this.config.debug, e);
205
+ }
206
+ get _isClosed() {
207
+ return this.config.closable && !this.element.classList.contains("is-open") && !this.element.classList.contains("is-opening");
208
+ }
209
+ static _validateElement(e) {
210
+ if (!e.hasAttribute("data-panelset") && !e.tagName.includes("-")) throw Error("PanelSet: element must have [data-panelset] or be a custom element");
211
+ }
212
+ _autoWrapPanels() {
213
+ let e = document.createElement("div");
214
+ return e.className = "panel-wrapper", this.panels.forEach((t) => e.appendChild(t)), this.element.appendChild(e), e;
215
+ }
216
+ _collectPanels() {
217
+ return Array.from(this.element.querySelectorAll("[role=\"tabpanel\"]")).filter((e) => e.closest("[data-panelset], ps-panelset, [data-panel], ps-panel") === this.element);
218
+ }
219
+ _internalInit() {
220
+ this.panels.forEach((e) => {
221
+ e.classList.remove("fade", "incoming", "outgoing", "levelup", "leveldown"), e === this.activePanel ? (e.hidden = !1, e.classList.add("active")) : (e.hidden = !0, e.classList.remove("active"));
222
+ }), this.element.style.height = "", this._updateHighestPanel(), this.config.manageTriggers && this._updateTabTriggers(this.activePanel), this.config.manageLabels && this._reflectLabels();
223
+ }
224
+ _dispatch(e, t) {
225
+ this.element.dispatchEvent(new CustomEvent(e, {
226
+ detail: t,
227
+ bubbles: !0,
228
+ cancelable: !1
229
+ }));
230
+ }
231
+ _getVerticalMetrics(e) {
232
+ if (!e) return 0;
233
+ let t = getComputedStyle(e);
234
+ return (parseFloat(t.paddingTop) || 0) + (parseFloat(t.paddingBottom) || 0) + (parseFloat(t.borderTopWidth) || 0) + (parseFloat(t.borderBottomWidth) || 0);
235
+ }
236
+ _measureHeight(e) {
237
+ let t = e.offsetHeight;
238
+ return t += this._getVerticalMetrics(this.panelWrapper), t += this._getVerticalMetrics(this.element), t;
239
+ }
240
+ _updateHighestPanel() {
241
+ if (this.element.hasAttribute("data-panelset-trackheight")) {
242
+ console.warn("PanelSet: data-panelset-trackheight on parent only");
243
+ return;
244
+ }
245
+ let e = this.element.closest("[data-panelset-trackheight]");
246
+ if (!e) return;
247
+ this.panels.forEach((e) => {
248
+ e.hidden = !0, e.classList.remove("active");
249
+ });
250
+ let t = 0;
251
+ this.panels.forEach((e) => {
252
+ e.hidden = !1, e.classList.add("active"), e.style.visibility = "hidden";
253
+ let n = this.element.offsetHeight;
254
+ n > t && (t = n), e.hidden = !0, e.classList.remove("active"), e.style.visibility = "";
255
+ }), this.activePanel && (this.activePanel.hidden = !1, this.activePanel.classList.add("active")), e.style.setProperty("--ps-max-height", `${t}px`), this._log(`Max container height: ${t}px`);
256
+ }
257
+ _updateTabTriggers(e) {
258
+ this.panels.forEach((t) => {
259
+ t.id && document.querySelectorAll(`[aria-controls="${t.id}"]`).forEach((n) => {
260
+ n.setAttribute("aria-selected", String(t === e));
261
+ });
262
+ });
263
+ }
264
+ _reflectLabels() {
265
+ this.panels.forEach((e) => {
266
+ if (!e.id || e.hasAttribute("aria-labelledby") || e.hasAttribute("aria-label")) return;
267
+ let t = Array.from(document.querySelectorAll(`[aria-controls="${e.id}"]`));
268
+ if (t.length === 0) return;
269
+ let n = t.filter((e) => e.getAttribute("role") === "tab"), r = n.length === 1 ? n[0] : t.length === 1 ? t[0] : null;
270
+ r && (r.id || (r.id = this._uniqueId(`${e.id}-tab`)), e.setAttribute("aria-labelledby", r.id));
271
+ });
272
+ }
273
+ _uniqueId(e) {
274
+ let t = e, n = 2;
275
+ for (; document.getElementById(t);) t = `${e}-${n++}`;
276
+ return t;
277
+ }
278
+ _setTriggersActivating(e) {
279
+ this.panels.forEach((t) => {
280
+ t.id && document.querySelectorAll(`[aria-controls="${t.id}"]`).forEach((t) => {
281
+ t.classList.toggle("is-activating", e);
282
+ });
283
+ });
284
+ }
285
+ _cleanupPanels(e) {
286
+ this.panels.forEach((t) => {
287
+ t.classList.remove("fade", "incoming", "outgoing", "levelup", "leveldown"), t === e ? (t.classList.add("active"), t.hidden = !1, t.removeAttribute("inert")) : (t.classList.remove("active"), t.hidden = !0);
288
+ }), this.element.style.height = "", this.element.classList.remove("is-transitioning"), this.activePanel = e, this.config.manageTriggers && this._updateTabTriggers(e);
289
+ }
290
+ _resolveAutoFocus(e, t) {
291
+ if (this.config.manageTriggers) {
292
+ let t = e?.getAttribute("data-auto-focus");
293
+ if (t != null) {
294
+ if (t === "true") return !0;
295
+ if (t === "false") return !1;
296
+ if (t === "heading" || t === "first" || t === "input") return t;
297
+ }
298
+ }
299
+ return t === void 0 ? this.config.autoFocus : t;
300
+ }
301
+ _handleAutoFocus(e, n, r) {
302
+ t(e, n, r);
303
+ }
304
+ _animateOpenClose(t, n, r) {
305
+ let a = t ? "opening" : "closing", o = `is-${t ? "closing" : "opening"}`, s = `is-${a}`;
306
+ this._log(t ? "Opening" : "Closing");
307
+ let c = this._animOpenClose.start(), l = this.element.classList.contains(o) ? this.element.offsetHeight : null, u = t ? null : this.element.offsetHeight;
308
+ this.element.classList.remove(o), t || this.element.classList.remove("is-open"), t && this.element.removeAttribute("inert");
309
+ let d = () => {
310
+ this.element.setAttribute("inert", "");
311
+ let e = r instanceof PointerEvent && r.pointerType !== "";
312
+ this.config.returnFocus && this._returnFocusTarget && !e && this._returnFocusTarget.focus();
313
+ };
314
+ if (n && this.config.transitions) if (this.element.classList.add(s), i._nativeInterpolateSize) t ? (this.element.style.height = l === null ? "0px" : `${l}px`, requestAnimationFrame(() => {
315
+ this.element.style.height = "", e.waitForTransition(this.element, "height").then(() => {
316
+ c.aborted || (this.panelWrapper ? e.waitForTransition(this.panelWrapper) : Promise.resolve()).then(() => {
317
+ c.aborted || (this.element.classList.remove(s), this.element.classList.add("is-open"), this.element.offsetHeight);
318
+ });
319
+ });
320
+ })) : (this.element.style.height = l === null ? `${u}px` : `${l}px`, requestAnimationFrame(() => {
321
+ this.element.style.height = "", e.waitForTransition(this.element, "height").then(() => {
322
+ c.aborted || (this.element.classList.remove(s), this.element.offsetHeight, d());
323
+ });
324
+ }));
325
+ else {
326
+ let n = t ? this._measureHeight(this.pendingPanel) : 0, r = l === null ? t ? this.element.offsetHeight : u ?? 0 : l;
327
+ this.element.style.height = `${r}px`, getComputedStyle(this.element).height, requestAnimationFrame(() => {
328
+ this.element.style.height = `${n}px`, e.waitForTransition(this.element).then(() => {
329
+ c.aborted || (this.element.style.height = "", this.element.classList.remove(s), t && this.element.classList.add("is-open"), this.element.offsetHeight, t || d());
330
+ });
331
+ });
332
+ }
333
+ else t ? this.element.classList.add("is-open") : (this.element.classList.remove("is-open"), d()), this.element.style.height = "";
334
+ }
335
+ getActive() {
336
+ return this.pendingPanel?.id || null;
337
+ }
338
+ refresh() {
339
+ let e = this.activePanel;
340
+ this.panels = this._collectPanels(), this.panels.length !== 0 && (this.activePanel = e && this.panels.includes(e) ? e : this.panels.find((e) => e.classList.contains("active")) ?? this.panels[0], this.pendingPanel = this.activePanel, this.panelWrapper = this.element.querySelector(":scope > .panel-wrapper") || this.panelWrapper, this._internalInit(), this._reflectEnds(), this._log(`Refreshed (${this.panels.length} panels)`));
341
+ }
342
+ addPanel(e, t) {
343
+ e.hasAttribute("role") || e.setAttribute("role", "tabpanel");
344
+ let n = null;
345
+ return t?.before ? n = this.panels.find((e) => e.id === t.before) ?? null : t?.after ? n = this.panels.find((e) => e.id === t.after)?.nextElementSibling ?? null : typeof t?.index == "number" && (n = this.panels[t.index] ?? null), (this.panelWrapper || this._autoWrapPanels()).insertBefore(e, n), this.refresh(), e;
346
+ }
347
+ removePanel(e) {
348
+ let t = this.panels.find((t) => t.id === e);
349
+ t && (t.remove(), this.refresh());
350
+ }
351
+ destroy() {
352
+ this._animShow.start(), this._animOpenClose.start(), this._heightObserver?.disconnect(), this._heightObserver = null, this._verbController.abort(), delete this.element.panelSet, this._log("Destroyed");
353
+ }
354
+ _edgeInfo(e) {
355
+ let t = this.panels.length, n = e ? this.panels.indexOf(e) : -1;
356
+ return {
357
+ index: n,
358
+ total: t,
359
+ atStart: n <= 0,
360
+ atEnd: n === t - 1
361
+ };
362
+ }
363
+ static _installVerbDelegation() {
364
+ i._verbDelegationInstalled || (i._verbDelegationInstalled = !0, document.addEventListener("click", i._onVerbClick));
365
+ }
366
+ static _resolveVerbSet(e, t) {
367
+ let n = e.getAttribute(`data-ps-${t}`);
368
+ return n ? document.querySelector(n) : e.closest("[data-panelset], ps-panelset");
369
+ }
370
+ _initVerbButtons() {
371
+ let { signal: e } = this._verbController;
372
+ this.element.addEventListener("ps:activationstart", this._onActivationEdge, { signal: e }), this.element.addEventListener("ps:activationcomplete", this._onActivationEdge, { signal: e }), this._reflectEnds();
373
+ }
374
+ _reflectEnds() {
375
+ let { atStart: e, atEnd: t } = this._edgeInfo(this.pendingPanel);
376
+ this._reflectVerbEndState(e, t);
377
+ }
378
+ _reflectVerbEndState(e, t) {
379
+ if (this.config.loop) return;
380
+ let n = this._verbButtonsFor("prev"), r = this._verbButtonsFor("next");
381
+ if (this.config.disabledMode !== "native") {
382
+ n.forEach((t) => this._applyVerbDisabled(t, e)), r.forEach((e) => this._applyVerbDisabled(e, t));
383
+ return;
384
+ }
385
+ e || n.forEach((e) => this._applyVerbDisabled(e, !1)), t || r.forEach((e) => this._applyVerbDisabled(e, !1)), e && this._disableVerbNative(n, t ? [] : r), t && this._disableVerbNative(r, e ? [] : n);
386
+ }
387
+ _applyVerbDisabled(e, t) {
388
+ this.config.disabledMode === "native" ? t ? e.setAttribute("disabled", "") : e.removeAttribute("disabled") : e.setAttribute("aria-disabled", String(t));
389
+ let n = e.getAttribute("data-ps-disabled-hint");
390
+ n && d(e, n, t);
391
+ }
392
+ _disableVerbNative(e, t) {
393
+ e.forEach((e) => {
394
+ !e.hasAttribute("disabled") && document.activeElement === e && (t.find((e) => !e.hasAttribute("disabled")) ?? this._verbFocusFallback())?.focus(), this._applyVerbDisabled(e, !0);
395
+ });
396
+ }
397
+ _verbFocusFallback() {
398
+ let e = this.pendingPanel ?? this.activePanel;
399
+ return e ? (e.hasAttribute("tabindex") || e.setAttribute("tabindex", "-1"), e) : null;
400
+ }
401
+ _verbButtonsFor(e) {
402
+ return Array.from(document.querySelectorAll(`[data-ps-${e}]`)).filter((t) => i._resolveVerbSet(t, e) === this.element);
403
+ }
404
+ next(e) {
405
+ this._step(1, e);
406
+ }
407
+ prev(e) {
408
+ this._step(-1, e);
409
+ }
410
+ _step(e, t) {
411
+ let n = this.panels.length;
412
+ if (n === 0) return;
413
+ let r = this.panels.indexOf(this.pendingPanel), i = (r === -1 ? 0 : r) + e, a = !1;
414
+ if (i < 0 || i >= n) {
415
+ if (!this.config.loop) return;
416
+ i = (i + n) % n, a = !0;
417
+ }
418
+ let o = this.panels[i];
419
+ o && o !== this.pendingPanel && this.show(o.id, a ? {
420
+ ...t,
421
+ direction: e > 0 ? "forward" : "backward"
422
+ } : t);
423
+ }
424
+ open(t) {
425
+ let { event: n, transition: r = !0, autoFocus: i } = t || {};
426
+ if (!this.config.closable) {
427
+ this._log("Not closable");
428
+ return;
429
+ }
430
+ let a = this._isClosed, o = this.element.classList.contains("is-closing"), s = this.element.classList.contains("is-loading");
431
+ if (!a && !o || this.element.classList.contains("is-transitioning") && !s) return;
432
+ let c = n?.target instanceof HTMLElement ? n.target.closest("button, a, [role=\"tab\"]") ?? n.target : null, l = this._resolveAutoFocus(c, i);
433
+ c && (this._returnFocusTarget = c), this._animateOpenClose(!0, r), l !== !1 && l !== void 0 && this.pendingPanel && (r && this.config.transitions ? e.waitForTransition(this.element).then(() => {
434
+ this._handleAutoFocus(this.pendingPanel, l, n);
435
+ }) : this._handleAutoFocus(this.pendingPanel, l, n));
436
+ }
437
+ close(e) {
438
+ let { transition: t = !0, event: n } = e || {};
439
+ if (!this.config.closable) {
440
+ this._log("Not closable");
441
+ return;
442
+ }
443
+ let r = this._isClosed, i = this.element.classList.contains("is-closing"), a = this.element.classList.contains("is-opening"), o = this.element.classList.contains("is-loading");
444
+ (r || i) && !a || this.element.classList.contains("is-transitioning") && !o || this._animateOpenClose(!1, t, n);
445
+ }
446
+ toggle(e) {
447
+ let { event: t, transition: n = !0, autoFocus: r } = e || {}, i = this._isClosed, a = this.element.classList.contains("is-closing");
448
+ i || a ? this.open({
449
+ event: t,
450
+ transition: n,
451
+ autoFocus: r
452
+ }) : this.close({
453
+ transition: n,
454
+ event: t
455
+ });
456
+ }
457
+ onBeforeOpen(e, t = {}) {
458
+ this.hasAsyncContent = !0, h(this.element, "ps:beforeopen", (e) => e.targetPanel, e, t);
459
+ }
460
+ async show(t, n) {
461
+ if (this.config.interruptible === !1 && this._activating) return;
462
+ let { event: r, transition: i = !0, autoFocus: a, direction: o } = n || {}, s = r?.target instanceof HTMLElement ? r.target.closest("button, a, [role=\"tab\"]") ?? r.target : null, c = this._resolveAutoFocus(s, a), l = this.panels.find((e) => e.id === t);
463
+ if (!l) {
464
+ this._log(`Panel not found: ${t}`);
465
+ return;
466
+ }
467
+ let u = new CustomEvent("ps:beforeactivate", {
468
+ detail: {
469
+ panelId: t,
470
+ targetPanel: l,
471
+ outgoingPanel: this.activePanel ?? null,
472
+ trigger: s
473
+ },
474
+ bubbles: !0,
475
+ cancelable: !0
476
+ });
477
+ if (!this.element.dispatchEvent(u)) {
478
+ this._log(`Vetoed by ps:beforeactivate: ${t}`);
479
+ return;
480
+ }
481
+ let d = this._isClosed, f = this.element.classList.contains("is-closing"), p = this.element.classList.contains("is-loading");
482
+ if (l === this.pendingPanel) {
483
+ d || f ? this.open({
484
+ event: r,
485
+ transition: i,
486
+ autoFocus: c
487
+ }) : this.config.closable && this.config.closeOnTab && this.close({
488
+ transition: i,
489
+ event: r
490
+ });
491
+ return;
492
+ }
493
+ if ((this.element.classList.contains("is-opening") || f) && !p) return;
494
+ if (d) {
495
+ this.pendingPanel = l, this._cleanupPanels(l), this.open({
496
+ event: r,
497
+ transition: i,
498
+ autoFocus: c
499
+ });
500
+ return;
501
+ }
502
+ let h = this._activating;
503
+ this._activating = !0, this.config.manageTriggers && this.config.interruptible === !1 && this._setTriggersActivating(!0);
504
+ let g = this.pendingPanel, _ = g?.id;
505
+ this.pendingPanel = l;
506
+ let v = h && l === this.activePanel && g !== l;
507
+ this.config.manageTriggers && this._updateTabTriggers(l), this._persistState(t), this.element.classList.remove("is-loading"), !v && g && g !== this.activePanel && g !== l && (g.classList.remove("incoming", "outgoing", "levelup", "leveldown"), g.hidden || g.classList.remove("active"));
508
+ let y = this._isLoadingAsync, b = this._animShow.signal.aborted, x = this._animShow.start();
509
+ !b && y && _ && _ !== t && this._dispatch("ps:activationaborted", {
510
+ panelId: _,
511
+ trigger: s
512
+ }), this._isLoadingAsync = !1, this._log(`${g?.id || "none"} > ${t}`);
513
+ let S = {
514
+ panelId: t,
515
+ targetPanel: l,
516
+ outgoingPanel: g,
517
+ signal: x,
518
+ promise: null,
519
+ waitUntil() {}
520
+ };
521
+ m(S);
522
+ let C = new CustomEvent("ps:beforeopen", {
523
+ detail: S,
524
+ bubbles: !0,
525
+ cancelable: !1
526
+ });
527
+ this.element.dispatchEvent(C);
528
+ let w = S.promise;
529
+ if (w) {
530
+ this._isLoadingAsync = !0, this._log("Waiting for content..."), this.element.style.setProperty("--ps-loading-delay", `${this.config.loadingDelay}ms`), this.element.classList.add("is-loading");
531
+ let n = null, r = i !== !1 && this.config.transitions !== !1, a = r;
532
+ if (typeof this.config.transitions == "object" && (a = r && this.config.transitions.height !== !1), a) if (d) this.element.classList.add("is-open", "is-opening"), this.element.style.height = "0px", requestAnimationFrame(() => {
533
+ this.element.style.height = `${this.config.loadingHeight}px`;
534
+ }), n = e.waitForTransition(this.element, "height");
535
+ else {
536
+ let t = this.element.offsetHeight, r = Math.max(t, this.config.loadingHeight);
537
+ r > t && (this.element.style.height = `${t}px`, requestAnimationFrame(() => {
538
+ this.element.style.height = `${r}px`;
539
+ }), n = e.waitForTransition(this.element, "height"));
540
+ }
541
+ try {
542
+ if (await Promise.all([w, n].filter(Boolean)), x.aborted) {
543
+ this._log(`Aborted during load: ${t}`), this.element.classList.remove("is-loading"), this.element.style.removeProperty("--ps-loading-delay");
544
+ return;
545
+ }
546
+ this._log("Content loaded"), l.dataset.loaded === "true" && this._updateHighestPanel();
547
+ } catch (e) {
548
+ let t = e;
549
+ this._log(`Load failed: ${t.message}`), this.element.classList.remove("is-loading"), this.element.style.removeProperty("--ps-loading-delay"), t.name !== "AbortError" && console.error("Panel load error:", e), this._activating = !1, this.config.manageTriggers && this.config.interruptible === !1 && this._setTriggersActivating(!1);
550
+ return;
551
+ }
552
+ this.element.classList.remove("is-loading"), this.element.style.removeProperty("--ps-loading-delay"), this.element.classList.remove("is-opening");
553
+ }
554
+ if (x.aborted) {
555
+ this._log(`Aborted: ${t}`);
556
+ return;
557
+ }
558
+ let T = v ? g : this.activePanel;
559
+ this._dispatch("ps:activationstart", {
560
+ panelId: t,
561
+ trigger: s,
562
+ outgoingPanel: T,
563
+ ...this._edgeInfo(l)
564
+ });
565
+ let E = i !== !1 && this.config.transitions !== !1, D = E, O = E;
566
+ typeof this.config.transitions == "object" && (D = E && this.config.transitions.panels !== !1, O = E && this.config.transitions.height !== !1), this.panels.forEach((e) => e.classList.toggle("fade", D));
567
+ let k = null;
568
+ if (v) k = this._switchDirection === "leveldown" ? "levelup" : "leveldown";
569
+ else if (this.config.levels && T && T !== l) if (o) k = o === "forward" ? "levelup" : "leveldown";
570
+ else {
571
+ let e = this.panels.indexOf(T), t = this.panels.indexOf(l);
572
+ e !== -1 && t !== -1 && e !== t && (k = t > e ? "levelup" : "leveldown");
573
+ }
574
+ this._switchDirection = k, this.panels.forEach((e) => e.classList.remove("outgoing", "levelup", "leveldown"));
575
+ let A = this.element.offsetHeight;
576
+ O && (this.element.style.height = `${A}px`), l.hidden = !1, l.setAttribute("inert", ""), l.classList.add("incoming"), k && l.classList.add(k), D && this.element.classList.add("is-transitioning"), T && T !== l && (T.classList.remove("active", "incoming"), T.classList.add("outgoing"), k && T.classList.add(k), T.hidden = !1, T.setAttribute("inert", "")), requestAnimationFrame(() => requestAnimationFrame(() => {
577
+ l.classList.add("active"), T && T !== l && T.classList.remove("incoming");
578
+ let n = this._measureHeight(l), i = A !== n;
579
+ O && (this.element.style.height = `${n}px`);
580
+ let a = [];
581
+ D && a.push(e.waitForTransition(l)), O && i && a.push(e.waitForTransition(this.element)), a.length || a.push(Promise.resolve()), Promise.all(a).then(() => {
582
+ if (x.aborted) {
583
+ this._log(`Interrupted: ${t}`);
584
+ return;
585
+ }
586
+ this._cleanupPanels(l), this._log(`✓ ${t}`), c !== !1 && c !== void 0 && this._handleAutoFocus(l, c, r), this._activating = !1, this.config.manageTriggers && this.config.interruptible === !1 && this._setTriggersActivating(!1), this._dispatch("ps:activationcomplete", {
587
+ panelId: t,
588
+ trigger: s,
589
+ outgoingPanel: T,
590
+ ...this._edgeInfo(l)
591
+ });
592
+ });
593
+ }));
594
+ }
595
+ };
596
+ g = _, g.defaults = {
597
+ align: "start",
598
+ transitions: !0,
599
+ levels: !1,
600
+ loop: !1,
601
+ closable: !1,
602
+ closeOnTab: !1,
603
+ disabledMode: "aria",
604
+ loadingHeight: 150,
605
+ loadingDelay: 320,
606
+ returnFocus: !1,
607
+ autoFocus: !1,
608
+ persist: !1,
609
+ deepLink: !1,
610
+ interruptible: !0,
611
+ manageTriggers: !0,
612
+ manageLabels: !0,
613
+ debug: !1
614
+ }, g._nativeInterpolateSize = typeof CSS < "u" && CSS.supports("interpolate-size: allow-keywords"), g._verbDelegationInstalled = !1, g.attrs = {
615
+ align: ["panelsetAlign", "string"],
616
+ transitions: ["transitions", "json"],
617
+ levels: ["psLevels", "boolean"],
618
+ loop: ["psLoop", "boolean"],
619
+ closable: ["closable", "boolean"],
620
+ closeOnTab: ["closeOnTab", "boolean"],
621
+ disabledMode: ["psDisabledMode", "string"],
622
+ loadingHeight: ["loadingHeight", "number"],
623
+ loadingDelay: ["loadingDelay", "number"],
624
+ autoFocus: ["autoFocus", "string"],
625
+ returnFocus: ["returnFocus", "boolean"],
626
+ persist: ["panelPersist", "boolean"],
627
+ deepLink: ["panelDeeplink", "boolean"],
628
+ interruptible: ["interruptible", "boolean"],
629
+ manageTriggers: ["manageTriggers", "boolean"],
630
+ manageLabels: ["manageLabels", "boolean"],
631
+ debug: ["debug", "boolean"]
632
+ }, g._onVerbClick = (e) => {
633
+ let t = e.target;
634
+ if (!(t instanceof Element)) return;
635
+ let n = t.closest("[data-ps-next], [data-ps-prev], [data-ps-close]");
636
+ if (!n || n.getAttribute("aria-disabled") === "true") return;
637
+ let r = n.hasAttribute("data-ps-next") ? "next" : n.hasAttribute("data-ps-prev") ? "prev" : "close", i = g._resolveVerbSet(n, r), a = i?.panelSet;
638
+ if (!a) {
639
+ i && u("PanelSet", i, i.dataset.debug != null && i.dataset.debug !== "false", `data-ps-${r}: PanelSet is not initialised. Add a PanelSet.init().`);
640
+ return;
641
+ }
642
+ a[r]({ event: e });
643
+ };
644
+ //#endregion
645
+ //#region src/js/functions/pinning.ts
646
+ var v = (e) => {
647
+ let t = e.parentElement;
648
+ return t?.querySelector("[data-panel-body]") ? Array.from(t.children).find((e) => e instanceof HTMLElement && e.hasAttribute("data-panel-body")) ?? null : null;
649
+ }, y = (e) => {
650
+ let t = Array.from(e.querySelectorAll("[data-panel-pin]"));
651
+ t.length && t.map((e) => ({
652
+ el: e,
653
+ pin: e.dataset.panelPin,
654
+ w: e.offsetWidth
655
+ })).forEach(({ el: e, pin: t, w: n }) => {
656
+ e.style.boxSizing = "border-box", e.style.width = `${n}px`, t === "end" && (e.style.marginLeft = `calc(100% - ${n}px)`);
657
+ });
658
+ }, b = (e) => {
659
+ e.querySelectorAll("[data-panel-pin]").forEach((e) => {
660
+ e.style.boxSizing = "", e.style.width = "", e.style.marginLeft = "";
661
+ });
662
+ }, x;
663
+ function S(e, t) {
664
+ let { groupSelector: n, scopeSelector: r = n, itemSelector: i, filter: a } = t, o = (e, t) => {
665
+ if (e.closest(r) !== t) return !1;
666
+ let n = e.parentElement?.closest(i);
667
+ return !n || !t.contains(n);
668
+ }, s = e.closest(n);
669
+ return !s || !o(e, s) ? [] : [...s.querySelectorAll(i)].filter((t) => t !== e && o(t, s) && (a ? a(t) : !0));
670
+ }
671
+ var C = class i {
672
+ static init(e = "[data-panel]", t = {}) {
673
+ let n, r;
674
+ return typeof e == "string" ? (n = e, r = t) : (r = e, n = "[data-panel]"), Array.from(document.querySelectorAll(n)).filter((e) => !e.panel).filter((e) => !e.dataset.panel || e.dataset.panel === "data-panel").map((e) => new i(e, r));
675
+ }
676
+ constructor(t, s = {}) {
677
+ this._returnFocusTarget = null, this._tempCloseGroup = null, this._anim = new e(), this._listenerController = new AbortController(), this._activating = !1, this._parsePanelParam = () => {
678
+ let { id: e } = this.element;
679
+ return e ? n().includes(e) : !1;
680
+ }, this._updatePanelParam = (e) => {
681
+ let { id: t } = this.element;
682
+ if (!t) return;
683
+ let i = n();
684
+ r(e ? [...new Set([...i, t])] : i.filter((e) => e !== t));
685
+ }, this._resolveStateConfig = () => {
686
+ let e = (e) => this.element.hasAttribute(e) ? this.element.getAttribute(e) !== "false" : void 0, t = e("data-panel-persist"), n = e("data-panel-deeplink"), r, i, a = this.element.parentElement;
687
+ for (; a && !a.hasAttribute("data-panel");) {
688
+ if (a.hasAttribute("data-panel-group")) {
689
+ a.hasAttribute("data-panel-persist") && (r = a.getAttribute("data-panel-persist") !== "false"), a.hasAttribute("data-panel-deeplink") && (i = a.getAttribute("data-panel-deeplink") !== "false");
690
+ break;
691
+ }
692
+ a = a.parentElement;
693
+ }
694
+ return {
695
+ persist: t ?? r ?? this.config.persist,
696
+ deepLink: n ?? i ?? this.config.deepLink
697
+ };
698
+ }, this._persistState = (e) => {
699
+ if (!this.element.id) return;
700
+ let { persist: t, deepLink: n } = this._resolveStateConfig();
701
+ t && o(`panel:${this.element.id}`, e ? "open" : "closed"), n ? this._updatePanelParam(e) : !e && this._parsePanelParam() && this._updatePanelParam(!1);
702
+ }, this._resolveInitialState = () => {
703
+ let { id: e } = this.element;
704
+ if (!e) return !1;
705
+ if (this._parsePanelParam()) return !0;
706
+ let { persist: t } = this._resolveStateConfig();
707
+ return !!(t && a(`panel:${e}`) === "open");
708
+ }, this._cssProp = () => this.config.axis === "horizontal" ? "width" : "height";
709
+ let l = typeof t == "string" ? document.querySelector(t) : t;
710
+ if (!l) throw Error(`Panel: No element found for selector "${t}"`);
711
+ if (this.element = l, l.panel = this, !l.querySelector(":scope > .panel-wrapper")) {
712
+ let e = document.createElement("div");
713
+ e.className = "panel-wrapper", e.append(...Array.from(l.childNodes)), l.appendChild(e);
714
+ }
715
+ let u = c(l.dataset, i.attrs);
716
+ this.config = {
717
+ ...i.defaults,
718
+ ...s,
719
+ ...u
720
+ }, this.config.axis === "horizontal" && (l.dataset.panelAxis = "horizontal"), this.config.align !== "start" && (l.dataset.panelAlign = this.config.align), this._wireImplicitTriggers(), this._bindTriggers(), this._resolveInitialState() || this.element.classList.contains("is-open") ? (this.element.classList.add("is-open"), this.element.removeAttribute("inert"), this._setTriggerState(!0), this.element.classList.add("is-restored"), requestAnimationFrame(() => requestAnimationFrame(() => this.element.classList.remove("is-restored"))), this._dispatch("panel:opened")) : this.element.setAttribute("inert", ""), i._nativeInterpolateSize && p(this.config.debug), this._log("Initialized");
721
+ }
722
+ _log(e) {
723
+ u("Panel", this.element, this.config.debug, e);
724
+ }
725
+ _wireImplicitTriggers() {
726
+ let e = (e) => e.hasAttribute("data-panel") || !!e.panel, t = (e) => {
727
+ this.element.id || (this.element.id = `panel-${++i._autoIdCounter}`), e.setAttribute("aria-controls", this.element.id), e.hasAttribute("aria-expanded") || e.setAttribute("aria-expanded", "false"), e.removeAttribute("data-panel-trigger");
728
+ }, n = (e) => e.hasAttribute("data-panel-trigger") ? e : /^H[1-6]$/.test(e.tagName) ? e.querySelector(":scope > [data-panel-trigger]") : null;
729
+ for (let r of ["previousElementSibling", "nextElementSibling"]) {
730
+ let i = this.element[r];
731
+ for (; i && !e(i);) {
732
+ let e = n(i);
733
+ if (e) {
734
+ t(e);
735
+ break;
736
+ }
737
+ i = i[r];
738
+ }
739
+ }
740
+ }
741
+ _bindTriggers() {
742
+ let e = this.element.id;
743
+ if (!e) return;
744
+ let { signal: t } = this._listenerController;
745
+ document.querySelectorAll(`[aria-controls="${e}"]`).forEach((e) => {
746
+ e.addEventListener("click", (t) => {
747
+ this._returnFocusTarget = e, this.toggle(t);
748
+ }, { signal: t });
749
+ }), this.element.querySelectorAll("[data-panel-close]").forEach((e) => {
750
+ e.closest("[data-panel]") === this.element && e.addEventListener("click", () => this.close(), { signal: t });
751
+ }), this.config.closeOnResize && window.addEventListener("resize", () => {
752
+ if (!this.isOpen || this.element.classList.contains("is-closing")) return;
753
+ let e = v(this.element);
754
+ e && b(e), this.close();
755
+ }, { signal: t });
756
+ }
757
+ _setTriggerState(e) {
758
+ let t = this.element.id;
759
+ t && document.querySelectorAll(`[aria-controls="${t}"]`).forEach((t) => t.setAttribute("aria-expanded", String(e)));
760
+ }
761
+ _cleanupTempClose() {
762
+ this._tempCloseGroup && (this._tempCloseGroup.style.removeProperty("--ps-tempclose-speed"), this._tempCloseGroup.style.removeProperty("--ps-tempclose-timing"), this._tempCloseGroup = null);
763
+ }
764
+ _closeGroupSiblings() {
765
+ let e = this.element.closest("[data-panel-group]"), t = e?.hasAttribute("data-panel-close-siblings") ?? !1;
766
+ if (!this.config.closeSiblings && !t) return;
767
+ let n = e ? S(this.element, {
768
+ groupSelector: "[data-panel-group]",
769
+ itemSelector: "[data-panel]",
770
+ filter: (e) => !!e.panel?.isOpen
771
+ }) : Array.from(this.element.parentElement?.children ?? []).filter((e) => e instanceof HTMLElement && e !== this.element && !!e.panel?.isOpen);
772
+ n.length && e && (e.style.setProperty("--ps-tempclose-speed", "var(--ps-open-speed)"), e.style.setProperty("--ps-tempclose-timing", "var(--ps-open-timing)"), this._tempCloseGroup = e), n.forEach((e) => {
773
+ e.panel._returnFocusTarget = null, e.panel.close();
774
+ });
775
+ }
776
+ _handleAutoFocus(e) {
777
+ this.config.autoFocus && t(this.element, this.config.autoFocus, e);
778
+ }
779
+ _dispatch(e) {
780
+ (e === "panel:opened" || e === "panel:closed") && (this._activating = !1);
781
+ let t = { trigger: this._returnFocusTarget };
782
+ this.element.dispatchEvent(new CustomEvent(e, {
783
+ detail: t,
784
+ bubbles: !0
785
+ }));
786
+ }
787
+ get isOpen() {
788
+ return this.element.classList.contains("is-open") || this.element.classList.contains("is-opening");
789
+ }
790
+ async open(e) {
791
+ if (this.isOpen && !this.element.classList.contains("is-closing") || this.config.interruptible === !1 && this._activating) return;
792
+ this._activating = !0;
793
+ let t = this._anim.start(), n = this._cssProp(), r = {
794
+ signal: t,
795
+ promise: null,
796
+ waitUntil() {},
797
+ trigger: this._returnFocusTarget
798
+ };
799
+ m(r), this.element.dispatchEvent(new CustomEvent("panel:beforeopen", {
800
+ detail: r,
801
+ bubbles: !0
802
+ })), r.promise ? await this._openAsync(t, n, r.promise, e) : this._openSync(t, n, e);
803
+ }
804
+ async _openAsync(t, n, r, a) {
805
+ let o = await Promise.race([r.then(() => !0), new Promise((e) => {
806
+ let n = setTimeout(() => e(!1), this.config.loadingDelay);
807
+ t.addEventListener("abort", () => clearTimeout(n));
808
+ })]).catch(() => !1);
809
+ if (t.aborted) return;
810
+ if (o) {
811
+ this._openSync(t, n, a);
812
+ return;
813
+ }
814
+ this.element.classList.remove("is-closing"), this.element.removeAttribute("inert"), this.element.classList.add("is-loading"), this.element.querySelector(":scope > .panel-wrapper")?.replaceChildren(), this.element.style.setProperty("--ps-loading-delay", "0ms"), this._setTriggerState(!0), this._persistState(!0), this._dispatch("panel:opening");
815
+ let s = v(this.element);
816
+ s && y(s);
817
+ let c;
818
+ this.config.transitions ? (this.element.classList.add("is-opening"), this.element.style[n] = "0px", getComputedStyle(this.element)[n], requestAnimationFrame(() => {
819
+ this.element.style[n] = `${this.config.loadingHeight}px`;
820
+ }), c = e.waitForTransition(this.element, n)) : this.element.style[n] = `${this.config.loadingHeight}px`;
821
+ try {
822
+ await Promise.all([r, c].filter(Boolean));
823
+ } catch {} finally {
824
+ this.element.classList.remove("is-loading"), this.element.style.removeProperty("--ps-loading-delay");
825
+ }
826
+ if (t.aborted) return;
827
+ let l = this.element.getBoundingClientRect(), u = n === "height" ? l.height : l.width;
828
+ if (this.element.style[n] = "", this.config.transitions) if (i._nativeInterpolateSize) e.waitForTransition(this.element, n).then(() => {
829
+ t.aborted || (this.element.classList.remove("is-opening"), this.element.classList.add("is-open"), this._dispatch("panel:opened"), this._log("Opened"), this._handleAutoFocus(a));
830
+ });
831
+ else {
832
+ this.element.style[n] = "auto";
833
+ let r = this.element.getBoundingClientRect(), i = n === "height" ? r.height : r.width;
834
+ this.element.style[n] = `${u}px`, getComputedStyle(this.element)[n], requestAnimationFrame(() => {
835
+ this.element.style[n] = `${i}px`, e.waitForTransition(this.element, n).then(() => {
836
+ t.aborted || (this.element.style[n] = "", this.element.classList.remove("is-opening"), this.element.classList.add("is-open"), this._dispatch("panel:opened"), this._log("Opened"), this._handleAutoFocus(a));
837
+ });
838
+ });
839
+ }
840
+ else this.element.classList.remove("is-opening"), this.element.classList.add("is-open"), this._dispatch("panel:opened"), this._log("Opened"), this._handleAutoFocus(a);
841
+ }
842
+ _openSync(t, n, r) {
843
+ let a = this.element.classList.contains("is-closing") ? this.element.getBoundingClientRect()[n === "height" ? "height" : "width"] : null;
844
+ this.element.classList.remove("is-closing"), this.element.removeAttribute("inert");
845
+ let o = v(this.element);
846
+ if (this.config.transitions) if (i._nativeInterpolateSize) this.element.classList.add("is-opening"), this.element.style[n] = a === null ? "0px" : `${a}px`, o && y(o), getComputedStyle(this.element)[n], this._setTriggerState(!0), this._persistState(!0), this._closeGroupSiblings(), this._dispatch("panel:opening"), requestAnimationFrame(() => {
847
+ this.element.style[n] = "", e.waitForTransition(this.element, n).then(() => {
848
+ t.aborted || (this.element.classList.remove("is-opening"), this.element.classList.add("is-open"), this._dispatch("panel:opened"), this._cleanupTempClose(), this._log("Opened"), this._handleAutoFocus(r));
849
+ });
850
+ });
851
+ else {
852
+ this._setTriggerState(!0), this._persistState(!0), this._closeGroupSiblings(), this._dispatch("panel:opening"), this.element.style[n] = "auto";
853
+ let i = this.element.getBoundingClientRect(), s = n === "height" ? i.height : i.width;
854
+ this.element.style[n] = a === null ? "0px" : `${a}px`, this.element.classList.add("is-opening"), o && y(o), getComputedStyle(this.element)[n], requestAnimationFrame(() => {
855
+ this.element.style[n] = `${s}px`, e.waitForTransition(this.element, n).then(() => {
856
+ t.aborted || (this.element.style[n] = "", this.element.classList.remove("is-opening"), this.element.classList.add("is-open"), this._dispatch("panel:opened"), this._cleanupTempClose(), this._log("Opened"), this._handleAutoFocus(r));
857
+ });
858
+ });
859
+ }
860
+ else this._setTriggerState(!0), this._persistState(!0), this._closeGroupSiblings(), this._dispatch("panel:opening"), this.element.classList.add("is-open"), this._dispatch("panel:opened"), this._cleanupTempClose(), this._log("Opened"), this._handleAutoFocus(r);
861
+ }
862
+ onBeforeOpen(e, t = {}) {
863
+ h(this.element, "panel:beforeopen", () => this.element, e, t);
864
+ }
865
+ close(t) {
866
+ if (!this.isOpen || this.config.interruptible === !1 && this._activating) return;
867
+ this._activating = !0, this.element.setAttribute("inert", ""), this._setTriggerState(!1);
868
+ let n = this._cssProp(), r = v(this.element), i = this._anim.start();
869
+ this._dispatch("panel:closing");
870
+ let a = () => {
871
+ this.element.classList.remove("is-closing", "is-open", "is-opening"), this.element.style[n] = "", r && b(r), this._persistState(!1), this._dispatch("panel:closed"), this._log("Closed");
872
+ let e = t instanceof PointerEvent && t.pointerType !== "";
873
+ this.config.returnFocus && this._returnFocusTarget && !e && this._returnFocusTarget.focus();
874
+ };
875
+ if (!this.config.transitions) {
876
+ a();
877
+ return;
878
+ }
879
+ let o = this.element.getBoundingClientRect(), s = n === "height" ? o.height : o.width;
880
+ this.element.style[n] = `${s}px`, this.element.classList.remove("is-opening", "is-open"), this.element.classList.add("is-closing"), getComputedStyle(this.element)[n], requestAnimationFrame(() => {
881
+ this.element.style[n] = "0px", e.waitForTransition(this.element, n).then(() => {
882
+ i.aborted || a();
883
+ });
884
+ });
885
+ }
886
+ toggle(e) {
887
+ this.element.classList.contains("is-closing") ? this.open(e) : this.isOpen ? this.close(e) : (e?.target && (this._returnFocusTarget = e.target.closest("button, a") ?? e.target), this.open(e));
888
+ }
889
+ destroy() {
890
+ this._anim.start(), this._listenerController.abort(), this.element.classList.remove("is-opening", "is-closing", "is-loading", "is-open"), this.element.style[this._cssProp()] = "", this.element.setAttribute("inert", ""), this._setTriggerState(!1);
891
+ let e = v(this.element);
892
+ e && b(e), delete this.element.panel, this._log("Destroyed");
893
+ }
894
+ };
895
+ x = C, x.defaults = {
896
+ axis: "vertical",
897
+ align: "start",
898
+ closeOnResize: !1,
899
+ transitions: !0,
900
+ autoFocus: !1,
901
+ returnFocus: !0,
902
+ closeSiblings: !1,
903
+ loadingDelay: 320,
904
+ loadingHeight: 150,
905
+ interruptible: !0,
906
+ persist: !1,
907
+ deepLink: !1,
908
+ debug: !1
909
+ }, x.attrs = {
910
+ axis: ["panelAxis", "string"],
911
+ align: ["panelAlign", "string"],
912
+ autoFocus: ["panelAutoFocus", "string"],
913
+ closeOnResize: ["panelCloseOnResize", "boolean"],
914
+ transitions: ["panelTransitions", "boolean"],
915
+ returnFocus: ["panelReturnFocus", "boolean"],
916
+ closeSiblings: ["panelCloseSiblings", "boolean"],
917
+ loadingDelay: ["panelLoadingDelay", "number"],
918
+ loadingHeight: ["panelLoadingHeight", "number"],
919
+ interruptible: ["panelInterruptible", "boolean"],
920
+ persist: ["panelPersist", "boolean"],
921
+ deepLink: ["panelDeeplink", "boolean"],
922
+ debug: ["debug", "boolean"]
923
+ }, x._nativeInterpolateSize = typeof CSS < "u" && CSS.supports("interpolate-size: allow-keywords"), x._autoIdCounter = 0;
924
+ //#endregion
925
+ //#region src/js/panelcontrol.ts
926
+ var w, T = class e {
927
+ static init(t = "[data-panelcontrol]", n = {}) {
928
+ let r, i;
929
+ return typeof t == "string" ? (r = t, i = n) : (i = t, r = i.selector || "[data-panelcontrol]"), Array.from(document.querySelectorAll(r)).filter((e) => !e.panelControl).map((t) => new e(t, i));
930
+ }
931
+ constructor(t, n = {}) {
932
+ this._setEl = null, this._controller = new AbortController(), this._isTablist = !1, this._activationWired = !1, this._reflectCloseable = () => {
933
+ let e = this.panelSet, t = this.panelSetElement, n = !1;
934
+ if (e) n = !!(e.config.closable && e.config.closeOnTab);
935
+ else if (t) {
936
+ let e = t.dataset.closable != null || t.hasAttribute("closable"), r = t.dataset.closeOnTab != null || t.hasAttribute("close-on-tab");
937
+ n = e && r;
938
+ }
939
+ this.element.toggleAttribute("data-closeable", n);
940
+ }, this._enabled = (e) => e.getAttribute("aria-disabled") !== "true" && !e.hidden, this._onActivation = (e) => {
941
+ let t = this._tabs().find((t) => t.getAttribute("aria-controls") === e.detail?.panelId);
942
+ t && this._setRoving(t);
943
+ }, this._onKeydown = (e) => {
944
+ let t = this._tabs().filter(this._enabled);
945
+ if (!t.length) return;
946
+ let n = this.element.getAttribute("aria-orientation") === "vertical", r = n ? "ArrowDown" : "ArrowRight", i = n ? "ArrowUp" : "ArrowLeft", a = t.indexOf(document.activeElement), o;
947
+ switch (e.key) {
948
+ case r:
949
+ o = t[(a + 1) % t.length];
950
+ break;
951
+ case i:
952
+ o = t[(a - 1 + t.length) % t.length];
953
+ break;
954
+ case "Home":
955
+ o = t[0];
956
+ break;
957
+ case "End":
958
+ o = t[t.length - 1];
959
+ break;
960
+ case "Enter":
961
+ case " ":
962
+ a >= 0 && (e.preventDefault(), this._activate(t[a], e));
963
+ return;
964
+ default: return;
965
+ }
966
+ o && (e.preventDefault(), this._setRoving(o), o.focus(), this._autoActivate() && this._activate(o, e));
967
+ };
968
+ let r = typeof t == "string" ? document.querySelector(t) : t;
969
+ if (!r) throw Error(`PanelControl: No element found for selector "${t}"`);
970
+ if (this.element = r, r.panelControl) return console.warn("PanelControl: already initialized"), r.panelControl;
971
+ r.panelControl = this;
972
+ let i = c(r.dataset, e.attrs);
973
+ this.config = {
974
+ ...e.defaults,
975
+ ...n,
976
+ ...i
977
+ }, this._isTablist = r.getAttribute("role") === "tablist", this._bindTriggers(), this._isTablist && this._setupKeyboard();
978
+ let a = this.panelSetElement;
979
+ this._log(`Initialized (${a ? "linked to a PanelSet" : "no PanelSet found yet"}${this._isTablist ? ", tablist keyboard nav" : ""})`);
980
+ }
981
+ get panelSetElement() {
982
+ if (!this._setEl) {
983
+ let e = this._resolvePanelSet();
984
+ e && (this._setEl = e, this._onElementResolved(e));
985
+ }
986
+ return this._setEl;
987
+ }
988
+ get panelSet() {
989
+ return this.panelSetElement?.panelSet;
990
+ }
991
+ show(e, t) {
992
+ this.panelSet?.show(e, t);
993
+ }
994
+ setTabState(e, t) {
995
+ let n = t === "disabled";
996
+ this.element.querySelectorAll(`[aria-controls="${e}"]`).forEach((e) => {
997
+ e.setAttribute("aria-disabled", String(n));
998
+ let t = e.getAttribute("data-pc-disabled-hint");
999
+ t && d(e, t, n), this._isTablist && n && (e.tabIndex = -1);
1000
+ }), this._isTablist && n && this._ensureRovingStop();
1001
+ }
1002
+ _log(e) {
1003
+ u("PanelControl", this.element, this.config.debug, e);
1004
+ }
1005
+ _resolvePanelSet() {
1006
+ let e = this.element.getAttribute("data-panelcontrol");
1007
+ if (e) return document.querySelector(e);
1008
+ let t = this.element.querySelector("[aria-controls]")?.getAttribute("aria-controls");
1009
+ return t ? document.getElementById(t)?.closest("[data-panelset], ps-panelset") ?? null : null;
1010
+ }
1011
+ _onElementResolved(e) {
1012
+ let { signal: t } = this._controller;
1013
+ this._isTablist && !this._activationWired && (e.addEventListener("ps:activationcomplete", this._onActivation, { signal: t }), this._activationWired = !0), this._reflectCloseable(), e.panelSet || e.addEventListener("ps:ready", this._reflectCloseable, {
1014
+ once: !0,
1015
+ signal: t
1016
+ });
1017
+ }
1018
+ _bindTriggers() {
1019
+ let { signal: e } = this._controller;
1020
+ this.element.querySelectorAll("[aria-controls]").forEach((t) => {
1021
+ t.addEventListener("click", (e) => {
1022
+ this._activate(t, e);
1023
+ }, { signal: e });
1024
+ });
1025
+ }
1026
+ _activate(e, t) {
1027
+ if (e.getAttribute("aria-disabled") === "true") return;
1028
+ let n = e.getAttribute("aria-controls");
1029
+ if (n) {
1030
+ if (!this.panelSet) {
1031
+ this._log(`Can’t activate '${n}': its PanelSet is not initialised. Add a PanelSet.init().`);
1032
+ return;
1033
+ }
1034
+ this.panelSet.show(n, { event: t }), this._isTablist && this._setRoving(e);
1035
+ }
1036
+ }
1037
+ _tabs() {
1038
+ return Array.from(this.element.querySelectorAll("[role=\"tab\"]"));
1039
+ }
1040
+ _setRoving(e) {
1041
+ this._tabs().forEach((t) => {
1042
+ t.tabIndex = t === e ? 0 : -1;
1043
+ });
1044
+ }
1045
+ _ensureRovingStop() {
1046
+ let e = this._tabs();
1047
+ if (e.some((e) => e.tabIndex === 0 && this._enabled(e))) return;
1048
+ let t = e.find((e) => e.getAttribute("aria-selected") === "true" && this._enabled(e)) ?? e.find(this._enabled);
1049
+ t && this._setRoving(t);
1050
+ }
1051
+ _setupKeyboard() {
1052
+ let e = this._tabs();
1053
+ if (!e.length) return;
1054
+ let t = e.find((e) => e.getAttribute("aria-selected") === "true") ?? e[0];
1055
+ this._setRoving(t), this.element.addEventListener("keydown", this._onKeydown, { signal: this._controller.signal });
1056
+ }
1057
+ _autoActivate() {
1058
+ return this.config.activation === "auto" && !this._autoFocusInPlay() && !this.panelSet?.hasAsyncContent;
1059
+ }
1060
+ _autoFocusInPlay() {
1061
+ let e = this.panelSet;
1062
+ if (e && e.config.autoFocus !== !1) return !0;
1063
+ let t = this.panelSetElement, n = t && (t.dataset.autoFocus ?? t.getAttribute("auto-focus"));
1064
+ return n != null && n !== "false" ? !0 : this._tabs().some((e) => {
1065
+ let t = e.getAttribute("data-auto-focus");
1066
+ return t != null && t !== "false";
1067
+ });
1068
+ }
1069
+ destroy() {
1070
+ this._controller.abort(), delete this.element.panelControl, this._log("Destroyed");
1071
+ }
1072
+ };
1073
+ w = T, w.defaults = {
1074
+ activation: "manual",
1075
+ debug: !1
1076
+ }, w.attrs = {
1077
+ activation: ["activation", "string"],
1078
+ debug: ["debug", "boolean"]
1079
+ };
1080
+ //#endregion
1081
+ //#region src/js/panel.element.ts
1082
+ var E = class extends HTMLElement {
1083
+ connectedCallback() {
1084
+ if (this.panel) return;
1085
+ let e = l(this, C.attrs);
1086
+ new C(this, e);
1087
+ }
1088
+ disconnectedCallback() {}
1089
+ }, D = class extends HTMLElement {
1090
+ connectedCallback() {
1091
+ if (this.panelSet) return;
1092
+ let e = l(this, _.attrs);
1093
+ new _(this, e);
1094
+ }
1095
+ disconnectedCallback() {}
1096
+ }, O = class extends HTMLElement {
1097
+ connectedCallback() {
1098
+ if (this.panelControl) return;
1099
+ let e = l(this, T.attrs);
1100
+ new T(this, e);
1101
+ }
1102
+ disconnectedCallback() {}
1103
+ };
1104
+ function k(e = "ps") {
1105
+ let t = `${e}-panelcontrol`;
1106
+ customElements.get(t) || customElements.define(t, O);
1107
+ }
1108
+ //#endregion
1109
+ //#region src/js/index.ts
1110
+ function A(e = "ps") {
1111
+ let t = (e, t) => {
1112
+ customElements.get(e) || customElements.define(e, t);
1113
+ };
1114
+ t(`${e}-panel`, E), t(`${e}-panelset`, D), t(`${e}-panelcontrol`, O);
1115
+ }
1116
+ //#endregion
1117
+ export { E as a, _ as c, D as i, O as n, T as o, k as r, C as s, A as t };
1118
+
1119
+ //# sourceMappingURL=panelset-core.js.map