panelset 0.5.4 → 1.0.2

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.

Potentially problematic release.


This version of panelset might be problematic. Click here for more details.

package/CHANGELOG.md ADDED
@@ -0,0 +1,45 @@
1
+ # Changelog
2
+
3
+ ## [1.0.2] - 2026-02-16
4
+
5
+ ### Changed
6
+ - Changed API to make it more flexible.
7
+
8
+
9
+ ## [1.0.1] - 2026-02-16
10
+
11
+ ### Changed
12
+ - Changed API to include event.
13
+
14
+
15
+ ## [1.0.0] - 2026-02-13
16
+
17
+ ### Changed
18
+ - Stable version 1. Docs will still follow.
19
+
20
+ ### Added
21
+ - Added autofocus
22
+
23
+
24
+ ## [0.5.4] - 2026-02-11
25
+
26
+ ### Changed
27
+ - Added warning if no panels found
28
+
29
+
30
+ ## [0.5.3] - 2026-02-08
31
+
32
+ ### Added
33
+ - Added height tracking
34
+
35
+
36
+ ## [0.5.2] - 2026-01-06
37
+
38
+ ### Changed
39
+ - Added default export
40
+ - Added warning if selector does not have the data-tabs attribute
41
+ - Wrote more docs (will follow)
42
+
43
+
44
+ ## [0.5.0] - 2026-01-04
45
+ - First commit
package/dist/index.d.ts CHANGED
@@ -53,6 +53,7 @@ declare class PanelSet {
53
53
  private _updateHighestPanel;
54
54
  private _cleanupPanels;
55
55
  private _waitForTransition;
56
+ private _handleAutoFocus;
56
57
  private _animateOpenClose;
57
58
  /**
58
59
  * Get the ID of the currently active panel
@@ -61,19 +62,19 @@ declare class PanelSet {
61
62
  getActive(): string | null;
62
63
  /**
63
64
  * Open a closable panelset
64
- * @param withTransition - Whether to animate
65
+ * @param options - Configuration options
65
66
  */
66
- open(withTransition?: boolean): void;
67
+ open(options?: ShowOptions): void;
67
68
  /**
68
69
  * Close a closable panelset
69
- * @param withTransition - Whether to animate
70
+ * @param options - Configuration options
70
71
  */
71
- close(withTransition?: boolean): void;
72
+ close(options?: ShowOptions): void;
72
73
  /**
73
74
  * Toggle a closable panelset between open and closed
74
- * @param withTransition - Whether to animate
75
+ * @param options - Configuration options
75
76
  */
76
- toggle(withTransition?: boolean): void;
77
+ toggle(options?: ShowOptions): void;
77
78
  /**
78
79
  * Register a handler for async content loading
79
80
  * @param handler - Async content handler function
@@ -83,15 +84,15 @@ declare class PanelSet {
83
84
  /**
84
85
  * Show a panel by ID
85
86
  * @param panelId - ID of the panel to show
86
- * @param withTransition - Whether to animate the transition
87
- * @param options - Additional options (trigger name)
87
+ * @param options - Configuration options for this activation
88
88
  */
89
- show(panelId: string, withTransition?: boolean, options?: ShowOptions): Promise<void>;
89
+ show(panelId: string, options?: ShowOptions): Promise<void>;
90
90
  }
91
91
  export { PanelSet }
92
92
  export default PanelSet;
93
93
 
