@magic-spells/dialog-panel 0.2.0 → 0.2.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.
@@ -2,198 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- /**
6
- * Retrieves all focusable elements within a given container.
7
- *
8
- * @param {HTMLElement} container - The container element to search for focusable elements.
9
- * @returns {HTMLElement[]} An array of focusable elements found within the container.
10
- */
11
- const getFocusableElements = (container) => {
12
- const focusableSelectors =
13
- 'summary, a[href], button:not(:disabled), [tabindex]:not([tabindex^="-"]):not(focus-trap-start):not(focus-trap-end), [draggable], area, input:not([type=hidden]):not(:disabled), select:not(:disabled), textarea:not(:disabled), object, iframe';
14
- return Array.from(container.querySelectorAll(focusableSelectors));
15
- };
16
-
17
- class FocusTrap extends HTMLElement {
18
- /** @type {boolean} Indicates whether the styles have been injected into the DOM. */
19
- static styleInjected = false;
20
-
21
- constructor() {
22
- super();
23
- this.trapStart = null;
24
- this.trapEnd = null;
25
-
26
- // Inject styles only once, when the first FocusTrap instance is created.
27
- if (!FocusTrap.styleInjected) {
28
- this.injectStyles();
29
- FocusTrap.styleInjected = true;
30
- }
31
- }
32
-
33
- /**
34
- * Injects necessary styles for the focus trap into the document's head.
35
- * This ensures that focus-trap-start and focus-trap-end elements are hidden.
36
- */
37
- injectStyles() {
38
- const style = document.createElement('style');
39
- style.textContent = `
40
- focus-trap-start,
41
- focus-trap-end {
42
- position: absolute;
43
- width: 1px;
44
- height: 1px;
45
- margin: -1px;
46
- padding: 0;
47
- border: 0;
48
- clip: rect(0, 0, 0, 0);
49
- overflow: hidden;
50
- white-space: nowrap;
51
- }
52
- `;
53
- document.head.appendChild(style);
54
- }
55
-
56
- /**
57
- * Called when the element is connected to the DOM.
58
- * Sets up the focus trap and adds the keydown event listener.
59
- */
60
- connectedCallback() {
61
- this.setupTrap();
62
- this.addEventListener('keydown', this.handleKeyDown);
63
- }
64
-
65
- /**
66
- * Called when the element is disconnected from the DOM.
67
- * Removes the keydown event listener.
68
- */
69
- disconnectedCallback() {
70
- this.removeEventListener('keydown', this.handleKeyDown);
71
- }
72
-
73
- /**
74
- * Sets up the focus trap by adding trap start and trap end elements.
75
- * Focuses the trap start element to initiate the focus trap.
76
- */
77
- setupTrap() {
78
- // check to see it there are any focusable children
79
- const focusableElements = getFocusableElements(this);
80
- // exit if there aren't any
81
- if (focusableElements.length === 0) return;
82
-
83
- // create trap start and end elements
84
- this.trapStart = document.createElement('focus-trap-start');
85
- this.trapEnd = document.createElement('focus-trap-end');
86
-
87
- // add to DOM
88
- this.prepend(this.trapStart);
89
- this.append(this.trapEnd);
90
- }
91
-
92
- /**
93
- * Handles the keydown event. If the Escape key is pressed, the focus trap is exited.
94
- *
95
- * @param {KeyboardEvent} e - The keyboard event object.
96
- */
97
- handleKeyDown = (e) => {
98
- if (e.key === 'Escape') {
99
- e.preventDefault();
100
- this.exitTrap();
101
- }
102
- };
103
-
104
- /**
105
- * Exits the focus trap by hiding the current container and shifting focus
106
- * back to the trigger element that opened the trap.
107
- */
108
- exitTrap() {
109
- const container = this.closest('[aria-hidden="false"]');
110
- if (!container) return;
111
-
112
- container.setAttribute('aria-hidden', 'true');
113
-
114
- const trigger = document.querySelector(
115
- `[aria-expanded="true"][aria-controls="${container.id}"]`
116
- );
117
- if (trigger) {
118
- trigger.setAttribute('aria-expanded', 'false');
119
- trigger.focus();
120
- }
121
- }
122
- }
123
-
124
- class FocusTrapStart extends HTMLElement {
125
- /**
126
- * Called when the element is connected to the DOM.
127
- * Sets the tabindex and adds the focus event listener.
128
- */
129
- connectedCallback() {
130
- this.setAttribute('tabindex', '0');
131
- this.addEventListener('focus', this.handleFocus);
132
- }
133
-
134
- /**
135
- * Called when the element is disconnected from the DOM.
136
- * Removes the focus event listener.
137
- */
138
- disconnectedCallback() {
139
- this.removeEventListener('focus', this.handleFocus);
140
- }
141
-
142
- /**
143
- * Handles the focus event. If focus moves backwards from the first focusable element,
144
- * it is cycled to the last focusable element, and vice versa.
145
- *
146
- * @param {FocusEvent} e - The focus event object.
147
- */
148
- handleFocus = (e) => {
149
- const trap = this.closest('focus-trap');
150
- const focusableElements = getFocusableElements(trap);
151
-
152
- if (focusableElements.length === 0) return;
153
-
154
- const firstElement = focusableElements[0];
155
- const lastElement =
156
- focusableElements[focusableElements.length - 1];
157
-
158
- if (e.relatedTarget === firstElement) {
159
- lastElement.focus();
160
- } else {
161
- firstElement.focus();
162
- }
163
- };
164
- }
165
-
166
- class FocusTrapEnd extends HTMLElement {
167
- /**
168
- * Called when the element is connected to the DOM.
169
- * Sets the tabindex and adds the focus event listener.
170
- */
171
- connectedCallback() {
172
- this.setAttribute('tabindex', '0');
173
- this.addEventListener('focus', this.handleFocus);
174
- }
175
-
176
- /**
177
- * Called when the element is disconnected from the DOM.
178
- * Removes the focus event listener.
179
- */
180
- disconnectedCallback() {
181
- this.removeEventListener('focus', this.handleFocus);
182
- }
183
-
184
- /**
185
- * Handles the focus event. When the trap end is focused, focus is shifted back to the trap start.
186
- */
187
- handleFocus = () => {
188
- const trap = this.closest('focus-trap');
189
- const trapStart = trap.querySelector('focus-trap-start');
190
- trapStart.focus();
191
- };
192
- }
193
-
194
- customElements.define('focus-trap', FocusTrap);
195
- customElements.define('focus-trap-start', FocusTrapStart);
196
- customElements.define('focus-trap-end', FocusTrapEnd);
5
+ require('@magic-spells/focus-trap');
197
6
 
