@magic-spells/dialog-panel 0.2.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -114
- package/dist/dialog-panel.cjs.js +281 -230
- package/dist/dialog-panel.cjs.js.map +1 -1
- package/dist/dialog-panel.css +108 -62
- package/dist/dialog-panel.esm.js +281 -226
- package/dist/dialog-panel.esm.js.map +1 -1
- package/dist/dialog-panel.js +273 -413
- package/dist/dialog-panel.js.map +1 -1
- package/dist/dialog-panel.min.css +1 -1
- package/dist/dialog-panel.min.js +1 -1
- package/package.json +11 -20
- package/src/dialog-panel.css +117 -0
- package/src/dialog-panel.js +282 -227
- package/dist/dialog-panel.scss +0 -2
- package/dist/scss/dialog-panel.scss +0 -73
- package/dist/scss/variables.scss +0 -54
- package/src/index.scss +0 -2
- package/src/scss/dialog-panel.scss +0 -73
- package/src/scss/variables.scss +0 -54
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
1
|
+
{"version":3,"file":"dialog-panel.cjs.js","sources":["../src/dialog-panel.js"],"sourcesContent":["import './dialog-panel.css';\n\n/**\n * DialogPanel - A lightweight web component wrapper for native <dialog> elements\n * with state-driven animations.\n *\n * @extends HTMLElement\n *\n * @property {string} state - Current state: 'hidden' | 'showing' | 'shown' | 'hiding'\n * @property {HTMLDialogElement} dialog - Reference to inner <dialog> element\n * @property {boolean} isOpen - True if state is 'showing' or 'shown'\n * @property {HTMLElement|null} triggerElement - Element that triggered current action\n *\n * @fires beforeShow - Fired before showing starts (cancelable)\n * @fires shown - Fired after show animation completes\n * @fires beforeHide - Fired before hiding starts (cancelable)\n * @fires hidden - Fired after hide animation completes\n */\nclass DialogPanel extends HTMLElement {\n\t// Private fields\n\t#state = 'hidden';\n\t#triggerElement = null;\n\t#dialog = null;\n\t#result = null;\n\n\t// Event handler references for cleanup\n\t#handlers = {\n\t\tclick: null,\n\t\tdialogClick: null,\n\t\tcancel: null,\n\t};\n\n\t// Animation cleanup references\n\t#pendingRAF = null;\n\t#pendingTimeout = null;\n\n\t// Fallback timeout for transitionend (in ms)\n\tstatic TRANSITION_FALLBACK_TIMEOUT = 500;\n\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// Find inner dialog element\n\t\t_.#dialog = _.querySelector('dialog');\n\n\t\tif (!_.#dialog) {\n\t\t\tconsole.warn(\n\t\t\t\t'DialogPanel: No <dialog> element found inside <dialog-panel>'\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Auto-create dialog-backdrop if not present\n\t\tif (!_.querySelector('dialog-backdrop')) {\n\t\t\tconst backdrop = document.createElement('dialog-backdrop');\n\t\t\t_.insertBefore(backdrop, _.firstChild);\n\t\t}\n\n\t\t// Set initial state attribute\n\t\t_.#setState('hidden');\n\n\t\t// Bind event handlers\n\t\t_.#bindEvents();\n\t}\n\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// Cancel pending animations\n\t\tif (_.#pendingRAF) {\n\t\t\tcancelAnimationFrame(_.#pendingRAF);\n\t\t\t_.#pendingRAF = null;\n\t\t}\n\t\tif (_.#pendingTimeout) {\n\t\t\tclearTimeout(_.#pendingTimeout);\n\t\t\t_.#pendingTimeout = null;\n\t\t}\n\n\t\t// Clean up event listeners\n\t\tif (_.#handlers.click) {\n\t\t\t_.removeEventListener('click', _.#handlers.click);\n\t\t}\n\t\tif (_.#dialog) {\n\t\t\tif (_.#handlers.dialogClick) {\n\t\t\t\t_.#dialog.removeEventListener(\n\t\t\t\t\t'click',\n\t\t\t\t\t_.#handlers.dialogClick\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (_.#handlers.cancel) {\n\t\t\t\t_.#dialog.removeEventListener('cancel', _.#handlers.cancel);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Bind event listeners for close buttons, backdrop, and escape key\n\t * @private\n\t */\n\t#bindEvents() {\n\t\tconst _ = this;\n\n\t\t// Handle close buttons with data-action-hide-dialog\n\t\t_.#handlers.click = (e) => {\n\t\t\tconst trigger = e.target.closest('[data-action-hide-dialog]');\n\t\t\tif (trigger) {\n\t\t\t\te.stopPropagation();\n\t\t\t\t_.hide(trigger);\n\t\t\t}\n\t\t};\n\t\t_.addEventListener('click', _.#handlers.click);\n\n\t\t// Handle backdrop click - detect clicks outside dialog bounds\n\t\t// This works because clicks on ::backdrop still fire on the dialog element\n\t\t_.#handlers.dialogClick = (e) => {\n\t\t\tconst rect = _.#dialog.getBoundingClientRect();\n\t\t\tconst clickedOutside =\n\t\t\t\te.clientX < rect.left ||\n\t\t\t\te.clientX > rect.right ||\n\t\t\t\te.clientY < rect.top ||\n\t\t\t\te.clientY > rect.bottom;\n\t\t\tif (clickedOutside) {\n\t\t\t\te.stopPropagation();\n\t\t\t\t_.hide();\n\t\t\t}\n\t\t};\n\t\t_.#dialog.addEventListener('click', _.#handlers.dialogClick);\n\n\t\t// Handle escape key - intercept native cancel and animate close\n\t\t_.#handlers.cancel = (e) => {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\t_.hide();\n\t\t};\n\t\t_.#dialog.addEventListener('cancel', _.#handlers.cancel);\n\t}\n\n\t/**\n\t * Show the dialog with animation\n\t * @param {HTMLElement} [triggerEl=null] - The element that triggered the show\n\t * @returns {boolean} False if show was prevented via beforeShow event\n\t */\n\tshow(triggerEl = null) {\n\t\tconst _ = this;\n\n\t\t// Check if already showing/shown\n\t\tif (_.#state === 'showing' || _.#state === 'shown') return true;\n\n\t\t// If currently hiding, ignore (let hide complete first)\n\t\tif (_.#state === 'hiding') return false;\n\n\t\t// Store trigger element for focus return later\n\t\t_.#triggerElement = triggerEl || null;\n\n\t\t// Fire beforeShow (cancelable)\n\t\tif (!_.#emit('beforeShow', { cancelable: true })) return false;\n\n\t\t// Set state to 'showing' and open native dialog\n\t\t_.#setState('showing');\n\t\t_.#dialog.showModal();\n\n\t\t// Double RAF ensures browser has painted the 'showing' state\n\t\t// before we transition to 'shown'\n\t\t_.#pendingRAF = requestAnimationFrame(() => {\n\t\t\t_.#pendingRAF = requestAnimationFrame(() => {\n\t\t\t\t_.#pendingRAF = null;\n\t\t\t\t_.#setState('shown');\n\n\t\t\t\t// Wait for transition to complete before firing 'shown' event\n\t\t\t\t_.#waitForTransition(() => {\n\t\t\t\t\t_.#emit('shown');\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Hide the dialog with animation\n\t * @param {HTMLElement} [triggerEl=null] - The element that triggered the hide\n\t * @returns {boolean} False if hide was prevented via beforeHide event\n\t */\n\thide(triggerEl = null) {\n\t\tconst _ = this;\n\n\t\t// Check if already hiding/hidden\n\t\tif (_.#state === 'hiding' || _.#state === 'hidden') return true;\n\n\t\t// If currently showing, ignore (let show complete first)\n\t\tif (_.#state === 'showing') return false;\n\n\t\t// Capture result from trigger element\n\t\t_.#result = triggerEl?.dataset?.result ?? null;\n\n\t\t// Fire beforeHide (cancelable)\n\t\tif (\n\t\t\t!_.#emit('beforeHide', {\n\t\t\t\tcancelable: true,\n\t\t\t\tresult: _.#result,\n\t\t\t\ttriggerElement: triggerEl,\n\t\t\t})\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Set state to 'hiding' - this triggers CSS exit animation\n\t\t_.#setState('hiding');\n\n\t\t// Wait for transition to complete\n\t\t_.#waitForTransition(() => {\n\t\t\t_.#dialog.close();\n\t\t\t_.#setState('hidden');\n\t\t\t_.#emit('hidden', {\n\t\t\t\tresult: _.#result,\n\t\t\t\ttriggerElement: triggerEl,\n\t\t\t});\n\n\t\t\t// Return focus to trigger element\n\t\t\tif (_.#triggerElement) _.#triggerElement.focus();\n\n\t\t\t// Clean up\n\t\t\t_.#triggerElement = null;\n\t\t\t_.#result = null;\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Wait for CSS transition to complete with fallback timeout\n\t * @param {Function} callback - Called when transition completes\n\t * @private\n\t */\n\t#waitForTransition(callback) {\n\t\tconst _ = this;\n\t\tlet called = false;\n\n\t\tconst done = () => {\n\t\t\tif (called) return;\n\t\t\tcalled = true;\n\t\t\t_.#dialog.removeEventListener('transitionend', onTransitionEnd);\n\t\t\tif (_.#pendingTimeout) {\n\t\t\t\tclearTimeout(_.#pendingTimeout);\n\t\t\t\t_.#pendingTimeout = null;\n\t\t\t}\n\t\t\tcallback();\n\t\t};\n\n\t\tconst onTransitionEnd = (e) => {\n\t\t\tif (e.target === _.#dialog) done();\n\t\t};\n\n\t\t_.#dialog.addEventListener('transitionend', onTransitionEnd);\n\n\t\t_.#pendingTimeout = setTimeout(\n\t\t\tdone,\n\t\t\tDialogPanel.TRANSITION_FALLBACK_TIMEOUT\n\t\t);\n\t}\n\n\t/**\n\t * Set the component state\n\t * @param {string} newState - The new state\n\t * @private\n\t */\n\t#setState(newState) {\n\t\tthis.#state = newState;\n\t\tthis.setAttribute('state', newState);\n\t}\n\n\t/**\n\t * Emit a custom event\n\t * @param {string} name - Event name\n\t * @param {Object} options - Event options\n\t * @returns {boolean} False if event was cancelled\n\t * @private\n\t */\n\t#emit(name, options = {}) {\n\t\tconst _ = this;\n\t\tconst { cancelable = false, ...detail } = options;\n\n\t\tconst event = new CustomEvent(name, {\n\t\t\tbubbles: true,\n\t\t\tcomposed: true,\n\t\t\tcancelable,\n\t\t\tdetail: {\n\t\t\t\ttriggerElement: _.#triggerElement,\n\t\t\t\tresult: _.#result,\n\t\t\t\tstate: _.#state,\n\t\t\t\t...detail,\n\t\t\t},\n\t\t});\n\n\t\treturn _.dispatchEvent(event);\n\t}\n\n\t// Read-only properties\n\tget state() {\n\t\treturn this.#state;\n\t}\n\tget dialog() {\n\t\treturn this.#dialog;\n\t}\n\tget isOpen() {\n\t\treturn this.#state === 'showing' || this.#state === 'shown';\n\t}\n\tget triggerElement() {\n\t\treturn this.#triggerElement;\n\t}\n}\n\n/**\n * DialogBackdrop - A custom backdrop element that animates with the dialog-panel state.\n * Use this instead of native ::backdrop for consistent cross-browser animations.\n *\n * @extends HTMLElement\n */\nclass DialogBackdrop extends HTMLElement {\n\t#panel = null;\n\t#handlers = {\n\t\tclick: null,\n\t};\n\n\tconnectedCallback() {\n\t\tconst _ = this;\n\n\t\t// Find parent dialog-panel\n\t\t_.#panel = _.closest('dialog-panel');\n\n\t\tif (!_.#panel) {\n\t\t\tconsole.warn(\n\t\t\t\t'DialogBackdrop: Must be inside a <dialog-panel> element'\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle click to close\n\t\t_.#handlers.click = () => {\n\t\t\t_.#panel.hide();\n\t\t};\n\t\t_.addEventListener('click', _.#handlers.click);\n\t}\n\n\tdisconnectedCallback() {\n\t\tconst _ = this;\n\t\tif (_.#handlers.click) {\n\t\t\t_.removeEventListener('click', _.#handlers.click);\n\t\t}\n\t}\n}\n\n// Register the custom elements\n// Note: dialog-backdrop must be defined BEFORE dialog-panel,\n// because dialog-panel's connectedCallback may create dialog-backdrop elements\nif (!customElements.get('dialog-backdrop')) {\n\tcustomElements.define('dialog-backdrop', DialogBackdrop);\n}\nif (!customElements.get('dialog-panel')) {\n\tcustomElements.define('dialog-panel', DialogPanel);\n}\n\nexport { DialogPanel, DialogBackdrop };\n"],"names":[],"mappings":"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"}
|
package/dist/dialog-panel.css
CHANGED
|
@@ -1,71 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
--dp-overlay-z-index: 1000;
|
|
8
|
-
--dp-overlay-background: rgba(20, 23, 26, 0.4);
|
|
9
|
-
--dp-overlay-backdrop-filter: blur(2px) saturate(120%);
|
|
10
|
-
--dp-overlay-transition: all 400ms ease-out;
|
|
11
|
-
--dp-content-display: block;
|
|
12
|
-
--dp-content-background: white;
|
|
13
|
-
--dp-content-z-index: 1001;
|
|
14
|
-
--dp-content-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
|
15
|
-
--dp-content-border-radius: 8px;
|
|
16
|
-
--dp-transition-duration: 400ms;
|
|
17
|
-
--dp-transition-timing: ease-out;
|
|
18
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* dialog-panel basic centered modal styles
|
|
3
|
+
*
|
|
4
|
+
* This provides a simple fade in/out animation for a centered modal dialog.
|
|
5
|
+
* Developers can customize or replace these styles to match their design.
|
|
6
|
+
*/
|
|
19
7
|
|
|
8
|
+
/* Wrapper doesn't affect layout */
|
|
20
9
|
dialog-panel {
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
display: contents;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Base dialog styles with transitions */
|
|
14
|
+
dialog-panel > dialog {
|
|
15
|
+
border: none;
|
|
16
|
+
border-radius: 0.5rem;
|
|
17
|
+
padding: 0;
|
|
18
|
+
max-width: 32rem;
|
|
19
|
+
width: 90vw;
|
|
20
|
+
max-height: 85vh;
|
|
21
|
+
overflow: visible;
|
|
22
|
+
background: white;
|
|
23
|
+
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
|
24
|
+
|
|
25
|
+
/* Start hidden */
|
|
26
|
+
opacity: 0;
|
|
27
|
+
transform: scale(0.95);
|
|
28
|
+
|
|
29
|
+
/* Transition always defined on base */
|
|
30
|
+
transition:
|
|
31
|
+
opacity 0.3s ease-out,
|
|
32
|
+
transform 0.3s ease-out;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* When using dialog-backdrop element, make native ::backdrop transparent
|
|
36
|
+
but keep it clickable (clicks detected via bounding rect check) */
|
|
37
|
+
dialog-panel:has(dialog-backdrop) > dialog::backdrop {
|
|
38
|
+
background: transparent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Native backdrop (when not using dialog-backdrop) */
|
|
42
|
+
dialog-panel:not(:has(dialog-backdrop)) > dialog::backdrop {
|
|
43
|
+
background: rgba(0, 0, 0, 0.3);
|
|
44
|
+
opacity: 0;
|
|
45
|
+
transition: opacity 0.3s ease-out;
|
|
23
46
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
|
|
48
|
+
/* Custom dialog-backdrop element */
|
|
49
|
+
dialog-backdrop {
|
|
50
|
+
position: fixed;
|
|
51
|
+
background: rgba(0, 0, 0, 0.3);
|
|
52
|
+
opacity: 0;
|
|
53
|
+
transition: opacity 0.3s ease-out;
|
|
54
|
+
pointer-events: none;
|
|
55
|
+
z-index: 9999999;
|
|
56
|
+
top: 50%;
|
|
57
|
+
left: 50%;
|
|
58
|
+
width: 200vw;
|
|
59
|
+
height: 200dvh;
|
|
60
|
+
transform: translateY(-50%) translateX(-50%);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Showing state - dialog is open but still at initial values
|
|
64
|
+
(this is the starting point for the fade-in animation) */
|
|
65
|
+
dialog-panel[state='showing'] > dialog {
|
|
66
|
+
opacity: 0;
|
|
67
|
+
transform: scale(0.95);
|
|
30
68
|
}
|
|
31
69
|
|
|
32
|
-
|
|
33
|
-
dialog
|
|
34
|
-
|
|
35
|
-
top: 0;
|
|
36
|
-
left: 0;
|
|
37
|
-
width: 100vw;
|
|
38
|
-
height: 100vh;
|
|
39
|
-
opacity: 0;
|
|
40
|
-
pointer-events: none;
|
|
41
|
-
z-index: var(--dp-overlay-z-index, 1000);
|
|
42
|
-
transition: var(--dp-overlay-transition, all 300ms ease-out);
|
|
43
|
-
background-color: var(--dp-overlay-background, rgba(20, 23, 26, 0.4));
|
|
44
|
-
backdrop-filter: var(--dp-overlay-backdrop-filter, blur(2px) saturate(120%));
|
|
70
|
+
dialog-panel:not(:has(dialog-backdrop))[state='showing']
|
|
71
|
+
> dialog::backdrop {
|
|
72
|
+
opacity: 0;
|
|
45
73
|
}
|
|
46
74
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
transform: translate(-50%, -50%) scale(0.95);
|
|
52
|
-
max-width: 90vw;
|
|
53
|
-
max-height: 85vh;
|
|
54
|
-
display: var(--dp-content-display, block);
|
|
55
|
-
opacity: 0;
|
|
56
|
-
background: var(--dp-content-background, white);
|
|
57
|
-
pointer-events: none;
|
|
58
|
-
z-index: var(--dp-content-z-index, 1001);
|
|
59
|
-
box-shadow: var(--dp-content-shadow, 0 10px 25px rgba(0, 0, 0, 0.15));
|
|
60
|
-
border-radius: var(--dp-content-border-radius, 8px);
|
|
61
|
-
overflow: auto;
|
|
62
|
-
transition: opacity var(--dp-transition-duration, 300ms) var(--dp-transition-timing, ease-out), transform var(--dp-transition-duration, 300ms) var(--dp-transition-timing, ease-out);
|
|
63
|
-
/* When shown, reset transform to center */
|
|
64
|
-
/* When explicitly hidden, remove from layout */
|
|
75
|
+
/* Shown state - fully visible (animates from showing → shown) */
|
|
76
|
+
dialog-panel[state='shown'] > dialog {
|
|
77
|
+
opacity: 1;
|
|
78
|
+
transform: scale(1);
|
|
65
79
|
}
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
|
|
81
|
+
dialog-panel:not(:has(dialog-backdrop))[state='shown']
|
|
82
|
+
> dialog::backdrop {
|
|
83
|
+
opacity: 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Hiding state - faster exit animation */
|
|
87
|
+
dialog-panel[state='hiding'] > dialog {
|
|
88
|
+
opacity: 0;
|
|
89
|
+
transform: scale(0.95);
|
|
90
|
+
transition:
|
|
91
|
+
opacity 0.2s ease-in,
|
|
92
|
+
transform 0.2s ease-in;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
dialog-panel:not(:has(dialog-backdrop))[state='hiding']
|
|
96
|
+
> dialog::backdrop {
|
|
97
|
+
opacity: 0;
|
|
98
|
+
transition: opacity 0.2s ease-in;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* dialog-backdrop state animations */
|
|
102
|
+
dialog-panel[state='showing'] > dialog-backdrop,
|
|
103
|
+
dialog-panel[state='hidden'] > dialog-backdrop {
|
|
104
|
+
opacity: 0;
|
|
105
|
+
pointer-events: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
dialog-panel[state='shown'] > dialog-backdrop {
|
|
109
|
+
opacity: 1;
|
|
110
|
+
pointer-events: auto;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
dialog-panel[state='hiding'] > dialog-backdrop {
|
|
114
|
+
opacity: 0;
|
|
115
|
+
pointer-events: none;
|
|
116
|
+
transition: opacity 0.2s ease-in;
|
|
68
117
|
}
|
|
69
|
-
dialog-content.hidden {
|
|
70
|
-
display: none;
|
|
71
|
-
}
|