94
94
  export declare interface PanelSetConfig {
95
+ selector?: string;
95
96
  transitions?: boolean | {
96
97
  panels?: boolean;
97
98
  height?: boolean;
@@ -99,8 +100,8 @@ export declare interface PanelSetConfig {
99
100
  closable?: boolean;
100
101
  emptyPanelHeight?: number;
101
102
  loadingDelay?: number;
103
+ autoFocus?: boolean | 'heading' | 'first';
102
104
  debug?: boolean;
103
- selector?: string;
104
105
  }
105
106
 
106
107
  export declare interface ReadyEventDetail {
@@ -109,7 +110,10 @@ export declare interface ReadyEventDetail {
109
110
  }
110
111
 
111
112
  export declare interface ShowOptions {
113
+ event?: Event;
114
+ transition?: boolean;
112
115
  trigger?: string;
116
+ autoFocus?: boolean | 'heading' | 'first' | ((panel: HTMLElement) => void);
113
117
  }
114
118
 
115
119
  export { }
package/dist/panelset.css CHANGED
@@ -1 +1 @@
1
- [data-panelset]{--fadeout-speed: .5s;--fadein-speed: .5s;--fadein-delay: .5s;--height-duration-ratio: 1;--transition-timing: ease-in-out;--loading-panel-opacity: .1;--close-speed: .5s;--open-speed: .5s;--open-timing: ease-in-out;--close-timing: ease-in-out;--loading-dim-duration: calc(var(--fadeout-speed) * (1 - var(--loading-panel-opacity)));--loading-fadeout-duration: calc(var(--fadeout-speed) * var(--loading-panel-opacity))}[data-panelset]{position:relative;transition:height calc((var(--fadein-speed) + var(--fadein-delay)) * var(--height-duration-ratio)) var(--transition-timing);will-change:height;box-sizing:border-box}[data-panelset] .panel-wrapper{position:relative}[data-panelset].is-closed{height:0!important;min-height:0}[data-panelset].is-closed .panel-wrapper{opacity:0;pointer-events:none}[data-panelset].is-opening{transition:height var(--open-speed) var(--open-timing),box-shadow var(--open-speed) var(--open-timing),border-color var(--open-speed) var(--open-timing)}[data-panelset].is-opening .panel-wrapper{transition:opacity var(--open-speed) var(--open-timing);transition-delay:calc(.5 * var(--open-speed));opacity:1}[data-panelset].is-closing{transition:height var(--close-speed) var(--close-timing),box-shadow var(--close-speed) var(--close-timing),border-color var(--open-speed) var(--open-timing)}[data-panelset].is-closing .panel-wrapper{transition:opacity var(--close-speed) var(--close-timing);opacity:0}[data-panelset] [role=tabpanel]{opacity:0;position:absolute;top:0;left:0;width:100%;box-sizing:border-box}[data-panelset] [role=tabpanel].fade{transition:all var(--fadeout-speed) var(--transition-timing);pointer-events:none}[data-panelset] [role=tabpanel].fade.incoming{transition-duration:var(--fadein-speed);transition-delay:var(--fadein-delay)}[data-panelset] [role=tabpanel].active{opacity:1;position:relative}[data-panelset] [role=tabpanel].no-transition,[data-panelset] [role=tabpanel].incoming.no-transition{transition:none}[data-panelset].is-transitioning,[data-panelset].is-opening,[data-panelset].is-closing{overflow:hidden}@media(prefers-reduced-motion:reduce){[data-panelset]{--fadeout-speed: 0s !important;--fadein-speed: 0s !important;--fadein-delay: 0s !important;--loading-dim-duration: 0s !important;--loading-fadeout-duration: 0s !important;--close-speed: 0s !important;--open-speed: 0s !important;transition:none!important}[data-panelset] [role=tabpanel]{transition:none!important}[data-panelset]:after{transition:none!important;animation-play-state:paused!important}[data-panelset] .panel-wrapper{transition:none!important}}[data-panelset]:after{content:"";position:absolute;top:50%;left:50%;width:40px;height:40px;transform:translate(-50%,-50%);border:4px solid rgba(0,0,0,.1);border-top-color:#0064ffcc;border-radius:50%;opacity:0;pointer-events:none;transition:opacity var(--loading-dim-duration) var(--transition-timing);animation:spin .8s linear infinite;animation-play-state:running;z-index:11}[data-panelset] .panel-wrapper{transition:opacity var(--fadeout-speed) var(--transition-timing) var(--fadein-speed)}[data-panelset].is-loading{pointer-events:none}[data-panelset].is-loading:after{opacity:1}[data-panelset].is-loading .panel-wrapper{transition:opacity var(--fadeout-speed) var(--transition-timing);opacity:var(--loading-panel-opacity)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}
1
+ [data-panelset]{--fadeout-speed: .5s;--fadein-speed: .5s;--fadein-delay: .5s;--height-duration-ratio: 1;--transition-timing: ease-in-out;--loading-panel-opacity: .1;--close-speed: .5s;--open-speed: .5s;--open-timing: ease-in-out;--close-timing: ease-in-out;--loading-dim-duration: calc(var(--fadeout-speed) * (1 - var(--loading-panel-opacity)));--loading-fadeout-duration: calc(var(--fadeout-speed) * var(--loading-panel-opacity))}[data-panelset]{position:relative;transition:height calc((var(--fadein-speed) + var(--fadein-delay)) * var(--height-duration-ratio)) var(--transition-timing);will-change:height;box-sizing:border-box}[data-panelset] .panel-wrapper{position:relative}[data-panelset].is-closed{height:0!important;min-height:0}[data-panelset].is-closed .panel-wrapper{opacity:0;pointer-events:none}[data-panelset].is-opening{transition:height var(--open-speed) var(--open-timing),box-shadow var(--open-speed) var(--open-timing),border-color var(--open-speed) var(--open-timing)}[data-panelset].is-opening .panel-wrapper{transition:opacity var(--open-speed) var(--open-timing);transition-delay:calc(.5 * var(--open-speed));opacity:1}[data-panelset].is-closing{transition:height var(--close-speed) var(--close-timing),box-shadow var(--close-speed) var(--close-timing),border-color var(--open-speed) var(--open-timing)}[data-panelset].is-closing .panel-wrapper{transition:opacity var(--close-speed) var(--close-timing);opacity:0}[data-panelset] [role=tabpanel]{opacity:0;position:absolute;top:0;left:0;width:100%;box-sizing:border-box}[data-panelset] [role=tabpanel].fade{transition:all var(--fadeout-speed) var(--transition-timing);pointer-events:none}[data-panelset] [role=tabpanel].fade.incoming{transition-duration:var(--fadein-speed);transition-delay:var(--fadein-delay)}[data-panelset] [role=tabpanel].active{opacity:1;position:relative}[data-panelset] [role=tabpanel].no-transition,[data-panelset] [role=tabpanel].incoming.no-transition{transition:none}[data-panelset] [role=tabpanel]:focus{outline:none;background:orange}[data-panelset].is-transitioning,[data-panelset].is-opening,[data-panelset].is-closing{overflow:hidden}@media(prefers-reduced-motion:reduce){[data-panelset]{--fadeout-speed: 0s !important;--fadein-speed: 0s !important;--fadein-delay: 0s !important;--loading-dim-duration: 0s !important;--loading-fadeout-duration: 0s !important;--close-speed: 0s !important;--open-speed: 0s !important;transition:none!important}[data-panelset] [role=tabpanel]{transition:none!important}[data-panelset]:after{transition:none!important;animation-play-state:paused!important}[data-panelset] .panel-wrapper{transition:none!important}}[data-panelset]:after{content:"";position:absolute;top:50%;left:50%;width:40px;height:40px;transform:translate(-50%,-50%);border:4px solid rgba(0,0,0,.1);border-top-color:#0064ffcc;border-radius:50%;opacity:0;pointer-events:none;transition:opacity var(--loading-dim-duration) var(--transition-timing);animation:spin .8s linear infinite;animation-play-state:running;z-index:11}[data-panelset] .panel-wrapper{transition:opacity var(--fadeout-speed) var(--transition-timing) var(--fadein-speed)}[data-panelset].is-loading{pointer-events:none}[data-panelset].is-loading:after{opacity:1}[data-panelset].is-loading .panel-wrapper{transition:opacity var(--fadeout-speed) var(--transition-timing);opacity:var(--loading-panel-opacity)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}
package/dist/panelset.js CHANGED
@@ -1,70 +1,71 @@
1
- const h = class h {
2
- constructor(e, s = {}) {
1
+ const d = class d {
2
+ constructor(t, i = {}) {
3
3
  this._openCloseGeneration = 0, this._isLoadingAsync = !1;
4
- let t;
5
- if (typeof e == "string") {
6
- if (t = document.querySelector(e), !t)
7
- throw new Error(`PanelSet: No element found for selector "${e}"`);
4
+ let e;
5
+ if (typeof t == "string") {
6
+ if (e = document.querySelector(t), !e)
7
+ throw new Error(`PanelSet: No element found for selector "${t}"`);
8
8
  } else
9
- t = e;
10
- if (this.element = t, h._validateElement(t), t.panelSet || t.dataset.panelset === "true")
11
- return console.warn("PanelSet: Element already initialized, returning existing instance"), t.panelSet;
12
- t.panelSet = this;
13
- const i = h._getDataConfig(t);
14
- if (this.config = h._mergeConfig(
15
- h.defaults,
16
- i,
17
- s
18
- ), this.panels = Array.from(t.querySelectorAll('[role="tabpanel"]')), this.panels.length === 0) {
19
- const a = `<${t.tagName.toLowerCase()}${t.id ? ` id="${t.id}"` : ""}${t.className ? ` class="${t.className}"` : ""}>`;
9
+ e = t;
10
+ if (this.element = e, d._validateElement(e), e.panelSet || e.dataset.panelset === "true")
11
+ return console.warn("PanelSet: Element already initialized, returning existing instance"), e.panelSet;
12
+ e.panelSet = this;
13
+ const n = d._getDataConfig(e);
14
+ if (this.config = d._mergeConfig(
15
+ d.defaults,
16
+ n,
17
+ i
18
+ ), this.panels = Array.from(e.querySelectorAll('[role="tabpanel"]')), this.panels.length === 0) {
19
+ const a = `<${e.tagName.toLowerCase()}${e.id ? ` id="${e.id}"` : ""}${e.className ? ` class="${e.className}"` : ""}>`;
20
20
  console.error(`PanelSet: No panels with [role="tabpanel"] found inside ${a}. Make sure panel elements are children of the [data-panelset] element.`), this.panels = [], this.activePanel = null, this.panelWrapper = null, this.pendingPanel = null;
21
21
  return;
22
22
  }
23
23
  this.activePanel = this.panels.find((a) => a.classList.contains("active")) || this.panels[0], this.panelWrapper = this.element.querySelector(".panel-wrapper") || this._autoWrapPanels(), this.pendingPanel = this.activePanel, this.element.dataset.panelset = "true", this._log(`Initialized (${this.panels.length} panels)`), this._dispatch("ps:ready", { container: this.element, instance: this }), this._internalInit();
24
- let n;
24
+ let o;
25
25
  window.addEventListener("resize", () => {
26
- clearTimeout(n), n = setTimeout(() => {
26
+ clearTimeout(o), o = setTimeout(() => {
27
27
  this._updateHighestPanel();
28
28
  }, 250);
29
29
  });
30
30
  }
31
31
  // Parse data attributes from element
32
- static _getDataConfig(e) {
33
- const s = e.dataset, t = {}, i = {
32
+ static _getDataConfig(t) {
33
+ const i = t.dataset, e = {}, n = {
34
34
  transitions: "json",
35
35
  closable: "boolean",
36
36
  emptyPanelHeight: "number",
37
37
  loadingDelay: "number",
38
+ // We do not support autofocus here. I do not think it is needed per whole PanelSet.
38
39
  debug: "boolean"
39
40
  };
40
- for (const [n, a] of Object.entries(i)) {
41
- if (!(n in s)) continue;
42
- const o = s[n];
43
- if (o !== void 0)
41
+ for (const [o, a] of Object.entries(n)) {
42
+ if (!(o in i)) continue;
43
+ const s = i[o];
44
+ if (s !== void 0)
44
45
  switch (a) {
45
46
  case "boolean":
46
- t[n] = o !== "false";
47
+ e[o] = s !== "false";
47
48
  break;
48
49
  case "number":
49
- t[n] = parseInt(o, 10);
50
+ e[o] = parseInt(s, 10);
50
51
  break;
51
52
  case "json":
52
53
  try {
53
- t[n] = JSON.parse(o);
54
+ e[o] = JSON.parse(s);
54
55
  } catch {
55
- t[n] = o !== "false";
56
+ e[o] = s !== "false";
56
57
  }
57
58
  break;
58
59
  }
59
60
  }
60
- return t;
61
+ return e;
61
62
  }
62
63
  // Merge configurations
63
- static _mergeConfig(e, s, t) {
64
+ static _mergeConfig(t, i, e) {
64
65
  return {
65
- ...e,
66
- ...s,
67
- ...t
66
+ ...t,
67
+ ...i,
68
+ ...e
68
69
  };
69
70
  }
70
71
  /**
@@ -73,120 +74,135 @@ const h = class h {
73
74
  * @param options - Additional config options (when first param is selector)
74
75
  * @returns Array of PanelSet instances
75
76
  */
76
- static init(e = {}, s = {}) {
77
- let t, i;
78
- typeof e == "string" ? (t = e, i = s) : (i = e, t = i.selector || "[data-panelset]");
79
- const n = document.querySelectorAll(t), a = [];
80
- return n.forEach((o) => {
77
+ static init(t = {}, i = {}) {
78
+ let e, n;
79
+ typeof t == "string" ? (e = t, n = i) : (n = t, e = n.selector || "[data-panelset]");
80
+ const o = document.querySelectorAll(e), a = [];
81
+ return o.forEach((s) => {
81
82
  try {
82
- h._validateElement(o);
83
- } catch (c) {
84
- console.error(c.message);
83
+ d._validateElement(s);
84
+ } catch (r) {
85
+ console.error(r.message);
85
86
  return;
86
87
  }
87
- if (o.panelSet || o.dataset.panelset === "true") {
88
- o.panelSet && a.push(o.panelSet);
88
+ if (s.panelSet || s.dataset.panelset === "true") {
89
+ s.panelSet && a.push(s.panelSet);
89
90
  return;
90
91
  }
91
- const l = new h(o, i);
92
+ const l = new d(s, n);
92
93
  a.push(l);
93
94
  }), a;
94
95
  }
95
96
  // Debug logging helper
96
- _log(e) {
97
+ _log(t) {
97
98
  if (!this.config.debug) return;
98
- const s = this.element.id || "no id";
99
- console.log(`[PanelSet] - "${s}" -`, e);
99
+ const i = this.element.id || "no id";
100
+ console.log(`[PanelSet] - "${i}" -`, t);
100
101
  }
101
- static _validateElement(e) {
102
- if (!e.hasAttribute("data-panelset")) {
103
- const s = `<${e.tagName.toLowerCase()}${e.id ? ` id="${e.id}"` : ""}${e.className ? ` class="${e.className}"` : ""}>`;
104
- throw new Error(`PanelSet: Element is missing required data-panelset attribute. Element: ${s}`);
102
+ static _validateElement(t) {
103
+ if (!t.hasAttribute("data-panelset")) {
104
+ const i = `<${t.tagName.toLowerCase()}${t.id ? ` id="${t.id}"` : ""}${t.className ? ` class="${t.className}"` : ""}>`;
105
+ throw new Error(`PanelSet: Element is missing required data-panelset attribute. Element: ${i}`);
105
106
  }
106
107
  }
107
108
  _autoWrapPanels() {
108
- const e = document.createElement("div");
109
- return e.className = "panel-wrapper", this.panels.forEach((s) => e.appendChild(s)), this.element.appendChild(e), e;
109
+ const t = document.createElement("div");
110
+ return t.className = "panel-wrapper", this.panels.forEach((i) => t.appendChild(i)), this.element.appendChild(t), t;
110
111
  }
111
112
  _internalInit() {
112
- this.panels.forEach((e) => {
113
- e.classList.remove("fade", "incoming"), e !== this.activePanel ? (e.hidden = !0, e.classList.remove("active")) : (e.hidden = !1, e.classList.add("active"));
113
+ this.panels.forEach((t) => {
114
+ t.classList.remove("fade", "incoming"), t !== this.activePanel ? (t.hidden = !0, t.classList.remove("active")) : (t.hidden = !1, t.classList.add("active"));
114
115
  }), this.element.style.height = "", this._updateHighestPanel();
115
116
  }
116
117
  // Dispatch custom event helper
117
- _dispatch(e, s) {
118
+ _dispatch(t, i) {
118
119
  this.element.dispatchEvent(
119
- new CustomEvent(e, {
120
- detail: s,
120
+ new CustomEvent(t, {
121
+ detail: i,
121
122
  bubbles: !0,
122
123
  cancelable: !1
123
124
  })
124
125
  );
125
126
  }
126
127
  /* --- Modular helpers --- */
127
- _getVerticalMetrics(e) {
128
- if (!e) return 0;
129
- const s = getComputedStyle(e);
130
- return ["paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth"].reduce((t, i) => t + (parseFloat(s[i]) || 0), 0);
128
+ _getVerticalMetrics(t) {
129
+ if (!t) return 0;
130
+ const i = getComputedStyle(t);
131
+ return ["paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth"].reduce((e, n) => e + (parseFloat(i[n]) || 0), 0);
131
132
  }
132
- _measureHeight(e) {
133
- let s = e.offsetHeight;
134
- return s += this._getVerticalMetrics(this.panelWrapper), s += this._getVerticalMetrics(this.element), s;
133
+ _measureHeight(t) {
134
+ let i = t.offsetHeight;
135
+ return i += this._getVerticalMetrics(this.panelWrapper), i += this._getVerticalMetrics(this.element), i;
135
136
  }
136
137
  _updateHighestPanel() {
137
138
  if (this.element.hasAttribute("data-ps-track-height")) {
138
139
  console.warn("PanelSet: data-ps-track-height should be placed on a parent element, not on [data-panelset] itself. Height tracking skipped.");
139
140
  return;
140
141
  }
141
- const e = this.element.closest("[data-ps-track-height]");
142
- if (!e) return;
143
- let s = 0;
144
- this.panels.forEach((t) => {
145
- const i = t.hidden, n = t.classList.contains("active");
146
- this.panels.forEach((o) => {
147
- o.hidden = !0, o.classList.remove("active");
148
- }), t.hidden = !1, t.classList.add("active"), t.style.visibility = "hidden", this.element.offsetHeight;
142
+ const t = this.element.closest("[data-ps-track-height]");
143
+ if (!t) return;
144
+ let i = 0;
145
+ this.panels.forEach((e) => {
146
+ const n = e.hidden, o = e.classList.contains("active");
147
+ this.panels.forEach((s) => {
148
+ s.hidden = !0, s.classList.remove("active");
149
+ }), e.hidden = !1, e.classList.add("active"), e.style.visibility = "hidden", this.element.offsetHeight;
149
150
  const a = this.element.offsetHeight;
150
- a > s && (s = a), t.hidden = i, n || t.classList.remove("active"), t.style.visibility = "";
151
- }), this.activePanel && (this.activePanel.hidden = !1, this.activePanel.classList.add("active")), this.panels.forEach((t) => {
152
- t !== this.activePanel && (t.hidden = !0, t.classList.remove("active"));
153
- }), e.style.setProperty("--ps-max-height", `${s}px`), this._log(`Max container height: ${s}px (set on tracking parent)`);
151
+ a > i && (i = a), e.hidden = n, o || e.classList.remove("active"), e.style.visibility = "";
152
+ }), this.activePanel && (this.activePanel.hidden = !1, this.activePanel.classList.add("active")), this.panels.forEach((e) => {
153
+ e !== this.activePanel && (e.hidden = !0, e.classList.remove("active"));
154
+ }), t.style.setProperty("--ps-max-height", `${i}px`), this._log(`Max container height: ${i}px (set on tracking parent)`);
154
155
  }
155
- _cleanupPanels(e) {
156
- this.panels.forEach((s) => {
157
- s.classList.remove("fade", "incoming"), s !== e ? (s.classList.remove("active"), s.hidden = !0) : (s.classList.add("active"), s.hidden = !1);
158
- }), this.element.style.height = "", this.element.classList.remove("is-transitioning"), this.activePanel = e;
156
+ _cleanupPanels(t) {
157
+ this.panels.forEach((i) => {
158
+ i.classList.remove("fade", "incoming"), i !== t ? (i.classList.remove("active"), i.hidden = !0) : (i.classList.add("active"), i.hidden = !1);
159
+ }), this.element.style.height = "", this.element.classList.remove("is-transitioning"), this.activePanel = t;
159
160
  }
160
- _waitForTransition(e) {
161
- return new Promise((s) => {
162
- const t = getComputedStyle(e), i = parseFloat(t.transitionDuration) || 0, n = parseFloat(t.transitionDelay) || 0;
163
- if (i + n === 0) {
164
- s();
161
+ _waitForTransition(t) {
162
+ return new Promise((i) => {
163
+ const e = getComputedStyle(t), n = parseFloat(e.transitionDuration) || 0, o = parseFloat(e.transitionDelay) || 0;
164
+ if (n + o === 0) {
165
+ i();
165
166
  return;
166
167
  }
167
- const a = (o) => {
168
- o.target === e && (e.removeEventListener("transitionend", a), s());
168
+ const a = (s) => {
169
+ s.target === t && (t.removeEventListener("transitionend", a), i());
169
170
  };
170
- e.addEventListener("transitionend", a);
171
+ t.addEventListener("transitionend", a);
171
172
  });
172
173
  }
174
+ _handleAutoFocus(t, i, e) {
175
+ if (this._log(`AutoFocus called with event: ${e ? e.type : "none"}`), i && e && !(e.type.startsWith("key") || e instanceof MouseEvent && e.detail === 0)) {
176
+ this._log("Skipping autofocus (touch/mouse interaction)");
177
+ return;
178
+ }
179
+ if (i === !0)
180
+ t.hasAttribute("tabindex") || t.setAttribute("tabindex", "-1"), t.focus(), this._log(`Auto-focused panel: ${t.id}`);
181
+ else if (i === "heading") {
182
+ const n = t.querySelector("h1, h2, h3, h4, h5, h6");
183
+ n && (n.hasAttribute("tabindex") || n.setAttribute("tabindex", "-1"), n.focus(), this._log(`Auto-focused heading in: ${t.id}`));
184
+ } else if (i === "first") {
185
+ const n = t.querySelector('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
186
+ n && (n.focus(), this._log(`Auto-focused first element in: ${t.id}`));
187
+ } else typeof i == "function" && (i(t), this._log(`Auto-focused (custom) in: ${t.id}`));
188
+ }
173
189
  // Shared helper for open/close
174
- _animateOpenClose(e, s) {
175
- const t = e ? "opening" : "closing", n = `is-${e ? "closing" : "opening"}`, a = `is-${t}`;
176
- this._log(e ? "Opening" : "Closing"), this._openCloseGeneration++;
177
- const o = this._openCloseGeneration;
178
- this.element.classList.contains(n) && this.element.classList.remove(n);
179
- const l = e ? this._measureHeight(this.pendingPanel) : 0;
180
- if (s && this.config.transitions) {
190
+ _animateOpenClose(t, i) {
191
+ const e = t ? "opening" : "closing", o = `is-${t ? "closing" : "opening"}`, a = `is-${e}`;
192
+ this._log(t ? "Opening" : "Closing"), this._openCloseGeneration++;
193
+ const s = this._openCloseGeneration;
194
+ this.element.classList.contains(o) && this.element.classList.remove(o);
195
+ const l = t ? this._measureHeight(this.pendingPanel) : 0;
196
+ if (i && this.config.transitions) {
181
197
  this.element.classList.add(a);
182
- const c = this.element.offsetHeight;
183
- this.element.style.height = `${c}px`, e && this.element.classList.remove("is-closed"), requestAnimationFrame(() => {
198
+ const r = this.element.offsetHeight;
199
+ this.element.style.height = `${r}px`, t && this.element.classList.remove("is-closed"), requestAnimationFrame(() => {
184
200
  this.element.style.height = `${l}px`, this._waitForTransition(this.element).then(() => {
185
- this._openCloseGeneration === o && (this.element.style.height = "", this.element.classList.remove(a), e || this.element.classList.add("is-closed"));
201
+ this._openCloseGeneration === s && (this.element.style.height = "", this.element.classList.remove(a), t || this.element.classList.add("is-closed"));
186
202
  });
187
203
  });
188
204
  } else
189
- e ? this.element.classList.remove("is-closed") : this.element.classList.add("is-closed"), this.element.style.height = "";
205
+ t ? this.element.classList.remove("is-closed") : this.element.classList.add("is-closed"), this.element.style.height = "";
190
206
  }
191
207
  /**
192
208
  * Get the ID of the currently active panel
@@ -197,54 +213,71 @@ const h = class h {
197
213
  }
198
214
  /**
199
215
  * Open a closable panelset
200
- * @param withTransition - Whether to animate
216
+ * @param options - Configuration options
201
217
  */
202
- open(e = !0) {
218
+ open(t) {
219
+ const {
220
+ event: i,
221
+ transition: e = !0,
222
+ autoFocus: n
223
+ } = t || {};
203
224
  if (!this.config.closable) {
204
225
  this._log("Cannot open: closable is false");
205
226
  return;
206
227
  }
207
- const s = this.element.classList.contains("is-closed"), t = this.element.classList.contains("is-closing");
208
- !s && !t || this._animateOpenClose(!0, e);
228
+ const o = this.element.classList.contains("is-closed"), a = this.element.classList.contains("is-closing");
229
+ if (!o && !a) return;
230
+ this._animateOpenClose(!0, e);
231
+ const s = n ?? this.config.autoFocus;
232
+ s !== !1 && s !== void 0 && this.pendingPanel && (e && this.config.transitions ? this._waitForTransition(this.element).then(() => {
233
+ this._handleAutoFocus(this.pendingPanel, s, i);
234
+ }) : this._handleAutoFocus(this.pendingPanel, s, i));
209
235
  }
210
236
  /**
211
237
  * Close a closable panelset
212
- * @param withTransition - Whether to animate
238
+ * @param options - Configuration options
213
239
  */
214
- close(e = !0) {
240
+ close(t) {
241
+ const {
242
+ transition: i = !0
243
+ } = t || {};
215
244
  if (!this.config.closable) {
216
245
  this._log("Cannot close: closable is false");
217
246
  return;
218
247
  }
219
- const s = this.element.classList.contains("is-closed"), t = this.element.classList.contains("is-opening");
220
- s && !t || this._animateOpenClose(!1, e);
248
+ const e = this.element.classList.contains("is-closed"), n = this.element.classList.contains("is-opening");
249
+ e && !n || this._animateOpenClose(!1, i);
221
250
  }
222
251
  /**
223
252
  * Toggle a closable panelset between open and closed
224
- * @param withTransition - Whether to animate
253
+ * @param options - Configuration options
225
254
  */
226
- toggle(e = !0) {
227
- const s = this.element.classList.contains("is-closed"), t = this.element.classList.contains("is-closing");
228
- s || t ? this.open(e) : this.close(e);
255
+ toggle(t) {
256
+ const {
257
+ event: i,
258
+ transition: e = !0,
259
+ autoFocus: n
260
+ } = t || {}, o = this.element.classList.contains("is-closed"), a = this.element.classList.contains("is-closing");
261
+ o || a ? this.open({ event: i, transition: e, autoFocus: n }) : this.close({ transition: e });
229
262
  }
230
263
  /**
231
264
  * Register a handler for async content loading
232
265
  * @param handler - Async content handler function
233
266
  * @param options - Handler options (once: whether to load only once)
234
267
  */
235
- onBeforeActivate(e, s = {}) {
236
- const t = s.once === !0;
237
- this.element.addEventListener("ps:beforeactivate", (i) => {
238
- const n = i, { targetPanel: a, signal: o } = n.detail;
239
- if (t && a.dataset.loaded === "true") {
268
+ onBeforeActivate(t, i = {}) {
269
+ const e = i.once === !0;
270
+ this.element.addEventListener("ps:beforeactivate", (n) => {
271
+ const o = n, { targetPanel: a, signal: s } = o.detail;
272
+ if (e && a.dataset.loaded === "true") {
240
273
  this.config.debug && this._log(`Skipping ${a.id} (already loaded)`);
241
274
  return;
242
275
  }
243
- const l = e(a, o);
244
- l && typeof l.then == "function" && (n.detail.promise = l.then(() => {
245
- t && (a.dataset.loaded = "true");
246
- }).catch((c) => {
247
- throw c.name === "AbortError" ? (this.config.debug && this._log(`Load aborted: ${a.id}`), c) : (this._log(`Load failed: ${c.message}`), c);
276
+ const l = t(a, s);
277
+ l && typeof l.then == "function" && (o.detail.promise = l.then(() => {
278
+ e && (a.dataset.loaded = "true");
279
+ }).catch((r) => {
280
+ throw r.name === "AbortError" ? (this.config.debug && this._log(`Load aborted: ${a.id}`), r) : (this._log(`Load failed: ${r.message}`), r);
248
281
  }));
249
282
  });
250
283
  }
@@ -252,109 +285,116 @@ const h = class h {
252
285
  /**
253
286
  * Show a panel by ID
254
287
  * @param panelId - ID of the panel to show
255
- * @param withTransition - Whether to animate the transition
256
- * @param options - Additional options (trigger name)
288
+ * @param options - Configuration options for this activation
257
289
  */
258
- async show(e, s = !0, t = {}) {
259
- const i = this.panels.find((r) => r.id === e);
260
- if (!i) {
261
- this._log(`Panel not found: ${e}`);
290
+ async show(t, i) {
291
+ const {
292
+ event: e,
293
+ transition: n = !0,
294
+ trigger: o,
295
+ autoFocus: a
296
+ } = i || {}, s = this.panels.find((c) => c.id === t);
297
+ if (!s) {
298
+ this._log(`Panel not found: ${t}`);
262
299
  return;
263
300
  }
264
- if (i === this.pendingPanel) return;
265
- const n = this.pendingPanel, a = n?.id;
266
- this.pendingPanel = i, this.element.classList.remove("is-loading"), n && n !== this.activePanel && n !== i && (n.classList.remove("incoming"), n.hidden || n.classList.remove("active"));
267
- const o = this._isLoadingAsync;
268
- this._currentAbortController && (this._currentAbortController.abort(), o && a && a !== e && this._dispatch("ps:activationaborted", {
269
- panelId: a,
301
+ if (s === this.pendingPanel) return;
302
+ const l = this.pendingPanel, r = l?.id;
303
+ this.pendingPanel = s, this.element.classList.remove("is-loading"), l && l !== this.activePanel && l !== s && (l.classList.remove("incoming"), l.hidden || l.classList.remove("active"));
304
+ const $ = this._isLoadingAsync;
305
+ this._currentAbortController && (this._currentAbortController.abort(), $ && r && r !== t && this._dispatch("ps:activationaborted", {
306
+ panelId: r,
270
307
  trigger: null
271
308
  }));
272
- const l = new AbortController();
273
- this._currentAbortController = l, this._isLoadingAsync = !1, this._log(`${n?.id || "none"} → ${e}`);
274
- const c = {
275
- panelId: e,
276
- targetPanel: i,
277
- outgoingPanel: n,
278
- signal: l.signal,
309
+ const p = new AbortController();
310
+ this._currentAbortController = p, this._isLoadingAsync = !1, this._log(`${l?.id || "none"} → ${t}`);
311
+ const y = {
312
+ panelId: t,
313
+ targetPanel: s,
314
+ outgoingPanel: l,
315
+ signal: p.signal,
279
316
  promise: null
280
- }, y = new CustomEvent("ps:beforeactivate", {
281
- detail: c,
317
+ }, C = new CustomEvent("ps:beforeactivate", {
318
+ detail: y,
282
319
  bubbles: !0,
283
320
  cancelable: !1
284
321
  });
285
- this.element.dispatchEvent(y);
286
- const _ = c.promise;
287
- if (_) {
322
+ this.element.dispatchEvent(C);
323
+ const P = y.promise;
324
+ if (P) {
288
325
  this._isLoadingAsync = !0, this._log("Waiting for content...");
289
- let r, g = !1;
290
- if (this.config.loadingDelay > 0 ? r = setTimeout(() => {
291
- this.element.classList.add("is-loading"), g = !0;
292
- }, this.config.loadingDelay) : (this.element.classList.add("is-loading"), g = !0), !(this.activePanel && this.activePanel !== i)) {
293
- const m = s !== !1 && this.config.transitions !== !1;
294
- let u = m;
295
- if (typeof this.config.transitions == "object" && (u = m && this.config.transitions.height !== !1), u) {
296
- const C = this.element.offsetHeight;
297
- this.element.style.height = `${C}px`, requestAnimationFrame(() => {
326
+ let c, f = !1;
327
+ if (this.config.loadingDelay > 0 ? c = setTimeout(() => {
328
+ this.element.classList.add("is-loading"), f = !0;
329
+ }, this.config.loadingDelay) : (this.element.classList.add("is-loading"), f = !0), !(this.activePanel && this.activePanel !== s)) {
330
+ const h = n !== !1 && this.config.transitions !== !1;
331
+ let m = h;
332
+ if (typeof this.config.transitions == "object" && (m = h && this.config.transitions.height !== !1), m) {
333
+ const w = this.element.offsetHeight;
334
+ this.element.style.height = `${w}px`, requestAnimationFrame(() => {
298
335
  this.element.style.height = `${this.config.emptyPanelHeight}px`;
299
336
  });
300
337
  }
301
338
  }
302
339
  try {
303
- if (await _, r && clearTimeout(r), l.signal.aborted) {
304
- this._log(`Aborted during load: ${e}`), g && this.element.classList.remove("is-loading");
340
+ if (await P, c && clearTimeout(c), p.signal.aborted) {
341
+ this._log(`Aborted during load: ${t}`), f && this.element.classList.remove("is-loading");
305
342
  return;
306
343
  }
307
- this._log("Content loaded"), i.dataset.loaded === "true" && this._updateHighestPanel();
308
- } catch (m) {
309
- r && clearTimeout(r);
310
- const u = m;
311
- this._log(`Load failed: ${u.message}`), g && this.element.classList.remove("is-loading"), u.name !== "AbortError" && console.error("Panel load error:", m);
344
+ this._log("Content loaded"), s.dataset.loaded === "true" && this._updateHighestPanel();
345
+ } catch (h) {
346
+ c && clearTimeout(c);
347
+ const m = h;
348
+ this._log(`Load failed: ${m.message}`), f && this.element.classList.remove("is-loading"), m.name !== "AbortError" && console.error("Panel load error:", h);
312
349
  return;
313
350
  }
314
- g && this.element.classList.remove("is-loading");
351
+ f && this.element.classList.remove("is-loading");
315
352
  }
316
- if (l.signal.aborted) {
317
- this._log(`Aborted: ${e}`);
353
+ if (p.signal.aborted) {
354
+ this._log(`Aborted: ${t}`);
318
355
  return;
319
356
  }
320
357
  this._dispatch("ps:activationstart", {
321
- panelId: e,
322
- trigger: t.trigger || null
358
+ panelId: t,
359
+ trigger: o || null
323
360
  });
324
- const p = s !== !1 && this.config.transitions !== !1;
325
- let v = p, b = p;
326
- typeof this.config.transitions == "object" && (v = p && this.config.transitions.panels !== !1, b = p && this.config.transitions.height !== !1), this.panels.forEach((r) => r.classList.toggle("fade", v));
361
+ const v = n !== !1 && this.config.transitions !== !1;
362
+ let b = v, _ = v;
363
+ typeof this.config.transitions == "object" && (b = v && this.config.transitions.panels !== !1, _ = v && this.config.transitions.height !== !1), this.panels.forEach((c) => c.classList.toggle("fade", b));
327
364
  const L = this.element.offsetHeight;
328
- b && (this.element.style.height = `${L}px`);
329
- const d = this.activePanel;
330
- i.hidden = !1, i.classList.add("incoming"), v && this.element.classList.add("is-transitioning"), d && d !== i && (d.classList.remove("active", "incoming"), d.hidden = !1), requestAnimationFrame(() => {
331
- i.classList.add("active"), d && d !== i && d.classList.remove("incoming");
332
- const r = this._measureHeight(i), g = L !== r;
333
- b && (this.element.style.height = `${r}px`);
334
- const f = [];
335
- v && f.push(this._waitForTransition(i)), b && g && f.push(this._waitForTransition(this.element)), f.length || f.push(Promise.resolve()), Promise.all(f).then(() => {
336
- if (this.pendingPanel !== i) {
337
- this._log(`Interrupted: ${e}`);
365
+ _ && (this.element.style.height = `${L}px`);
366
+ const g = this.activePanel;
367
+ s.hidden = !1, s.classList.add("incoming"), b && this.element.classList.add("is-transitioning"), g && g !== s && (g.classList.remove("active", "incoming"), g.hidden = !1), requestAnimationFrame(() => {
368
+ s.classList.add("active"), g && g !== s && g.classList.remove("incoming");
369
+ const c = this._measureHeight(s), f = L !== c;
370
+ _ && (this.element.style.height = `${c}px`);
371
+ const u = [];
372
+ b && u.push(this._waitForTransition(s)), _ && f && u.push(this._waitForTransition(this.element)), u.length || u.push(Promise.resolve()), Promise.all(u).then(() => {
373
+ if (this.pendingPanel !== s) {
374
+ this._log(`Interrupted: ${t}`);
338
375
  return;
339
376
  }
340
- this._cleanupPanels(i), this._log(`✓ ${e}`), this._dispatch("ps:activationcomplete", {
341
- panelId: e,
342
- trigger: t.trigger || null
377
+ this._cleanupPanels(s), this._log(`✓ ${t}`);
378
+ const h = a ?? this.config.autoFocus;
379
+ h !== !1 && h !== void 0 && this._handleAutoFocus(s, h, e), this._dispatch("ps:activationcomplete", {
380
+ panelId: t,
381
+ trigger: o || null
343
382
  });
344
383
  });
345
384
  });
346
385
  }
347
386
  };
348
- h.defaults = {
387
+ d.defaults = {
349
388
  transitions: !0,
350
389
  closable: !1,
351
390
  emptyPanelHeight: 200,
352
391
  loadingDelay: 300,
392
+ autoFocus: !0,
353
393
  debug: !1
354
394
  };
355
- let P = h;
395
+ let A = d;
356
396
  export {
357
- P as PanelSet,
358
- P as default
397
+ A as PanelSet,
398
+ A as default
359
399
  };
360
400
  //# sourceMappingURL=panelset.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"panelset.js","sources":["../src/lib/index.ts"],"sourcesContent":["import './styles/panelset.scss';\n\n// Configuration types\nexport interface PanelSetConfig {\n\ttransitions?: boolean | {\n\t\tpanels?: boolean;\n\t\theight?: boolean;\n\t};\n\tclosable?: boolean;\n\temptyPanelHeight?: number;\n\tloadingDelay?: number;\n\tdebug?: boolean;\n\tselector?: string;\n}\n\n// Event detail types\nexport interface ReadyEventDetail {\n\tcontainer: HTMLElement;\n\tinstance: PanelSet;\n}\n\nexport interface BeforeActivateEventDetail {\n\tpanelId: string;\n\ttargetPanel: HTMLElement;\n\toutgoingPanel: HTMLElement | null;\n\tsignal: AbortSignal;\n\tpromise: Promise<void> | null;\n}\n\nexport interface ActivationEventDetail {\n\tpanelId: string;\n\ttrigger: string | null;\n}\n\nexport interface ActivationAbortedEventDetail {\n\tpanelId: string;\n\ttrigger: string | null;\n}\n\n// Handler options\nexport interface HandlerOptions {\n\tonce?: boolean;\n}\n\n// Show options\nexport interface ShowOptions {\n\ttrigger?: string;\n}\n\n// Async content handler type\nexport type AsyncContentHandler = (\n\ttargetPanel: HTMLElement,\n\tsignal: AbortSignal\n) => Promise<void> | void;\n\n// Extend HTMLElement to include panelSet property\ndeclare global {\n\tinterface HTMLElement {\n\t\tpanelSet?: PanelSet;\n\t}\n}\n\nexport class PanelSet {\n\t// Default configuration\n\tstatic defaults: Required<Omit<PanelSetConfig, 'selector'>> = {\n\t\ttransitions: true,\n\t\tclosable: false,\n\t\temptyPanelHeight: 200,\n\t\tloadingDelay: 300,\n\t\tdebug: false\n\t};\n\n\t// Instance properties\n\telement!: HTMLElement;\n\tconfig!: Required<Omit<PanelSetConfig, 'selector'>>;\n\tpanels!: HTMLElement[];\n\tactivePanel!: HTMLElement;\n\tpanelWrapper!: HTMLElement;\n\tpendingPanel!: HTMLElement;\n\n\tprivate _openCloseGeneration: number = 0;\n\tprivate _isLoadingAsync: boolean = false;\n\tprivate _currentAbortController?: AbortController;\n\n\t// Parse data attributes from element\n\tstatic _getDataConfig(element: HTMLElement): Partial<PanelSetConfig> {\n\t\tconst data = element.dataset;\n\t\tconst config: Partial<PanelSetConfig> = {};\n\n\t\t// Define attribute types\n\t\tconst attrs: Record<string, 'json' | 'boolean' | 'number'> = {\n\t\t\ttransitions: 'json',\n\t\t\tclosable: 'boolean',\n\t\t\temptyPanelHeight: 'number',\n\t\t\tloadingDelay: 'number',\n\t\t\tdebug: 'boolean'\n\t\t};\n\n\t\t// Parse each attribute\n\t\tfor (const [key, type] of Object.entries(attrs)) {\n\t\t\tif (!(key in data)) continue;\n\n\t\t\tconst value = data[key];\n\t\t\tif (value === undefined) continue;\n\n\t\t\tswitch (type) {\n\t\t\t\tcase 'boolean':\n\t\t\t\t\t(config as any)[key] = value !== 'false';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'number':\n\t\t\t\t\t(config as any)[key] = parseInt(value, 10);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'json':\n\t\t\t\t\ttry {\n\t\t\t\t\t\t(config as any)[key] = JSON.parse(value);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to boolean parsing\n\t\t\t\t\t\t(config as any)[key] = value !== 'false';\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn config;\n\t}\n\n\t// Merge configurations\n\tstatic _mergeConfig(\n\t\tdefaults: Required<Omit<PanelSetConfig, 'selector'>>,\n\t\tdataConfig: Partial<PanelSetConfig>,\n\t\toptions: Partial<PanelSetConfig>\n\t): Required<Omit<PanelSetConfig, 'selector'>> {\n\t\treturn {\n\t\t\t...defaults,\n\t\t\t...dataConfig,\n\t\t\t...options\n\t\t} as Required<Omit<PanelSetConfig, 'selector'>>;\n\t}\n\n\t/**\n\t * Initialize PanelSet instances\n\t * @param selectorOrOptions - CSS selector string or config object\n\t * @param options - Additional config options (when first param is selector)\n\t * @returns Array of PanelSet instances\n\t */\n\tstatic init(selectorOrOptions: string | PanelSetConfig = {}, options: PanelSetConfig = {}): PanelSet[] {\n\t\t// Handle different call signatures\n\t\tlet selector: string;\n\t\tlet config: PanelSetConfig;\n\n\t\tif (typeof selectorOrOptions === 'string') {\n\t\t\t// init('#demo') or init('#demo', {debug: true})\n\t\t\tselector = selectorOrOptions;\n\t\t\tconfig = options;\n\t\t} else {\n\t\t\t// init() or init({selector: '#demo', debug: true})\n\t\t\tconfig = selectorOrOptions;\n\t\t\tselector = config.selector || '[data-panelset]';\n\t\t}\n\n\t\tconst elements = document.querySelectorAll<HTMLElement>(selector);\n\t\tconst instances: PanelSet[] = [];\n\n\t\telements.forEach(el => {\n\n\t\t\ttry {\n\t\t\t\tPanelSet._validateElement(el);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error((error as Error).message);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip if already initialized\n\t\t\tif (el.panelSet || el.dataset.panelset === 'true') {\n\t\t\t\tif (el.panelSet) instances.push(el.panelSet);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst instance = new PanelSet(el, config);\n\t\t\tinstances.push(instance);\n\t\t});\n\n\t\treturn instances;\n\t}\n\n\tconstructor(elementOrSelector: HTMLElement | string, options: PanelSetConfig = {}) {\n\t\t// Handle both element and selector\n\t\tlet element: HTMLElement | null;\n\t\tif (typeof elementOrSelector === 'string') {\n\t\t\telement = document.querySelector<HTMLElement>(elementOrSelector);\n\t\t\tif (!element) {\n\t\t\t\tthrow new Error(`PanelSet: No element found for selector \"${elementOrSelector}\"`);\n\t\t\t}\n\t\t} else {\n\t\t\telement = elementOrSelector;\n\t\t}\n\n\t\tthis.element = element;\n\n\t\t// Validate element\n\t\tPanelSet._validateElement(element);\n\n\t\t// Check if already initialized\n\t\tif (element.panelSet || element.dataset.panelset === 'true') {\n\t\t\tconsole.warn('PanelSet: Element already initialized, returning existing instance');\n\t\t\treturn element.panelSet!;\n\t\t}\n\n\t\t// Store instance on element\n\t\telement.panelSet = this;\n\n\t\tconst dataConfig = PanelSet._getDataConfig(element);\n\t\tthis.config = PanelSet._mergeConfig(\n\t\t\tPanelSet.defaults,\n\t\t\tdataConfig,\n\t\t\toptions\n\t\t);\n\n\t\tthis.panels = Array.from(element.querySelectorAll<HTMLElement>('[role=\"tabpanel\"]'));\n\n\t\tif (this.panels.length === 0) {\n\t\t\tconst elementDesc = `<${element.tagName.toLowerCase()}${element.id ? ` id=\"${element.id}\"` : ''}${element.className ? ` class=\"${element.className}\"` : ''}>`;\n\t\t\tconsole.error(`PanelSet: No panels with [role=\"tabpanel\"] found inside ${elementDesc}. Make sure panel elements are children of the [data-panelset] element.`);\n\t\t\t// Set safe defaults and bail\n\t\t\tthis.panels = [];\n\t\t\tthis.activePanel = null as any;\n\t\t\tthis.panelWrapper = null as any;\n\t\t\tthis.pendingPanel = null as any;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.activePanel =\n\t\t\tthis.panels.find(p => p.classList.contains('active')) || this.panels[0];\n\t\tthis.panelWrapper =\n\t\t\tthis.element.querySelector<HTMLElement>('.panel-wrapper') || this._autoWrapPanels();\n\n\t\tthis.pendingPanel = this.activePanel;\n\n\n\n\n\t\tthis.element.dataset.panelset = 'true';\n\n\t\tthis._log(`Initialized (${this.panels.length} panels)`);\n\t\tthis._dispatch<ReadyEventDetail>('ps:ready', { container: this.element, instance: this });\n\n\t\tthis._internalInit();\n\n\t\tlet resizeTimeout: ReturnType<typeof setTimeout>;\n\t\twindow.addEventListener('resize', () => {\n\t\t\tclearTimeout(resizeTimeout);\n\t\t\tresizeTimeout = setTimeout(() => {\n\t\t\t\tthis._updateHighestPanel();\n\t\t\t}, 250);\n\t\t});\n\n\t}\n\n\t// Debug logging helper\n\tprivate _log(message: string): void {\n\t\tif (!this.config.debug) return;\n\t\tconst id = this.element.id || 'no id';\n\t\tconsole.log(`[PanelSet] - \"${id}\" -`, message);\n\t}\n\n\tprivate static _validateElement(element: HTMLElement): void {\n\t\tif (!element.hasAttribute('data-panelset')) {\n\t\t\tconst elementDesc = `<${element.tagName.toLowerCase()}${element.id ? ` id=\"${element.id}\"` : ''}${element.className ? ` class=\"${element.className}\"` : ''}>`;\n\t\t\tthrow new Error(`PanelSet: Element is missing required data-panelset attribute. Element: ${elementDesc}`);\n\t\t}\n\t}\n\n\tprivate _autoWrapPanels(): HTMLElement {\n\t\tconst wrapper = document.createElement('div');\n\t\twrapper.className = 'panel-wrapper';\n\t\tthis.panels.forEach(panel => wrapper.appendChild(panel));\n\t\tthis.element.appendChild(wrapper);\n\t\treturn wrapper;\n\t}\n\n\tprivate _internalInit(): void {\n\t\tthis.panels.forEach(panel => {\n\t\t\tpanel.classList.remove('fade', 'incoming');\n\t\t\tif (panel !== this.activePanel) {\n\t\t\t\tpanel.hidden = true;\n\t\t\t\tpanel.classList.remove('active');\n\t\t\t} else {\n\t\t\t\tpanel.hidden = false;\n\t\t\t\tpanel.classList.add('active');\n\t\t\t}\n\t\t});\n\t\tthis.element.style.height = '';\n\t\tthis._updateHighestPanel();\n\t}\n\n\t// Dispatch custom event helper\n\tprivate _dispatch<T = unknown>(eventName: string, detail: T): void {\n\t\tthis.element.dispatchEvent(\n\t\t\tnew CustomEvent(eventName, {\n\t\t\t\tdetail,\n\t\t\t\tbubbles: true,\n\t\t\t\tcancelable: false\n\t\t\t})\n\t\t);\n\t}\n\n\t/* --- Modular helpers --- */\n\n\tprivate _getVerticalMetrics(el: HTMLElement | null): number {\n\t\tif (!el) return 0;\n\t\tconst s = getComputedStyle(el);\n\t\treturn ['paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth']\n\t\t\t.reduce((sum, prop) => sum + (parseFloat(s[prop as keyof CSSStyleDeclaration] as string) || 0), 0);\n\t}\n\n\tprivate _measureHeight(panel: HTMLElement): number {\n\t\tlet total = panel.offsetHeight;\n\t\ttotal += this._getVerticalMetrics(this.panelWrapper);\n\t\ttotal += this._getVerticalMetrics(this.element);\n\t\treturn total;\n\t}\n\n\tprivate _updateHighestPanel(): void {\n\n\t\t// Warn if user tries self-tracking\n\t\tif (this.element.hasAttribute('data-ps-track-height')) {\n\t\t\tconsole.warn('PanelSet: data-ps-track-height should be placed on a parent element, not on [data-panelset] itself. Height tracking skipped.');\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Look for parent with tracking attribute\n\t\tconst trackingParent = this.element.closest('[data-ps-track-height]');\n\t\tif (!trackingParent) return; // Skip if no tracking parent found\n\t\t\n\t\tlet maxContainerHeight = 0;\n\t\t\n\t\t// Measure each panel as if it were active\n\t\tthis.panels.forEach(panel => {\n\t\t\t// Save state\n\t\t\tconst wasHidden = panel.hidden;\n\t\t\tconst wasActive = panel.classList.contains('active');\n\t\t\t\n\t\t\t// Make this panel active temporarily\n\t\t\tthis.panels.forEach(p => {\n\t\t\t\tp.hidden = true;\n\t\t\t\tp.classList.remove('active');\n\t\t\t});\n\t\t\t\n\t\t\tpanel.hidden = false;\n\t\t\tpanel.classList.add('active');\n\t\t\tpanel.style.visibility = 'hidden';\n\t\t\t\n\t\t\t// Force reflow\n\t\t\tthis.element.offsetHeight;\n\t\t\t\n\t\t\t// Measure the CONTAINER height (includes padding and borders)\n\t\t\tconst containerHeight = this.element.offsetHeight;\n\t\t\tif (containerHeight > maxContainerHeight) {\n\t\t\t\tmaxContainerHeight = containerHeight;\n\t\t\t}\n\t\t\t\n\t\t\t// Restore state\n\t\t\tpanel.hidden = wasHidden;\n\t\t\tif (!wasActive) panel.classList.remove('active');\n\t\t\tpanel.style.visibility = '';\n\t\t});\n\n\t\tif (this.activePanel) {\n\t\t\tthis.activePanel.hidden = false;\n\t\t\tthis.activePanel.classList.add('active');\n\t\t}\n\t\tthis.panels.forEach(p => {\n\t\t\tif (p !== this.activePanel) {\n\t\t\t\tp.hidden = true;\n\t\t\t\tp.classList.remove('active');\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Set CSS variable on the tracking parent\n\t\t(trackingParent as HTMLElement).style.setProperty('--ps-max-height', `${maxContainerHeight}px`);\n\t\tthis._log(`Max container height: ${maxContainerHeight}px (set on tracking parent)`);\n\t}\n\n\tprivate _cleanupPanels(newPanel: HTMLElement): void {\n\t\tthis.panels.forEach(panel => {\n\t\t\tpanel.classList.remove('fade', 'incoming');\n\t\t\tif (panel !== newPanel) {\n\t\t\t\tpanel.classList.remove('active');\n\t\t\t\tpanel.hidden = true;\n\t\t\t} else {\n\t\t\t\tpanel.classList.add('active');\n\t\t\t\tpanel.hidden = false;\n\t\t\t}\n\t\t});\n\t\tthis.element.style.height = '';\n\t\tthis.element.classList.remove('is-transitioning');\n\t\tthis.activePanel = newPanel;\n\t}\n\n\tprivate _waitForTransition(element: HTMLElement): Promise<void> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst styles = getComputedStyle(element);\n\t\t\tconst duration = parseFloat(styles.transitionDuration) || 0;\n\t\t\tconst delay = parseFloat(styles.transitionDelay) || 0;\n\t\t\tif (duration + delay === 0) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst handler = (e: TransitionEvent) => {\n\t\t\t\tif (e.target !== element) return;\n\t\t\t\telement.removeEventListener('transitionend', handler);\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\telement.addEventListener('transitionend', handler);\n\t\t});\n\t}\n\n\t// Shared helper for open/close\n\tprivate _animateOpenClose(isOpening: boolean, withTransition: boolean): void {\n\t\tconst action = isOpening ? 'opening' : 'closing';\n\t\tconst oppositeAction = isOpening ? 'closing' : 'opening';\n\t\tconst oppositeClass = `is-${oppositeAction}`;\n\t\tconst actionClass = `is-${action}`;\n\n\t\tthis._log(isOpening ? 'Opening' : 'Closing');\n\n\t\tthis._openCloseGeneration++;\n\t\tconst myGeneration = this._openCloseGeneration;\n\n\t\t// Remove opposite state if interrupting\n\t\tif (this.element.classList.contains(oppositeClass)) {\n\t\t\tthis.element.classList.remove(oppositeClass);\n\t\t}\n\n\t\tconst targetHeight = isOpening ? this._measureHeight(this.pendingPanel) : 0;\n\n\t\tif (withTransition && this.config.transitions) {\n\t\t\tthis.element.classList.add(actionClass);\n\n\t\t\tconst currentHeight = this.element.offsetHeight;\n\t\t\tthis.element.style.height = `${currentHeight}px`;\n\n\t\t\tif (isOpening) this.element.classList.remove('is-closed');\n\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tthis.element.style.height = `${targetHeight}px`;\n\n\t\t\t\tthis._waitForTransition(this.element).then(() => {\n\t\t\t\t\tif (this._openCloseGeneration === myGeneration) {\n\t\t\t\t\t\tthis.element.style.height = '';\n\t\t\t\t\t\tthis.element.classList.remove(actionClass);\n\t\t\t\t\t\tif (!isOpening) this.element.classList.add('is-closed');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tif (isOpening) {\n\t\t\t\tthis.element.classList.remove('is-closed');\n\t\t\t} else {\n\t\t\t\tthis.element.classList.add('is-closed');\n\t\t\t}\n\t\t\tthis.element.style.height = '';\n\t\t}\n\t}\n\n\t/**\n\t * Get the ID of the currently active panel\n\t * @returns Panel ID or null if no panel is active\n\t */\n\tgetActive(): string | null {\n\t\treturn this.pendingPanel?.id || null;\n\t}\n\n\t/**\n\t * Open a closable panelset\n\t * @param withTransition - Whether to animate\n\t */\n\topen(withTransition: boolean = true): void {\n\t\tif (!this.config.closable) {\n\t\t\tthis._log('Cannot open: closable is false');\n\t\t\treturn;\n\t\t}\n\n\t\tconst isClosed = this.element.classList.contains('is-closed');\n\t\tconst isClosing = this.element.classList.contains('is-closing');\n\n\t\tif (!isClosed && !isClosing) return;\n\n\t\tthis._animateOpenClose(true, withTransition);\n\t}\n\n\t/**\n\t * Close a closable panelset\n\t * @param withTransition - Whether to animate\n\t */\n\tclose(withTransition: boolean = true): void {\n\t\tif (!this.config.closable) {\n\t\t\tthis._log('Cannot close: closable is false');\n\t\t\treturn;\n\t\t}\n\n\t\tconst isClosed = this.element.classList.contains('is-closed');\n\t\tconst isOpening = this.element.classList.contains('is-opening');\n\n\t\tif (isClosed && !isOpening) return;\n\n\t\tthis._animateOpenClose(false, withTransition);\n\t}\n\n\t/**\n\t * Toggle a closable panelset between open and closed\n\t * @param withTransition - Whether to animate\n\t */\n\ttoggle(withTransition: boolean = true): void {\n\t\tconst isClosed = this.element.classList.contains('is-closed');\n\t\tconst isClosing = this.element.classList.contains('is-closing');\n\n\t\t// If closed or closing, open it\n\t\tif (isClosed || isClosing) {\n\t\t\tthis.open(withTransition);\n\t\t} else {\n\t\t\tthis.close(withTransition);\n\t\t}\n\t}\n\n\t/**\n\t * Register a handler for async content loading\n\t * @param handler - Async content handler function\n\t * @param options - Handler options (once: whether to load only once)\n\t */\n\tonBeforeActivate(handler: AsyncContentHandler, options: HandlerOptions = {}): void {\n\t\tconst once = options.once === true; // Default: false (always reload)\n\n\t\tthis.element.addEventListener('ps:beforeactivate', (e) => {\n\t\t\tconst event = e as CustomEvent<BeforeActivateEventDetail>;\n\t\t\tconst { targetPanel, signal } = event.detail;\n\n\t\t\t// Skip if already loaded and once=true\n\t\t\tif (once && targetPanel.dataset.loaded === 'true') {\n\t\t\t\tif (this.config.debug) {\n\t\t\t\t\tthis._log(`Skipping ${targetPanel.id} (already loaded)`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Call user handler\n\t\t\tconst result = handler(targetPanel, signal);\n\n\t\t\t// If handler returns a promise, attach it to the event\n\t\t\tif (result && typeof result.then === 'function') {\n\t\t\t\tevent.detail.promise = result\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t// Auto-mark as loaded on success if once=true\n\t\t\t\t\t\tif (once) {\n\t\t\t\t\t\t\ttargetPanel.dataset.loaded = 'true';\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tif (error.name === 'AbortError') {\n\t\t\t\t\t\t\tif (this.config.debug) {\n\t\t\t\t\t\t\t\tthis._log(`Load aborted: ${targetPanel.id}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._log(`Load failed: ${error.message}`);\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/* --- Main logic --- */\n\n\t/**\n\t * Show a panel by ID\n\t * @param panelId - ID of the panel to show\n\t * @param withTransition - Whether to animate the transition\n\t * @param options - Additional options (trigger name)\n\t */\n\tasync show(panelId: string, withTransition: boolean = true, options: ShowOptions = {}): Promise<void> {\n\t\tconst newPanel = this.panels.find(p => p.id === panelId);\n\n\t\tif (!newPanel) {\n\t\t\tthis._log(`Panel not found: ${panelId}`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (newPanel === this.pendingPanel) return;\n\n\t\tconst prevPanel = this.pendingPanel;\n\t\tconst prevPanelId = prevPanel?.id;\n\t\tthis.pendingPanel = newPanel;\n\n\t\tthis.element.classList.remove('is-loading');\n\n\t\tif (prevPanel && prevPanel !== this.activePanel && prevPanel !== newPanel) {\n\t\t\tprevPanel.classList.remove('incoming');\n\t\t\tif (prevPanel.hidden) {\n\t\t\t\t// Was never visible, keep hidden\n\t\t\t} else {\n\t\t\t\tprevPanel.classList.remove('active');\n\t\t\t}\n\t\t}\n\n\t\tconst wasLoadingAsync = this._isLoadingAsync;\n\n\t\tif (this._currentAbortController) {\n\t\t\tthis._currentAbortController.abort();\n\n\t\t\t// Only fire abort if we're cancelling an async operation\n\t\t\tif (wasLoadingAsync && prevPanelId && prevPanelId !== panelId) {\n\t\t\t\tthis._dispatch<ActivationAbortedEventDetail>('ps:activationaborted', {\n\t\t\t\t\tpanelId: prevPanelId,\n\t\t\t\t\ttrigger: null\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tthis._currentAbortController = abortController;\n\t\tthis._isLoadingAsync = false;\n\n\t\tthis._log(`${prevPanel?.id || 'none'} → ${panelId}`);\n\n\t\tconst beforeActivateDetail: BeforeActivateEventDetail = {\n\t\t\tpanelId,\n\t\t\ttargetPanel: newPanel,\n\t\t\toutgoingPanel: prevPanel,\n\t\t\tsignal: abortController.signal,\n\t\t\tpromise: null\n\t\t};\n\n\t\tconst beforeActivateEvent = new CustomEvent('ps:beforeactivate', {\n\t\t\tdetail: beforeActivateDetail,\n\t\t\tbubbles: true,\n\t\t\tcancelable: false\n\t\t});\n\n\t\tthis.element.dispatchEvent(beforeActivateEvent);\n\n\t\tconst userPromise = beforeActivateDetail.promise;\n\n\t\tif (userPromise) {\n\t\t\tthis._isLoadingAsync = true;\n\t\t\tthis._log('Waiting for content...');\n\n\t\t\tlet spinnerTimeout: ReturnType<typeof setTimeout> | undefined;\n\t\t\tlet loadingShown = false;\n\n\t\t\tif (this.config.loadingDelay > 0) {\n\t\t\t\tspinnerTimeout = setTimeout(() => {\n\t\t\t\t\tthis.element.classList.add('is-loading');\n\t\t\t\t\tloadingShown = true;\n\t\t\t\t}, this.config.loadingDelay);\n\t\t\t} else {\n\t\t\t\tthis.element.classList.add('is-loading');\n\t\t\t\tloadingShown = true;\n\t\t\t}\n\n\t\t\tconst hasPreviousPanel = this.activePanel && this.activePanel !== newPanel;\n\n\t\t\tif (!hasPreviousPanel) {\n\t\t\t\tconst shouldTransition = withTransition !== false && this.config.transitions !== false;\n\t\t\t\tlet heightTransition = shouldTransition;\n\t\t\t\tif (typeof this.config.transitions === 'object') {\n\t\t\t\t\theightTransition = shouldTransition && this.config.transitions.height !== false;\n\t\t\t\t}\n\n\t\t\t\tif (heightTransition) {\n\t\t\t\t\tconst currentHeight = this.element.offsetHeight;\n\t\t\t\t\tthis.element.style.height = `${currentHeight}px`;\n\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tthis.element.style.height = `${this.config.emptyPanelHeight}px`;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait userPromise;\n\n\t\t\t\tif (spinnerTimeout) clearTimeout(spinnerTimeout);\n\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\tthis._log(`Aborted during load: ${panelId}`);\n\t\t\t\t\tif (loadingShown) this.element.classList.remove('is-loading');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._log('Content loaded');\n\n\t\t\t\tif (newPanel.dataset.loaded === 'true') {\n\t\t\t\t\tthis._updateHighestPanel();\n\t\t\t\t}\n\n\n\t\t\t} catch (error) {\n\t\t\t\tif (spinnerTimeout) clearTimeout(spinnerTimeout);\n\n\t\t\t\tconst err = error as Error;\n\t\t\t\tthis._log(`Load failed: ${err.message}`);\n\t\t\t\tif (loadingShown) this.element.classList.remove('is-loading');\n\n\t\t\t\tif (err.name !== 'AbortError') {\n\t\t\t\t\tconsole.error('Panel load error:', error);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (loadingShown) this.element.classList.remove('is-loading');\n\t\t}\n\n\t\tif (abortController.signal.aborted) {\n\t\t\tthis._log(`Aborted: ${panelId}`);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._dispatch<ActivationEventDetail>('ps:activationstart', {\n\t\t\tpanelId,\n\t\t\ttrigger: options.trigger || null\n\t\t});\n\n\t\tconst shouldTransition = withTransition !== false && this.config.transitions !== false;\n\n\t\tlet panelTransition = shouldTransition;\n\t\tlet heightTransition = shouldTransition;\n\n\n\t\tif (typeof this.config.transitions === 'object') {\n\t\t\tpanelTransition = shouldTransition && this.config.transitions.panels !== false;\n\t\t\theightTransition = shouldTransition && this.config.transitions.height !== false;\n\t\t}\n\n\t\tthis.panels.forEach(panel => panel.classList.toggle('fade', panelTransition));\n\n\t\tconst startHeight = this.element.offsetHeight;\n\t\tif (heightTransition) {\n\t\t\tthis.element.style.height = `${startHeight}px`;\n\t\t}\n\n\t\tconst outgoingPanel = this.activePanel;\n\n\t\tnewPanel.hidden = false;\n\t\tnewPanel.classList.add('incoming');\n\t\tif (panelTransition) {\n\t\t\t// Apply general transitioning class for overflow: hidden\n\t\t\tthis.element.classList.add('is-transitioning');\n\t\t}\n\t\tif (outgoingPanel && outgoingPanel !== newPanel) {\n\t\t\toutgoingPanel.classList.remove('active', 'incoming');\n\t\t\toutgoingPanel.hidden = false;\n\t\t}\n\n\t\trequestAnimationFrame(() => {\n\t\t\tnewPanel.classList.add('active');\n\t\t\tif (outgoingPanel && outgoingPanel !== newPanel) {\n\t\t\t\toutgoingPanel.classList.remove('incoming');\n\t\t\t}\n\n\t\t\tconst targetHeight = this._measureHeight(newPanel);\n\t\t\tconst heightChanged = startHeight !== targetHeight;\n\n\t\t\tif (heightTransition) {\n\t\t\t\tthis.element.style.height = `${targetHeight}px`;\n\t\t\t}\n\n\t\t\tconst promises: Promise<void>[] = [];\n\t\t\tif (panelTransition) {\n\t\t\t\tpromises.push(this._waitForTransition(newPanel));\n\t\t\t}\n\t\t\tif (heightTransition && heightChanged) {\n\t\t\t\tpromises.push(this._waitForTransition(this.element));\n\t\t\t}\n\t\t\tif (!promises.length) promises.push(Promise.resolve());\n\n\t\t\tPromise.all(promises).then(() => {\n\t\t\t\t// Check if interrupted by another activation\n\t\t\t\tif (this.pendingPanel !== newPanel) {\n\t\t\t\t\tthis._log(`Interrupted: ${panelId}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._cleanupPanels(newPanel);\n\t\t\t\tthis._log(`✓ ${panelId}`);\n\t\t\t\tthis._dispatch<ActivationEventDetail>('ps:activationcomplete', {\n\t\t\t\t\tpanelId,\n\t\t\t\t\ttrigger: options.trigger || null\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n}\n\nexport default PanelSet;"],"names":["_PanelSet","elementOrSelector","options","element","dataConfig","elementDesc","p","resizeTimeout","data","config","attrs","key","type","value","defaults","selectorOrOptions","selector","elements","instances","el","error","instance","message","id","wrapper","panel","eventName","detail","sum","prop","total","trackingParent","maxContainerHeight","wasHidden","wasActive","containerHeight","newPanel","resolve","styles","duration","delay","handler","e","isOpening","withTransition","action","oppositeClass","actionClass","myGeneration","targetHeight","currentHeight","isClosed","isClosing","once","event","targetPanel","signal","result","panelId","prevPanel","prevPanelId","wasLoadingAsync","abortController","beforeActivateDetail","beforeActivateEvent","userPromise","spinnerTimeout","loadingShown","shouldTransition","heightTransition","err","panelTransition","startHeight","outgoingPanel","heightChanged","promises","PanelSet"],"mappings":"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"}
1
+ {"version":3,"file":"panelset.js","sources":["../src/lib/index.ts"],"sourcesContent":["import './styles/panelset.scss';\n\n// Configuration types\nexport interface PanelSetConfig {\n\tselector?: string;\n\ttransitions?: boolean | {\n\t\tpanels?: boolean;\n\t\theight?: boolean;\n\t};\n\tclosable?: boolean;\n\temptyPanelHeight?: number;\n\tloadingDelay?: number;\n\tautoFocus?: boolean | 'heading' | 'first';\n\tdebug?: boolean;\n}\n\n// Event detail types\nexport interface ReadyEventDetail {\n\tcontainer: HTMLElement;\n\tinstance: PanelSet;\n}\n\nexport interface BeforeActivateEventDetail {\n\tpanelId: string;\n\ttargetPanel: HTMLElement;\n\toutgoingPanel: HTMLElement | null;\n\tsignal: AbortSignal;\n\tpromise: Promise<void> | null;\n}\n\nexport interface ActivationEventDetail {\n\tpanelId: string;\n\ttrigger: string | null;\n}\n\nexport interface ActivationAbortedEventDetail {\n\tpanelId: string;\n\ttrigger: string | null;\n}\n\n// Handler options\nexport interface HandlerOptions {\n\tonce?: boolean;\n}\n\n// Show options\nexport interface ShowOptions {\n\tevent?: Event;\n\ttransition?: boolean;\n\ttrigger?: string;\n\tautoFocus?: boolean | 'heading' | 'first' | ((panel: HTMLElement) => void);\n}\n\n// Async content handler type\nexport type AsyncContentHandler = (\n\ttargetPanel: HTMLElement,\n\tsignal: AbortSignal\n) => Promise<void> | void;\n\ndeclare global {\n\tinterface HTMLElement {\n\t\tpanelSet?: PanelSet;\n\t}\n}\n\nexport class PanelSet {\n\t// Default configuration\n\tstatic defaults: Required<Omit<PanelSetConfig, 'selector'>> = {\n\t\ttransitions: true,\n\t\tclosable: false,\n\t\temptyPanelHeight: 200,\n\t\tloadingDelay: 300,\n\t\tautoFocus: true,\n\t\tdebug: false\n\t};\n\n\t// Instance properties\n\telement!: HTMLElement;\n\tconfig!: Required<Omit<PanelSetConfig, 'selector'>>;\n\tpanels!: HTMLElement[];\n\tactivePanel!: HTMLElement;\n\tpanelWrapper!: HTMLElement;\n\tpendingPanel!: HTMLElement;\n\n\tprivate _openCloseGeneration: number = 0;\n\tprivate _isLoadingAsync: boolean = false;\n\tprivate _currentAbortController?: AbortController;\n\n\t// Parse data attributes from element\n\tstatic _getDataConfig(element: HTMLElement): Partial<PanelSetConfig> {\n\t\tconst data = element.dataset;\n\t\tconst config: Partial<PanelSetConfig> = {};\n\n\t\t// Define attribute types\n\t\tconst attrs: Record<string, 'json' | 'boolean' | 'number'> = {\n\t\t\ttransitions: 'json',\n\t\t\tclosable: 'boolean',\n\t\t\temptyPanelHeight: 'number',\n\t\t\tloadingDelay: 'number',\n\t\t\t// We do not support autofocus here. I do not think it is needed per whole PanelSet.\n\t\t\tdebug: 'boolean'\n\t\t};\n\n\t\t// Parse each attribute\n\t\tfor (const [key, type] of Object.entries(attrs)) {\n\t\t\tif (!(key in data)) continue;\n\n\t\t\tconst value = data[key];\n\t\t\tif (value === undefined) continue;\n\n\t\t\tswitch (type) {\n\t\t\t\tcase 'boolean':\n\t\t\t\t\t(config as any)[key] = value !== 'false';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'number':\n\t\t\t\t\t(config as any)[key] = parseInt(value, 10);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'json':\n\t\t\t\t\ttry {\n\t\t\t\t\t\t(config as any)[key] = JSON.parse(value);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to boolean parsing\n\t\t\t\t\t\t(config as any)[key] = value !== 'false';\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn config;\n\t}\n\n\t// Merge configurations\n\tstatic _mergeConfig(\n\t\tdefaults: Required<Omit<PanelSetConfig, 'selector'>>,\n\t\tdataConfig: Partial<PanelSetConfig>,\n\t\toptions: Partial<PanelSetConfig>\n\t): Required<Omit<PanelSetConfig, 'selector'>> {\n\t\treturn {\n\t\t\t...defaults,\n\t\t\t...dataConfig,\n\t\t\t...options\n\t\t} as Required<Omit<PanelSetConfig, 'selector'>>;\n\t}\n\n\t/**\n\t * Initialize PanelSet instances\n\t * @param selectorOrOptions - CSS selector string or config object\n\t * @param options - Additional config options (when first param is selector)\n\t * @returns Array of PanelSet instances\n\t */\n\tstatic init(selectorOrOptions: string | PanelSetConfig = {}, options: PanelSetConfig = {}): PanelSet[] {\n\t\t// Handle different call signatures\n\t\tlet selector: string;\n\t\tlet config: PanelSetConfig;\n\n\t\tif (typeof selectorOrOptions === 'string') {\n\t\t\t// init('#demo') or init('#demo', {debug: true})\n\t\t\tselector = selectorOrOptions;\n\t\t\tconfig = options;\n\t\t} else {\n\t\t\t// init() or init({selector: '#demo', debug: true})\n\t\t\tconfig = selectorOrOptions;\n\t\t\tselector = config.selector || '[data-panelset]';\n\t\t}\n\n\t\tconst elements = document.querySelectorAll<HTMLElement>(selector);\n\t\tconst instances: PanelSet[] = [];\n\n\t\telements.forEach(el => {\n\n\t\t\ttry {\n\t\t\t\tPanelSet._validateElement(el);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error((error as Error).message);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip if already initialized\n\t\t\tif (el.panelSet || el.dataset.panelset === 'true') {\n\t\t\t\tif (el.panelSet) instances.push(el.panelSet);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst instance = new PanelSet(el, config);\n\t\t\tinstances.push(instance);\n\t\t});\n\n\t\treturn instances;\n\t}\n\n\tconstructor(elementOrSelector: HTMLElement | string, options: PanelSetConfig = {}) {\n\t\t// Handle both element and selector\n\t\tlet element: HTMLElement | null;\n\t\tif (typeof elementOrSelector === 'string') {\n\t\t\telement = document.querySelector<HTMLElement>(elementOrSelector);\n\t\t\tif (!element) {\n\t\t\t\tthrow new Error(`PanelSet: No element found for selector \"${elementOrSelector}\"`);\n\t\t\t}\n\t\t} else {\n\t\t\telement = elementOrSelector;\n\t\t}\n\n\t\tthis.element = element;\n\n\t\t// Validate element\n\t\tPanelSet._validateElement(element);\n\n\t\t// Check if already initialized\n\t\tif (element.panelSet || element.dataset.panelset === 'true') {\n\t\t\tconsole.warn('PanelSet: Element already initialized, returning existing instance');\n\t\t\treturn element.panelSet!;\n\t\t}\n\n\t\t// Store instance on element\n\t\telement.panelSet = this;\n\n\t\tconst dataConfig = PanelSet._getDataConfig(element);\n\t\tthis.config = PanelSet._mergeConfig(\n\t\t\tPanelSet.defaults,\n\t\t\tdataConfig,\n\t\t\toptions\n\t\t);\n\n\t\tthis.panels = Array.from(element.querySelectorAll<HTMLElement>('[role=\"tabpanel\"]'));\n\n\t\tif (this.panels.length === 0) {\n\t\t\tconst elementDesc = `<${element.tagName.toLowerCase()}${element.id ? ` id=\"${element.id}\"` : ''}${element.className ? ` class=\"${element.className}\"` : ''}>`;\n\t\t\tconsole.error(`PanelSet: No panels with [role=\"tabpanel\"] found inside ${elementDesc}. Make sure panel elements are children of the [data-panelset] element.`);\n\t\t\t// Set safe defaults and bail\n\t\t\tthis.panels = [];\n\t\t\tthis.activePanel = null as any;\n\t\t\tthis.panelWrapper = null as any;\n\t\t\tthis.pendingPanel = null as any;\n\t\t\treturn;\n\t\t}\n\n\n\t\tthis.activePanel =\n\t\t\tthis.panels.find(p => p.classList.contains('active')) || this.panels[0];\n\t\tthis.panelWrapper =\n\t\t\tthis.element.querySelector<HTMLElement>('.panel-wrapper') || this._autoWrapPanels();\n\n\t\tthis.pendingPanel = this.activePanel;\n\n\n\n\n\t\tthis.element.dataset.panelset = 'true';\n\n\t\tthis._log(`Initialized (${this.panels.length} panels)`);\n\t\tthis._dispatch<ReadyEventDetail>('ps:ready', { container: this.element, instance: this });\n\n\t\tthis._internalInit();\n\n\t\tlet resizeTimeout: ReturnType<typeof setTimeout>;\n\t\twindow.addEventListener('resize', () => {\n\t\t\tclearTimeout(resizeTimeout);\n\t\t\tresizeTimeout = setTimeout(() => {\n\t\t\t\tthis._updateHighestPanel();\n\t\t\t}, 250);\n\t\t});\n\n\t}\n\n\t// Debug logging helper\n\tprivate _log(message: string): void {\n\t\tif (!this.config.debug) return;\n\t\tconst id = this.element.id || 'no id';\n\t\tconsole.log(`[PanelSet] - \"${id}\" -`, message);\n\t}\n\n\tprivate static _validateElement(element: HTMLElement): void {\n\t\tif (!element.hasAttribute('data-panelset')) {\n\t\t\tconst elementDesc = `<${element.tagName.toLowerCase()}${element.id ? ` id=\"${element.id}\"` : ''}${element.className ? ` class=\"${element.className}\"` : ''}>`;\n\t\t\tthrow new Error(`PanelSet: Element is missing required data-panelset attribute. Element: ${elementDesc}`);\n\t\t}\n\t}\n\n\tprivate _autoWrapPanels(): HTMLElement {\n\t\tconst wrapper = document.createElement('div');\n\t\twrapper.className = 'panel-wrapper';\n\t\tthis.panels.forEach(panel => wrapper.appendChild(panel));\n\t\tthis.element.appendChild(wrapper);\n\t\treturn wrapper;\n\t}\n\n\tprivate _internalInit(): void {\n\t\tthis.panels.forEach(panel => {\n\t\t\tpanel.classList.remove('fade', 'incoming');\n\t\t\tif (panel !== this.activePanel) {\n\t\t\t\tpanel.hidden = true;\n\t\t\t\tpanel.classList.remove('active');\n\t\t\t} else {\n\t\t\t\tpanel.hidden = false;\n\t\t\t\tpanel.classList.add('active');\n\t\t\t}\n\t\t});\n\t\tthis.element.style.height = '';\n\t\tthis._updateHighestPanel();\n\t}\n\t\n\n\t// Dispatch custom event helper\n\tprivate _dispatch<T = unknown>(eventName: string, detail: T): void {\n\t\tthis.element.dispatchEvent(\n\t\t\tnew CustomEvent(eventName, {\n\t\t\t\tdetail,\n\t\t\t\tbubbles: true,\n\t\t\t\tcancelable: false\n\t\t\t})\n\t\t);\n\t}\n\n\t/* --- Modular helpers --- */\n\n\tprivate _getVerticalMetrics(el: HTMLElement | null): number {\n\t\tif (!el) return 0;\n\t\tconst s = getComputedStyle(el);\n\t\treturn ['paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth']\n\t\t\t.reduce((sum, prop) => sum + (parseFloat(s[prop as keyof CSSStyleDeclaration] as string) || 0), 0);\n\t}\n\n\tprivate _measureHeight(panel: HTMLElement): number {\n\t\tlet total = panel.offsetHeight;\n\t\ttotal += this._getVerticalMetrics(this.panelWrapper);\n\t\ttotal += this._getVerticalMetrics(this.element);\n\t\treturn total;\n\t}\n\n\tprivate _updateHighestPanel(): void {\n\n\t\t// Warn if user tries self-tracking\n\t\tif (this.element.hasAttribute('data-ps-track-height')) {\n\t\t\tconsole.warn('PanelSet: data-ps-track-height should be placed on a parent element, not on [data-panelset] itself. Height tracking skipped.');\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Look for parent with tracking attribute\n\t\tconst trackingParent = this.element.closest('[data-ps-track-height]');\n\t\tif (!trackingParent) return; // Skip if no tracking parent found\n\t\t\n\t\tlet maxContainerHeight = 0;\n\t\t\n\t\t// Measure each panel as if it were active\n\t\tthis.panels.forEach(panel => {\n\t\t\t// Save state\n\t\t\tconst wasHidden = panel.hidden;\n\t\t\tconst wasActive = panel.classList.contains('active');\n\t\t\t\n\t\t\t// Make this panel active temporarily\n\t\t\tthis.panels.forEach(p => {\n\t\t\t\tp.hidden = true;\n\t\t\t\tp.classList.remove('active');\n\t\t\t});\n\t\t\t\n\t\t\tpanel.hidden = false;\n\t\t\tpanel.classList.add('active');\n\t\t\tpanel.style.visibility = 'hidden';\n\t\t\t\n\t\t\t// Force reflow\n\t\t\tthis.element.offsetHeight;\n\t\t\t\n\t\t\t// Measure the CONTAINER height (includes padding and borders)\n\t\t\tconst containerHeight = this.element.offsetHeight;\n\t\t\tif (containerHeight > maxContainerHeight) {\n\t\t\t\tmaxContainerHeight = containerHeight;\n\t\t\t}\n\t\t\t\n\t\t\t// Restore state\n\t\t\tpanel.hidden = wasHidden;\n\t\t\tif (!wasActive) panel.classList.remove('active');\n\t\t\tpanel.style.visibility = '';\n\t\t});\n\n\t\tif (this.activePanel) {\n\t\t\tthis.activePanel.hidden = false;\n\t\t\tthis.activePanel.classList.add('active');\n\t\t}\n\t\tthis.panels.forEach(p => {\n\t\t\tif (p !== this.activePanel) {\n\t\t\t\tp.hidden = true;\n\t\t\t\tp.classList.remove('active');\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Set CSS variable on the tracking parent\n\t\t(trackingParent as HTMLElement).style.setProperty('--ps-max-height', `${maxContainerHeight}px`);\n\t\tthis._log(`Max container height: ${maxContainerHeight}px (set on tracking parent)`);\n\t}\n\n\tprivate _cleanupPanels(newPanel: HTMLElement): void {\n\t\tthis.panels.forEach(panel => {\n\t\t\tpanel.classList.remove('fade', 'incoming');\n\t\t\tif (panel !== newPanel) {\n\t\t\t\tpanel.classList.remove('active');\n\t\t\t\tpanel.hidden = true;\n\t\t\t} else {\n\t\t\t\tpanel.classList.add('active');\n\t\t\t\tpanel.hidden = false;\n\t\t\t}\n\t\t});\n\t\tthis.element.style.height = '';\n\t\tthis.element.classList.remove('is-transitioning');\n\t\tthis.activePanel = newPanel;\n\t}\n\n\tprivate _waitForTransition(element: HTMLElement): Promise<void> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst styles = getComputedStyle(element);\n\t\t\tconst duration = parseFloat(styles.transitionDuration) || 0;\n\t\t\tconst delay = parseFloat(styles.transitionDelay) || 0;\n\t\t\tif (duration + delay === 0) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst handler = (e: TransitionEvent) => {\n\t\t\t\tif (e.target !== element) return;\n\t\t\t\telement.removeEventListener('transitionend', handler);\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\telement.addEventListener('transitionend', handler);\n\t\t});\n\t}\n\n\tprivate _handleAutoFocus(panel: HTMLElement, autoFocus: boolean | 'heading' | 'first' | ((panel: HTMLElement) => void), event?: Event): void {\n\n\t\tthis._log(`AutoFocus called with event: ${event ? event.type : 'none'}`);\n\n\t\tif (autoFocus && event) {\n\t\t\tconst isKeyboardEvent = \n\t\t\t\tevent.type.startsWith('key') || \n\t\t\t\t(event instanceof MouseEvent && event.detail === 0);\n\t\t\t\n\t\t\t// If touch/mouse, skip autofocus\n\t\t\tif (!isKeyboardEvent) {\n\t\t\t\tthis._log('Skipping autofocus (touch/mouse interaction)');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (autoFocus === true) {\n\t\t\t// Focus the panel itself\n\t\t\tif (!panel.hasAttribute('tabindex')) {\n\t\t\t\tpanel.setAttribute('tabindex', '-1');\n\t\t\t}\n\t\t\tpanel.focus();\n\t\t\tthis._log(`Auto-focused panel: ${panel.id}`);\n\t\t} else if (autoFocus === 'heading') {\n\t\t\t// Focus first heading\n\t\t\tconst heading = panel.querySelector<HTMLElement>('h1, h2, h3, h4, h5, h6');\n\t\t\tif (heading) {\n\t\t\t\tif (!heading.hasAttribute('tabindex')) {\n\t\t\t\t\theading.setAttribute('tabindex', '-1');\n\t\t\t\t}\n\t\t\t\theading.focus();\n\t\t\t\tthis._log(`Auto-focused heading in: ${panel.id}`);\n\t\t\t}\n\t\t} else if (autoFocus === 'first') {\n\t\t\t// Focus first focusable element\n\t\t\tconst focusable = panel.querySelector<HTMLElement>('a, button, input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\t\t\tif (focusable) {\n\t\t\t\tfocusable.focus();\n\t\t\t\tthis._log(`Auto-focused first element in: ${panel.id}`);\n\t\t\t}\n\t\t} else if (typeof autoFocus === 'function') {\n\t\t\t// Custom function\n\t\t\tautoFocus(panel);\n\t\t\tthis._log(`Auto-focused (custom) in: ${panel.id}`);\n\t\t}\n\t}\n\n\t// Shared helper for open/close\n\tprivate _animateOpenClose(isOpening: boolean, withTransition: boolean): void {\n\t\tconst action = isOpening ? 'opening' : 'closing';\n\t\tconst oppositeAction = isOpening ? 'closing' : 'opening';\n\t\tconst oppositeClass = `is-${oppositeAction}`;\n\t\tconst actionClass = `is-${action}`;\n\n\t\tthis._log(isOpening ? 'Opening' : 'Closing');\n\n\t\tthis._openCloseGeneration++;\n\t\tconst myGeneration = this._openCloseGeneration;\n\n\t\t// Remove opposite state if interrupting\n\t\tif (this.element.classList.contains(oppositeClass)) {\n\t\t\tthis.element.classList.remove(oppositeClass);\n\t\t}\n\n\t\tconst targetHeight = isOpening ? this._measureHeight(this.pendingPanel) : 0;\n\n\t\tif (withTransition && this.config.transitions) {\n\t\t\tthis.element.classList.add(actionClass);\n\n\t\t\tconst currentHeight = this.element.offsetHeight;\n\t\t\tthis.element.style.height = `${currentHeight}px`;\n\n\t\t\tif (isOpening) this.element.classList.remove('is-closed');\n\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tthis.element.style.height = `${targetHeight}px`;\n\n\t\t\t\tthis._waitForTransition(this.element).then(() => {\n\t\t\t\t\tif (this._openCloseGeneration === myGeneration) {\n\t\t\t\t\t\tthis.element.style.height = '';\n\t\t\t\t\t\tthis.element.classList.remove(actionClass);\n\t\t\t\t\t\tif (!isOpening) this.element.classList.add('is-closed');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tif (isOpening) {\n\t\t\t\tthis.element.classList.remove('is-closed');\n\t\t\t} else {\n\t\t\t\tthis.element.classList.add('is-closed');\n\t\t\t}\n\t\t\tthis.element.style.height = '';\n\t\t}\n\t}\n\n\t/**\n\t * Get the ID of the currently active panel\n\t * @returns Panel ID or null if no panel is active\n\t */\n\tgetActive(): string | null {\n\t\treturn this.pendingPanel?.id || null;\n\t}\n\n\n\t/**\n\t * Open a closable panelset\n\t * @param options - Configuration options\n\t */\n\topen(options?: ShowOptions): void {\n\t\tconst {\n\t\t\tevent,\n\t\t\ttransition = true,\n\t\t\tautoFocus\n\t\t} = options || {};\n\n\t\tif (!this.config.closable) {\n\t\t\tthis._log('Cannot open: closable is false');\n\t\t\treturn;\n\t\t}\n\n\t\tconst isClosed = this.element.classList.contains('is-closed');\n\t\tconst isClosing = this.element.classList.contains('is-closing');\n\n\t\tif (!isClosed && !isClosing) return;\n\n\t\tthis._animateOpenClose(true, transition);\n\t\t\n\t\t// Handle autofocus after opening\n\t\tconst finalAutoFocus = autoFocus ?? this.config.autoFocus;\n\t\tif (finalAutoFocus !== false && finalAutoFocus !== undefined && this.pendingPanel) {\n\t\t\tif (transition && this.config.transitions) {\n\t\t\t\tthis._waitForTransition(this.element).then(() => {\n\t\t\t\t\tthis._handleAutoFocus(this.pendingPanel, finalAutoFocus, event);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis._handleAutoFocus(this.pendingPanel, finalAutoFocus, event);\n\t\t\t}\n\t\t}\n\t}\n\n\n\t/**\n\t * Close a closable panelset\n\t * @param options - Configuration options\n\t */\n\tclose(options?: ShowOptions): void {\n\t\tconst {\n\t\t\ttransition = true\n\t\t} = options || {};\n\n\t\tif (!this.config.closable) {\n\t\t\tthis._log('Cannot close: closable is false');\n\t\t\treturn;\n\t\t}\n\n\t\tconst isClosed = this.element.classList.contains('is-closed');\n\t\tconst isOpening = this.element.classList.contains('is-opening');\n\n\t\tif (isClosed && !isOpening) return;\n\n\t\tthis._animateOpenClose(false, transition);\n\t}\n\n\n\t/**\n\t * Toggle a closable panelset between open and closed\n\t * @param options - Configuration options\n\t */\n\ttoggle(options?: ShowOptions): void {\n\t\tconst {\n\t\t\tevent,\n\t\t\ttransition = true,\n\t\t\tautoFocus\n\t\t} = options || {};\n\n\t\tconst isClosed = this.element.classList.contains('is-closed');\n\t\tconst isClosing = this.element.classList.contains('is-closing');\n\n\t\t// If closed or closing, open it\n\t\tif (isClosed || isClosing) {\n\t\t\tthis.open({ event, transition, autoFocus });\n\t\t} else {\n\t\t\tthis.close({ transition });\n\t\t}\n\t}\n\n\t/**\n\t * Register a handler for async content loading\n\t * @param handler - Async content handler function\n\t * @param options - Handler options (once: whether to load only once)\n\t */\n\tonBeforeActivate(handler: AsyncContentHandler, options: HandlerOptions = {}): void {\n\t\tconst once = options.once === true; // Default: false (always reload)\n\n\t\tthis.element.addEventListener('ps:beforeactivate', (e) => {\n\t\t\tconst event = e as CustomEvent<BeforeActivateEventDetail>;\n\t\t\tconst { targetPanel, signal } = event.detail;\n\n\t\t\t// Skip if already loaded and once=true\n\t\t\tif (once && targetPanel.dataset.loaded === 'true') {\n\t\t\t\tif (this.config.debug) {\n\t\t\t\t\tthis._log(`Skipping ${targetPanel.id} (already loaded)`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Call user handler\n\t\t\tconst result = handler(targetPanel, signal);\n\n\t\t\t// If handler returns a promise, attach it to the event\n\t\t\tif (result && typeof result.then === 'function') {\n\t\t\t\tevent.detail.promise = result\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t// Auto-mark as loaded on success if once=true\n\t\t\t\t\t\tif (once) {\n\t\t\t\t\t\t\ttargetPanel.dataset.loaded = 'true';\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tif (error.name === 'AbortError') {\n\t\t\t\t\t\t\tif (this.config.debug) {\n\t\t\t\t\t\t\t\tthis._log(`Load aborted: ${targetPanel.id}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._log(`Load failed: ${error.message}`);\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/* --- Main logic --- */\n\n\n\t/**\n\t * Show a panel by ID\n\t * @param panelId - ID of the panel to show\n\t * @param options - Configuration options for this activation\n\t */\n\tasync show(panelId: string, options?: ShowOptions): Promise<void> {\n\t\t// Destructure options with defaults\n\t\tconst {\n\t\t\tevent,\n\t\t\ttransition = true,\n\t\t\ttrigger,\n\t\t\tautoFocus\n\t\t} = options || {};\n\n\t\tconst newPanel = this.panels.find(p => p.id === panelId);\n\n\t\tif (!newPanel) {\n\t\t\tthis._log(`Panel not found: ${panelId}`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (newPanel === this.pendingPanel) return;\n\n\t\tconst prevPanel = this.pendingPanel;\n\t\tconst prevPanelId = prevPanel?.id;\n\t\tthis.pendingPanel = newPanel;\n\n\t\tthis.element.classList.remove('is-loading');\n\n\t\tif (prevPanel && prevPanel !== this.activePanel && prevPanel !== newPanel) {\n\t\t\tprevPanel.classList.remove('incoming');\n\t\t\tif (prevPanel.hidden) {\n\t\t\t\t// Was never visible, keep hidden\n\t\t\t} else {\n\t\t\t\tprevPanel.classList.remove('active');\n\t\t\t}\n\t\t}\n\n\t\tconst wasLoadingAsync = this._isLoadingAsync;\n\n\t\tif (this._currentAbortController) {\n\t\t\tthis._currentAbortController.abort();\n\n\t\t\t// Only fire abort if we're cancelling an async operation\n\t\t\tif (wasLoadingAsync && prevPanelId && prevPanelId !== panelId) {\n\t\t\t\tthis._dispatch<ActivationAbortedEventDetail>('ps:activationaborted', {\n\t\t\t\t\tpanelId: prevPanelId,\n\t\t\t\t\ttrigger: null\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tthis._currentAbortController = abortController;\n\t\tthis._isLoadingAsync = false;\n\n\t\tthis._log(`${prevPanel?.id || 'none'} → ${panelId}`);\n\n\t\tconst beforeActivateDetail: BeforeActivateEventDetail = {\n\t\t\tpanelId,\n\t\t\ttargetPanel: newPanel,\n\t\t\toutgoingPanel: prevPanel,\n\t\t\tsignal: abortController.signal,\n\t\t\tpromise: null\n\t\t};\n\n\t\tconst beforeActivateEvent = new CustomEvent('ps:beforeactivate', {\n\t\t\tdetail: beforeActivateDetail,\n\t\t\tbubbles: true,\n\t\t\tcancelable: false\n\t\t});\n\n\t\tthis.element.dispatchEvent(beforeActivateEvent);\n\n\t\tconst userPromise = beforeActivateDetail.promise;\n\n\t\tif (userPromise) {\n\t\t\tthis._isLoadingAsync = true;\n\t\t\tthis._log('Waiting for content...');\n\n\t\t\tlet spinnerTimeout: ReturnType<typeof setTimeout> | undefined;\n\t\t\tlet loadingShown = false;\n\n\t\t\tif (this.config.loadingDelay > 0) {\n\t\t\t\tspinnerTimeout = setTimeout(() => {\n\t\t\t\t\tthis.element.classList.add('is-loading');\n\t\t\t\t\tloadingShown = true;\n\t\t\t\t}, this.config.loadingDelay);\n\t\t\t} else {\n\t\t\t\tthis.element.classList.add('is-loading');\n\t\t\t\tloadingShown = true;\n\t\t\t}\n\n\t\t\tconst hasPreviousPanel = this.activePanel && this.activePanel !== newPanel;\n\n\t\t\tif (!hasPreviousPanel) {\n\t\t\t\tconst shouldTransition = transition !== false && this.config.transitions !== false;\n\t\t\t\tlet heightTransition = shouldTransition;\n\t\t\t\tif (typeof this.config.transitions === 'object') {\n\t\t\t\t\theightTransition = shouldTransition && this.config.transitions.height !== false;\n\t\t\t\t}\n\n\t\t\t\tif (heightTransition) {\n\t\t\t\t\tconst currentHeight = this.element.offsetHeight;\n\t\t\t\t\tthis.element.style.height = `${currentHeight}px`;\n\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tthis.element.style.height = `${this.config.emptyPanelHeight}px`;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait userPromise;\n\n\t\t\t\tif (spinnerTimeout) clearTimeout(spinnerTimeout);\n\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\tthis._log(`Aborted during load: ${panelId}`);\n\t\t\t\t\tif (loadingShown) this.element.classList.remove('is-loading');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._log('Content loaded');\n\n\t\t\t\tif (newPanel.dataset.loaded === 'true') {\n\t\t\t\t\tthis._updateHighestPanel();\n\t\t\t\t}\n\n\n\t\t\t} catch (error) {\n\t\t\t\tif (spinnerTimeout) clearTimeout(spinnerTimeout);\n\n\t\t\t\tconst err = error as Error;\n\t\t\t\tthis._log(`Load failed: ${err.message}`);\n\t\t\t\tif (loadingShown) this.element.classList.remove('is-loading');\n\n\t\t\t\tif (err.name !== 'AbortError') {\n\t\t\t\t\tconsole.error('Panel load error:', error);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (loadingShown) this.element.classList.remove('is-loading');\n\t\t}\n\n\t\tif (abortController.signal.aborted) {\n\t\t\tthis._log(`Aborted: ${panelId}`);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._dispatch<ActivationEventDetail>('ps:activationstart', {\n\t\t\tpanelId,\n\t\t\ttrigger: trigger || null\n\t\t});\n\n\t\tconst shouldTransition = transition !== false && this.config.transitions !== false;\n\n\t\tlet panelTransition = shouldTransition;\n\t\tlet heightTransition = shouldTransition;\n\n\n\t\tif (typeof this.config.transitions === 'object') {\n\t\t\tpanelTransition = shouldTransition && this.config.transitions.panels !== false;\n\t\t\theightTransition = shouldTransition && this.config.transitions.height !== false;\n\t\t}\n\n\t\tthis.panels.forEach(panel => panel.classList.toggle('fade', panelTransition));\n\n\t\tconst startHeight = this.element.offsetHeight;\n\t\tif (heightTransition) {\n\t\t\tthis.element.style.height = `${startHeight}px`;\n\t\t}\n\n\t\tconst outgoingPanel = this.activePanel;\n\n\t\tnewPanel.hidden = false;\n\t\tnewPanel.classList.add('incoming');\n\t\tif (panelTransition) {\n\t\t\t// Apply general transitioning class for overflow: hidden\n\t\t\tthis.element.classList.add('is-transitioning');\n\t\t}\n\t\tif (outgoingPanel && outgoingPanel !== newPanel) {\n\t\t\toutgoingPanel.classList.remove('active', 'incoming');\n\t\t\toutgoingPanel.hidden = false;\n\t\t}\n\n\t\trequestAnimationFrame(() => {\n\t\t\tnewPanel.classList.add('active');\n\t\t\tif (outgoingPanel && outgoingPanel !== newPanel) {\n\t\t\t\toutgoingPanel.classList.remove('incoming');\n\t\t\t}\n\n\t\t\tconst targetHeight = this._measureHeight(newPanel);\n\t\t\tconst heightChanged = startHeight !== targetHeight;\n\n\t\t\tif (heightTransition) {\n\t\t\t\tthis.element.style.height = `${targetHeight}px`;\n\t\t\t}\n\n\t\t\tconst promises: Promise<void>[] = [];\n\t\t\tif (panelTransition) {\n\t\t\t\tpromises.push(this._waitForTransition(newPanel));\n\t\t\t}\n\t\t\tif (heightTransition && heightChanged) {\n\t\t\t\tpromises.push(this._waitForTransition(this.element));\n\t\t\t}\n\t\t\tif (!promises.length) promises.push(Promise.resolve());\n\n\t\t\tPromise.all(promises).then(() => {\n\t\t\t\t// Check if interrupted by another activation\n\t\t\t\tif (this.pendingPanel !== newPanel) {\n\t\t\t\t\tthis._log(`Interrupted: ${panelId}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._cleanupPanels(newPanel);\n\t\t\t\tthis._log(`✓ ${panelId}`);\n\t\t\t\t\n\t\t\t\t// Handle auto-focus\n\t\t\t\tconst finalAutoFocus = autoFocus ?? this.config.autoFocus;\n\t\t\t\tif (finalAutoFocus !== false && finalAutoFocus !== undefined) {\n\t\t\t\t\tthis._handleAutoFocus(newPanel, finalAutoFocus, event);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis._dispatch<ActivationEventDetail>('ps:activationcomplete', {\n\t\t\t\t\tpanelId,\n\t\t\t\t\ttrigger: trigger || null\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\n}\n\nexport default PanelSet;"],"names":["_PanelSet","elementOrSelector","options","element","dataConfig","elementDesc","p","resizeTimeout","data","config","attrs","key","type","value","defaults","selectorOrOptions","selector","elements","instances","el","error","instance","message","id","wrapper","panel","eventName","detail","s","sum","prop","total","trackingParent","maxContainerHeight","wasHidden","wasActive","containerHeight","newPanel","resolve","styles","duration","delay","handler","e","autoFocus","event","heading","focusable","isOpening","withTransition","action","oppositeClass","actionClass","myGeneration","targetHeight","currentHeight","transition","isClosed","isClosing","finalAutoFocus","once","targetPanel","signal","result","panelId","trigger","prevPanel","prevPanelId","wasLoadingAsync","abortController","beforeActivateDetail","beforeActivateEvent","userPromise","spinnerTimeout","loadingShown","shouldTransition","heightTransition","err","panelTransition","startHeight","outgoingPanel","heightChanged","promises","PanelSet"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panelset",
3
- "version": "0.5.4",
3
+ "version": "1.0.2",
4
4
  "description": "Flexible panel management with smooth transitions",
5
5
  "type": "module",
6
6
  "main": "./dist/panelset.js",
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "files": [
16
16
  "dist",
17
- "README.md"
17
+ "README.md",
18
+ "CHANGELOG.md"
18
19
  ],
19
20
  "scripts": {
20
21
  "start": "npm run dev",