panelset 1.0.0 → 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 +45 -0
- package/dist/index.d.ts +10 -9
- package/dist/panelset.css +1 -1
- package/dist/panelset.js +213 -188
- package/dist/panelset.js.map +1 -1
- package/package.json +3 -2
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
|
@@ -62,19 +62,19 @@ declare class PanelSet {
|
|
|
62
62
|
getActive(): string | null;
|
|
63
63
|
/**
|
|
64
64
|
* Open a closable panelset
|
|
65
|
-
* @param
|
|
65
|
+
* @param options - Configuration options
|
|
66
66
|
*/
|
|
67
|
-
open(
|
|
67
|
+
open(options?: ShowOptions): void;
|
|
68
68
|
/**
|
|
69
69
|
* Close a closable panelset
|
|
70
|
-
* @param
|
|
70
|
+
* @param options - Configuration options
|
|
71
71
|
*/
|
|
72
|
-
close(
|
|
72
|
+
close(options?: ShowOptions): void;
|
|
73
73
|
/**
|
|
74
74
|
* Toggle a closable panelset between open and closed
|
|
75
|
-
* @param
|
|
75
|
+
* @param options - Configuration options
|
|
76
76
|
*/
|
|
77
|
-
toggle(
|
|
77
|
+
toggle(options?: ShowOptions): void;
|
|
78
78
|
/**
|
|
79
79
|
* Register a handler for async content loading
|
|
80
80
|
* @param handler - Async content handler function
|
|
@@ -84,10 +84,9 @@ declare class PanelSet {
|
|
|
84
84
|
/**
|
|
85
85
|
* Show a panel by ID
|
|
86
86
|
* @param panelId - ID of the panel to show
|
|
87
|
-
* @param
|
|
88
|
-
* @param options - Additional options (trigger name)
|
|
87
|
+
* @param options - Configuration options for this activation
|
|
89
88
|
*/
|
|
90
|
-
show(panelId: string,
|
|
89
|
+
show(panelId: string, options?: ShowOptions): Promise<void>;
|
|
91
90
|
}
|
|
92
91
|
export { PanelSet }
|
|
93
92
|
export default PanelSet;
|
|
@@ -111,6 +110,8 @@ export declare interface ReadyEventDetail {
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
export declare interface ShowOptions {
|
|
113
|
+
event?: Event;
|
|
114
|
+
transition?: boolean;
|
|
114
115
|
trigger?: string;
|
|
115
116
|
autoFocus?: boolean | 'heading' | 'first' | ((panel: HTMLElement) => void);
|
|
116
117
|
}
|
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] [role=tabpanel]:focus{outline: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,36 +1,36 @@
|
|
|
1
1
|
const d = class d {
|
|
2
|
-
constructor(
|
|
2
|
+
constructor(t, i = {}) {
|
|
3
3
|
this._openCloseGeneration = 0, this._isLoadingAsync = !1;
|
|
4
|
-
let
|
|
5
|
-
if (typeof
|
|
6
|
-
if (
|
|
7
|
-
throw new Error(`PanelSet: No element found for selector "${
|
|
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
|
-
|
|
10
|
-
if (this.element =
|
|
11
|
-
return console.warn("PanelSet: Element already initialized, returning existing instance"),
|
|
12
|
-
|
|
13
|
-
const
|
|
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
14
|
if (this.config = d._mergeConfig(
|
|
15
15
|
d.defaults,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
), this.panels = Array.from(
|
|
19
|
-
const a = `<${
|
|
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
|
|
24
|
+
let o;
|
|
25
25
|
window.addEventListener("resize", () => {
|
|
26
|
-
clearTimeout(
|
|
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(
|
|
33
|
-
const
|
|
32
|
+
static _getDataConfig(t) {
|
|
33
|
+
const i = t.dataset, e = {}, n = {
|
|
34
34
|
transitions: "json",
|
|
35
35
|
closable: "boolean",
|
|
36
36
|
emptyPanelHeight: "number",
|
|
@@ -38,34 +38,34 @@ const d = class d {
|
|
|
38
38
|
// We do not support autofocus here. I do not think it is needed per whole PanelSet.
|
|
39
39
|
debug: "boolean"
|
|
40
40
|
};
|
|
41
|
-
for (const [
|
|
42
|
-
if (!(
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
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)
|
|
45
45
|
switch (a) {
|
|
46
46
|
case "boolean":
|
|
47
|
-
|
|
47
|
+
e[o] = s !== "false";
|
|
48
48
|
break;
|
|
49
49
|
case "number":
|
|
50
|
-
|
|
50
|
+
e[o] = parseInt(s, 10);
|
|
51
51
|
break;
|
|
52
52
|
case "json":
|
|
53
53
|
try {
|
|
54
|
-
|
|
54
|
+
e[o] = JSON.parse(s);
|
|
55
55
|
} catch {
|
|
56
|
-
|
|
56
|
+
e[o] = s !== "false";
|
|
57
57
|
}
|
|
58
58
|
break;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
return
|
|
61
|
+
return e;
|
|
62
62
|
}
|
|
63
63
|
// Merge configurations
|
|
64
|
-
static _mergeConfig(
|
|
64
|
+
static _mergeConfig(t, i, e) {
|
|
65
65
|
return {
|
|
66
|
-
...
|
|
67
|
-
...
|
|
68
|
-
...
|
|
66
|
+
...t,
|
|
67
|
+
...i,
|
|
68
|
+
...e
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
@@ -74,131 +74,135 @@ const d = class d {
|
|
|
74
74
|
* @param options - Additional config options (when first param is selector)
|
|
75
75
|
* @returns Array of PanelSet instances
|
|
76
76
|
*/
|
|
77
|
-
static init(
|
|
78
|
-
let
|
|
79
|
-
typeof
|
|
80
|
-
const
|
|
81
|
-
return
|
|
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) => {
|
|
82
82
|
try {
|
|
83
|
-
d._validateElement(
|
|
84
|
-
} catch (
|
|
85
|
-
console.error(
|
|
83
|
+
d._validateElement(s);
|
|
84
|
+
} catch (r) {
|
|
85
|
+
console.error(r.message);
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
|
-
if (
|
|
89
|
-
|
|
88
|
+
if (s.panelSet || s.dataset.panelset === "true") {
|
|
89
|
+
s.panelSet && a.push(s.panelSet);
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
|
-
const l = new d(
|
|
92
|
+
const l = new d(s, n);
|
|
93
93
|
a.push(l);
|
|
94
94
|
}), a;
|
|
95
95
|
}
|
|
96
96
|
// Debug logging helper
|
|
97
|
-
_log(
|
|
97
|
+
_log(t) {
|
|
98
98
|
if (!this.config.debug) return;
|
|
99
|
-
const
|
|
100
|
-
console.log(`[PanelSet] - "${
|
|
99
|
+
const i = this.element.id || "no id";
|
|
100
|
+
console.log(`[PanelSet] - "${i}" -`, t);
|
|
101
101
|
}
|
|
102
|
-
static _validateElement(
|
|
103
|
-
if (!
|
|
104
|
-
const
|
|
105
|
-
throw new Error(`PanelSet: Element is missing required data-panelset attribute. Element: ${
|
|
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}`);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
_autoWrapPanels() {
|
|
109
|
-
const
|
|
110
|
-
return
|
|
109
|
+
const t = document.createElement("div");
|
|
110
|
+
return t.className = "panel-wrapper", this.panels.forEach((i) => t.appendChild(i)), this.element.appendChild(t), t;
|
|
111
111
|
}
|
|
112
112
|
_internalInit() {
|
|
113
|
-
this.panels.forEach((
|
|
114
|
-
|
|
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"));
|
|
115
115
|
}), this.element.style.height = "", this._updateHighestPanel();
|
|
116
116
|
}
|
|
117
117
|
// Dispatch custom event helper
|
|
118
|
-
_dispatch(
|
|
118
|
+
_dispatch(t, i) {
|
|
119
119
|
this.element.dispatchEvent(
|
|
120
|
-
new CustomEvent(
|
|
121
|
-
detail:
|
|
120
|
+
new CustomEvent(t, {
|
|
121
|
+
detail: i,
|
|
122
122
|
bubbles: !0,
|
|
123
123
|
cancelable: !1
|
|
124
124
|
})
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
127
|
/* --- Modular helpers --- */
|
|
128
|
-
_getVerticalMetrics(
|
|
129
|
-
if (!
|
|
130
|
-
const
|
|
131
|
-
return ["paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth"].reduce((
|
|
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);
|
|
132
132
|
}
|
|
133
|
-
_measureHeight(
|
|
134
|
-
let
|
|
135
|
-
return
|
|
133
|
+
_measureHeight(t) {
|
|
134
|
+
let i = t.offsetHeight;
|
|
135
|
+
return i += this._getVerticalMetrics(this.panelWrapper), i += this._getVerticalMetrics(this.element), i;
|
|
136
136
|
}
|
|
137
137
|
_updateHighestPanel() {
|
|
138
138
|
if (this.element.hasAttribute("data-ps-track-height")) {
|
|
139
139
|
console.warn("PanelSet: data-ps-track-height should be placed on a parent element, not on [data-panelset] itself. Height tracking skipped.");
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
144
|
-
let
|
|
145
|
-
this.panels.forEach((
|
|
146
|
-
const
|
|
147
|
-
this.panels.forEach((
|
|
148
|
-
|
|
149
|
-
}),
|
|
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;
|
|
150
150
|
const a = this.element.offsetHeight;
|
|
151
|
-
a >
|
|
152
|
-
}), this.activePanel && (this.activePanel.hidden = !1, this.activePanel.classList.add("active")), this.panels.forEach((
|
|
153
|
-
|
|
154
|
-
}),
|
|
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)`);
|
|
155
155
|
}
|
|
156
|
-
_cleanupPanels(
|
|
157
|
-
this.panels.forEach((
|
|
158
|
-
|
|
159
|
-
}), this.element.style.height = "", this.element.classList.remove("is-transitioning"), this.activePanel =
|
|
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;
|
|
160
160
|
}
|
|
161
|
-
_waitForTransition(
|
|
162
|
-
return new Promise((
|
|
163
|
-
const
|
|
164
|
-
if (
|
|
165
|
-
|
|
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();
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
|
-
const a = (
|
|
169
|
-
|
|
168
|
+
const a = (s) => {
|
|
169
|
+
s.target === t && (t.removeEventListener("transitionend", a), i());
|
|
170
170
|
};
|
|
171
|
-
|
|
171
|
+
t.addEventListener("transitionend", a);
|
|
172
172
|
});
|
|
173
173
|
}
|
|
174
|
-
_handleAutoFocus(
|
|
175
|
-
if (
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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}`));
|
|
184
188
|
}
|
|
185
189
|
// Shared helper for open/close
|
|
186
|
-
_animateOpenClose(
|
|
187
|
-
const
|
|
188
|
-
this._log(
|
|
189
|
-
const
|
|
190
|
-
this.element.classList.contains(
|
|
191
|
-
const l =
|
|
192
|
-
if (
|
|
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) {
|
|
193
197
|
this.element.classList.add(a);
|
|
194
|
-
const
|
|
195
|
-
this.element.style.height = `${
|
|
198
|
+
const r = this.element.offsetHeight;
|
|
199
|
+
this.element.style.height = `${r}px`, t && this.element.classList.remove("is-closed"), requestAnimationFrame(() => {
|
|
196
200
|
this.element.style.height = `${l}px`, this._waitForTransition(this.element).then(() => {
|
|
197
|
-
this._openCloseGeneration ===
|
|
201
|
+
this._openCloseGeneration === s && (this.element.style.height = "", this.element.classList.remove(a), t || this.element.classList.add("is-closed"));
|
|
198
202
|
});
|
|
199
203
|
});
|
|
200
204
|
} else
|
|
201
|
-
|
|
205
|
+
t ? this.element.classList.remove("is-closed") : this.element.classList.add("is-closed"), this.element.style.height = "";
|
|
202
206
|
}
|
|
203
207
|
/**
|
|
204
208
|
* Get the ID of the currently active panel
|
|
@@ -209,54 +213,71 @@ const d = class d {
|
|
|
209
213
|
}
|
|
210
214
|
/**
|
|
211
215
|
* Open a closable panelset
|
|
212
|
-
* @param
|
|
216
|
+
* @param options - Configuration options
|
|
213
217
|
*/
|
|
214
|
-
open(
|
|
218
|
+
open(t) {
|
|
219
|
+
const {
|
|
220
|
+
event: i,
|
|
221
|
+
transition: e = !0,
|
|
222
|
+
autoFocus: n
|
|
223
|
+
} = t || {};
|
|
215
224
|
if (!this.config.closable) {
|
|
216
225
|
this._log("Cannot open: closable is false");
|
|
217
226
|
return;
|
|
218
227
|
}
|
|
219
|
-
const
|
|
220
|
-
!
|
|
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));
|
|
221
235
|
}
|
|
222
236
|
/**
|
|
223
237
|
* Close a closable panelset
|
|
224
|
-
* @param
|
|
238
|
+
* @param options - Configuration options
|
|
225
239
|
*/
|
|
226
|
-
close(
|
|
240
|
+
close(t) {
|
|
241
|
+
const {
|
|
242
|
+
transition: i = !0
|
|
243
|
+
} = t || {};
|
|
227
244
|
if (!this.config.closable) {
|
|
228
245
|
this._log("Cannot close: closable is false");
|
|
229
246
|
return;
|
|
230
247
|
}
|
|
231
|
-
const
|
|
232
|
-
|
|
248
|
+
const e = this.element.classList.contains("is-closed"), n = this.element.classList.contains("is-opening");
|
|
249
|
+
e && !n || this._animateOpenClose(!1, i);
|
|
233
250
|
}
|
|
234
251
|
/**
|
|
235
252
|
* Toggle a closable panelset between open and closed
|
|
236
|
-
* @param
|
|
253
|
+
* @param options - Configuration options
|
|
237
254
|
*/
|
|
238
|
-
toggle(
|
|
239
|
-
const
|
|
240
|
-
|
|
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 });
|
|
241
262
|
}
|
|
242
263
|
/**
|
|
243
264
|
* Register a handler for async content loading
|
|
244
265
|
* @param handler - Async content handler function
|
|
245
266
|
* @param options - Handler options (once: whether to load only once)
|
|
246
267
|
*/
|
|
247
|
-
onBeforeActivate(
|
|
248
|
-
const
|
|
249
|
-
this.element.addEventListener("ps:beforeactivate", (
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
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") {
|
|
252
273
|
this.config.debug && this._log(`Skipping ${a.id} (already loaded)`);
|
|
253
274
|
return;
|
|
254
275
|
}
|
|
255
|
-
const l =
|
|
256
|
-
l && typeof l.then == "function" && (
|
|
257
|
-
|
|
258
|
-
}).catch((
|
|
259
|
-
throw
|
|
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);
|
|
260
281
|
}));
|
|
261
282
|
});
|
|
262
283
|
}
|
|
@@ -264,96 +285,100 @@ const d = class d {
|
|
|
264
285
|
/**
|
|
265
286
|
* Show a panel by ID
|
|
266
287
|
* @param panelId - ID of the panel to show
|
|
267
|
-
* @param
|
|
268
|
-
* @param options - Additional options (trigger name)
|
|
288
|
+
* @param options - Configuration options for this activation
|
|
269
289
|
*/
|
|
270
|
-
async show(
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
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}`);
|
|
274
299
|
return;
|
|
275
300
|
}
|
|
276
|
-
if (
|
|
277
|
-
const
|
|
278
|
-
this.pendingPanel =
|
|
279
|
-
const
|
|
280
|
-
this._currentAbortController && (this._currentAbortController.abort(),
|
|
281
|
-
panelId:
|
|
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,
|
|
282
307
|
trigger: null
|
|
283
308
|
}));
|
|
284
|
-
const
|
|
285
|
-
this._currentAbortController =
|
|
286
|
-
const
|
|
287
|
-
panelId:
|
|
288
|
-
targetPanel:
|
|
289
|
-
outgoingPanel:
|
|
290
|
-
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,
|
|
291
316
|
promise: null
|
|
292
|
-
},
|
|
293
|
-
detail:
|
|
317
|
+
}, C = new CustomEvent("ps:beforeactivate", {
|
|
318
|
+
detail: y,
|
|
294
319
|
bubbles: !0,
|
|
295
320
|
cancelable: !1
|
|
296
321
|
});
|
|
297
|
-
this.element.dispatchEvent(
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
322
|
+
this.element.dispatchEvent(C);
|
|
323
|
+
const P = y.promise;
|
|
324
|
+
if (P) {
|
|
300
325
|
this._isLoadingAsync = !0, this._log("Waiting for content...");
|
|
301
|
-
let
|
|
302
|
-
if (this.config.loadingDelay > 0 ?
|
|
326
|
+
let c, f = !1;
|
|
327
|
+
if (this.config.loadingDelay > 0 ? c = setTimeout(() => {
|
|
303
328
|
this.element.classList.add("is-loading"), f = !0;
|
|
304
|
-
}, this.config.loadingDelay) : (this.element.classList.add("is-loading"), f = !0), !(this.activePanel && this.activePanel !==
|
|
305
|
-
const h =
|
|
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;
|
|
306
331
|
let m = h;
|
|
307
332
|
if (typeof this.config.transitions == "object" && (m = h && this.config.transitions.height !== !1), m) {
|
|
308
|
-
const
|
|
309
|
-
this.element.style.height = `${
|
|
333
|
+
const w = this.element.offsetHeight;
|
|
334
|
+
this.element.style.height = `${w}px`, requestAnimationFrame(() => {
|
|
310
335
|
this.element.style.height = `${this.config.emptyPanelHeight}px`;
|
|
311
336
|
});
|
|
312
337
|
}
|
|
313
338
|
}
|
|
314
339
|
try {
|
|
315
|
-
if (await
|
|
316
|
-
this._log(`Aborted during load: ${
|
|
340
|
+
if (await P, c && clearTimeout(c), p.signal.aborted) {
|
|
341
|
+
this._log(`Aborted during load: ${t}`), f && this.element.classList.remove("is-loading");
|
|
317
342
|
return;
|
|
318
343
|
}
|
|
319
|
-
this._log("Content loaded"),
|
|
344
|
+
this._log("Content loaded"), s.dataset.loaded === "true" && this._updateHighestPanel();
|
|
320
345
|
} catch (h) {
|
|
321
|
-
|
|
346
|
+
c && clearTimeout(c);
|
|
322
347
|
const m = h;
|
|
323
348
|
this._log(`Load failed: ${m.message}`), f && this.element.classList.remove("is-loading"), m.name !== "AbortError" && console.error("Panel load error:", h);
|
|
324
349
|
return;
|
|
325
350
|
}
|
|
326
351
|
f && this.element.classList.remove("is-loading");
|
|
327
352
|
}
|
|
328
|
-
if (
|
|
329
|
-
this._log(`Aborted: ${
|
|
353
|
+
if (p.signal.aborted) {
|
|
354
|
+
this._log(`Aborted: ${t}`);
|
|
330
355
|
return;
|
|
331
356
|
}
|
|
332
357
|
this._dispatch("ps:activationstart", {
|
|
333
|
-
panelId:
|
|
334
|
-
trigger:
|
|
358
|
+
panelId: t,
|
|
359
|
+
trigger: o || null
|
|
335
360
|
});
|
|
336
|
-
const
|
|
337
|
-
let
|
|
338
|
-
typeof this.config.transitions == "object" && (
|
|
339
|
-
const
|
|
340
|
-
|
|
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));
|
|
364
|
+
const L = this.element.offsetHeight;
|
|
365
|
+
_ && (this.element.style.height = `${L}px`);
|
|
341
366
|
const g = this.activePanel;
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
const
|
|
345
|
-
|
|
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`);
|
|
346
371
|
const u = [];
|
|
347
|
-
|
|
348
|
-
if (this.pendingPanel !==
|
|
349
|
-
this._log(`Interrupted: ${
|
|
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}`);
|
|
350
375
|
return;
|
|
351
376
|
}
|
|
352
|
-
this._cleanupPanels(
|
|
353
|
-
const h =
|
|
354
|
-
h !== !1 && h !== void 0 && this._handleAutoFocus(
|
|
355
|
-
panelId:
|
|
356
|
-
trigger:
|
|
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
|
|
357
382
|
});
|
|
358
383
|
});
|
|
359
384
|
});
|
|
@@ -367,9 +392,9 @@ d.defaults = {
|
|
|
367
392
|
autoFocus: !0,
|
|
368
393
|
debug: !1
|
|
369
394
|
};
|
|
370
|
-
let
|
|
395
|
+
let A = d;
|
|
371
396
|
export {
|
|
372
|
-
|
|
373
|
-
|
|
397
|
+
A as PanelSet,
|
|
398
|
+
A as default
|
|
374
399
|
};
|
|
375
400
|
//# sourceMappingURL=panelset.js.map
|
package/dist/panelset.js.map
CHANGED
|
@@ -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\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\ttrigger?: string;\n\tautoFocus?: boolean | 'heading' | 'first' | ((panel: HTMLElement) => void); // Add this\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\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\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\tprivate _handleAutoFocus(panel: HTMLElement, autoFocus: boolean | 'heading' | 'first' | ((panel: HTMLElement) => void)): void {\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\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\t\n\t\t\t\t// Handle auto-focus\n\t\t\t\tconst autoFocus = options.autoFocus ?? this.config.autoFocus;\n\t\t\t\tif (autoFocus !== false && autoFocus !== undefined) {\n\t\t\t\t\tthis._handleAutoFocus(newPanel, autoFocus);\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: options.trigger || null\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\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","autoFocus","heading","focusable","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": "1.0.
|
|
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",
|