@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.
@@ -204,21 +204,24 @@
204
204
  class DialogPanel extends HTMLElement {
205
205
  #handleTransitionEnd;
206
206
  #scrollPosition = 0;
207
-
207
+
208
208
  /**
209
209
  * Clean up event listeners when component is removed from DOM
210
210
  */
211
211
  disconnectedCallback() {
212
212
  const _ = this;
213
213
  if (_.contentPanel) {
214
- _.contentPanel.removeEventListener('transitionend', _.#handleTransitionEnd);
214
+ _.contentPanel.removeEventListener(
215
+ 'transitionend',
216
+ _.#handleTransitionEnd
217
+ );
215
218
  }
216
-
219
+
217
220
  // Ensure body scroll is restored if component is removed while open
218
221
  document.body.classList.remove('overflow-hidden');
219
222
  this.#restoreScroll();
220
223
  }
221
-
224
+
222
225
  /**
223
226
  * Saves current scroll position and locks body scrolling
224
227
  * @private
@@ -227,12 +230,12 @@
227
230
  const _ = this;
228
231
  // Save current scroll position
229
232
  _.#scrollPosition = window.pageYOffset;
230
-
233
+
231
234
  // Apply fixed position to body
232
235
  document.body.classList.add('overflow-hidden');
233
236
  document.body.style.top = `-${_.#scrollPosition}px`;
234
237
  }
235
-
238
+
236
239
  /**
237
240
  * Restores scroll position when dialog is closed
238
241
  * @private
@@ -242,7 +245,7 @@
242
245
  // Remove fixed positioning
243
246
  document.body.classList.remove('overflow-hidden');
244
247
  document.body.style.removeProperty('top');
245
-
248
+
246
249
  // Restore scroll position
247
250
  window.scrollTo(0, _.#scrollPosition);
248
251
  }
@@ -260,17 +263,22 @@
260
263
  _.contentPanel = _.querySelector('dialog-content');
261
264
  _.focusTrap = document.createElement('focus-trap');
262
265
  _.triggerEl = null;
263
-
266
+
264
267
  // Create a handler for transition end events
265
268
  _.#handleTransitionEnd = (e) => {
266
- if (e.propertyName === 'opacity' && _.getAttribute('aria-hidden') === 'true') {
269
+ if (
270
+ e.propertyName === 'opacity' &&
271
+ _.getAttribute('aria-hidden') === 'true'
272
+ ) {
267
273
  _.contentPanel.classList.add('hidden');
268
-
274
+
269
275
  // Dispatch afterHide event - dialog has completed its transition
270
- _.dispatchEvent(new CustomEvent('afterHide', {
271
- bubbles: true,
272
- detail: { triggerElement: _.triggerEl }
273
- }));
276
+ _.dispatchEvent(
277
+ new CustomEvent('afterHide', {
278
+ bubbles: true,
279
+ detail: { triggerElement: _.triggerEl },
280
+ })
281
+ );
274
282
  }
275
283
  };
276
284
 
@@ -305,12 +313,10 @@
305
313
  */
306
314
  #bindUI() {
307
315
  const _ = this;
308
-
316
+
309
317
  // Handle trigger buttons
310
318
  document.addEventListener('click', (e) => {
311
- const trigger = e.target.closest(
312
- `[aria-controls="${_.id}"]`
313
- );
319
+ const trigger = e.target.closest(`[aria-controls="${_.id}"]`);
314
320
  if (!trigger) return;
315
321
 
316
322
  if (trigger.getAttribute('data-prevent-default') === 'true') {
@@ -325,9 +331,12 @@
325
331
  if (!e.target.closest('[data-action="hide-dialog"]')) return;
326
332
  _.hide();
327
333
  });
328
-
334
+
329
335
  // Add transition end listener
330
- _.contentPanel.addEventListener('transitionend', _.#handleTransitionEnd);
336
+ _.contentPanel.addEventListener(
337
+ 'transitionend',
338
+ _.#handleTransitionEnd
339
+ );
331
340
  }
332
341
 
333
342
  /**
@@ -357,17 +366,17 @@
357
366
  const beforeShowEvent = new CustomEvent('beforeShow', {
358
367
  bubbles: true,
359
368
  cancelable: true,
360
- detail: { triggerElement: _.triggerEl }
369
+ detail: { triggerElement: _.triggerEl },
361
370
  });
362
-
371
+
363
372
  const showAllowed = _.dispatchEvent(beforeShowEvent);
364
-
373
+
365
374
  // If event was canceled (preventDefault was called), don't show the dialog
366
375
  if (!showAllowed) return false;
367
376
 
368
377
  // Remove the hidden class first to ensure content is rendered
369
378
  _.contentPanel.classList.remove('hidden');
370
-
379
+
371
380
  // Give the browser a moment to process before starting animation
372
381
  requestAnimationFrame(() => {
373
382
  // Update ARIA states
@@ -375,10 +384,10 @@
375
384
  if (_.triggerEl) {
376
385
  _.triggerEl.setAttribute('aria-expanded', 'true');
377
386
  }
378
-
387
+
379
388
  // Lock body scrolling and save scroll position
380
389
  _.#lockScroll();
381
-
390
+
382
391
  // Focus management
383
392
  const firstFocusable = _.querySelector(
384
393
  'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
@@ -388,14 +397,16 @@
388
397
  firstFocusable.focus();
389
398
  });
390
399
  }
391
-
400
+
392
401
  // Dispatch show event - dialog is now visible
393
- _.dispatchEvent(new CustomEvent('show', {
394
- bubbles: true,
395
- detail: { triggerElement: _.triggerEl }
396
- }));
402
+ _.dispatchEvent(
403
+ new CustomEvent('show', {
404
+ bubbles: true,
405
+ detail: { triggerElement: _.triggerEl },
406
+ })
407
+ );
397
408
  });
398
-
409
+
399
410
  return true;
400
411
  }
401
412
 
@@ -408,19 +419,19 @@
408
419
  */
409
420
  hide() {
410
421
  const _ = this;
411
-
422
+
412
423
  // Dispatch beforeHide event - allows preventing the dialog from closing
413
424
  const beforeHideEvent = new CustomEvent('beforeHide', {
414
425
  bubbles: true,
415
426
  cancelable: true,
416
- detail: { triggerElement: _.triggerEl }
427
+ detail: { triggerElement: _.triggerEl },
417
428
  });
418
-
429
+
419
430
  const hideAllowed = _.dispatchEvent(beforeHideEvent);
420
-
431
+
421
432
  // If event was canceled (preventDefault was called), don't hide the dialog
422
433
  if (!hideAllowed) return false;
423
-
434
+
424
435
  // Restore body scroll and scroll position
425
436
  _.#restoreScroll();
426
437
 
@@ -435,13 +446,15 @@
435
446
  // Set aria-hidden to start transition
436
447
  // The transitionend event handler will add display:none when complete
437
448
  _.setAttribute('aria-hidden', 'true');
438
-
449
+
439
450
  // Dispatch hide event - dialog is now starting to hide
440
- _.dispatchEvent(new CustomEvent('hide', {
441
- bubbles: true,
442
- detail: { triggerElement: _.triggerEl }
443
- }));
444
-
451
+ _.dispatchEvent(
452
+ new CustomEvent('hide', {
453
+ bubbles: true,
454
+ detail: { triggerElement: _.triggerEl },
455
+ })
456
+ );
457
+
445
458
  return true;
446
459
  }
447
460
  }
@@ -477,9 +490,15 @@
477
490
  }
478
491
  }