198
7
  /**
199
8
  * Custom element that creates an accessible modal dialog panel with focus management
@@ -202,21 +11,24 @@ customElements.define('focus-trap-end', FocusTrapEnd);
202
11
  class DialogPanel extends HTMLElement {
203
12
  #handleTransitionEnd;
204
13
  #scrollPosition = 0;
205
-
14
+
206
15
  /**
207
16
  * Clean up event listeners when component is removed from DOM
208
17
  */
209
18
  disconnectedCallback() {
210
19
  const _ = this;
211
20
  if (_.contentPanel) {
212
- _.contentPanel.removeEventListener('transitionend', _.#handleTransitionEnd);
21
+ _.contentPanel.removeEventListener(
22
+ 'transitionend',
23
+ _.#handleTransitionEnd
24
+ );
213
25
  }
214
-
26
+
215
27
  // Ensure body scroll is restored if component is removed while open
216
28
  document.body.classList.remove('overflow-hidden');
217
29
  this.#restoreScroll();
218
30
  }
219
-
31
+
220
32
  /**
221
33
  * Saves current scroll position and locks body scrolling
222
34
  * @private
@@ -225,12 +37,12 @@ class DialogPanel extends HTMLElement {
225
37
  const _ = this;
226
38
  // Save current scroll position
227
39
  _.#scrollPosition = window.pageYOffset;
228
-
40
+
229
41
  // Apply fixed position to body
230
42
  document.body.classList.add('overflow-hidden');
231
43
  document.body.style.top = `-${_.#scrollPosition}px`;
232
44
  }
233
-
45
+
234
46
  /**
235
47
  * Restores scroll position when dialog is closed
236
48
  * @private
@@ -240,7 +52,7 @@ class DialogPanel extends HTMLElement {
240
52
  // Remove fixed positioning
241
53
  document.body.classList.remove('overflow-hidden');
242
54
  document.body.style.removeProperty('top');
243
-
55
+
244
56
  // Restore scroll position
245
57
  window.scrollTo(0, _.#scrollPosition);
246
58
  }
@@ -258,17 +70,22 @@ class DialogPanel extends HTMLElement {
258
70
  _.contentPanel = _.querySelector('dialog-content');
259
71
  _.focusTrap = document.createElement('focus-trap');
260
72
  _.triggerEl = null;
261
-
73
+
262
74
  // Create a handler for transition end events
263
75
  _.#handleTransitionEnd = (e) => {
264
- if (e.propertyName === 'opacity' && _.getAttribute('aria-hidden') === 'true') {
76
+ if (
77
+ e.propertyName === 'opacity' &&
78
+ _.getAttribute('aria-hidden') === 'true'
79
+ ) {
265
80
  _.contentPanel.classList.add('hidden');
266
-
81
+
267
82
  // Dispatch afterHide event - dialog has completed its transition
268
- _.dispatchEvent(new CustomEvent('afterHide', {
269
- bubbles: true,
270
- detail: { triggerElement: _.triggerEl }
271
- }));
83
+ _.dispatchEvent(
84
+ new CustomEvent('afterHide', {
85
+ bubbles: true,
86
+ detail: { triggerElement: _.triggerEl },
87
+ })
88
+ );
272
89
  }
273
90
  };
274
91
 
@@ -303,12 +120,10 @@ class DialogPanel extends HTMLElement {
303
120
  */
304
121
  #bindUI() {
305
122
  const _ = this;
306
-
123
+
307
124
  // Handle trigger buttons
308
125
  document.addEventListener('click', (e) => {
309
- const trigger = e.target.closest(
310
- `[aria-controls="${_.id}"]`
311
- );
126
+ const trigger = e.target.closest(`[aria-controls="${_.id}"]`);
312
127
  if (!trigger) return;
313
128
 
314
129
  if (trigger.getAttribute('data-prevent-default') === 'true') {
@@ -323,9 +138,12 @@ class DialogPanel extends HTMLElement {
323
138
  if (!e.target.closest('[data-action="hide-dialog"]')) return;
324
139
  _.hide();
325
140
  });
326
-
141
+
327
142
  // Add transition end listener
328
- _.contentPanel.addEventListener('transitionend', _.#handleTransitionEnd);
143
+ _.contentPanel.addEventListener(
144
+ 'transitionend',
145
+ _.#handleTransitionEnd
146
+ );
329
147
  }
330
148
 
331
149
  /**
@@ -355,17 +173,17 @@ class DialogPanel extends HTMLElement {
355
173
  const beforeShowEvent = new CustomEvent('beforeShow', {
356
174
  bubbles: true,
357
175
  cancelable: true,
358
- detail: { triggerElement: _.triggerEl }
176
+ detail: { triggerElement: _.triggerEl },
359
177
  });
360
-
178
+
361
179
  const showAllowed = _.dispatchEvent(beforeShowEvent);
362
-
180
+
363
181
  // If event was canceled (preventDefault was called), don't show the dialog
364
182
  if (!showAllowed) return false;
365
183
 
366
184
  // Remove the hidden class first to ensure content is rendered
367
185
  _.contentPanel.classList.remove('hidden');
368
-
186
+
369
187
  // Give the browser a moment to process before starting animation
370
188
  requestAnimationFrame(() => {
371
189
  // Update ARIA states
@@ -373,10 +191,10 @@ class DialogPanel extends HTMLElement {
373
191
  if (_.triggerEl) {
374
192
  _.triggerEl.setAttribute('aria-expanded', 'true');
375
193
  }
376
-
194
+
377
195
  // Lock body scrolling and save scroll position
378
196
  _.#lockScroll();
379
-
197
+
380
198
  // Focus management
381
199
  const firstFocusable = _.querySelector(
382
200
  'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
@@ -386,14 +204,16 @@ class DialogPanel extends HTMLElement {
386
204
  firstFocusable.focus();
387
205
  });
388
206
  }
389
-
207
+
390
208
  // Dispatch show event - dialog is now visible
391
- _.dispatchEvent(new CustomEvent('show', {
392
- bubbles: true,
393
- detail: { triggerElement: _.triggerEl }
394
- }));
209
+ _.dispatchEvent(
210
+ new CustomEvent('show', {
211
+ bubbles: true,
212
+ detail: { triggerElement: _.triggerEl },
213
+ })
214
+ );
395
215
  });
396
-
216
+
397
217
  return true;
398
218
  }
399
219
 
@@ -406,19 +226,19 @@ class DialogPanel extends HTMLElement {
406
226
  */
407
227
  hide() {
408
228
  const _ = this;
409
-
229
+
410
230
  // Dispatch beforeHide event - allows preventing the dialog from closing
411
231
  const beforeHideEvent = new CustomEvent('beforeHide', {
412
232
  bubbles: true,
413
233
  cancelable: true,
414
- detail: { triggerElement: _.triggerEl }
234
+ detail: { triggerElement: _.triggerEl },
415
235
  });
416
-
236
+
417
237
  const hideAllowed = _.dispatchEvent(beforeHideEvent);
418
-
238
+
419
239
  // If event was canceled (preventDefault was called), don't hide the dialog
420
240
  if (!hideAllowed) return false;
421
-
241
+
422
242
  // Restore body scroll and scroll position
423
243
  _.#restoreScroll();
424
244
 
@@ -433,13 +253,15 @@ class DialogPanel extends HTMLElement {
433
253
  // Set aria-hidden to start transition
434
254
  // The transitionend event handler will add display:none when complete
435
255
  _.setAttribute('aria-hidden', 'true');
436
-
256
+
437
257
  // Dispatch hide event - dialog is now starting to hide
438
- _.dispatchEvent(new CustomEvent('hide', {
439
- bubbles: true,
440
- detail: { triggerElement: _.triggerEl }
441
- }));
442
-
258
+ _.dispatchEvent(
259
+ new CustomEvent('hide', {
260
+ bubbles: true,
261
+ detail: { triggerElement: _.triggerEl },
262
+ })
263
+ );
264
+
443
265
  return true;
444
266
  }
445
267
  }
@@ -475,9 +297,15 @@ class DialogContent extends HTMLElement {
475
297
  }
476
298
  }
477
299
 
478
- customElements.define('dialog-panel', DialogPanel);
479
- customElements.define('dialog-overlay', DialogOverlay);
480
- customElements.define('dialog-content', DialogContent);
300
+ if (!customElements.get('dialog-panel')) {
301
+ customElements.define('dialog-panel', DialogPanel);
302
+ }
303
+ if (!customElements.get('dialog-overlay')) {
304
+ customElements.define('dialog-overlay', DialogOverlay);
305
+ }
306
+ if (!customElements.get('dialog-content')) {
307
+ customElements.define('dialog-content', DialogContent);
308
+ }
481
309
 
482
310
  exports.DialogContent = DialogContent;
483
311
  exports.DialogOverlay = DialogOverlay;
@@ -1 +1 @@
1
- {"version":3,"file":"dialog-panel.cjs.js","sources":["../node_modules/@magic-spells/focus-trap/dist/focus-trap.esm.js","../src/dialog-panel.js"],"sourcesContent":["/**\n * Retrieves all focusable elements within a given container.\n *\n * @param {HTMLElement} container - The container element to search for focusable elements.\n * @returns {HTMLElement[]} An array of focusable elements found within the container.\n */\nconst getFocusableElements = (container) => {\n\tconst focusableSelectors =\n\t\t'summary, a[href], button:not(:disabled), [tabindex]:not([tabindex^=\"-\"]):not(focus-trap-start):not(focus-trap-end), [draggable], area, input:not([type=hidden]):not(:disabled), select:not(:disabled), textarea:not(:disabled), object, iframe';\n\treturn Array.from(container.querySelectorAll(focusableSelectors));\n};\n\nclass FocusTrap extends HTMLElement {\n\t/** @type {boolean} Indicates whether the styles have been injected into the DOM. */\n\tstatic styleInjected = false;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.trapStart = null;\n\t\tthis.trapEnd = null;\n\n\t\t// Inject styles only once, when the first FocusTrap instance is created.\n\t\tif (!FocusTrap.styleInjected) {\n\t\t\tthis.injectStyles();\n\t\t\tFocusTrap.styleInjected = true;\n\t\t}\n\t}\n\n\t/**\n\t * Injects necessary styles for the focus trap into the document's head.\n\t * This ensures that focus-trap-start and focus-trap-end elements are hidden.\n\t */\n\tinjectStyles() {\n\t\tconst style = document.createElement('style');\n\t\tstyle.textContent = `\n focus-trap-start,\n focus-trap-end {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n clip: rect(0, 0, 0, 0);\n overflow: hidden;\n white-space: nowrap;\n }\n `;\n\t\tdocument.head.appendChild(style);\n\t}\n\n\t/**\n\t * Called when the element is connected to the DOM.\n\t * Sets up the focus trap and adds the keydown event listener.\n\t */\n\tconnectedCallback() {\n\t\tthis.setupTrap();\n\t\tthis.addEventListener('keydown', this.handleKeyDown);\n\t}\n\n\t/**\n\t * Called when the element is disconnected from the DOM.\n\t * Removes the keydown event listener.\n\t */\n\tdisconnectedCallback() {\n\t\tthis.removeEventListener('keydown', this.handleKeyDown);\n\t}\n\n\t/**\n\t * Sets up the focus trap by adding trap start and trap end elements.\n\t * Focuses the trap start element to initiate the focus trap.\n\t */\n\tsetupTrap() {\n\t\t// check to see it there are any focusable children\n\t\tconst focusableElements = getFocusableElements(this);\n\t\t// exit if there aren't any\n\t\tif (focusableElements.length === 0) return;\n\n\t\t// create trap start and end elements\n\t\tthis.trapStart = document.createElement('focus-trap-start');\n\t\tthis.trapEnd = document.createElement('focus-trap-end');\n\n\t\t// add to DOM\n\t\tthis.prepend(this.trapStart);\n\t\tthis.append(this.trapEnd);\n\t}\n\n\t/**\n\t * Handles the keydown event. If the Escape key is pressed, the focus trap is exited.\n\t *\n\t * @param {KeyboardEvent} e - The keyboard event object.\n\t */\n\thandleKeyDown = (e) => {\n\t\tif (e.key === 'Escape') {\n\t\t\te.preventDefault();\n\t\t\tthis.exitTrap();\n\t\t}\n\t};\n\n\t/**\n\t * Exits the focus trap by hiding the current container and shifting focus\n\t * back to the trigger element that opened the trap.\n\t */\n\texitTrap() {\n\t\tconst container = this.closest('[aria-hidden=\"false\"]');\n\t\tif (!container) return;\n\n\t\tcontainer.setAttribute('aria-hidden', 'true');\n\n\t\tconst trigger = document.querySelector(\n\t\t\t`[aria-expanded=\"true\"][aria-controls=\"${container.id}\"]`\n\t\t);\n\t\tif (trigger) {\n\t\t\ttrigger.setAttribute('aria-expanded', 'false');\n\t\t\ttrigger.focus();\n\t\t}\n\t}\n}\n\nclass FocusTrapStart extends HTMLElement {\n\t/**\n\t * Called when the element is connected to the DOM.\n\t * Sets the tabindex and adds the focus event listener.\n\t */\n\tconnectedCallback() {\n\t\tthis.setAttribute('tabindex', '0');\n\t\tthis.addEventListener('focus', this.handleFocus);\n\t}\n\n\t/**\n\t * Called when the element is disconnected from the DOM.\n\t * Removes the focus event listener.\n\t */\n\tdisconnectedCallback() {\n\t\tthis.removeEventListener('focus', this.handleFocus);\n\t}\n\n\t/**\n\t * Handles the focus event. If focus moves backwards from the first focusable element,\n\t * it is cycled to the last focusable element, and vice versa.\n\t *\n\t * @param {FocusEvent} e - The focus event object.\n\t */\n\thandleFocus = (e) => {\n\t\tconst trap = this.closest('focus-trap');\n\t\tconst focusableElements = getFocusableElements(trap);\n\n\t\tif (focusableElements.length === 0) return;\n\n\t\tconst firstElement = focusableElements[0];\n\t\tconst lastElement =\n\t\t\tfocusableElements[focusableElements.length - 1];\n\n\t\tif (e.relatedTarget === firstElement) {\n\t\t\tlastElement.focus();\n\t\t} else {\n\t\t\tfirstElement.focus();\n\t\t}\n\t};\n}\n\nclass FocusTrapEnd extends HTMLElement {\n\t/**\n\t * Called when the element is connected to the DOM.\n\t * Sets the tabindex and adds the focus event listener.\n\t */\n\tconnectedCallback() {\n\t\tthis.setAttribute('tabindex', '0');\n\t\tthis.addEventListener('focus', this.handleFocus);\n\t}\n\n\t/**\n\t * Called when the element is disconnected from the DOM.\n\t * Removes the focus event listener.\n\t */\n\tdisconnectedCallback() {\n\t\tthis.removeEventListener('focus', this.handleFocus);\n\t}\n\n\t/**\n\t * Handles the focus event. When the trap end is focused, focus is shifted back to the trap start.\n\t */\n\thandleFocus = () => {\n\t\tconst trap = this.closest('focus-trap');\n\t\tconst trapStart = trap.querySelector('focus-trap-start');\n\t\ttrapStart.focus();\n\t};\n}\n\ncustomElements.define('focus-trap', FocusTrap);\ncustomElements.define('focus-trap-start', FocusTrapStart);\ncustomElements.define('focus-trap-end', FocusTrapEnd);\n//# sourceMappingURL=focus-trap.esm.js.map\n","import './index.scss';\nimport '@magic-spells/focus-trap';\n\n/**\n * Custom element that creates an accessible modal dialog panel with focus management\n * @extends HTMLElement\n */\nclass DialogPanel extends HTMLElement {\n\t#handleTransitionEnd;\n\t#scrollPosition = 0;\n\t\n\t/**\n\t * Clean up event listeners when component is removed from DOM\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tif (_.contentPanel) {\n\t\t\t_.contentPanel.removeEventListener('transitionend', _.#handleTransitionEnd);\n\t\t}\n\t\t\n\t\t// Ensure body scroll is restored if component is removed while open\n\t\tdocument.body.classList.remove('overflow-hidden');\n\t\tthis.#restoreScroll();\n\t}\n\t\n\t/**\n\t * Saves current scroll position and locks body scrolling\n\t * @private\n\t */\n\t#lockScroll() {\n\t\tconst _ = this;\n\t\t// Save current scroll position\n\t\t_.#scrollPosition = window.pageYOffset;\n\t\t\n\t\t// Apply fixed position to body\n\t\tdocument.body.classList.add('overflow-hidden');\n\t\tdocument.body.style.top = `-${_.#scrollPosition}px`;\n\t}\n\t\n\t/**\n\t * Restores scroll position when dialog is closed\n\t * @private\n\t */\n\t#restoreScroll() {\n\t\tconst _ = this;\n\t\t// Remove fixed positioning\n\t\tdocument.body.classList.remove('overflow-hidden');\n\t\tdocument.body.style.removeProperty('top');\n\t\t\n\t\t// Restore scroll position\n\t\twindow.scrollTo(0, _.#scrollPosition);\n\t}\n\t/**\n\t * Initializes the dialog panel, sets up focus trap and overlay\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\t\t_.id = _.getAttribute('id');\n\t\t_.setAttribute('role', 'dialog');\n\t\t_.setAttribute('aria-modal', 'true');\n\t\t_.setAttribute('aria-hidden', 'true');\n\n\t\t_.contentPanel = _.querySelector('dialog-content');\n\t\t_.focusTrap = document.createElement('focus-trap');\n\t\t_.triggerEl = null;\n\t\t\n\t\t// Create a handler for transition end events\n\t\t_.#handleTransitionEnd = (e) => {\n\t\t\tif (e.propertyName === 'opacity' && _.getAttribute('aria-hidden') === 'true') {\n\t\t\t\t_.contentPanel.classList.add('hidden');\n\t\t\t\t\n\t\t\t\t// Dispatch afterHide event - dialog has completed its transition\n\t\t\t\t_.dispatchEvent(new CustomEvent('afterHide', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tdetail: { triggerElement: _.triggerEl }\n\t\t\t\t}));\n\t\t\t}\n\t\t};\n\n\t\t// Ensure we have labelledby and describedby references\n\t\tif (!_.getAttribute('aria-labelledby')) {\n\t\t\tconst heading = _.querySelector('h1, h2, h3');\n\t\t\tif (heading && !heading.id) {\n\t\t\t\theading.id = `${_.id}-title`;\n\t\t\t}\n\t\t\tif (heading?.id) {\n\t\t\t\t_.setAttribute('aria-labelledby', heading.id);\n\t\t\t}\n\t\t}\n\n\t\t_.contentPanel.parentNode.insertBefore(\n\t\t\t_.focusTrap,\n\t\t\t_.contentPanel\n\t\t);\n\t\t_.focusTrap.appendChild(_.contentPanel);\n\n\t\t_.focusTrap.setupTrap();\n\n\t\t// Add modal overlay\n\t\t_.prepend(document.createElement('dialog-overlay'));\n\t\t_.#bindUI();\n\t\t_.#bindKeyboard();\n\t}\n\n\t/**\n\t * Binds click events for showing and hiding the dialog\n\t * @private\n\t */\n\t#bindUI() {\n\t\tconst _ = this;\n\t\t\n\t\t// Handle trigger buttons\n\t\tdocument.addEventListener('click', (e) => {\n\t\t\tconst trigger = e.target.closest(\n\t\t\t\t`[aria-controls=\"${_.id}\"]`\n\t\t\t);\n\t\t\tif (!trigger) return;\n\n\t\t\tif (trigger.getAttribute('data-prevent-default') === 'true') {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\t_.show(trigger);\n\t\t});\n\n\t\t// Handle close buttons\n\t\t_.addEventListener('click', (e) => {\n\t\t\tif (!e.target.closest('[data-action=\"hide-dialog\"]')) return;\n\t\t\t_.hide();\n\t\t});\n\t\t\n\t\t// Add transition end listener\n\t\t_.contentPanel.addEventListener('transitionend', _.#handleTransitionEnd);\n\t}\n\n\t/**\n\t * Binds keyboard events for accessibility\n\t * @private\n\t */\n\t#bindKeyboard() {\n\t\tthis.addEventListener('keydown', (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.hide();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Shows the dialog and traps focus within it\n\t * @param {HTMLElement} [triggerEl=null] - The element that triggered the dialog\n\t * @fires DialogPanel#beforeShow - Fired before the dialog starts to show\n\t * @fires DialogPanel#show - Fired when the dialog has been shown\n\t * @returns {boolean} False if the show was prevented by a beforeShow event handler\n\t */\n\tshow(triggerEl = null) {\n\t\tconst _ = this;\n\t\t_.triggerEl = triggerEl || false;\n\n\t\t// Dispatch beforeShow event - allows preventing the dialog from opening\n\t\tconst beforeShowEvent = new CustomEvent('beforeShow', {\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t\tdetail: { triggerElement: _.triggerEl }\n\t\t});\n\t\t\n\t\tconst showAllowed = _.dispatchEvent(beforeShowEvent);\n\t\t\n\t\t// If event was canceled (preventDefault was called), don't show the dialog\n\t\tif (!showAllowed) return false;\n\n\t\t// Remove the hidden class first to ensure content is rendered\n\t\t_.contentPanel.classList.remove('hidden');\n\t\t\n\t\t// Give the browser a moment to process before starting animation\n\t\trequestAnimationFrame(() => {\n\t\t\t// Update ARIA states\n\t\t\t_.setAttribute('aria-hidden', 'false');\n\t\t\tif (_.triggerEl) {\n\t\t\t\t_.triggerEl.setAttribute('aria-expanded', 'true');\n\t\t\t}\n\t\n\t\t\t// Lock body scrolling and save scroll position\n\t\t\t_.#lockScroll();\n\t\n\t\t\t// Focus management\n\t\t\tconst firstFocusable = _.querySelector(\n\t\t\t\t'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\t\t\t);\n\t\t\tif (firstFocusable) {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tfirstFocusable.focus();\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Dispatch show event - dialog is now visible\n\t\t\t_.dispatchEvent(new CustomEvent('show', {\n\t\t\t\tbubbles: true,\n\t\t\t\tdetail: { triggerElement: _.triggerEl }\n\t\t\t}));\n\t\t});\n\t\t\n\t\treturn true;\n\t}\n\n\t/**\n\t * Hides the dialog and restores focus\n\t * @fires DialogPanel#beforeHide - Fired before the dialog starts to hide\n\t * @fires DialogPanel#hide - Fired when the dialog has started hiding (transition begins)\n\t * @fires DialogPanel#afterHide - Fired when the dialog has completed its hide transition\n\t * @returns {boolean} False if the hide was prevented by a beforeHide event handler\n\t */\n\thide() {\n\t\tconst _ = this;\n\t\t\n\t\t// Dispatch beforeHide event - allows preventing the dialog from closing\n\t\tconst beforeHideEvent = new CustomEvent('beforeHide', {\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t\tdetail: { triggerElement: _.triggerEl }\n\t\t});\n\t\t\n\t\tconst hideAllowed = _.dispatchEvent(beforeHideEvent);\n\t\t\n\t\t// If event was canceled (preventDefault was called), don't hide the dialog\n\t\tif (!hideAllowed) return false;\n\t\t\n\t\t// Restore body scroll and scroll position\n\t\t_.#restoreScroll();\n\n\t\t// Update ARIA states\n\t\tif (_.triggerEl) {\n\t\t\t// remove focus from modal panel first\n\t\t\t_.triggerEl.focus();\n\t\t\t// mark trigger as no longer expanded\n\t\t\t_.triggerEl.setAttribute('aria-expanded', 'false');\n\t\t}\n\n\t\t// Set aria-hidden to start transition\n\t\t// The transitionend event handler will add display:none when complete\n\t\t_.setAttribute('aria-hidden', 'true');\n\t\t\n\t\t// Dispatch hide event - dialog is now starting to hide\n\t\t_.dispatchEvent(new CustomEvent('hide', {\n\t\t\tbubbles: true,\n\t\t\tdetail: { triggerElement: _.triggerEl }\n\t\t}));\n\t\t\n\t\treturn true;\n\t}\n}\n\n/**\n * Custom element that creates a clickable overlay for the dialog\n * @extends HTMLElement\n */\nclass DialogOverlay extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.setAttribute('tabindex', '-1'); // Changed to -1 as it shouldn't be focusable\n\t\tthis.setAttribute('aria-hidden', 'true');\n\t\tthis.dialogPanel = this.closest('dialog-panel');\n\t\tthis.#bindUI();\n\t}\n\n\t#bindUI() {\n\t\tthis.addEventListener('click', () => {\n\t\t\tthis.dialogPanel.hide();\n\t\t});\n\t}\n}\n\n/**\n * Custom element that wraps the content of the dialog\n * @extends HTMLElement\n */\nclass DialogContent extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.setAttribute('role', 'document'); // Optional: helps with document structure\n\t}\n}\n\ncustomElements.define('dialog-panel', DialogPanel);\ncustomElements.define('dialog-overlay', DialogOverlay);\ncustomElements.define('dialog-content', DialogContent);\n\nexport { DialogPanel, DialogOverlay, DialogContent };\nexport default DialogPanel;"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"dialog-panel.cjs.js","sources":["../src/dialog-panel.js"],"sourcesContent":["import './index.scss';\nimport '@magic-spells/focus-trap';\n\n/**\n * Custom element that creates an accessible modal dialog panel with focus management\n * @extends HTMLElement\n */\nclass DialogPanel extends HTMLElement {\n\t#handleTransitionEnd;\n\t#scrollPosition = 0;\n\n\t/**\n\t * Clean up event listeners when component is removed from DOM\n\t */\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tif (_.contentPanel) {\n\t\t\t_.contentPanel.removeEventListener(\n\t\t\t\t'transitionend',\n\t\t\t\t_.#handleTransitionEnd\n\t\t\t);\n\t\t}\n\n\t\t// Ensure body scroll is restored if component is removed while open\n\t\tdocument.body.classList.remove('overflow-hidden');\n\t\tthis.#restoreScroll();\n\t}\n\n\t/**\n\t * Saves current scroll position and locks body scrolling\n\t * @private\n\t */\n\t#lockScroll() {\n\t\tconst _ = this;\n\t\t// Save current scroll position\n\t\t_.#scrollPosition = window.pageYOffset;\n\n\t\t// Apply fixed position to body\n\t\tdocument.body.classList.add('overflow-hidden');\n\t\tdocument.body.style.top = `-${_.#scrollPosition}px`;\n\t}\n\n\t/**\n\t * Restores scroll position when dialog is closed\n\t * @private\n\t */\n\t#restoreScroll() {\n\t\tconst _ = this;\n\t\t// Remove fixed positioning\n\t\tdocument.body.classList.remove('overflow-hidden');\n\t\tdocument.body.style.removeProperty('top');\n\n\t\t// Restore scroll position\n\t\twindow.scrollTo(0, _.#scrollPosition);\n\t}\n\t/**\n\t * Initializes the dialog panel, sets up focus trap and overlay\n\t */\n\tconstructor() {\n\t\tsuper();\n\t\tconst _ = this;\n\t\t_.id = _.getAttribute('id');\n\t\t_.setAttribute('role', 'dialog');\n\t\t_.setAttribute('aria-modal', 'true');\n\t\t_.setAttribute('aria-hidden', 'true');\n\n\t\t_.contentPanel = _.querySelector('dialog-content');\n\t\t_.focusTrap = document.createElement('focus-trap');\n\t\t_.triggerEl = null;\n\n\t\t// Create a handler for transition end events\n\t\t_.#handleTransitionEnd = (e) => {\n\t\t\tif (\n\t\t\t\te.propertyName === 'opacity' &&\n\t\t\t\t_.getAttribute('aria-hidden') === 'true'\n\t\t\t) {\n\t\t\t\t_.contentPanel.classList.add('hidden');\n\n\t\t\t\t// Dispatch afterHide event - dialog has completed its transition\n\t\t\t\t_.dispatchEvent(\n\t\t\t\t\tnew CustomEvent('afterHide', {\n\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\tdetail: { triggerElement: _.triggerEl },\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\t// Ensure we have labelledby and describedby references\n\t\tif (!_.getAttribute('aria-labelledby')) {\n\t\t\tconst heading = _.querySelector('h1, h2, h3');\n\t\t\tif (heading && !heading.id) {\n\t\t\t\theading.id = `${_.id}-title`;\n\t\t\t}\n\t\t\tif (heading?.id) {\n\t\t\t\t_.setAttribute('aria-labelledby', heading.id);\n\t\t\t}\n\t\t}\n\n\t\t_.contentPanel.parentNode.insertBefore(\n\t\t\t_.focusTrap,\n\t\t\t_.contentPanel\n\t\t);\n\t\t_.focusTrap.appendChild(_.contentPanel);\n\n\t\t_.focusTrap.setupTrap();\n\n\t\t// Add modal overlay\n\t\t_.prepend(document.createElement('dialog-overlay'));\n\t\t_.#bindUI();\n\t\t_.#bindKeyboard();\n\t}\n\n\t/**\n\t * Binds click events for showing and hiding the dialog\n\t * @private\n\t */\n\t#bindUI() {\n\t\tconst _ = this;\n\n\t\t// Handle trigger buttons\n\t\tdocument.addEventListener('click', (e) => {\n\t\t\tconst trigger = e.target.closest(`[aria-controls=\"${_.id}\"]`);\n\t\t\tif (!trigger) return;\n\n\t\t\tif (trigger.getAttribute('data-prevent-default') === 'true') {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\t_.show(trigger);\n\t\t});\n\n\t\t// Handle close buttons\n\t\t_.addEventListener('click', (e) => {\n\t\t\tif (!e.target.closest('[data-action=\"hide-dialog\"]')) return;\n\t\t\t_.hide();\n\t\t});\n\n\t\t// Add transition end listener\n\t\t_.contentPanel.addEventListener(\n\t\t\t'transitionend',\n\t\t\t_.#handleTransitionEnd\n\t\t);\n\t}\n\n\t/**\n\t * Binds keyboard events for accessibility\n\t * @private\n\t */\n\t#bindKeyboard() {\n\t\tthis.addEventListener('keydown', (e) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tthis.hide();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Shows the dialog and traps focus within it\n\t * @param {HTMLElement} [triggerEl=null] - The element that triggered the dialog\n\t * @fires DialogPanel#beforeShow - Fired before the dialog starts to show\n\t * @fires DialogPanel#show - Fired when the dialog has been shown\n\t * @returns {boolean} False if the show was prevented by a beforeShow event handler\n\t */\n\tshow(triggerEl = null) {\n\t\tconst _ = this;\n\t\t_.triggerEl = triggerEl || false;\n\n\t\t// Dispatch beforeShow event - allows preventing the dialog from opening\n\t\tconst beforeShowEvent = new CustomEvent('beforeShow', {\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t\tdetail: { triggerElement: _.triggerEl },\n\t\t});\n\n\t\tconst showAllowed = _.dispatchEvent(beforeShowEvent);\n\n\t\t// If event was canceled (preventDefault was called), don't show the dialog\n\t\tif (!showAllowed) return false;\n\n\t\t// Remove the hidden class first to ensure content is rendered\n\t\t_.contentPanel.classList.remove('hidden');\n\n\t\t// Give the browser a moment to process before starting animation\n\t\trequestAnimationFrame(() => {\n\t\t\t// Update ARIA states\n\t\t\t_.setAttribute('aria-hidden', 'false');\n\t\t\tif (_.triggerEl) {\n\t\t\t\t_.triggerEl.setAttribute('aria-expanded', 'true');\n\t\t\t}\n\n\t\t\t// Lock body scrolling and save scroll position\n\t\t\t_.#lockScroll();\n\n\t\t\t// Focus management\n\t\t\tconst firstFocusable = _.querySelector(\n\t\t\t\t'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\t\t\t);\n\t\t\tif (firstFocusable) {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tfirstFocusable.focus();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Dispatch show event - dialog is now visible\n\t\t\t_.dispatchEvent(\n\t\t\t\tnew CustomEvent('show', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tdetail: { triggerElement: _.triggerEl },\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Hides the dialog and restores focus\n\t * @fires DialogPanel#beforeHide - Fired before the dialog starts to hide\n\t * @fires DialogPanel#hide - Fired when the dialog has started hiding (transition begins)\n\t * @fires DialogPanel#afterHide - Fired when the dialog has completed its hide transition\n\t * @returns {boolean} False if the hide was prevented by a beforeHide event handler\n\t */\n\thide() {\n\t\tconst _ = this;\n\n\t\t// Dispatch beforeHide event - allows preventing the dialog from closing\n\t\tconst beforeHideEvent = new CustomEvent('beforeHide', {\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t\tdetail: { triggerElement: _.triggerEl },\n\t\t});\n\n\t\tconst hideAllowed = _.dispatchEvent(beforeHideEvent);\n\n\t\t// If event was canceled (preventDefault was called), don't hide the dialog\n\t\tif (!hideAllowed) return false;\n\n\t\t// Restore body scroll and scroll position\n\t\t_.#restoreScroll();\n\n\t\t// Update ARIA states\n\t\tif (_.triggerEl) {\n\t\t\t// remove focus from modal panel first\n\t\t\t_.triggerEl.focus();\n\t\t\t// mark trigger as no longer expanded\n\t\t\t_.triggerEl.setAttribute('aria-expanded', 'false');\n\t\t}\n\n\t\t// Set aria-hidden to start transition\n\t\t// The transitionend event handler will add display:none when complete\n\t\t_.setAttribute('aria-hidden', 'true');\n\n\t\t// Dispatch hide event - dialog is now starting to hide\n\t\t_.dispatchEvent(\n\t\t\tnew CustomEvent('hide', {\n\t\t\t\tbubbles: true,\n\t\t\t\tdetail: { triggerElement: _.triggerEl },\n\t\t\t})\n\t\t);\n\n\t\treturn true;\n\t}\n}\n\n/**\n * Custom element that creates a clickable overlay for the dialog\n * @extends HTMLElement\n */\nclass DialogOverlay extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.setAttribute('tabindex', '-1'); // Changed to -1 as it shouldn't be focusable\n\t\tthis.setAttribute('aria-hidden', 'true');\n\t\tthis.dialogPanel = this.closest('dialog-panel');\n\t\tthis.#bindUI();\n\t}\n\n\t#bindUI() {\n\t\tthis.addEventListener('click', () => {\n\t\t\tthis.dialogPanel.hide();\n\t\t});\n\t}\n}\n\n/**\n * Custom element that wraps the content of the dialog\n * @extends HTMLElement\n */\nclass DialogContent extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.setAttribute('role', 'document'); // Optional: helps with document structure\n\t}\n}\n\nif (!customElements.get('dialog-panel')) {\n\tcustomElements.define('dialog-panel', DialogPanel);\n}\nif (!customElements.get('dialog-overlay')) {\n\tcustomElements.define('dialog-overlay', DialogOverlay);\n}\nif (!customElements.get('dialog-content')) {\n\tcustomElements.define('dialog-content', DialogContent);\n}\n\nexport { DialogPanel, DialogOverlay, DialogContent };\nexport default DialogPanel;\n"],"names":[],"mappings":"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"}