@magic-spells/collapsible-content 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -6
- package/dist/collapsible-content.cjs.js +190 -63
- package/dist/collapsible-content.cjs.js.map +1 -1
- package/dist/collapsible-content.css +1 -0
- package/dist/collapsible-content.esm.js +190 -64
- package/dist/collapsible-content.esm.js.map +1 -1
- package/dist/collapsible-content.js +190 -63
- package/dist/collapsible-content.js.map +1 -1
- package/dist/collapsible-content.min.css +1 -1
- package/dist/collapsible-content.min.js +1 -1
- package/package.json +1 -1
- package/src/collapsible-content.css +1 -0
- package/src/collapsible-content.js +190 -64
|
@@ -6,35 +6,34 @@
|
|
|
6
6
|
|
|
7
7
|
const DEFAULT_SPEED = 900; // px per second
|
|
8
8
|
const MIN_DURATION = 0.25; // seconds
|
|
9
|
-
const MAX_DURATION =
|
|
9
|
+
const MAX_DURATION = 0.8; // seconds
|
|
10
|
+
|
|
11
|
+
// hidden hook the content element uses to report a state change to its component
|
|
12
|
+
const NOTIFY = Symbol('collapsible:notify');
|
|
13
|
+
|
|
14
|
+
// named accordion groups — group attribute value -> Set of components
|
|
15
|
+
const namedGroups = new Map();
|
|
16
|
+
|
|
17
|
+
// <collapsible-group> element -> Set of components that joined it
|
|
18
|
+
const elementGroups = new WeakMap();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Optional ancestor element that links components without a shared group name.
|
|
22
|
+
* Add the `exclusive` attribute to make opening one item close the others.
|
|
23
|
+
*/
|
|
24
|
+
class CollapsibleGroup extends HTMLElement {}
|
|
10
25
|
|
|
11
26
|
/**
|
|
12
27
|
* Custom element that creates a collapsible/expandable component with proper accessibility
|
|
13
28
|
*/
|
|
14
29
|
class CollapsibleComponent extends HTMLElement {
|
|
15
|
-
static #groups = new Map();
|
|
16
|
-
|
|
17
|
-
static #addToGroup(name, instance) {
|
|
18
|
-
if (!CollapsibleComponent.#groups.has(name)) {
|
|
19
|
-
CollapsibleComponent.#groups.set(name, new Set());
|
|
20
|
-
}
|
|
21
|
-
CollapsibleComponent.#groups.get(name).add(instance);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static #removeFromGroup(name, instance) {
|
|
25
|
-
const group = CollapsibleComponent.#groups.get(name);
|
|
26
|
-
if (group) {
|
|
27
|
-
group.delete(instance);
|
|
28
|
-
if (group.size === 0) CollapsibleComponent.#groups.delete(name);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
30
|
static get observedAttributes() {
|
|
33
31
|
return ['group'];
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
#handleClick;
|
|
37
35
|
#abortController;
|
|
36
|
+
#groupElement = null;
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* Initializes the component and sets up references to child elements
|
|
@@ -49,10 +48,7 @@
|
|
|
49
48
|
|
|
50
49
|
// define click handler — content is source of truth
|
|
51
50
|
_.#handleClick = () => {
|
|
52
|
-
|
|
53
|
-
_.content.collapsed = !wasCollapsed;
|
|
54
|
-
_.button.setAttribute('aria-expanded', !_.content.collapsed);
|
|
55
|
-
if (wasCollapsed) _.#closeSiblings();
|
|
51
|
+
_.content.collapsed = !_.content.collapsed;
|
|
56
52
|
};
|
|
57
53
|
}
|
|
58
54
|
|
|
@@ -63,6 +59,13 @@
|
|
|
63
59
|
connectedCallback() {
|
|
64
60
|
const _ = this;
|
|
65
61
|
|
|
62
|
+
// (re)join a group on every connect — a DOM move runs disconnect then connect,
|
|
63
|
+
// and attributeChangedCallback only fires on a real attribute change.
|
|
64
|
+
// Both registries are Sets, so re-adding on first connect is a no-op.
|
|
65
|
+
const name = _.#groupName;
|
|
66
|
+
if (name) _.#addToNamedGroup(name);
|
|
67
|
+
else _.#joinGroupElement();
|
|
68
|
+
|
|
66
69
|
// initialize element references once
|
|
67
70
|
_.button = _.querySelector('button');
|
|
68
71
|
_.content = _.querySelector('collapsible-content');
|
|
@@ -116,8 +119,16 @@
|
|
|
116
119
|
|
|
117
120
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
118
121
|
if (name !== 'group') return;
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
const _ = this;
|
|
123
|
+
|
|
124
|
+
// an empty group="" counts as no name
|
|
125
|
+
if (oldValue) _.#removeFromNamedGroup(oldValue);
|
|
126
|
+
if (newValue) _.#addToNamedGroup(newValue);
|
|
127
|
+
|
|
128
|
+
// an explicit group name wins over any ancestor <collapsible-group>
|
|
129
|
+
if (!_.isConnected) return;
|
|
130
|
+
if (newValue) _.#leaveGroupElement();
|
|
131
|
+
else _.#joinGroupElement();
|
|
121
132
|
}
|
|
122
133
|
|
|
123
134
|
/**
|
|
@@ -126,26 +137,108 @@
|
|
|
126
137
|
*/
|
|
127
138
|
disconnectedCallback() {
|
|
128
139
|
const _ = this;
|
|
129
|
-
const
|
|
130
|
-
if (
|
|
140
|
+
const name = _.#groupName;
|
|
141
|
+
if (name) _.#removeFromNamedGroup(name);
|
|
142
|
+
_.#leaveGroupElement();
|
|
131
143
|
if (_.#abortController) {
|
|
132
144
|
_.#abortController.abort();
|
|
133
145
|
_.#abortController = null;
|
|
134
146
|
}
|
|
135
147
|
}
|
|
136
148
|
|
|
137
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Whether the panel is currently expanded
|
|
151
|
+
* @returns {boolean}
|
|
152
|
+
*/
|
|
153
|
+
get open() {
|
|
154
|
+
return !!this.content && !this.content.collapsed;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
set open(value) {
|
|
158
|
+
if (this.content) this.content.collapsed = !value;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Expands the panel (no-op if already expanded) */
|
|
162
|
+
show() {
|
|
163
|
+
this.open = true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Collapses the panel (no-op if already collapsed) */
|
|
167
|
+
hide() {
|
|
168
|
+
this.open = false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Toggles the panel */
|
|
172
|
+
toggle() {
|
|
173
|
+
this.open = !this.open;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Reports a state change coming from the content element
|
|
178
|
+
* @param {CollapsibleContent} content - the content element that changed
|
|
179
|
+
* @param {boolean} open - the new expanded state
|
|
180
|
+
*/
|
|
181
|
+
[NOTIFY](content, open) {
|
|
138
182
|
const _ = this;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
183
|
+
if (_.content !== content) return;
|
|
184
|
+
|
|
185
|
+
if (_.button) _.button.setAttribute('aria-expanded', String(open));
|
|
186
|
+
if (open) _.#closeSiblings();
|
|
187
|
+
|
|
188
|
+
_.dispatchEvent(
|
|
189
|
+
new CustomEvent('collapsible:toggle', {
|
|
190
|
+
bubbles: true,
|
|
191
|
+
composed: true,
|
|
192
|
+
detail: { open, content },
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Group name, with an empty group="" normalized to null */
|
|
198
|
+
get #groupName() {
|
|
199
|
+
return this.getAttribute('group') || null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
#addToNamedGroup(name) {
|
|
203
|
+
if (!namedGroups.has(name)) namedGroups.set(name, new Set());
|
|
204
|
+
namedGroups.get(name).add(this);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
#removeFromNamedGroup(name) {
|
|
208
|
+
const group = namedGroups.get(name);
|
|
142
209
|
if (!group) return;
|
|
143
|
-
|
|
210
|
+
group.delete(this);
|
|
211
|
+
if (group.size === 0) namedGroups.delete(name);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#joinGroupElement() {
|
|
215
|
+
const _ = this;
|
|
216
|
+
const element = _.closest('collapsible-group');
|
|
217
|
+
if (!element) return;
|
|
218
|
+
if (!elementGroups.has(element)) elementGroups.set(element, new Set());
|
|
219
|
+
elementGroups.get(element).add(_);
|
|
220
|
+
_.#groupElement = element;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#leaveGroupElement() {
|
|
224
|
+
const _ = this;
|
|
225
|
+
if (!_.#groupElement) return;
|
|
226
|
+
elementGroups.get(_.#groupElement)?.delete(_);
|
|
227
|
+
_.#groupElement = null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#closeSiblings() {
|
|
231
|
+
const _ = this;
|
|
232
|
+
const name = _.#groupName;
|
|
233
|
+
let siblings = null;
|
|
234
|
+
if (name) siblings = namedGroups.get(name);
|
|
235
|
+
else if (_.#groupElement?.hasAttribute('exclusive'))
|
|
236
|
+
siblings = elementGroups.get(_.#groupElement);
|
|
237
|
+
if (!siblings) return;
|
|
238
|
+
|
|
239
|
+
for (const sibling of siblings) {
|
|
144
240
|
if (sibling === _) continue;
|
|
145
|
-
if (!sibling.content.collapsed)
|
|
146
|
-
sibling.content.collapsed = true;
|
|
147
|
-
sibling.button.setAttribute('aria-expanded', 'false');
|
|
148
|
-
}
|
|
241
|
+
if (sibling.content && !sibling.content.collapsed) sibling.content.collapsed = true;
|
|
149
242
|
}
|
|
150
243
|
}
|
|
151
244
|
}
|
|
@@ -154,9 +247,14 @@
|
|
|
154
247
|
* Custom element that provides animated collapsible content
|
|
155
248
|
*/
|
|
156
249
|
class CollapsibleContent extends HTMLElement {
|
|
250
|
+
static get observedAttributes() {
|
|
251
|
+
return ['open'];
|
|
252
|
+
}
|
|
253
|
+
|
|
157
254
|
#handleTransitionEnd;
|
|
158
255
|
#abortController;
|
|
159
|
-
#
|
|
256
|
+
#ready = false;
|
|
257
|
+
#selfWrite = false;
|
|
160
258
|
|
|
161
259
|
/**
|
|
162
260
|
* Initializes the content element and binds event handlers
|
|
@@ -170,7 +268,6 @@
|
|
|
170
268
|
if (event.target !== _) return;
|
|
171
269
|
if (event.propertyName !== 'height') return;
|
|
172
270
|
|
|
173
|
-
_.#animating = false;
|
|
174
271
|
_.style.removeProperty('--collapsible-duration');
|
|
175
272
|
|
|
176
273
|
// remove the inline height to allow dynamic content changes
|
|
@@ -193,6 +290,9 @@
|
|
|
193
290
|
_.addEventListener('transitionend', _.#handleTransitionEnd, {
|
|
194
291
|
signal: _.#abortController.signal,
|
|
195
292
|
});
|
|
293
|
+
|
|
294
|
+
// from here on, an external `open` attribute change animates
|
|
295
|
+
_.#ready = true;
|
|
196
296
|
}
|
|
197
297
|
|
|
198
298
|
/**
|
|
@@ -201,13 +301,24 @@
|
|
|
201
301
|
*/
|
|
202
302
|
disconnectedCallback() {
|
|
203
303
|
const _ = this;
|
|
204
|
-
_.#
|
|
304
|
+
_.#ready = false;
|
|
205
305
|
if (_.#abortController) {
|
|
206
306
|
_.#abortController.abort();
|
|
207
307
|
_.#abortController = null;
|
|
208
308
|
}
|
|
209
309
|
}
|
|
210
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Runs the transition when `open` is added or removed from outside
|
|
313
|
+
*/
|
|
314
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
315
|
+
const _ = this;
|
|
316
|
+
if (name !== 'open' || _.#selfWrite || !_.#ready) return;
|
|
317
|
+
// only presence matters — ignore value-only changes (open -> open="x")
|
|
318
|
+
if ((oldValue === null) === (newValue === null)) return;
|
|
319
|
+
_.#transition(newValue === null);
|
|
320
|
+
}
|
|
321
|
+
|
|
211
322
|
get #speed() {
|
|
212
323
|
const attr = this.getAttribute('speed');
|
|
213
324
|
if (attr === null) return DEFAULT_SPEED;
|
|
@@ -237,52 +348,64 @@
|
|
|
237
348
|
}
|
|
238
349
|
|
|
239
350
|
/**
|
|
240
|
-
*
|
|
241
|
-
* @param {boolean}
|
|
351
|
+
* Animates to the requested state, then reports the change
|
|
352
|
+
* @param {boolean} collapsed - target state (the `open` attribute already matches)
|
|
242
353
|
*/
|
|
243
|
-
|
|
354
|
+
#transition(collapsed) {
|
|
244
355
|
const _ = this;
|
|
245
|
-
const collapsed = Boolean(value);
|
|
246
|
-
if (_.collapsed === collapsed) return;
|
|
247
356
|
|
|
248
357
|
// check if transitions are enabled (respects prefers-reduced-motion)
|
|
249
358
|
const hasTransition = getComputedStyle(_).transitionDuration !== '0s';
|
|
250
359
|
|
|
251
360
|
if (collapsed) {
|
|
252
|
-
_.removeAttribute('open');
|
|
253
361
|
_.setAttribute('aria-hidden', 'true');
|
|
254
362
|
_.setAttribute('inert', '');
|
|
255
363
|
|
|
256
364
|
if (!hasTransition) {
|
|
257
365
|
_.style.height = '0px';
|
|
258
|
-
|
|
366
|
+
} else {
|
|
367
|
+
// capture current height in px (converts auto or mid-animation value)
|
|
368
|
+
const currentHeight = _.getBoundingClientRect().height;
|
|
369
|
+
_.style.height = `${currentHeight}px`;
|
|
370
|
+
_.#setDynamicDuration(currentHeight, 0);
|
|
371
|
+
_.offsetHeight; // force reflow — browser commits the px start value
|
|
372
|
+
_.style.height = '0px';
|
|
259
373
|
}
|
|
260
|
-
|
|
261
|
-
// capture current height in px (converts auto or mid-animation value)
|
|
262
|
-
const currentHeight = _.getBoundingClientRect().height;
|
|
263
|
-
_.style.height = `${currentHeight}px`;
|
|
264
|
-
_.#setDynamicDuration(currentHeight, 0);
|
|
265
|
-
_.#animating = true;
|
|
266
|
-
_.offsetHeight; // force reflow — browser commits the px start value
|
|
267
|
-
_.style.height = '0px';
|
|
268
374
|
} else {
|
|
269
|
-
_.setAttribute('open', '');
|
|
270
375
|
_.removeAttribute('aria-hidden');
|
|
271
376
|
_.removeAttribute('inert');
|
|
272
377
|
|
|
273
378
|
if (!hasTransition) {
|
|
274
379
|
_.style.height = 'auto';
|
|
275
|
-
|
|
380
|
+
} else {
|
|
381
|
+
// capture current height in px (0px or mid-animation value)
|
|
382
|
+
const currentHeight = _.getBoundingClientRect().height;
|
|
383
|
+
_.style.height = `${currentHeight}px`;
|
|
384
|
+
_.#setDynamicDuration(currentHeight, _.scrollHeight);
|
|
385
|
+
_.offsetHeight; // force reflow — browser commits the px start value
|
|
386
|
+
_.style.height = `${_.scrollHeight}px`;
|
|
276
387
|
}
|
|
277
|
-
|
|
278
|
-
// capture current height in px (0px or mid-animation value)
|
|
279
|
-
const currentHeight = _.getBoundingClientRect().height;
|
|
280
|
-
_.style.height = `${currentHeight}px`;
|
|
281
|
-
_.#setDynamicDuration(currentHeight, _.scrollHeight);
|
|
282
|
-
_.#animating = true;
|
|
283
|
-
_.offsetHeight; // force reflow — browser commits the px start value
|
|
284
|
-
_.style.height = `${_.scrollHeight}px`;
|
|
285
388
|
}
|
|
389
|
+
|
|
390
|
+
_.closest('collapsible-component')?.[NOTIFY]?.(_, !collapsed);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Handles setting the collapsed state with animation
|
|
395
|
+
* @param {boolean} value - Whether element should be collapsed
|
|
396
|
+
*/
|
|
397
|
+
set collapsed(value) {
|
|
398
|
+
const _ = this;
|
|
399
|
+
const collapsed = Boolean(value);
|
|
400
|
+
if (_.collapsed === collapsed) return;
|
|
401
|
+
|
|
402
|
+
// mirror to the attribute without re-entering attributeChangedCallback
|
|
403
|
+
_.#selfWrite = true;
|
|
404
|
+
if (collapsed) _.removeAttribute('open');
|
|
405
|
+
else _.setAttribute('open', '');
|
|
406
|
+
_.#selfWrite = false;
|
|
407
|
+
|
|
408
|
+
_.#transition(collapsed);
|
|
286
409
|
}
|
|
287
410
|
|
|
288
411
|
/**
|
|
@@ -301,9 +424,13 @@
|
|
|
301
424
|
if (!customElements.get('collapsible-component')) {
|
|
302
425
|
customElements.define('collapsible-component', CollapsibleComponent);
|
|
303
426
|
}
|
|
427
|
+
if (!customElements.get('collapsible-group')) {
|
|
428
|
+
customElements.define('collapsible-group', CollapsibleGroup);
|
|
429
|
+
}
|
|
304
430
|
|
|
305
431
|
exports.CollapsibleComponent = CollapsibleComponent;
|
|
306
432
|
exports.CollapsibleContent = CollapsibleContent;
|
|
433
|
+
exports.CollapsibleGroup = CollapsibleGroup;
|
|
307
434
|
|
|
308
435
|
}));
|
|
309
436
|
//# sourceMappingURL=collapsible-content.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapsible-content.js","sources":["../src/collapsible-content.js"],"sourcesContent":["import './collapsible-content.css';\n\nconst DEFAULT_SPEED = 900; // px per second\nconst MIN_DURATION = 0.25; // seconds\nconst MAX_DURATION = 1.0; // seconds\n\n/**\n * Custom element that creates a collapsible/expandable component with proper accessibility\n */\nclass CollapsibleComponent extends HTMLElement {\n\tstatic #groups = new Map();\n\n\tstatic #addToGroup(name, instance) {\n\t\tif (!CollapsibleComponent.#groups.has(name)) {\n\t\t\tCollapsibleComponent.#groups.set(name, new Set());\n\t\t}\n\t\tCollapsibleComponent.#groups.get(name).add(instance);\n\t}\n\n\tstatic #removeFromGroup(name, instance) {\n\t\tconst group = CollapsibleComponent.#groups.get(name);\n\t\tif (group) {\n\t\t\tgroup.delete(instance);\n\t\t\tif (group.size === 0) CollapsibleComponent.#groups.delete(name);\n\t\t}\n\t}\n\n\tstatic get observedAttributes() {\n\t\treturn ['group'];\n\t}\n\n\t#handleClick;\n\t#abortController;\n\n\t/**\n\t * Initializes the component and sets up references to child elements\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// store references to elements once to avoid re-querying\n\t\t_.button = null;\n\t\t_.content = null;\n\n\t\t// define click handler — content is source of truth\n\t\t_.#handleClick = () => {\n\t\t\tconst wasCollapsed = _.content.collapsed;\n\t\t\t_.content.collapsed = !wasCollapsed;\n\t\t\t_.button.setAttribute('aria-expanded', !_.content.collapsed);\n\t\t\tif (wasCollapsed) _.#closeSiblings();\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets up accessibility attributes and event listeners\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// initialize element references once\n\t\t_.button = _.querySelector('button');\n\t\t_.content = _.querySelector('collapsible-content');\n\n\t\tif (!_.button || !_.content) {\n\t\t\tconst error = new Error(\n\t\t\t\t'CollapsibleComponent requires a <button> and a <collapsible-content>.'\n\t\t\t);\n\t\t\tconsole.error(error.message);\n\t\t\t_.dispatchEvent(\n\t\t\t\tnew CustomEvent('collapsible-error', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tdetail: { error },\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// generate ids if not provided\n\t\t_.button.id ||= `collapsible-button-${crypto.randomUUID().slice(0, 8)}`;\n\t\t_.content.id ||= `collapsible-content-${crypto.randomUUID().slice(0, 8)}`;\n\n\t\t// set accessibility attributes\n\t\tif (!_.button.hasAttribute('type')) {\n\t\t\t_.button.type = 'button';\n\t\t}\n\t\t_.button.setAttribute('aria-controls', _.content.id);\n\t\t_.content.setAttribute('aria-labelledby', _.button.id);\n\t\tif (!_.content.hasAttribute('role')) {\n\t\t\t_.content.setAttribute('role', 'region');\n\t\t}\n\n\t\t// set initial state without triggering an opening/closing animation\n\t\tconst open = _.content.hasAttribute('open');\n\t\t_.button.setAttribute('aria-expanded', open);\n\t\t_.content.style.height = open ? 'auto' : '0px';\n\t\tif (open) {\n\t\t\t_.content.removeAttribute('aria-hidden');\n\t\t\t_.content.removeAttribute('inert');\n\t\t} else {\n\t\t\t_.content.setAttribute('aria-hidden', 'true');\n\t\t\t_.content.setAttribute('inert', '');\n\t\t}\n\n\t\t// use AbortController to prevent duplicate listeners on reconnection\n\t\t_.#abortController = new AbortController();\n\t\t_.button.addEventListener('click', _.#handleClick, {\n\t\t\tsignal: _.#abortController.signal,\n\t\t});\n\t}\n\n\tattributeChangedCallback(name, oldValue, newValue) {\n\t\tif (name !== 'group') return;\n\t\tif (oldValue) CollapsibleComponent.#removeFromGroup(oldValue, this);\n\t\tif (newValue) CollapsibleComponent.#addToGroup(newValue, this);\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tconst group = _.getAttribute('group');\n\t\tif (group) CollapsibleComponent.#removeFromGroup(group, _);\n\t\tif (_.#abortController) {\n\t\t\t_.#abortController.abort();\n\t\t\t_.#abortController = null;\n\t\t}\n\t}\n\n\t#closeSiblings() {\n\t\tconst _ = this;\n\t\tconst groupName = _.getAttribute('group');\n\t\tif (!groupName) return;\n\t\tconst group = CollapsibleComponent.#groups.get(groupName);\n\t\tif (!group) return;\n\t\tfor (const sibling of group) {\n\t\t\tif (sibling === _) continue;\n\t\t\tif (!sibling.content.collapsed) {\n\t\t\t\tsibling.content.collapsed = true;\n\t\t\t\tsibling.button.setAttribute('aria-expanded', 'false');\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Custom element that provides animated collapsible content\n */\nclass CollapsibleContent extends HTMLElement {\n\t#handleTransitionEnd;\n\t#abortController;\n\t#animating = false;\n\n\t/**\n\t * Initializes the content element and binds event handlers\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// define event handler using arrow function for proper binding\n\t\t_.#handleTransitionEnd = (event) => {\n\t\t\tif (event.target !== _) return;\n\t\t\tif (event.propertyName !== 'height') return;\n\n\t\t\t_.#animating = false;\n\t\t\t_.style.removeProperty('--collapsible-duration');\n\n\t\t\t// remove the inline height to allow dynamic content changes\n\t\t\tif (!_.collapsed) {\n\t\t\t\t_.style.height = 'auto';\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets initial height based on open attribute\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\t\t_.style.height = _.hasAttribute('open') ? 'auto' : '0';\n\n\t\t// use AbortController to prevent duplicate listeners on reconnection\n\t\t_.#abortController = new AbortController();\n\t\t_.addEventListener('transitionend', _.#handleTransitionEnd, {\n\t\t\tsignal: _.#abortController.signal,\n\t\t});\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\t_.#animating = false;\n\t\tif (_.#abortController) {\n\t\t\t_.#abortController.abort();\n\t\t\t_.#abortController = null;\n\t\t}\n\t}\n\n\tget #speed() {\n\t\tconst attr = this.getAttribute('speed');\n\t\tif (attr === null) return DEFAULT_SPEED;\n\t\tconst value = Number(attr);\n\t\treturn value > 0 ? value : DEFAULT_SPEED;\n\t}\n\n\tget #minDuration() {\n\t\tconst attr = this.getAttribute('min-duration');\n\t\tif (attr === null) return MIN_DURATION;\n\t\tconst value = Number(attr);\n\t\treturn value > 0 ? value : MIN_DURATION;\n\t}\n\n\tget #maxDuration() {\n\t\tconst attr = this.getAttribute('max-duration');\n\t\tif (attr === null) return MAX_DURATION;\n\t\tconst value = Number(attr);\n\t\treturn value > 0 ? value : MAX_DURATION;\n\t}\n\n\t#setDynamicDuration(currentHeight, targetHeight) {\n\t\tconst _ = this;\n\t\tconst delta = Math.abs(targetHeight - currentHeight);\n\t\tconst duration = Math.min(_.#maxDuration, Math.max(_.#minDuration, delta / _.#speed));\n\t\t_.style.setProperty('--collapsible-duration', `${duration.toFixed(3)}s`);\n\t}\n\n\t/**\n\t * Handles setting the collapsed state with animation\n\t * @param {boolean} value - Whether element should be collapsed\n\t */\n\tset collapsed(value) {\n\t\tconst _ = this;\n\t\tconst collapsed = Boolean(value);\n\t\tif (_.collapsed === collapsed) return;\n\n\t\t// check if transitions are enabled (respects prefers-reduced-motion)\n\t\tconst hasTransition = getComputedStyle(_).transitionDuration !== '0s';\n\n\t\tif (collapsed) {\n\t\t\t_.removeAttribute('open');\n\t\t\t_.setAttribute('aria-hidden', 'true');\n\t\t\t_.setAttribute('inert', '');\n\n\t\t\tif (!hasTransition) {\n\t\t\t\t_.style.height = '0px';\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// capture current height in px (converts auto or mid-animation value)\n\t\t\tconst currentHeight = _.getBoundingClientRect().height;\n\t\t\t_.style.height = `${currentHeight}px`;\n\t\t\t_.#setDynamicDuration(currentHeight, 0);\n\t\t\t_.#animating = true;\n\t\t\t_.offsetHeight; // force reflow — browser commits the px start value\n\t\t\t_.style.height = '0px';\n\t\t} else {\n\t\t\t_.setAttribute('open', '');\n\t\t\t_.removeAttribute('aria-hidden');\n\t\t\t_.removeAttribute('inert');\n\n\t\t\tif (!hasTransition) {\n\t\t\t\t_.style.height = 'auto';\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// capture current height in px (0px or mid-animation value)\n\t\t\tconst currentHeight = _.getBoundingClientRect().height;\n\t\t\t_.style.height = `${currentHeight}px`;\n\t\t\t_.#setDynamicDuration(currentHeight, _.scrollHeight);\n\t\t\t_.#animating = true;\n\t\t\t_.offsetHeight; // force reflow — browser commits the px start value\n\t\t\t_.style.height = `${_.scrollHeight}px`;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the collapsed state\n\t * @returns {boolean} Whether element is collapsed\n\t */\n\tget collapsed() {\n\t\treturn !this.hasAttribute('open');\n\t}\n}\n\n// register custom elements if not already defined\nif (!customElements.get('collapsible-content')) {\n\tcustomElements.define('collapsible-content', CollapsibleContent);\n}\nif (!customElements.get('collapsible-component')) {\n\tcustomElements.define('collapsible-component', CollapsibleComponent);\n}\n\nexport { CollapsibleContent, CollapsibleComponent };\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"collapsible-content.js","sources":["../src/collapsible-content.js"],"sourcesContent":["import './collapsible-content.css';\n\nconst DEFAULT_SPEED = 900; // px per second\nconst MIN_DURATION = 0.25; // seconds\nconst MAX_DURATION = 0.8; // seconds\n\n// hidden hook the content element uses to report a state change to its component\nconst NOTIFY = Symbol('collapsible:notify');\n\n// named accordion groups — group attribute value -> Set of components\nconst namedGroups = new Map();\n\n// <collapsible-group> element -> Set of components that joined it\nconst elementGroups = new WeakMap();\n\n/**\n * Optional ancestor element that links components without a shared group name.\n * Add the `exclusive` attribute to make opening one item close the others.\n */\nclass CollapsibleGroup extends HTMLElement {}\n\n/**\n * Custom element that creates a collapsible/expandable component with proper accessibility\n */\nclass CollapsibleComponent extends HTMLElement {\n\tstatic get observedAttributes() {\n\t\treturn ['group'];\n\t}\n\n\t#handleClick;\n\t#abortController;\n\t#groupElement = null;\n\n\t/**\n\t * Initializes the component and sets up references to child elements\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// store references to elements once to avoid re-querying\n\t\t_.button = null;\n\t\t_.content = null;\n\n\t\t// define click handler — content is source of truth\n\t\t_.#handleClick = () => {\n\t\t\t_.content.collapsed = !_.content.collapsed;\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets up accessibility attributes and event listeners\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// (re)join a group on every connect — a DOM move runs disconnect then connect,\n\t\t// and attributeChangedCallback only fires on a real attribute change.\n\t\t// Both registries are Sets, so re-adding on first connect is a no-op.\n\t\tconst name = _.#groupName;\n\t\tif (name) _.#addToNamedGroup(name);\n\t\telse _.#joinGroupElement();\n\n\t\t// initialize element references once\n\t\t_.button = _.querySelector('button');\n\t\t_.content = _.querySelector('collapsible-content');\n\n\t\tif (!_.button || !_.content) {\n\t\t\tconst error = new Error(\n\t\t\t\t'CollapsibleComponent requires a <button> and a <collapsible-content>.'\n\t\t\t);\n\t\t\tconsole.error(error.message);\n\t\t\t_.dispatchEvent(\n\t\t\t\tnew CustomEvent('collapsible-error', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tdetail: { error },\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// generate ids if not provided\n\t\t_.button.id ||= `collapsible-button-${crypto.randomUUID().slice(0, 8)}`;\n\t\t_.content.id ||= `collapsible-content-${crypto.randomUUID().slice(0, 8)}`;\n\n\t\t// set accessibility attributes\n\t\tif (!_.button.hasAttribute('type')) {\n\t\t\t_.button.type = 'button';\n\t\t}\n\t\t_.button.setAttribute('aria-controls', _.content.id);\n\t\t_.content.setAttribute('aria-labelledby', _.button.id);\n\t\tif (!_.content.hasAttribute('role')) {\n\t\t\t_.content.setAttribute('role', 'region');\n\t\t}\n\n\t\t// set initial state without triggering an opening/closing animation\n\t\tconst open = _.content.hasAttribute('open');\n\t\t_.button.setAttribute('aria-expanded', open);\n\t\t_.content.style.height = open ? 'auto' : '0px';\n\t\tif (open) {\n\t\t\t_.content.removeAttribute('aria-hidden');\n\t\t\t_.content.removeAttribute('inert');\n\t\t} else {\n\t\t\t_.content.setAttribute('aria-hidden', 'true');\n\t\t\t_.content.setAttribute('inert', '');\n\t\t}\n\n\t\t// use AbortController to prevent duplicate listeners on reconnection\n\t\t_.#abortController = new AbortController();\n\t\t_.button.addEventListener('click', _.#handleClick, {\n\t\t\tsignal: _.#abortController.signal,\n\t\t});\n\t}\n\n\tattributeChangedCallback(name, oldValue, newValue) {\n\t\tif (name !== 'group') return;\n\t\tconst _ = this;\n\n\t\t// an empty group=\"\" counts as no name\n\t\tif (oldValue) _.#removeFromNamedGroup(oldValue);\n\t\tif (newValue) _.#addToNamedGroup(newValue);\n\n\t\t// an explicit group name wins over any ancestor <collapsible-group>\n\t\tif (!_.isConnected) return;\n\t\tif (newValue) _.#leaveGroupElement();\n\t\telse _.#joinGroupElement();\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tconst name = _.#groupName;\n\t\tif (name) _.#removeFromNamedGroup(name);\n\t\t_.#leaveGroupElement();\n\t\tif (_.#abortController) {\n\t\t\t_.#abortController.abort();\n\t\t\t_.#abortController = null;\n\t\t}\n\t}\n\n\t/**\n\t * Whether the panel is currently expanded\n\t * @returns {boolean}\n\t */\n\tget open() {\n\t\treturn !!this.content && !this.content.collapsed;\n\t}\n\n\tset open(value) {\n\t\tif (this.content) this.content.collapsed = !value;\n\t}\n\n\t/** Expands the panel (no-op if already expanded) */\n\tshow() {\n\t\tthis.open = true;\n\t}\n\n\t/** Collapses the panel (no-op if already collapsed) */\n\thide() {\n\t\tthis.open = false;\n\t}\n\n\t/** Toggles the panel */\n\ttoggle() {\n\t\tthis.open = !this.open;\n\t}\n\n\t/**\n\t * Reports a state change coming from the content element\n\t * @param {CollapsibleContent} content - the content element that changed\n\t * @param {boolean} open - the new expanded state\n\t */\n\t[NOTIFY](content, open) {\n\t\tconst _ = this;\n\t\tif (_.content !== content) return;\n\n\t\tif (_.button) _.button.setAttribute('aria-expanded', String(open));\n\t\tif (open) _.#closeSiblings();\n\n\t\t_.dispatchEvent(\n\t\t\tnew CustomEvent('collapsible:toggle', {\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t\tdetail: { open, content },\n\t\t\t})\n\t\t);\n\t}\n\n\t/** Group name, with an empty group=\"\" normalized to null */\n\tget #groupName() {\n\t\treturn this.getAttribute('group') || null;\n\t}\n\n\t#addToNamedGroup(name) {\n\t\tif (!namedGroups.has(name)) namedGroups.set(name, new Set());\n\t\tnamedGroups.get(name).add(this);\n\t}\n\n\t#removeFromNamedGroup(name) {\n\t\tconst group = namedGroups.get(name);\n\t\tif (!group) return;\n\t\tgroup.delete(this);\n\t\tif (group.size === 0) namedGroups.delete(name);\n\t}\n\n\t#joinGroupElement() {\n\t\tconst _ = this;\n\t\tconst element = _.closest('collapsible-group');\n\t\tif (!element) return;\n\t\tif (!elementGroups.has(element)) elementGroups.set(element, new Set());\n\t\telementGroups.get(element).add(_);\n\t\t_.#groupElement = element;\n\t}\n\n\t#leaveGroupElement() {\n\t\tconst _ = this;\n\t\tif (!_.#groupElement) return;\n\t\telementGroups.get(_.#groupElement)?.delete(_);\n\t\t_.#groupElement = null;\n\t}\n\n\t#closeSiblings() {\n\t\tconst _ = this;\n\t\tconst name = _.#groupName;\n\t\tlet siblings = null;\n\t\tif (name) siblings = namedGroups.get(name);\n\t\telse if (_.#groupElement?.hasAttribute('exclusive'))\n\t\t\tsiblings = elementGroups.get(_.#groupElement);\n\t\tif (!siblings) return;\n\n\t\tfor (const sibling of siblings) {\n\t\t\tif (sibling === _) continue;\n\t\t\tif (sibling.content && !sibling.content.collapsed) sibling.content.collapsed = true;\n\t\t}\n\t}\n}\n\n/**\n * Custom element that provides animated collapsible content\n */\nclass CollapsibleContent extends HTMLElement {\n\tstatic get observedAttributes() {\n\t\treturn ['open'];\n\t}\n\n\t#handleTransitionEnd;\n\t#abortController;\n\t#ready = false;\n\t#selfWrite = false;\n\n\t/**\n\t * Initializes the content element and binds event handlers\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\n\t\t// define event handler using arrow function for proper binding\n\t\t_.#handleTransitionEnd = (event) => {\n\t\t\tif (event.target !== _) return;\n\t\t\tif (event.propertyName !== 'height') return;\n\n\t\t\t_.style.removeProperty('--collapsible-duration');\n\n\t\t\t// remove the inline height to allow dynamic content changes\n\t\t\tif (!_.collapsed) {\n\t\t\t\t_.style.height = 'auto';\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Called when element is added to the DOM\n\t * Sets initial height based on open attribute\n\t */\n\tconnectedCallback() {\n\t\tconst _ = this;\n\t\t_.style.height = _.hasAttribute('open') ? 'auto' : '0';\n\n\t\t// use AbortController to prevent duplicate listeners on reconnection\n\t\t_.#abortController = new AbortController();\n\t\t_.addEventListener('transitionend', _.#handleTransitionEnd, {\n\t\t\tsignal: _.#abortController.signal,\n\t\t});\n\n\t\t// from here on, an external `open` attribute change animates\n\t\t_.#ready = true;\n\t}\n\n\t/**\n\t * Called when element is removed from the DOM\n\t * Cleans up event listeners\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\t_.#ready = false;\n\t\tif (_.#abortController) {\n\t\t\t_.#abortController.abort();\n\t\t\t_.#abortController = null;\n\t\t}\n\t}\n\n\t/**\n\t * Runs the transition when `open` is added or removed from outside\n\t */\n\tattributeChangedCallback(name, oldValue, newValue) {\n\t\tconst _ = this;\n\t\tif (name !== 'open' || _.#selfWrite || !_.#ready) return;\n\t\t// only presence matters — ignore value-only changes (open -> open=\"x\")\n\t\tif ((oldValue === null) === (newValue === null)) return;\n\t\t_.#transition(newValue === null);\n\t}\n\n\tget #speed() {\n\t\tconst attr = this.getAttribute('speed');\n\t\tif (attr === null) return DEFAULT_SPEED;\n\t\tconst value = Number(attr);\n\t\treturn value > 0 ? value : DEFAULT_SPEED;\n\t}\n\n\tget #minDuration() {\n\t\tconst attr = this.getAttribute('min-duration');\n\t\tif (attr === null) return MIN_DURATION;\n\t\tconst value = Number(attr);\n\t\treturn value > 0 ? value : MIN_DURATION;\n\t}\n\n\tget #maxDuration() {\n\t\tconst attr = this.getAttribute('max-duration');\n\t\tif (attr === null) return MAX_DURATION;\n\t\tconst value = Number(attr);\n\t\treturn value > 0 ? value : MAX_DURATION;\n\t}\n\n\t#setDynamicDuration(currentHeight, targetHeight) {\n\t\tconst _ = this;\n\t\tconst delta = Math.abs(targetHeight - currentHeight);\n\t\tconst duration = Math.min(_.#maxDuration, Math.max(_.#minDuration, delta / _.#speed));\n\t\t_.style.setProperty('--collapsible-duration', `${duration.toFixed(3)}s`);\n\t}\n\n\t/**\n\t * Animates to the requested state, then reports the change\n\t * @param {boolean} collapsed - target state (the `open` attribute already matches)\n\t */\n\t#transition(collapsed) {\n\t\tconst _ = this;\n\n\t\t// check if transitions are enabled (respects prefers-reduced-motion)\n\t\tconst hasTransition = getComputedStyle(_).transitionDuration !== '0s';\n\n\t\tif (collapsed) {\n\t\t\t_.setAttribute('aria-hidden', 'true');\n\t\t\t_.setAttribute('inert', '');\n\n\t\t\tif (!hasTransition) {\n\t\t\t\t_.style.height = '0px';\n\t\t\t} else {\n\t\t\t\t// capture current height in px (converts auto or mid-animation value)\n\t\t\t\tconst currentHeight = _.getBoundingClientRect().height;\n\t\t\t\t_.style.height = `${currentHeight}px`;\n\t\t\t\t_.#setDynamicDuration(currentHeight, 0);\n\t\t\t\t_.offsetHeight; // force reflow — browser commits the px start value\n\t\t\t\t_.style.height = '0px';\n\t\t\t}\n\t\t} else {\n\t\t\t_.removeAttribute('aria-hidden');\n\t\t\t_.removeAttribute('inert');\n\n\t\t\tif (!hasTransition) {\n\t\t\t\t_.style.height = 'auto';\n\t\t\t} else {\n\t\t\t\t// capture current height in px (0px or mid-animation value)\n\t\t\t\tconst currentHeight = _.getBoundingClientRect().height;\n\t\t\t\t_.style.height = `${currentHeight}px`;\n\t\t\t\t_.#setDynamicDuration(currentHeight, _.scrollHeight);\n\t\t\t\t_.offsetHeight; // force reflow — browser commits the px start value\n\t\t\t\t_.style.height = `${_.scrollHeight}px`;\n\t\t\t}\n\t\t}\n\n\t\t_.closest('collapsible-component')?.[NOTIFY]?.(_, !collapsed);\n\t}\n\n\t/**\n\t * Handles setting the collapsed state with animation\n\t * @param {boolean} value - Whether element should be collapsed\n\t */\n\tset collapsed(value) {\n\t\tconst _ = this;\n\t\tconst collapsed = Boolean(value);\n\t\tif (_.collapsed === collapsed) return;\n\n\t\t// mirror to the attribute without re-entering attributeChangedCallback\n\t\t_.#selfWrite = true;\n\t\tif (collapsed) _.removeAttribute('open');\n\t\telse _.setAttribute('open', '');\n\t\t_.#selfWrite = false;\n\n\t\t_.#transition(collapsed);\n\t}\n\n\t/**\n\t * Gets the collapsed state\n\t * @returns {boolean} Whether element is collapsed\n\t */\n\tget collapsed() {\n\t\treturn !this.hasAttribute('open');\n\t}\n}\n\n// register custom elements if not already defined\nif (!customElements.get('collapsible-content')) {\n\tcustomElements.define('collapsible-content', CollapsibleContent);\n}\nif (!customElements.get('collapsible-component')) {\n\tcustomElements.define('collapsible-component', CollapsibleComponent);\n}\nif (!customElements.get('collapsible-group')) {\n\tcustomElements.define('collapsible-group', CollapsibleGroup);\n}\n\nexport { CollapsibleContent, CollapsibleComponent, CollapsibleGroup };\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
collapsible-component{display:block}collapsible-component button{background:none;border:none;cursor:pointer;text-align:left;width:100%}collapsible-component button:focus-visible{outline:2px solid currentColor;outline-offset:2px}collapsible-content{--collapsible-duration:0.35s;--collapsible-easing:ease;display:block;overflow:hidden;transition:height var(--collapsible-duration) var(--collapsible-easing)}@media (prefers-reduced-motion:reduce){collapsible-content{transition:none}}
|
|
1
|
+
collapsible-component,collapsible-group{display:block}collapsible-component button{background:none;border:none;cursor:pointer;text-align:left;width:100%}collapsible-component button:focus-visible{outline:2px solid currentColor;outline-offset:2px}collapsible-content{--collapsible-duration:0.35s;--collapsible-easing:ease;display:block;overflow:hidden;transition:height var(--collapsible-duration) var(--collapsible-easing)}@media (prefers-reduced-motion:reduce){collapsible-content{transition:none}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CollapsibleContent={})}(this,
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CollapsibleContent={})}(this,function(t){"use strict";const e=Symbol("collapsible:notify"),o=new Map,n=new WeakMap;class CollapsibleGroup extends HTMLElement{}class CollapsibleComponent extends HTMLElement{static get observedAttributes(){return["group"]}#t;#e;#o=null;constructor(){super();const t=this;t.button=null,t.content=null,t.#t=()=>{t.content.collapsed=!t.content.collapsed}}connectedCallback(){const t=this,e=t.#n;if(e?t.#l(e):t.#r(),t.button=t.querySelector("button"),t.content=t.querySelector("collapsible-content"),!t.button||!t.content){const e=new Error("CollapsibleComponent requires a <button> and a <collapsible-content>.");return console.error(e.message),void t.dispatchEvent(new CustomEvent("collapsible-error",{bubbles:!0,detail:{error:e}}))}t.button.id||=`collapsible-button-${crypto.randomUUID().slice(0,8)}`,t.content.id||=`collapsible-content-${crypto.randomUUID().slice(0,8)}`,t.button.hasAttribute("type")||(t.button.type="button"),t.button.setAttribute("aria-controls",t.content.id),t.content.setAttribute("aria-labelledby",t.button.id),t.content.hasAttribute("role")||t.content.setAttribute("role","region");const o=t.content.hasAttribute("open");t.button.setAttribute("aria-expanded",o),t.content.style.height=o?"auto":"0px",o?(t.content.removeAttribute("aria-hidden"),t.content.removeAttribute("inert")):(t.content.setAttribute("aria-hidden","true"),t.content.setAttribute("inert","")),t.#e=new AbortController,t.button.addEventListener("click",t.#t,{signal:t.#e.signal})}attributeChangedCallback(t,e,o){if("group"!==t)return;const n=this;e&&n.#s(e),o&&n.#l(o),n.isConnected&&(o?n.#i():n.#r())}disconnectedCallback(){const t=this,e=t.#n;e&&t.#s(e),t.#i(),t.#e&&(t.#e.abort(),t.#e=null)}get open(){return!!this.content&&!this.content.collapsed}set open(t){this.content&&(this.content.collapsed=!t)}show(){this.open=!0}hide(){this.open=!1}toggle(){this.open=!this.open}[e](t,e){const o=this;o.content===t&&(o.button&&o.button.setAttribute("aria-expanded",String(e)),e&&o.#a(),o.dispatchEvent(new CustomEvent("collapsible:toggle",{bubbles:!0,composed:!0,detail:{open:e,content:t}})))}get#n(){return this.getAttribute("group")||null}#l(t){o.has(t)||o.set(t,new Set),o.get(t).add(this)}#s(t){const e=o.get(t);e&&(e.delete(this),0===e.size&&o.delete(t))}#r(){const t=this,e=t.closest("collapsible-group");e&&(n.has(e)||n.set(e,new Set),n.get(e).add(t),t.#o=e)}#i(){const t=this;t.#o&&(n.get(t.#o)?.delete(t),t.#o=null)}#a(){const t=this,e=t.#n;let l=null;if(e?l=o.get(e):t.#o?.hasAttribute("exclusive")&&(l=n.get(t.#o)),l)for(const e of l)e!==t&&e.content&&!e.content.collapsed&&(e.content.collapsed=!0)}}class CollapsibleContent extends HTMLElement{static get observedAttributes(){return["open"]}#u;#e;#c=!1;#p=!1;constructor(){super();const t=this;t.#u=e=>{e.target===t&&"height"===e.propertyName&&(t.style.removeProperty("--collapsible-duration"),t.collapsed||(t.style.height="auto"))}}connectedCallback(){const t=this;t.style.height=t.hasAttribute("open")?"auto":"0",t.#e=new AbortController,t.addEventListener("transitionend",t.#u,{signal:t.#e.signal}),t.#c=!0}disconnectedCallback(){const t=this;t.#c=!1,t.#e&&(t.#e.abort(),t.#e=null)}attributeChangedCallback(t,e,o){const n=this;"open"===t&&!n.#p&&n.#c&&null===e!=(null===o)&&n.#b(null===o)}get#d(){const t=this.getAttribute("speed");if(null===t)return 900;const e=Number(t);return e>0?e:900}get#h(){const t=this.getAttribute("min-duration");if(null===t)return.25;const e=Number(t);return e>0?e:.25}get#m(){const t=this.getAttribute("max-duration");if(null===t)return.8;const e=Number(t);return e>0?e:.8}#g(t,e){const o=this,n=Math.abs(e-t),l=Math.min(o.#m,Math.max(o.#h,n/o.#d));o.style.setProperty("--collapsible-duration",`${l.toFixed(3)}s`)}#b(t){const o=this,n="0s"!==getComputedStyle(o).transitionDuration;if(t)if(o.setAttribute("aria-hidden","true"),o.setAttribute("inert",""),n){const t=o.getBoundingClientRect().height;o.style.height=`${t}px`,o.#g(t,0),o.offsetHeight,o.style.height="0px"}else o.style.height="0px";else if(o.removeAttribute("aria-hidden"),o.removeAttribute("inert"),n){const t=o.getBoundingClientRect().height;o.style.height=`${t}px`,o.#g(t,o.scrollHeight),o.offsetHeight,o.style.height=`${o.scrollHeight}px`}else o.style.height="auto";o.closest("collapsible-component")?.[e]?.(o,!t)}set collapsed(t){const e=this,o=Boolean(t);e.collapsed!==o&&(e.#p=!0,o?e.removeAttribute("open"):e.setAttribute("open",""),e.#p=!1,e.#b(o))}get collapsed(){return!this.hasAttribute("open")}}customElements.get("collapsible-content")||customElements.define("collapsible-content",CollapsibleContent),customElements.get("collapsible-component")||customElements.define("collapsible-component",CollapsibleComponent),customElements.get("collapsible-group")||customElements.define("collapsible-group",CollapsibleGroup),t.CollapsibleComponent=CollapsibleComponent,t.CollapsibleContent=CollapsibleContent,t.CollapsibleGroup=CollapsibleGroup});
|
package/package.json
CHANGED