479
492
 
480
- customElements.define('dialog-panel', DialogPanel);
481
- customElements.define('dialog-overlay', DialogOverlay);
482
- customElements.define('dialog-content', DialogContent);
493
+ if (!customElements.get('dialog-panel')) {
494
+ customElements.define('dialog-panel', DialogPanel);
495
+ }
496
+ if (!customElements.get('dialog-overlay')) {
497
+ customElements.define('dialog-overlay', DialogOverlay);
498
+ }
499
+ if (!customElements.get('dialog-content')) {
500
+ customElements.define('dialog-content', DialogContent);
501
+ }
483
502
 
484
503
  exports.DialogContent = DialogContent;
485
504
  exports.DialogOverlay = DialogOverlay;
@@ -1 +1 @@
1
- {"version":3,"file":"dialog-panel.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.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\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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","x_google_ignoreList":[0]}
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DialogPanel={})}(this,(function(e){"use strict";const t=e=>Array.from(e.querySelectorAll('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'));class FocusTrap extends HTMLElement{static styleInjected=!1;constructor(){super(),this.trapStart=null,this.trapEnd=null,FocusTrap.styleInjected||(this.injectStyles(),FocusTrap.styleInjected=!0)}injectStyles(){const e=document.createElement("style");e.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 ",document.head.appendChild(e)}connectedCallback(){this.setupTrap(),this.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){this.removeEventListener("keydown",this.handleKeyDown)}setupTrap(){0!==t(this).length&&(this.trapStart=document.createElement("focus-trap-start"),this.trapEnd=document.createElement("focus-trap-end"),this.prepend(this.trapStart),this.append(this.trapEnd))}handleKeyDown=e=>{"Escape"===e.key&&(e.preventDefault(),this.exitTrap())};exitTrap(){const e=this.closest('[aria-hidden="false"]');if(!e)return;e.setAttribute("aria-hidden","true");const t=document.querySelector(`[aria-expanded="true"][aria-controls="${e.id}"]`);t&&(t.setAttribute("aria-expanded","false"),t.focus())}}class FocusTrapStart extends HTMLElement{connectedCallback(){this.setAttribute("tabindex","0"),this.addEventListener("focus",this.handleFocus)}disconnectedCallback(){this.removeEventListener("focus",this.handleFocus)}handleFocus=e=>{const n=this.closest("focus-trap"),s=t(n);if(0===s.length)return;const i=s[0],a=s[s.length-1];e.relatedTarget===i?a.focus():i.focus()}}class FocusTrapEnd extends HTMLElement{connectedCallback(){this.setAttribute("tabindex","0"),this.addEventListener("focus",this.handleFocus)}disconnectedCallback(){this.removeEventListener("focus",this.handleFocus)}handleFocus=()=>{this.closest("focus-trap").querySelector("focus-trap-start").focus()}}customElements.define("focus-trap",FocusTrap),customElements.define("focus-trap-start",FocusTrapStart),customElements.define("focus-trap-end",FocusTrapEnd);class DialogPanel extends HTMLElement{#e;#t=0;disconnectedCallback(){const e=this;e.contentPanel&&e.contentPanel.removeEventListener("transitionend",e.#e),document.body.classList.remove("overflow-hidden"),this.#n()}#s(){this.#t=window.pageYOffset,document.body.classList.add("overflow-hidden"),document.body.style.top=`-${this.#t}px`}#n(){document.body.classList.remove("overflow-hidden"),document.body.style.removeProperty("top"),window.scrollTo(0,this.#t)}constructor(){super();const e=this;if(e.id=e.getAttribute("id"),e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-hidden","true"),e.contentPanel=e.querySelector("dialog-content"),e.focusTrap=document.createElement("focus-trap"),e.triggerEl=null,e.#e=t=>{"opacity"===t.propertyName&&"true"===e.getAttribute("aria-hidden")&&(e.contentPanel.classList.add("hidden"),e.dispatchEvent(new CustomEvent("afterHide",{bubbles:!0,detail:{triggerElement:e.triggerEl}})))},!e.getAttribute("aria-labelledby")){const t=e.querySelector("h1, h2, h3");t&&!t.id&&(t.id=`${e.id}-title`),t?.id&&e.setAttribute("aria-labelledby",t.id)}e.contentPanel.parentNode.insertBefore(e.focusTrap,e.contentPanel),e.focusTrap.appendChild(e.contentPanel),e.focusTrap.setupTrap(),e.prepend(document.createElement("dialog-overlay")),e.#i(),e.#a()}#i(){const e=this;document.addEventListener("click",(t=>{const n=t.target.closest(`[aria-controls="${e.id}"]`);n&&("true"===n.getAttribute("data-prevent-default")&&t.preventDefault(),e.show(n))})),e.addEventListener("click",(t=>{t.target.closest('[data-action="hide-dialog"]')&&e.hide()})),e.contentPanel.addEventListener("transitionend",e.#e)}#a(){this.addEventListener("keydown",(e=>{"Escape"===e.key&&this.hide()}))}show(e=null){const t=this;t.triggerEl=e||!1;const n=new CustomEvent("beforeShow",{bubbles:!0,cancelable:!0,detail:{triggerElement:t.triggerEl}});return!!t.dispatchEvent(n)&&(t.contentPanel.classList.remove("hidden"),requestAnimationFrame((()=>{t.setAttribute("aria-hidden","false"),t.triggerEl&&t.triggerEl.setAttribute("aria-expanded","true"),t.#s();const e=t.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');e&&requestAnimationFrame((()=>{e.focus()})),t.dispatchEvent(new CustomEvent("show",{bubbles:!0,detail:{triggerElement:t.triggerEl}}))})),!0)}hide(){const e=this,t=new CustomEvent("beforeHide",{bubbles:!0,cancelable:!0,detail:{triggerElement:e.triggerEl}});return!!e.dispatchEvent(t)&&(e.#n(),e.triggerEl&&(e.triggerEl.focus(),e.triggerEl.setAttribute("aria-expanded","false")),e.setAttribute("aria-hidden","true"),e.dispatchEvent(new CustomEvent("hide",{bubbles:!0,detail:{triggerElement:e.triggerEl}})),!0)}}class DialogOverlay extends HTMLElement{constructor(){super(),this.setAttribute("tabindex","-1"),this.setAttribute("aria-hidden","true"),this.dialogPanel=this.closest("dialog-panel"),this.#i()}#i(){this.addEventListener("click",(()=>{this.dialogPanel.hide()}))}}class DialogContent extends HTMLElement{constructor(){super(),this.setAttribute("role","document")}}customElements.define("dialog-panel",DialogPanel),customElements.define("dialog-overlay",DialogOverlay),customElements.define("dialog-content",DialogContent),e.DialogContent=DialogContent,e.DialogOverlay=DialogOverlay,e.DialogPanel=DialogPanel,e.default=DialogPanel,Object.defineProperty(e,"__esModule",{value:!0})}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DialogPanel={})}(this,(function(e){"use strict";const t=e=>Array.from(e.querySelectorAll('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'));class FocusTrap extends HTMLElement{static styleInjected=!1;constructor(){super(),this.trapStart=null,this.trapEnd=null,FocusTrap.styleInjected||(this.injectStyles(),FocusTrap.styleInjected=!0)}injectStyles(){const e=document.createElement("style");e.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 ",document.head.appendChild(e)}connectedCallback(){this.setupTrap(),this.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){this.removeEventListener("keydown",this.handleKeyDown)}setupTrap(){0!==t(this).length&&(this.trapStart=document.createElement("focus-trap-start"),this.trapEnd=document.createElement("focus-trap-end"),this.prepend(this.trapStart),this.append(this.trapEnd))}handleKeyDown=e=>{"Escape"===e.key&&(e.preventDefault(),this.exitTrap())};exitTrap(){const e=this.closest('[aria-hidden="false"]');if(!e)return;e.setAttribute("aria-hidden","true");const t=document.querySelector(`[aria-expanded="true"][aria-controls="${e.id}"]`);t&&(t.setAttribute("aria-expanded","false"),t.focus())}}class FocusTrapStart extends HTMLElement{connectedCallback(){this.setAttribute("tabindex","0"),this.addEventListener("focus",this.handleFocus)}disconnectedCallback(){this.removeEventListener("focus",this.handleFocus)}handleFocus=e=>{const n=this.closest("focus-trap"),s=t(n);if(0===s.length)return;const a=s[0],i=s[s.length-1];e.relatedTarget===a?i.focus():a.focus()}}class FocusTrapEnd extends HTMLElement{connectedCallback(){this.setAttribute("tabindex","0"),this.addEventListener("focus",this.handleFocus)}disconnectedCallback(){this.removeEventListener("focus",this.handleFocus)}handleFocus=()=>{this.closest("focus-trap").querySelector("focus-trap-start").focus()}}customElements.define("focus-trap",FocusTrap),customElements.define("focus-trap-start",FocusTrapStart),customElements.define("focus-trap-end",FocusTrapEnd);class DialogPanel extends HTMLElement{#e;#t=0;disconnectedCallback(){const e=this;e.contentPanel&&e.contentPanel.removeEventListener("transitionend",e.#e),document.body.classList.remove("overflow-hidden"),this.#n()}#s(){this.#t=window.pageYOffset,document.body.classList.add("overflow-hidden"),document.body.style.top=`-${this.#t}px`}#n(){document.body.classList.remove("overflow-hidden"),document.body.style.removeProperty("top"),window.scrollTo(0,this.#t)}constructor(){super();const e=this;if(e.id=e.getAttribute("id"),e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-hidden","true"),e.contentPanel=e.querySelector("dialog-content"),e.focusTrap=document.createElement("focus-trap"),e.triggerEl=null,e.#e=t=>{"opacity"===t.propertyName&&"true"===e.getAttribute("aria-hidden")&&(e.contentPanel.classList.add("hidden"),e.dispatchEvent(new CustomEvent("afterHide",{bubbles:!0,detail:{triggerElement:e.triggerEl}})))},!e.getAttribute("aria-labelledby")){const t=e.querySelector("h1, h2, h3");t&&!t.id&&(t.id=`${e.id}-title`),t?.id&&e.setAttribute("aria-labelledby",t.id)}e.contentPanel.parentNode.insertBefore(e.focusTrap,e.contentPanel),e.focusTrap.appendChild(e.contentPanel),e.focusTrap.setupTrap(),e.prepend(document.createElement("dialog-overlay")),e.#a(),e.#i()}#a(){const e=this;document.addEventListener("click",(t=>{const n=t.target.closest(`[aria-controls="${e.id}"]`);n&&("true"===n.getAttribute("data-prevent-default")&&t.preventDefault(),e.show(n))})),e.addEventListener("click",(t=>{t.target.closest('[data-action="hide-dialog"]')&&e.hide()})),e.contentPanel.addEventListener("transitionend",e.#e)}#i(){this.addEventListener("keydown",(e=>{"Escape"===e.key&&this.hide()}))}show(e=null){const t=this;t.triggerEl=e||!1;const n=new CustomEvent("beforeShow",{bubbles:!0,cancelable:!0,detail:{triggerElement:t.triggerEl}});return!!t.dispatchEvent(n)&&(t.contentPanel.classList.remove("hidden"),requestAnimationFrame((()=>{t.setAttribute("aria-hidden","false"),t.triggerEl&&t.triggerEl.setAttribute("aria-expanded","true"),t.#s();const e=t.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');e&&requestAnimationFrame((()=>{e.focus()})),t.dispatchEvent(new CustomEvent("show",{bubbles:!0,detail:{triggerElement:t.triggerEl}}))})),!0)}hide(){const e=this,t=new CustomEvent("beforeHide",{bubbles:!0,cancelable:!0,detail:{triggerElement:e.triggerEl}});return!!e.dispatchEvent(t)&&(e.#n(),e.triggerEl&&(e.triggerEl.focus(),e.triggerEl.setAttribute("aria-expanded","false")),e.setAttribute("aria-hidden","true"),e.dispatchEvent(new CustomEvent("hide",{bubbles:!0,detail:{triggerElement:e.triggerEl}})),!0)}}class DialogOverlay extends HTMLElement{constructor(){super(),this.setAttribute("tabindex","-1"),this.setAttribute("aria-hidden","true"),this.dialogPanel=this.closest("dialog-panel"),this.#a()}#a(){this.addEventListener("click",(()=>{this.dialogPanel.hide()}))}}class DialogContent extends HTMLElement{constructor(){super(),this.setAttribute("role","document")}}customElements.get("dialog-panel")||customElements.define("dialog-panel",DialogPanel),customElements.get("dialog-overlay")||customElements.define("dialog-overlay",DialogOverlay),customElements.get("dialog-content")||customElements.define("dialog-content",DialogContent),e.DialogContent=DialogContent,e.DialogOverlay=DialogOverlay,e.DialogPanel=DialogPanel,e.default=DialogPanel,Object.defineProperty(e,"__esModule",{value:!0})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magic-spells/dialog-panel",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A lightweight, customizable Dialog Panel web component for creating accessible and responsive modal dialogs.",
5
5
  "author": "Cory Schulz",
6
6
  "license": "MIT",
@@ -8,21 +8,24 @@ import '@magic-spells/focus-trap';
8
8
  class DialogPanel extends HTMLElement {
9
9
  #handleTransitionEnd;
10
10
  #scrollPosition = 0;
11
-
11
+
12
12
  /**
13
13
  * Clean up event listeners when component is removed from DOM
14
14
  */
15
15
  disconnectedCallback() {
16
16
  const _ = this;
17
17
  if (_.contentPanel) {
18
- _.contentPanel.removeEventListener('transitionend', _.#handleTransitionEnd);
18
+ _.contentPanel.removeEventListener(
19
+ 'transitionend',
20
+ _.#handleTransitionEnd
21
+ );
19
22
  }
20
-
23
+
21
24
  // Ensure body scroll is restored if component is removed while open
22
25
  document.body.classList.remove('overflow-hidden');
23
26
  this.#restoreScroll();
24
27
  }
25
-
28
+
26
29
  /**
27
30
  * Saves current scroll position and locks body scrolling
28
31
  * @private
@@ -31,12 +34,12 @@ class DialogPanel extends HTMLElement {
31
34
  const _ = this;
32
35
  // Save current scroll position
33
36
  _.#scrollPosition = window.pageYOffset;
34
-
37
+
35
38
  // Apply fixed position to body
36
39
  document.body.classList.add('overflow-hidden');
37
40
  document.body.style.top = `-${_.#scrollPosition}px`;
38
41
  }
39
-
42
+
40
43
  /**
41
44
  * Restores scroll position when dialog is closed
42
45
  * @private
@@ -46,7 +49,7 @@ class DialogPanel extends HTMLElement {
46
49
  // Remove fixed positioning
47
50
  document.body.classList.remove('overflow-hidden');
48
51
  document.body.style.removeProperty('top');
49
-
52
+
50
53
  // Restore scroll position
51
54
  window.scrollTo(0, _.#scrollPosition);
52
55
  }
@@ -64,17 +67,22 @@ class DialogPanel extends HTMLElement {
64
67
  _.contentPanel = _.querySelector('dialog-content');
65
68
  _.focusTrap = document.createElement('focus-trap');
66
69
  _.triggerEl = null;
67
-
70
+
68
71
  // Create a handler for transition end events
69
72
  _.#handleTransitionEnd = (e) => {
70
- if (e.propertyName === 'opacity' && _.getAttribute('aria-hidden') === 'true') {
73
+ if (
74
+ e.propertyName === 'opacity' &&
75
+ _.getAttribute('aria-hidden') === 'true'
76
+ ) {
71
77
  _.contentPanel.classList.add('hidden');
72
-
78
+
73
79
  // Dispatch afterHide event - dialog has completed its transition
74
- _.dispatchEvent(new CustomEvent('afterHide', {
75
- bubbles: true,
76
- detail: { triggerElement: _.triggerEl }
77
- }));
80
+ _.dispatchEvent(
81
+ new CustomEvent('afterHide', {
82
+ bubbles: true,
83
+ detail: { triggerElement: _.triggerEl },
84
+ })
85
+ );
78
86
  }
79
87
  };
80
88
 
@@ -109,12 +117,10 @@ class DialogPanel extends HTMLElement {
109
117
  */
110
118
  #bindUI() {
111
119
  const _ = this;
112
-
120
+
113
121
  // Handle trigger buttons
114
122
  document.addEventListener('click', (e) => {
115
- const trigger = e.target.closest(
116
- `[aria-controls="${_.id}"]`
117
- );
123
+ const trigger = e.target.closest(`[aria-controls="${_.id}"]`);
118
124
  if (!trigger) return;
119
125
 
120
126
  if (trigger.getAttribute('data-prevent-default') === 'true') {
@@ -129,9 +135,12 @@ class DialogPanel extends HTMLElement {
129
135
  if (!e.target.closest('[data-action="hide-dialog"]')) return;
130
136
  _.hide();
131
137
  });
132
-
138
+
133
139
  // Add transition end listener
134
- _.contentPanel.addEventListener('transitionend', _.#handleTransitionEnd);
140
+ _.contentPanel.addEventListener(
141
+ 'transitionend',
142
+ _.#handleTransitionEnd
143
+ );
135
144
  }
136
145
 
137
146
  /**
@@ -161,17 +170,17 @@ class DialogPanel extends HTMLElement {
161
170
  const beforeShowEvent = new CustomEvent('beforeShow', {
162
171
  bubbles: true,
163
172
  cancelable: true,
164
- detail: { triggerElement: _.triggerEl }
173
+ detail: { triggerElement: _.triggerEl },
165
174
  });
166
-
175
+
167
176
  const showAllowed = _.dispatchEvent(beforeShowEvent);
168
-
177
+
169
178
  // If event was canceled (preventDefault was called), don't show the dialog
170
179
  if (!showAllowed) return false;
171
180
 
172
181
  // Remove the hidden class first to ensure content is rendered
173
182
  _.contentPanel.classList.remove('hidden');
174
-
183
+
175
184
  // Give the browser a moment to process before starting animation
176
185
  requestAnimationFrame(() => {
177
186
  // Update ARIA states
@@ -179,10 +188,10 @@ class DialogPanel extends HTMLElement {
179
188
  if (_.triggerEl) {
180
189
  _.triggerEl.setAttribute('aria-expanded', 'true');
181
190
  }
182
-
191
+
183
192
  // Lock body scrolling and save scroll position
184
193
  _.#lockScroll();
185
-
194
+
186
195
  // Focus management
187
196
  const firstFocusable = _.querySelector(
188
197
  'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
@@ -192,14 +201,16 @@ class DialogPanel extends HTMLElement {
192
201
  firstFocusable.focus();
193
202
  });
194
203
  }
195
-
204
+
196
205
  // Dispatch show event - dialog is now visible
197
- _.dispatchEvent(new CustomEvent('show', {
198
- bubbles: true,
199
- detail: { triggerElement: _.triggerEl }
200
- }));
206
+ _.dispatchEvent(
207
+ new CustomEvent('show', {
208
+ bubbles: true,
209
+ detail: { triggerElement: _.triggerEl },
210
+ })
211
+ );
201
212
  });
202
-
213
+
203
214
  return true;
204
215
  }
205
216
 
@@ -212,19 +223,19 @@ class DialogPanel extends HTMLElement {
212
223
  */
213
224
  hide() {
214
225
  const _ = this;
215
-
226
+
216
227
  // Dispatch beforeHide event - allows preventing the dialog from closing
217
228
  const beforeHideEvent = new CustomEvent('beforeHide', {
218
229
  bubbles: true,
219
230
  cancelable: true,
220
- detail: { triggerElement: _.triggerEl }
231
+ detail: { triggerElement: _.triggerEl },
221
232
  });
222
-
233
+
223
234
  const hideAllowed = _.dispatchEvent(beforeHideEvent);
224
-
235
+
225
236
  // If event was canceled (preventDefault was called), don't hide the dialog
226
237
  if (!hideAllowed) return false;
227
-
238
+
228
239
  // Restore body scroll and scroll position
229
240
  _.#restoreScroll();
230
241
 
@@ -239,13 +250,15 @@ class DialogPanel extends HTMLElement {
239
250
  // Set aria-hidden to start transition
240
251
  // The transitionend event handler will add display:none when complete
241
252
  _.setAttribute('aria-hidden', 'true');
242
-
253
+
243
254
  // Dispatch hide event - dialog is now starting to hide
244
- _.dispatchEvent(new CustomEvent('hide', {
245
- bubbles: true,
246
- detail: { triggerElement: _.triggerEl }
247
- }));
248
-
255
+ _.dispatchEvent(
256
+ new CustomEvent('hide', {
257
+ bubbles: true,
258
+ detail: { triggerElement: _.triggerEl },
259
+ })
260
+ );
261
+
249
262
  return true;
250
263
  }
251
264
  }
@@ -281,9 +294,15 @@ class DialogContent extends HTMLElement {
281
294
  }
282
295
  }
283
296
 
284
- customElements.define('dialog-panel', DialogPanel);
285
- customElements.define('dialog-overlay', DialogOverlay);
286
- customElements.define('dialog-content', DialogContent);
297
+ if (!customElements.get('dialog-panel')) {
298
+ customElements.define('dialog-panel', DialogPanel);
299
+ }
300
+ if (!customElements.get('dialog-overlay')) {
301
+ customElements.define('dialog-overlay', DialogOverlay);
302
+ }
303
+ if (!customElements.get('dialog-content')) {
304
+ customElements.define('dialog-content', DialogContent);
305
+ }
287
306
 
288
307
  export { DialogPanel, DialogOverlay, DialogContent };
289
- export default DialogPanel;
308
+ export default DialogPanel;