@substrate-system/dialog 0.0.7 → 0.0.8

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 CHANGED
@@ -22,6 +22,7 @@ See [smashingmagazine.com article](https://www.smashingmagazine.com/2022/04/cta-
22
22
  - [Install](#install)
23
23
  - [Use](#use)
24
24
  * [FOUCE](#fouce)
25
+ * [CSS](#css)
25
26
  * [Bundler](#bundler)
26
27
  * [HTML only](#html-only)
27
28
  - [API](#api)
@@ -95,6 +96,48 @@ body {
95
96
  }
96
97
  ```
97
98
 
99
+ ### CSS
100
+
101
+ Customize the CSS with some variables.
102
+
103
+ ```css
104
+ :root {
105
+ /* Overlay */
106
+ --modal-overlay-z-index: 100000;
107
+ --modal-overlay-background-color: rgba(0, 0, 0, 0.5);
108
+ --modal-overlay-padding-top: 20px;
109
+ --modal-overlay-padding-left: 20px;
110
+ --modal-overlay-padding-right: 20px;
111
+ --modal-overlay-padding-bottom: 20px;
112
+
113
+ /* Dialog */
114
+ --modal-dialog-background-color: #fff;
115
+ --modal-dialog-border-radius: 0;
116
+ --modal-dialog-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.5);
117
+ --modal-dialog-padding-top: 20px;
118
+ --modal-dialog-padding-left: 20px;
119
+ --modal-dialog-padding-right: 20px;
120
+ --modal-dialog-padding-bottom: 20px;
121
+ --modal-dialog-width: 500px;
122
+
123
+ /* Close button */
124
+ --modal-close-color: #fff;
125
+ --modal-close-background-color: #000;
126
+ --modal-close-border-radius: 50%;
127
+ --modal-close-box-shadow: 0 0 0 1px #fff;
128
+ --modal-close-display: block;
129
+ --modal-close-font-family: 'Arial', sans-serif;
130
+ --modal-close-font-size: 23px;
131
+ --modal-close-line-height: 26px;
132
+ --modal-close-width: 26px;
133
+
134
+ /* Close button hover/focus */
135
+ --modal-close-color-hover: #000;
136
+ --modal-close-background-color-hover: #fff;
137
+ --modal-close-box-shadow-hover: 0 0 0 1px #000;
138
+ }
139
+ ```
140
+
98
141
  ### Bundler
99
142
 
100
143
  Just import. This calls the global function `window.customElements.define`.
package/dist/index.cjs CHANGED
@@ -109,10 +109,9 @@ class ModalWindow extends HTMLElement {
109
109
  const overlay = document.createElement("div");
110
110
  overlay.setAttribute("data-modal-overlay", "");
111
111
  this._modalOverlay = overlay;
112
- const dialog = document.createElement("div");
112
+ const dialog = document.createElement("dialog");
113
113
  dialog.setAttribute("aria-modal", "true");
114
114
  dialog.setAttribute("data-modal-dialog", "");
115
- dialog.setAttribute("role", "dialog");
116
115
  dialog.tabIndex = -1;
117
116
  this._modal = dialog;
118
117
  if (this._closable && this._showIcon) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import { define } from '@substrate-system/web-component'\n\n// for docuement.querySelector\ndeclare global {\n interface HTMLElementTagNameMap {\n 'modal-window':ModalWindow\n }\n}\n\n/**\n * Modal window web component.\n *\n * Opens/closes via the `active` attribute:\n * modal.setAttribute('active', 'true') // open\n * modal.setAttribute('active', 'false') // close\n * modal.removeAttribute('active') // close\n *\n * Or via methods:\n * modal.open()\n * modal.close()\n */\n\n// ==========\n// Constants.\n// ==========\n\nconst ACTIVE = 'active'\nconst ANIMATED = 'animated'\nconst ANIMATION_DURATION = 250\nconst ARIA_DESCRIBEDBY = 'aria-describedby'\nconst ARIA_LABEL = 'aria-label'\nconst CLOSE = 'close'\nconst CLOSE_TITLE = 'Close'\nconst NO_ICON = 'no-icon'\nconst DATA_HIDE = 'data-modal-hide'\nconst DATA_SHOW = 'data-modal-show'\nconst DATA_VISIBLE = 'data-visible'\nconst EMPTY_STRING = ''\nconst ESCAPE = 'escape'\nconst FALSE = 'false'\nconst FOCUSIN = 'focusin'\nconst HIDDEN = 'hidden'\nconst KEYDOWN = 'keydown'\nconst MODAL_LABEL_FALLBACK = 'modal'\nconst PREFERS_REDUCED_MOTION = '(prefers-reduced-motion: reduce)'\nconst SPACE = ' '\nconst SPACE_REGEX = /\\s+/g\nconst STATIC = 'static'\nconst TAB = 'tab'\nconst TRUE = 'true'\n\nconst FOCUSABLE_SELECTORS = [\n '[contenteditable]',\n '[tabindex=\"0\"]:not([disabled])',\n 'a[href]',\n 'audio[controls]',\n 'button:not([disabled])',\n 'iframe',\n \"input:not([disabled]):not([type='hidden'])\",\n 'select:not([disabled])',\n 'summary',\n 'textarea:not([disabled])',\n 'video[controls]',\n].join(',')\n\n// ====================\n// The component\n// ====================\n\nexport class ModalWindow extends HTMLElement {\n // Element references (set during build).\n _buttonClose:HTMLButtonElement|null = null\n _modal:HTMLDivElement|null = null\n _modalOverlay:HTMLDivElement|null = null\n _modalScroll:HTMLDivElement|null = null\n _modalContent:HTMLDivElement|null = null\n _focusTrap1:HTMLSpanElement|null = null\n _focusTrap2:HTMLSpanElement|null = null\n _heading:HTMLElement|null = null\n\n static TAG:string = 'modal-window'\n\n // State.\n _activeElement:HTMLElement|null = null\n _isActive = false\n _isAnimated = true\n _isBuilt = false\n _isHideShow = false\n _isStatic = false\n _timerForHide:number|undefined\n _timerForShow:number|undefined\n _closable:boolean = true\n _showIcon:boolean = true\n\n // =======================\n // Lifecycle: constructor.\n // =======================\n\n constructor () {\n super()\n this._bind()\n }\n\n // ============================\n // Helper: build modal structure.\n // ============================\n\n _buildModal (contentNodes:Node[]) {\n // Create focus trap\n const createFocusTrap = () => {\n const trap = document.createElement('span')\n trap.setAttribute('aria-hidden', 'true')\n trap.setAttribute('data-modal-focus-trap', '')\n trap.tabIndex = 0\n return trap\n }\n\n // Create scroll container\n const scroll = document.createElement('div')\n scroll.setAttribute('data-modal-scroll', '')\n this._modalScroll = scroll\n\n // Create overlay\n const overlay = document.createElement('div')\n overlay.setAttribute('data-modal-overlay', '')\n this._modalOverlay = overlay\n\n // Create dialog\n const dialog = document.createElement('div')\n dialog.setAttribute('aria-modal', 'true')\n dialog.setAttribute('data-modal-dialog', '')\n dialog.setAttribute('role', 'dialog')\n dialog.tabIndex = -1\n this._modal = dialog\n\n // Create close button if closable and icon should be shown\n if (this._closable && this._showIcon) {\n const closeBtn = document.createElement('button')\n closeBtn.setAttribute('data-modal-close', '')\n closeBtn.type = 'button'\n closeBtn.innerHTML = '×'\n dialog.appendChild(closeBtn)\n this._buttonClose = closeBtn\n }\n\n // Create content wrapper\n const content = document.createElement('div')\n content.setAttribute('data-modal-content', '')\n this._modalContent = content\n\n // Move content nodes into the content wrapper\n contentNodes.forEach(node => {\n content.appendChild(node)\n })\n\n dialog.appendChild(content)\n\n // Create focus traps\n this._focusTrap1 = createFocusTrap()\n this._focusTrap2 = createFocusTrap()\n\n // Assemble structure\n overlay.appendChild(dialog)\n scroll.appendChild(this._focusTrap1)\n scroll.appendChild(overlay)\n scroll.appendChild(this._focusTrap2)\n\n // Add to component\n this.appendChild(scroll)\n }\n\n // ============================\n // Lifecycle: watch attributes.\n // ============================\n\n static get observedAttributes () {\n return [ACTIVE, ANIMATED, ARIA_DESCRIBEDBY, CLOSE, STATIC]\n }\n\n // ==============================\n // Lifecycle: attributes changed.\n // ==============================\n\n attributeChangedCallback (name: string, oldValue: string, newValue: string) {\n // Different old/new values?\n if (oldValue !== newValue) {\n // Changed [active=\"\u2026\"] value?\n if (name === ACTIVE) {\n this._setActiveFlag()\n }\n\n // Changed [animated=\"\u2026\"] value?\n if (name === ANIMATED) {\n this._setAnimationFlag()\n }\n\n // Changed [aria-describedby=\"\u2026\"] value?\n if (name === ARIA_DESCRIBEDBY) {\n this._setModalDescription()\n }\n\n // Changed [close=\"\u2026\"] value?\n if (name === CLOSE) {\n this._setCloseTitle()\n }\n\n // Changed [static=\"\u2026\"] value?\n if (name === STATIC) {\n this._setStaticFlag()\n }\n }\n }\n\n // ===========================\n // Lifecycle: component mount.\n // ===========================\n\n connectedCallback () {\n // Build modal structure once.\n if (!this._isBuilt) {\n this._closable = this.getAttribute('closable') !== 'false'\n this._showIcon = !this.hasAttribute(NO_ICON)\n\n // Get heading for aria-label.\n this._heading = this.querySelector('h1, h2, h3, h4, h5, h6')\n\n // Collect all child nodes.\n const contentNodes = Array.from(this.childNodes)\n\n // Build the modal structure.\n this._buildModal(contentNodes)\n\n // Set animation flag.\n this._setAnimationFlag()\n\n // Set close title.\n this._setCloseTitle()\n\n // Set modal label.\n this._setModalLabel()\n\n // Set modal description.\n this._setModalDescription()\n\n // Set static flag.\n this._setStaticFlag()\n\n // Set active flag.\n this._setActiveFlag()\n\n this._isBuilt = true\n }\n\n this._addEvents()\n }\n\n // =============================\n // Lifecycle: component unmount.\n // =============================\n\n disconnectedCallback () {\n this._removeEvents()\n }\n\n // ============================\n // Helper: bind `this` context.\n // ============================\n\n _bind () {\n const propertyNames = Object.getOwnPropertyNames(\n Object.getPrototypeOf(this)\n ) as (keyof ModalWindow)[]\n\n propertyNames.forEach((name) => {\n // Bind functions.\n if (typeof this[name] === 'function') {\n // @ts-expect-error bind\n this[name] = this[name].bind(this)\n }\n })\n }\n\n // ===================\n // Helper: add events.\n // ===================\n\n _addEvents () {\n // Prevent doubles.\n this._removeEvents()\n\n document.addEventListener(FOCUSIN, this._handleFocusIn)\n document.addEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.addEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.addEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ======================\n // Helper: remove events.\n // ======================\n\n _removeEvents () {\n document.removeEventListener(FOCUSIN, this._handleFocusIn)\n document.removeEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.removeEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.removeEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ===========================\n // Helper: set animation flag.\n // ===========================\n\n _setAnimationFlag () {\n this._isAnimated = this.getAttribute(ANIMATED) !== FALSE\n }\n\n // ========================\n // Helper: add close title.\n // ========================\n\n _setCloseTitle () {\n // Get title.\n const title = this.getAttribute(CLOSE) || CLOSE_TITLE\n\n // Set title.\n if (this._buttonClose) {\n this._buttonClose.title = title\n this._buttonClose.setAttribute(ARIA_LABEL, title)\n }\n }\n\n // ========================\n // Helper: add modal label.\n // ========================\n\n _setModalLabel () {\n // Set later.\n let label = MODAL_LABEL_FALLBACK\n\n // Heading exists?\n if (this._heading) {\n // Get text.\n label = this._heading.textContent || label\n label = label.trim().replace(SPACE_REGEX, SPACE)\n }\n\n // Set label.\n if (this._modal) {\n this._modal.setAttribute(ARIA_LABEL, label)\n }\n }\n\n // ==============================\n // Helper: set modal description.\n // ==============================\n\n _setModalDescription () {\n if (!this._modal) return\n\n const describedBy = this.getAttribute(ARIA_DESCRIBEDBY)\n\n if (describedBy) {\n this._modal.setAttribute(ARIA_DESCRIBEDBY, describedBy)\n } else {\n this._modal.removeAttribute(ARIA_DESCRIBEDBY)\n }\n }\n\n // ========================\n // Helper: set active flag.\n // ========================\n\n _setActiveFlag () {\n // Get flag.\n const isActive = this.getAttribute(ACTIVE) === TRUE\n\n // Set flag.\n this._isActive = isActive\n\n // Set display.\n this._toggleModalDisplay(() => {\n // Focus modal?\n if (this._isActive) {\n this._focusModal()\n }\n })\n }\n\n // ========================\n // Helper: set static flag.\n // ========================\n\n _setStaticFlag () {\n this._isStatic = this.getAttribute(STATIC) === TRUE\n }\n\n // ======================\n // Helper: focus element.\n // ======================\n\n _focusElement (element: HTMLElement) {\n window.requestAnimationFrame(() => {\n if (typeof element.focus === 'function') {\n element.focus()\n }\n })\n }\n\n // ====================\n // Helper: focus modal.\n // ====================\n\n _focusModal () {\n window.requestAnimationFrame(() => {\n if (this._modal) {\n this._modal.focus()\n }\n if (this._modalScroll) {\n this._modalScroll.scrollTo(0, 0)\n }\n })\n }\n\n // =============================\n // Helper: detect outside modal.\n // =============================\n\n _isOutsideModal (element?: HTMLElement) {\n // Early exit.\n if (!this._isActive || !element || !this._modal) {\n return false\n }\n\n // Has element?\n const hasElement = this.contains(element) || this._modal.contains(element)\n\n // Get boolean.\n const bool = !hasElement\n\n // Expose boolean.\n return bool\n }\n\n // ===========================\n // Helper: detect motion pref.\n // ===========================\n\n _isMotionOkay () {\n // Get pref.\n const { matches } = window.matchMedia(PREFERS_REDUCED_MOTION)\n\n // Expose boolean.\n return this._isAnimated && !matches\n }\n\n // =====================\n // Helper: toggle modal.\n // =====================\n\n _toggleModalDisplay (callback: () => void) {\n if (!this._modalScroll) return\n\n // @ts-expect-error boolean\n this.setAttribute(ACTIVE, this._isActive)\n\n // Get booleans.\n const isModalVisible = this._modalScroll.getAttribute(DATA_VISIBLE) === TRUE\n const isMotionOkay = this._isMotionOkay()\n\n // Get delay.\n const delay = isMotionOkay ? ANIMATION_DURATION : 0\n\n // Get scrollbar width.\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n\n // Get active element.\n const activeElement = document.activeElement as HTMLElement\n\n // Cache active element?\n if (this._isActive && activeElement) {\n this._activeElement = activeElement\n }\n\n // =============\n // Modal active?\n // =============\n\n if (this._isActive) {\n // Show modal.\n this._modalScroll.setAttribute(DATA_VISIBLE, TRUE)\n\n // Hide scrollbar.\n document.documentElement.style.overflow = HIDDEN\n\n // Add placeholder?\n if (scrollbarWidth) {\n document.documentElement.style.paddingRight = `${scrollbarWidth}px`\n }\n\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_SHOW, TRUE)\n }\n\n // Fire callback.\n callback()\n\n // Await CSS animation.\n this._timerForShow = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForShow)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_SHOW)\n }, delay)\n } else if (isModalVisible) {\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_HIDE, TRUE)\n }\n\n // Fire callback?\n callback()\n\n // Await CSS animation.\n this._timerForHide = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForHide)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_HIDE)\n\n // Hide modal.\n this._modalScroll?.setAttribute(DATA_VISIBLE, FALSE)\n\n // Show scrollbar.\n document.documentElement.style.overflow = EMPTY_STRING\n\n // Remove placeholder.\n document.documentElement.style.paddingRight = EMPTY_STRING\n\n // Delay.\n }, delay)\n }\n }\n\n // =====================\n // Event: overlay click.\n // =====================\n\n _handleClickOverlay (event: MouseEvent) {\n if (this._isHideShow || this._isStatic) return\n if (!this._closable) return\n\n // Get layer.\n const target = event.target as HTMLElement\n\n // Outside modal? (clicked directly on overlay, not dialog)\n if (target === this._modalOverlay) {\n this.close()\n }\n }\n\n // ====================\n // Event: close button click.\n // ====================\n\n _handleClickClose () {\n this.close()\n }\n\n // =========================\n // Event: focus in document.\n // =========================\n\n _handleFocusIn () {\n if (!this._isActive || !this._modal) return\n\n const activeElement = document.activeElement as HTMLElement\n\n // Get booleans.\n const isFocusTrap1 = activeElement === this._focusTrap1\n const isFocusTrap2 = activeElement === this._focusTrap2\n\n // Get focusable elements in modal.\n const focusList = Array.from(\n this._modal.querySelectorAll(FOCUSABLE_SELECTORS)\n ) as HTMLElement[]\n\n // Get first & last items.\n const focusItemFirst = focusList[0]\n const focusItemLast = focusList[focusList.length - 1]\n\n // Focus trap: above?\n if (isFocusTrap1 && focusItemLast) {\n this._focusElement(focusItemLast)\n\n // Focus trap: below?\n } else if (isFocusTrap2 && focusItemFirst) {\n this._focusElement(focusItemFirst)\n\n // Outside modal?\n } else if (this._isOutsideModal(activeElement)) {\n this._focusModal()\n }\n }\n\n // =================\n // Event: key press.\n // =================\n\n _handleKeyDown ({ key }:KeyboardEvent) {\n if (!this._isActive) return\n\n key = key.toLowerCase()\n\n // Escape key?\n if (\n key === ESCAPE &&\n !this._isHideShow &&\n !this._isStatic &&\n this._closable\n ) {\n this.close()\n }\n\n // Tab key?\n if (key === TAB) {\n this._handleFocusIn()\n }\n }\n\n // =================\n // Public: open modal.\n // =================\n\n open () {\n this._isActive = true\n this._toggleModalDisplay(() => {\n this._focusModal()\n })\n }\n\n // =================\n // Public: close modal.\n // =================\n\n close () {\n this._isActive = false\n this._toggleModalDisplay(() => {\n if (this._activeElement) {\n this._focusElement(this._activeElement)\n }\n })\n }\n}\n\ndefine(ModalWindow.TAG, ModalWindow)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { define } from '@substrate-system/web-component'\n\n// for docuement.querySelector\ndeclare global {\n interface HTMLElementTagNameMap {\n 'modal-window':ModalWindow\n }\n}\n\n/**\n * Modal window web component.\n *\n * Opens/closes via the `active` attribute:\n * modal.setAttribute('active', 'true') // open\n * modal.setAttribute('active', 'false') // close\n * modal.removeAttribute('active') // close\n *\n * Or via methods:\n * modal.open()\n * modal.close()\n */\n\n// ==========\n// Constants.\n// ==========\n\nconst ACTIVE = 'active'\nconst ANIMATED = 'animated'\nconst ANIMATION_DURATION = 250\nconst ARIA_DESCRIBEDBY = 'aria-describedby'\nconst ARIA_LABEL = 'aria-label'\nconst CLOSE = 'close'\nconst CLOSE_TITLE = 'Close'\nconst NO_ICON = 'no-icon'\nconst DATA_HIDE = 'data-modal-hide'\nconst DATA_SHOW = 'data-modal-show'\nconst DATA_VISIBLE = 'data-visible'\nconst EMPTY_STRING = ''\nconst ESCAPE = 'escape'\nconst FALSE = 'false'\nconst FOCUSIN = 'focusin'\nconst HIDDEN = 'hidden'\nconst KEYDOWN = 'keydown'\nconst MODAL_LABEL_FALLBACK = 'modal'\nconst PREFERS_REDUCED_MOTION = '(prefers-reduced-motion: reduce)'\nconst SPACE = ' '\nconst SPACE_REGEX = /\\s+/g\nconst STATIC = 'static'\nconst TAB = 'tab'\nconst TRUE = 'true'\n\nconst FOCUSABLE_SELECTORS = [\n '[contenteditable]',\n '[tabindex=\"0\"]:not([disabled])',\n 'a[href]',\n 'audio[controls]',\n 'button:not([disabled])',\n 'iframe',\n \"input:not([disabled]):not([type='hidden'])\",\n 'select:not([disabled])',\n 'summary',\n 'textarea:not([disabled])',\n 'video[controls]',\n].join(',')\n\n// ====================\n// The component\n// ====================\n\nexport class ModalWindow extends HTMLElement {\n // Element references (set during build).\n _buttonClose:HTMLButtonElement|null = null\n _modal:HTMLDialogElement|null = null\n _modalOverlay:HTMLDivElement|null = null\n _modalScroll:HTMLDivElement|null = null\n _modalContent:HTMLDivElement|null = null\n _focusTrap1:HTMLSpanElement|null = null\n _focusTrap2:HTMLSpanElement|null = null\n _heading:HTMLElement|null = null\n\n static TAG:string = 'modal-window'\n\n // State.\n _activeElement:HTMLElement|null = null\n _isActive = false\n _isAnimated = true\n _isBuilt = false\n _isHideShow = false\n _isStatic = false\n _timerForHide:number|undefined\n _timerForShow:number|undefined\n _closable:boolean = true\n _showIcon:boolean = true\n\n // =======================\n // Lifecycle: constructor.\n // =======================\n\n constructor () {\n super()\n this._bind()\n }\n\n // ============================\n // Helper: build modal structure.\n // ============================\n\n _buildModal (contentNodes:Node[]) {\n // Create focus trap\n const createFocusTrap = () => {\n const trap = document.createElement('span')\n trap.setAttribute('aria-hidden', 'true')\n trap.setAttribute('data-modal-focus-trap', '')\n trap.tabIndex = 0\n return trap\n }\n\n // Create scroll container\n const scroll = document.createElement('div')\n scroll.setAttribute('data-modal-scroll', '')\n this._modalScroll = scroll\n\n // Create overlay\n const overlay = document.createElement('div')\n overlay.setAttribute('data-modal-overlay', '')\n this._modalOverlay = overlay\n\n // Create dialog\n const dialog = document.createElement('dialog')\n dialog.setAttribute('aria-modal', 'true')\n dialog.setAttribute('data-modal-dialog', '')\n dialog.tabIndex = -1\n this._modal = dialog\n\n // Create close button if closable and icon should be shown\n if (this._closable && this._showIcon) {\n const closeBtn = document.createElement('button')\n closeBtn.setAttribute('data-modal-close', '')\n closeBtn.type = 'button'\n closeBtn.innerHTML = '×'\n dialog.appendChild(closeBtn)\n this._buttonClose = closeBtn\n }\n\n // Create content wrapper\n const content = document.createElement('div')\n content.setAttribute('data-modal-content', '')\n this._modalContent = content\n\n // Move content nodes into the content wrapper\n contentNodes.forEach(node => {\n content.appendChild(node)\n })\n\n dialog.appendChild(content)\n\n // Create focus traps\n this._focusTrap1 = createFocusTrap()\n this._focusTrap2 = createFocusTrap()\n\n // Assemble structure\n overlay.appendChild(dialog)\n scroll.appendChild(this._focusTrap1)\n scroll.appendChild(overlay)\n scroll.appendChild(this._focusTrap2)\n\n // Add to component\n this.appendChild(scroll)\n }\n\n // ============================\n // Lifecycle: watch attributes.\n // ============================\n\n static get observedAttributes () {\n return [ACTIVE, ANIMATED, ARIA_DESCRIBEDBY, CLOSE, STATIC]\n }\n\n // ==============================\n // Lifecycle: attributes changed.\n // ==============================\n\n attributeChangedCallback (name: string, oldValue: string, newValue: string) {\n // Different old/new values?\n if (oldValue !== newValue) {\n // Changed [active=\"\u2026\"] value?\n if (name === ACTIVE) {\n this._setActiveFlag()\n }\n\n // Changed [animated=\"\u2026\"] value?\n if (name === ANIMATED) {\n this._setAnimationFlag()\n }\n\n // Changed [aria-describedby=\"\u2026\"] value?\n if (name === ARIA_DESCRIBEDBY) {\n this._setModalDescription()\n }\n\n // Changed [close=\"\u2026\"] value?\n if (name === CLOSE) {\n this._setCloseTitle()\n }\n\n // Changed [static=\"\u2026\"] value?\n if (name === STATIC) {\n this._setStaticFlag()\n }\n }\n }\n\n // ===========================\n // Lifecycle: component mount.\n // ===========================\n\n connectedCallback () {\n // Build modal structure once.\n if (!this._isBuilt) {\n this._closable = this.getAttribute('closable') !== 'false'\n this._showIcon = !this.hasAttribute(NO_ICON)\n\n // Get heading for aria-label.\n this._heading = this.querySelector('h1, h2, h3, h4, h5, h6')\n\n // Collect all child nodes.\n const contentNodes = Array.from(this.childNodes)\n\n // Build the modal structure.\n this._buildModal(contentNodes)\n\n // Set animation flag.\n this._setAnimationFlag()\n\n // Set close title.\n this._setCloseTitle()\n\n // Set modal label.\n this._setModalLabel()\n\n // Set modal description.\n this._setModalDescription()\n\n // Set static flag.\n this._setStaticFlag()\n\n // Set active flag.\n this._setActiveFlag()\n\n this._isBuilt = true\n }\n\n this._addEvents()\n }\n\n // =============================\n // Lifecycle: component unmount.\n // =============================\n\n disconnectedCallback () {\n this._removeEvents()\n }\n\n // ============================\n // Helper: bind `this` context.\n // ============================\n\n _bind () {\n const propertyNames = Object.getOwnPropertyNames(\n Object.getPrototypeOf(this)\n ) as (keyof ModalWindow)[]\n\n propertyNames.forEach((name) => {\n // Bind functions.\n if (typeof this[name] === 'function') {\n // @ts-expect-error bind\n this[name] = this[name].bind(this)\n }\n })\n }\n\n // ===================\n // Helper: add events.\n // ===================\n\n _addEvents () {\n // Prevent doubles.\n this._removeEvents()\n\n document.addEventListener(FOCUSIN, this._handleFocusIn)\n document.addEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.addEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.addEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ======================\n // Helper: remove events.\n // ======================\n\n _removeEvents () {\n document.removeEventListener(FOCUSIN, this._handleFocusIn)\n document.removeEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.removeEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.removeEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ===========================\n // Helper: set animation flag.\n // ===========================\n\n _setAnimationFlag () {\n this._isAnimated = this.getAttribute(ANIMATED) !== FALSE\n }\n\n // ========================\n // Helper: add close title.\n // ========================\n\n _setCloseTitle () {\n // Get title.\n const title = this.getAttribute(CLOSE) || CLOSE_TITLE\n\n // Set title.\n if (this._buttonClose) {\n this._buttonClose.title = title\n this._buttonClose.setAttribute(ARIA_LABEL, title)\n }\n }\n\n // ========================\n // Helper: add modal label.\n // ========================\n\n _setModalLabel () {\n // Set later.\n let label = MODAL_LABEL_FALLBACK\n\n // Heading exists?\n if (this._heading) {\n // Get text.\n label = this._heading.textContent || label\n label = label.trim().replace(SPACE_REGEX, SPACE)\n }\n\n // Set label.\n if (this._modal) {\n this._modal.setAttribute(ARIA_LABEL, label)\n }\n }\n\n // ==============================\n // Helper: set modal description.\n // ==============================\n\n _setModalDescription () {\n if (!this._modal) return\n\n const describedBy = this.getAttribute(ARIA_DESCRIBEDBY)\n\n if (describedBy) {\n this._modal.setAttribute(ARIA_DESCRIBEDBY, describedBy)\n } else {\n this._modal.removeAttribute(ARIA_DESCRIBEDBY)\n }\n }\n\n // ========================\n // Helper: set active flag.\n // ========================\n\n _setActiveFlag () {\n // Get flag.\n const isActive = this.getAttribute(ACTIVE) === TRUE\n\n // Set flag.\n this._isActive = isActive\n\n // Set display.\n this._toggleModalDisplay(() => {\n // Focus modal?\n if (this._isActive) {\n this._focusModal()\n }\n })\n }\n\n // ========================\n // Helper: set static flag.\n // ========================\n\n _setStaticFlag () {\n this._isStatic = this.getAttribute(STATIC) === TRUE\n }\n\n // ======================\n // Helper: focus element.\n // ======================\n\n _focusElement (element: HTMLElement) {\n window.requestAnimationFrame(() => {\n if (typeof element.focus === 'function') {\n element.focus()\n }\n })\n }\n\n // ====================\n // Helper: focus modal.\n // ====================\n\n _focusModal () {\n window.requestAnimationFrame(() => {\n if (this._modal) {\n this._modal.focus()\n }\n if (this._modalScroll) {\n this._modalScroll.scrollTo(0, 0)\n }\n })\n }\n\n // =============================\n // Helper: detect outside modal.\n // =============================\n\n _isOutsideModal (element?: HTMLElement) {\n // Early exit.\n if (!this._isActive || !element || !this._modal) {\n return false\n }\n\n // Has element?\n const hasElement = this.contains(element) || this._modal.contains(element)\n\n // Get boolean.\n const bool = !hasElement\n\n // Expose boolean.\n return bool\n }\n\n // ===========================\n // Helper: detect motion pref.\n // ===========================\n\n _isMotionOkay () {\n // Get pref.\n const { matches } = window.matchMedia(PREFERS_REDUCED_MOTION)\n\n // Expose boolean.\n return this._isAnimated && !matches\n }\n\n // =====================\n // Helper: toggle modal.\n // =====================\n\n _toggleModalDisplay (callback: () => void) {\n if (!this._modalScroll) return\n\n // @ts-expect-error boolean\n this.setAttribute(ACTIVE, this._isActive)\n\n // Get booleans.\n const isModalVisible = this._modalScroll.getAttribute(DATA_VISIBLE) === TRUE\n const isMotionOkay = this._isMotionOkay()\n\n // Get delay.\n const delay = isMotionOkay ? ANIMATION_DURATION : 0\n\n // Get scrollbar width.\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n\n // Get active element.\n const activeElement = document.activeElement as HTMLElement\n\n // Cache active element?\n if (this._isActive && activeElement) {\n this._activeElement = activeElement\n }\n\n // =============\n // Modal active?\n // =============\n\n if (this._isActive) {\n // Show modal.\n this._modalScroll.setAttribute(DATA_VISIBLE, TRUE)\n\n // Hide scrollbar.\n document.documentElement.style.overflow = HIDDEN\n\n // Add placeholder?\n if (scrollbarWidth) {\n document.documentElement.style.paddingRight = `${scrollbarWidth}px`\n }\n\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_SHOW, TRUE)\n }\n\n // Fire callback.\n callback()\n\n // Await CSS animation.\n this._timerForShow = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForShow)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_SHOW)\n }, delay)\n } else if (isModalVisible) {\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_HIDE, TRUE)\n }\n\n // Fire callback?\n callback()\n\n // Await CSS animation.\n this._timerForHide = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForHide)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_HIDE)\n\n // Hide modal.\n this._modalScroll?.setAttribute(DATA_VISIBLE, FALSE)\n\n // Show scrollbar.\n document.documentElement.style.overflow = EMPTY_STRING\n\n // Remove placeholder.\n document.documentElement.style.paddingRight = EMPTY_STRING\n\n // Delay.\n }, delay)\n }\n }\n\n // =====================\n // Event: overlay click.\n // =====================\n\n _handleClickOverlay (event: MouseEvent) {\n if (this._isHideShow || this._isStatic) return\n if (!this._closable) return\n\n // Get layer.\n const target = event.target as HTMLElement\n\n // Outside modal? (clicked directly on overlay, not dialog)\n if (target === this._modalOverlay) {\n this.close()\n }\n }\n\n // ====================\n // Event: close button click.\n // ====================\n\n _handleClickClose () {\n this.close()\n }\n\n // =========================\n // Event: focus in document.\n // =========================\n\n _handleFocusIn () {\n if (!this._isActive || !this._modal) return\n\n const activeElement = document.activeElement as HTMLElement\n\n // Get booleans.\n const isFocusTrap1 = activeElement === this._focusTrap1\n const isFocusTrap2 = activeElement === this._focusTrap2\n\n // Get focusable elements in modal.\n const focusList = Array.from(\n this._modal.querySelectorAll(FOCUSABLE_SELECTORS)\n ) as HTMLElement[]\n\n // Get first & last items.\n const focusItemFirst = focusList[0]\n const focusItemLast = focusList[focusList.length - 1]\n\n // Focus trap: above?\n if (isFocusTrap1 && focusItemLast) {\n this._focusElement(focusItemLast)\n\n // Focus trap: below?\n } else if (isFocusTrap2 && focusItemFirst) {\n this._focusElement(focusItemFirst)\n\n // Outside modal?\n } else if (this._isOutsideModal(activeElement)) {\n this._focusModal()\n }\n }\n\n // =================\n // Event: key press.\n // =================\n\n _handleKeyDown ({ key }:KeyboardEvent) {\n if (!this._isActive) return\n\n key = key.toLowerCase()\n\n // Escape key?\n if (\n key === ESCAPE &&\n !this._isHideShow &&\n !this._isStatic &&\n this._closable\n ) {\n this.close()\n }\n\n // Tab key?\n if (key === TAB) {\n this._handleFocusIn()\n }\n }\n\n // =================\n // Public: open modal.\n // =================\n\n open () {\n this._isActive = true\n this._toggleModalDisplay(() => {\n this._focusModal()\n })\n }\n\n // =================\n // Public: close modal.\n // =================\n\n close () {\n this._isActive = false\n this._toggleModalDisplay(() => {\n if (this._activeElement) {\n this._focusElement(this._activeElement)\n }\n })\n }\n}\n\ndefine(ModalWindow.TAG, ModalWindow)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.css CHANGED
@@ -85,14 +85,18 @@
85
85
 
86
86
  [data-modal-dialog] {
87
87
  background-color: var(--modal-dialog-background-color, #fff);
88
- border-radius: var(--modal-dialog-border-radius, 5px);
88
+ border-radius: var(--modal-dialog-border-radius, 0);
89
+ max-width: none;
90
+ max-height: none;
89
91
  box-shadow: var(--modal-dialog-box-shadow, 0 2px 5px 0 #00000080);
90
92
  padding-top: var(--modal-dialog-padding-top, 20px);
91
93
  padding-left: var(--modal-dialog-padding-left, 20px);
92
94
  padding-right: var(--modal-dialog-padding-right, 20px);
93
95
  padding-bottom: var(--modal-dialog-padding-bottom, 20px);
94
96
  width: var(--modal-dialog-width, 500px);
97
+ border: none;
95
98
  max-width: 100%;
99
+ display: block;
96
100
  position: relative;
97
101
  }
98
102
 
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ declare global {
5
5
  }
6
6
  export declare class ModalWindow extends HTMLElement {
7
7
  _buttonClose: HTMLButtonElement | null;
8
- _modal: HTMLDivElement | null;
8
+ _modal: HTMLDialogElement | null;
9
9
  _modalOverlay: HTMLDivElement | null;
10
10
  _modalScroll: HTMLDivElement | null;
11
11
  _modalContent: HTMLDivElement | null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,cAAc,EAAC,WAAW,CAAA;KAC7B;CACJ;AA8DD,qBAAa,WAAY,SAAQ,WAAW;IAExC,YAAY,EAAC,iBAAiB,GAAC,IAAI,CAAO;IAC1C,MAAM,EAAC,cAAc,GAAC,IAAI,CAAO;IACjC,aAAa,EAAC,cAAc,GAAC,IAAI,CAAO;IACxC,YAAY,EAAC,cAAc,GAAC,IAAI,CAAO;IACvC,aAAa,EAAC,cAAc,GAAC,IAAI,CAAO;IACxC,WAAW,EAAC,eAAe,GAAC,IAAI,CAAO;IACvC,WAAW,EAAC,eAAe,GAAC,IAAI,CAAO;IACvC,QAAQ,EAAC,WAAW,GAAC,IAAI,CAAO;IAEhC,MAAM,CAAC,GAAG,EAAC,MAAM,CAAiB;IAGlC,cAAc,EAAC,WAAW,GAAC,IAAI,CAAO;IACtC,SAAS,UAAQ;IACjB,WAAW,UAAO;IAClB,QAAQ,UAAQ;IAChB,WAAW,UAAQ;IACnB,SAAS,UAAQ;IACjB,aAAa,EAAC,MAAM,GAAC,SAAS,CAAA;IAC9B,aAAa,EAAC,MAAM,GAAC,SAAS,CAAA;IAC9B,SAAS,EAAC,OAAO,CAAO;IACxB,SAAS,EAAC,OAAO,CAAO;;IAexB,WAAW,CAAE,YAAY,EAAC,IAAI,EAAE;IAoEhC,MAAM,KAAK,kBAAkB,aAE5B;IAMD,wBAAwB,CAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAkC1E,iBAAiB;IA2CjB,oBAAoB;IAQpB,KAAK;IAkBL,UAAU;IAmBV,aAAa;IAgBb,iBAAiB;IAQjB,cAAc;IAed,cAAc;IAqBd,oBAAoB;IAgBpB,cAAc;IAoBd,cAAc;IAQd,aAAa,CAAE,OAAO,EAAE,WAAW;IAYnC,WAAW;IAeX,eAAe,CAAE,OAAO,CAAC,EAAE,WAAW;IAoBtC,aAAa;IAYb,mBAAmB,CAAE,QAAQ,EAAE,MAAM,IAAI;IA+FzC,mBAAmB,CAAE,KAAK,EAAE,UAAU;IAiBtC,iBAAiB;IAQjB,cAAc;IAoCd,cAAc,CAAE,EAAE,GAAG,EAAE,EAAC,aAAa;IAyBrC,IAAI;IAWJ,KAAK;CAQR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,cAAc,EAAC,WAAW,CAAA;KAC7B;CACJ;AA8DD,qBAAa,WAAY,SAAQ,WAAW;IAExC,YAAY,EAAC,iBAAiB,GAAC,IAAI,CAAO;IAC1C,MAAM,EAAC,iBAAiB,GAAC,IAAI,CAAO;IACpC,aAAa,EAAC,cAAc,GAAC,IAAI,CAAO;IACxC,YAAY,EAAC,cAAc,GAAC,IAAI,CAAO;IACvC,aAAa,EAAC,cAAc,GAAC,IAAI,CAAO;IACxC,WAAW,EAAC,eAAe,GAAC,IAAI,CAAO;IACvC,WAAW,EAAC,eAAe,GAAC,IAAI,CAAO;IACvC,QAAQ,EAAC,WAAW,GAAC,IAAI,CAAO;IAEhC,MAAM,CAAC,GAAG,EAAC,MAAM,CAAiB;IAGlC,cAAc,EAAC,WAAW,GAAC,IAAI,CAAO;IACtC,SAAS,UAAQ;IACjB,WAAW,UAAO;IAClB,QAAQ,UAAQ;IAChB,WAAW,UAAQ;IACnB,SAAS,UAAQ;IACjB,aAAa,EAAC,MAAM,GAAC,SAAS,CAAA;IAC9B,aAAa,EAAC,MAAM,GAAC,SAAS,CAAA;IAC9B,SAAS,EAAC,OAAO,CAAO;IACxB,SAAS,EAAC,OAAO,CAAO;;IAexB,WAAW,CAAE,YAAY,EAAC,IAAI,EAAE;IAmEhC,MAAM,KAAK,kBAAkB,aAE5B;IAMD,wBAAwB,CAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAkC1E,iBAAiB;IA2CjB,oBAAoB;IAQpB,KAAK;IAkBL,UAAU;IAmBV,aAAa;IAgBb,iBAAiB;IAQjB,cAAc;IAed,cAAc;IAqBd,oBAAoB;IAgBpB,cAAc;IAoBd,cAAc;IAQd,aAAa,CAAE,OAAO,EAAE,WAAW;IAYnC,WAAW;IAeX,eAAe,CAAE,OAAO,CAAC,EAAE,WAAW;IAoBtC,aAAa;IAYb,mBAAmB,CAAE,QAAQ,EAAE,MAAM,IAAI;IA+FzC,mBAAmB,CAAE,KAAK,EAAE,UAAU;IAiBtC,iBAAiB;IAQjB,cAAc;IAoCd,cAAc,CAAE,EAAE,GAAG,EAAE,EAAC,aAAa;IAyBrC,IAAI;IAWJ,KAAK;CAQR"}
package/dist/index.js CHANGED
@@ -87,10 +87,9 @@ class ModalWindow extends HTMLElement {
87
87
  const overlay = document.createElement("div");
88
88
  overlay.setAttribute("data-modal-overlay", "");
89
89
  this._modalOverlay = overlay;
90
- const dialog = document.createElement("div");
90
+ const dialog = document.createElement("dialog");
91
91
  dialog.setAttribute("aria-modal", "true");
92
92
  dialog.setAttribute("data-modal-dialog", "");
93
- dialog.setAttribute("role", "dialog");
94
93
  dialog.tabIndex = -1;
95
94
  this._modal = dialog;
96
95
  if (this._closable && this._showIcon) {
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import { define } from '@substrate-system/web-component'\n\n// for docuement.querySelector\ndeclare global {\n interface HTMLElementTagNameMap {\n 'modal-window':ModalWindow\n }\n}\n\n/**\n * Modal window web component.\n *\n * Opens/closes via the `active` attribute:\n * modal.setAttribute('active', 'true') // open\n * modal.setAttribute('active', 'false') // close\n * modal.removeAttribute('active') // close\n *\n * Or via methods:\n * modal.open()\n * modal.close()\n */\n\n// ==========\n// Constants.\n// ==========\n\nconst ACTIVE = 'active'\nconst ANIMATED = 'animated'\nconst ANIMATION_DURATION = 250\nconst ARIA_DESCRIBEDBY = 'aria-describedby'\nconst ARIA_LABEL = 'aria-label'\nconst CLOSE = 'close'\nconst CLOSE_TITLE = 'Close'\nconst NO_ICON = 'no-icon'\nconst DATA_HIDE = 'data-modal-hide'\nconst DATA_SHOW = 'data-modal-show'\nconst DATA_VISIBLE = 'data-visible'\nconst EMPTY_STRING = ''\nconst ESCAPE = 'escape'\nconst FALSE = 'false'\nconst FOCUSIN = 'focusin'\nconst HIDDEN = 'hidden'\nconst KEYDOWN = 'keydown'\nconst MODAL_LABEL_FALLBACK = 'modal'\nconst PREFERS_REDUCED_MOTION = '(prefers-reduced-motion: reduce)'\nconst SPACE = ' '\nconst SPACE_REGEX = /\\s+/g\nconst STATIC = 'static'\nconst TAB = 'tab'\nconst TRUE = 'true'\n\nconst FOCUSABLE_SELECTORS = [\n '[contenteditable]',\n '[tabindex=\"0\"]:not([disabled])',\n 'a[href]',\n 'audio[controls]',\n 'button:not([disabled])',\n 'iframe',\n \"input:not([disabled]):not([type='hidden'])\",\n 'select:not([disabled])',\n 'summary',\n 'textarea:not([disabled])',\n 'video[controls]',\n].join(',')\n\n// ====================\n// The component\n// ====================\n\nexport class ModalWindow extends HTMLElement {\n // Element references (set during build).\n _buttonClose:HTMLButtonElement|null = null\n _modal:HTMLDivElement|null = null\n _modalOverlay:HTMLDivElement|null = null\n _modalScroll:HTMLDivElement|null = null\n _modalContent:HTMLDivElement|null = null\n _focusTrap1:HTMLSpanElement|null = null\n _focusTrap2:HTMLSpanElement|null = null\n _heading:HTMLElement|null = null\n\n static TAG:string = 'modal-window'\n\n // State.\n _activeElement:HTMLElement|null = null\n _isActive = false\n _isAnimated = true\n _isBuilt = false\n _isHideShow = false\n _isStatic = false\n _timerForHide:number|undefined\n _timerForShow:number|undefined\n _closable:boolean = true\n _showIcon:boolean = true\n\n // =======================\n // Lifecycle: constructor.\n // =======================\n\n constructor () {\n super()\n this._bind()\n }\n\n // ============================\n // Helper: build modal structure.\n // ============================\n\n _buildModal (contentNodes:Node[]) {\n // Create focus trap\n const createFocusTrap = () => {\n const trap = document.createElement('span')\n trap.setAttribute('aria-hidden', 'true')\n trap.setAttribute('data-modal-focus-trap', '')\n trap.tabIndex = 0\n return trap\n }\n\n // Create scroll container\n const scroll = document.createElement('div')\n scroll.setAttribute('data-modal-scroll', '')\n this._modalScroll = scroll\n\n // Create overlay\n const overlay = document.createElement('div')\n overlay.setAttribute('data-modal-overlay', '')\n this._modalOverlay = overlay\n\n // Create dialog\n const dialog = document.createElement('div')\n dialog.setAttribute('aria-modal', 'true')\n dialog.setAttribute('data-modal-dialog', '')\n dialog.setAttribute('role', 'dialog')\n dialog.tabIndex = -1\n this._modal = dialog\n\n // Create close button if closable and icon should be shown\n if (this._closable && this._showIcon) {\n const closeBtn = document.createElement('button')\n closeBtn.setAttribute('data-modal-close', '')\n closeBtn.type = 'button'\n closeBtn.innerHTML = '×'\n dialog.appendChild(closeBtn)\n this._buttonClose = closeBtn\n }\n\n // Create content wrapper\n const content = document.createElement('div')\n content.setAttribute('data-modal-content', '')\n this._modalContent = content\n\n // Move content nodes into the content wrapper\n contentNodes.forEach(node => {\n content.appendChild(node)\n })\n\n dialog.appendChild(content)\n\n // Create focus traps\n this._focusTrap1 = createFocusTrap()\n this._focusTrap2 = createFocusTrap()\n\n // Assemble structure\n overlay.appendChild(dialog)\n scroll.appendChild(this._focusTrap1)\n scroll.appendChild(overlay)\n scroll.appendChild(this._focusTrap2)\n\n // Add to component\n this.appendChild(scroll)\n }\n\n // ============================\n // Lifecycle: watch attributes.\n // ============================\n\n static get observedAttributes () {\n return [ACTIVE, ANIMATED, ARIA_DESCRIBEDBY, CLOSE, STATIC]\n }\n\n // ==============================\n // Lifecycle: attributes changed.\n // ==============================\n\n attributeChangedCallback (name: string, oldValue: string, newValue: string) {\n // Different old/new values?\n if (oldValue !== newValue) {\n // Changed [active=\"\u2026\"] value?\n if (name === ACTIVE) {\n this._setActiveFlag()\n }\n\n // Changed [animated=\"\u2026\"] value?\n if (name === ANIMATED) {\n this._setAnimationFlag()\n }\n\n // Changed [aria-describedby=\"\u2026\"] value?\n if (name === ARIA_DESCRIBEDBY) {\n this._setModalDescription()\n }\n\n // Changed [close=\"\u2026\"] value?\n if (name === CLOSE) {\n this._setCloseTitle()\n }\n\n // Changed [static=\"\u2026\"] value?\n if (name === STATIC) {\n this._setStaticFlag()\n }\n }\n }\n\n // ===========================\n // Lifecycle: component mount.\n // ===========================\n\n connectedCallback () {\n // Build modal structure once.\n if (!this._isBuilt) {\n this._closable = this.getAttribute('closable') !== 'false'\n this._showIcon = !this.hasAttribute(NO_ICON)\n\n // Get heading for aria-label.\n this._heading = this.querySelector('h1, h2, h3, h4, h5, h6')\n\n // Collect all child nodes.\n const contentNodes = Array.from(this.childNodes)\n\n // Build the modal structure.\n this._buildModal(contentNodes)\n\n // Set animation flag.\n this._setAnimationFlag()\n\n // Set close title.\n this._setCloseTitle()\n\n // Set modal label.\n this._setModalLabel()\n\n // Set modal description.\n this._setModalDescription()\n\n // Set static flag.\n this._setStaticFlag()\n\n // Set active flag.\n this._setActiveFlag()\n\n this._isBuilt = true\n }\n\n this._addEvents()\n }\n\n // =============================\n // Lifecycle: component unmount.\n // =============================\n\n disconnectedCallback () {\n this._removeEvents()\n }\n\n // ============================\n // Helper: bind `this` context.\n // ============================\n\n _bind () {\n const propertyNames = Object.getOwnPropertyNames(\n Object.getPrototypeOf(this)\n ) as (keyof ModalWindow)[]\n\n propertyNames.forEach((name) => {\n // Bind functions.\n if (typeof this[name] === 'function') {\n // @ts-expect-error bind\n this[name] = this[name].bind(this)\n }\n })\n }\n\n // ===================\n // Helper: add events.\n // ===================\n\n _addEvents () {\n // Prevent doubles.\n this._removeEvents()\n\n document.addEventListener(FOCUSIN, this._handleFocusIn)\n document.addEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.addEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.addEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ======================\n // Helper: remove events.\n // ======================\n\n _removeEvents () {\n document.removeEventListener(FOCUSIN, this._handleFocusIn)\n document.removeEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.removeEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.removeEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ===========================\n // Helper: set animation flag.\n // ===========================\n\n _setAnimationFlag () {\n this._isAnimated = this.getAttribute(ANIMATED) !== FALSE\n }\n\n // ========================\n // Helper: add close title.\n // ========================\n\n _setCloseTitle () {\n // Get title.\n const title = this.getAttribute(CLOSE) || CLOSE_TITLE\n\n // Set title.\n if (this._buttonClose) {\n this._buttonClose.title = title\n this._buttonClose.setAttribute(ARIA_LABEL, title)\n }\n }\n\n // ========================\n // Helper: add modal label.\n // ========================\n\n _setModalLabel () {\n // Set later.\n let label = MODAL_LABEL_FALLBACK\n\n // Heading exists?\n if (this._heading) {\n // Get text.\n label = this._heading.textContent || label\n label = label.trim().replace(SPACE_REGEX, SPACE)\n }\n\n // Set label.\n if (this._modal) {\n this._modal.setAttribute(ARIA_LABEL, label)\n }\n }\n\n // ==============================\n // Helper: set modal description.\n // ==============================\n\n _setModalDescription () {\n if (!this._modal) return\n\n const describedBy = this.getAttribute(ARIA_DESCRIBEDBY)\n\n if (describedBy) {\n this._modal.setAttribute(ARIA_DESCRIBEDBY, describedBy)\n } else {\n this._modal.removeAttribute(ARIA_DESCRIBEDBY)\n }\n }\n\n // ========================\n // Helper: set active flag.\n // ========================\n\n _setActiveFlag () {\n // Get flag.\n const isActive = this.getAttribute(ACTIVE) === TRUE\n\n // Set flag.\n this._isActive = isActive\n\n // Set display.\n this._toggleModalDisplay(() => {\n // Focus modal?\n if (this._isActive) {\n this._focusModal()\n }\n })\n }\n\n // ========================\n // Helper: set static flag.\n // ========================\n\n _setStaticFlag () {\n this._isStatic = this.getAttribute(STATIC) === TRUE\n }\n\n // ======================\n // Helper: focus element.\n // ======================\n\n _focusElement (element: HTMLElement) {\n window.requestAnimationFrame(() => {\n if (typeof element.focus === 'function') {\n element.focus()\n }\n })\n }\n\n // ====================\n // Helper: focus modal.\n // ====================\n\n _focusModal () {\n window.requestAnimationFrame(() => {\n if (this._modal) {\n this._modal.focus()\n }\n if (this._modalScroll) {\n this._modalScroll.scrollTo(0, 0)\n }\n })\n }\n\n // =============================\n // Helper: detect outside modal.\n // =============================\n\n _isOutsideModal (element?: HTMLElement) {\n // Early exit.\n if (!this._isActive || !element || !this._modal) {\n return false\n }\n\n // Has element?\n const hasElement = this.contains(element) || this._modal.contains(element)\n\n // Get boolean.\n const bool = !hasElement\n\n // Expose boolean.\n return bool\n }\n\n // ===========================\n // Helper: detect motion pref.\n // ===========================\n\n _isMotionOkay () {\n // Get pref.\n const { matches } = window.matchMedia(PREFERS_REDUCED_MOTION)\n\n // Expose boolean.\n return this._isAnimated && !matches\n }\n\n // =====================\n // Helper: toggle modal.\n // =====================\n\n _toggleModalDisplay (callback: () => void) {\n if (!this._modalScroll) return\n\n // @ts-expect-error boolean\n this.setAttribute(ACTIVE, this._isActive)\n\n // Get booleans.\n const isModalVisible = this._modalScroll.getAttribute(DATA_VISIBLE) === TRUE\n const isMotionOkay = this._isMotionOkay()\n\n // Get delay.\n const delay = isMotionOkay ? ANIMATION_DURATION : 0\n\n // Get scrollbar width.\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n\n // Get active element.\n const activeElement = document.activeElement as HTMLElement\n\n // Cache active element?\n if (this._isActive && activeElement) {\n this._activeElement = activeElement\n }\n\n // =============\n // Modal active?\n // =============\n\n if (this._isActive) {\n // Show modal.\n this._modalScroll.setAttribute(DATA_VISIBLE, TRUE)\n\n // Hide scrollbar.\n document.documentElement.style.overflow = HIDDEN\n\n // Add placeholder?\n if (scrollbarWidth) {\n document.documentElement.style.paddingRight = `${scrollbarWidth}px`\n }\n\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_SHOW, TRUE)\n }\n\n // Fire callback.\n callback()\n\n // Await CSS animation.\n this._timerForShow = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForShow)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_SHOW)\n }, delay)\n } else if (isModalVisible) {\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_HIDE, TRUE)\n }\n\n // Fire callback?\n callback()\n\n // Await CSS animation.\n this._timerForHide = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForHide)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_HIDE)\n\n // Hide modal.\n this._modalScroll?.setAttribute(DATA_VISIBLE, FALSE)\n\n // Show scrollbar.\n document.documentElement.style.overflow = EMPTY_STRING\n\n // Remove placeholder.\n document.documentElement.style.paddingRight = EMPTY_STRING\n\n // Delay.\n }, delay)\n }\n }\n\n // =====================\n // Event: overlay click.\n // =====================\n\n _handleClickOverlay (event: MouseEvent) {\n if (this._isHideShow || this._isStatic) return\n if (!this._closable) return\n\n // Get layer.\n const target = event.target as HTMLElement\n\n // Outside modal? (clicked directly on overlay, not dialog)\n if (target === this._modalOverlay) {\n this.close()\n }\n }\n\n // ====================\n // Event: close button click.\n // ====================\n\n _handleClickClose () {\n this.close()\n }\n\n // =========================\n // Event: focus in document.\n // =========================\n\n _handleFocusIn () {\n if (!this._isActive || !this._modal) return\n\n const activeElement = document.activeElement as HTMLElement\n\n // Get booleans.\n const isFocusTrap1 = activeElement === this._focusTrap1\n const isFocusTrap2 = activeElement === this._focusTrap2\n\n // Get focusable elements in modal.\n const focusList = Array.from(\n this._modal.querySelectorAll(FOCUSABLE_SELECTORS)\n ) as HTMLElement[]\n\n // Get first & last items.\n const focusItemFirst = focusList[0]\n const focusItemLast = focusList[focusList.length - 1]\n\n // Focus trap: above?\n if (isFocusTrap1 && focusItemLast) {\n this._focusElement(focusItemLast)\n\n // Focus trap: below?\n } else if (isFocusTrap2 && focusItemFirst) {\n this._focusElement(focusItemFirst)\n\n // Outside modal?\n } else if (this._isOutsideModal(activeElement)) {\n this._focusModal()\n }\n }\n\n // =================\n // Event: key press.\n // =================\n\n _handleKeyDown ({ key }:KeyboardEvent) {\n if (!this._isActive) return\n\n key = key.toLowerCase()\n\n // Escape key?\n if (\n key === ESCAPE &&\n !this._isHideShow &&\n !this._isStatic &&\n this._closable\n ) {\n this.close()\n }\n\n // Tab key?\n if (key === TAB) {\n this._handleFocusIn()\n }\n }\n\n // =================\n // Public: open modal.\n // =================\n\n open () {\n this._isActive = true\n this._toggleModalDisplay(() => {\n this._focusModal()\n })\n }\n\n // =================\n // Public: close modal.\n // =================\n\n close () {\n this._isActive = false\n this._toggleModalDisplay(() => {\n if (this._activeElement) {\n this._focusElement(this._activeElement)\n }\n })\n }\n}\n\ndefine(ModalWindow.TAG, ModalWindow)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { define } from '@substrate-system/web-component'\n\n// for docuement.querySelector\ndeclare global {\n interface HTMLElementTagNameMap {\n 'modal-window':ModalWindow\n }\n}\n\n/**\n * Modal window web component.\n *\n * Opens/closes via the `active` attribute:\n * modal.setAttribute('active', 'true') // open\n * modal.setAttribute('active', 'false') // close\n * modal.removeAttribute('active') // close\n *\n * Or via methods:\n * modal.open()\n * modal.close()\n */\n\n// ==========\n// Constants.\n// ==========\n\nconst ACTIVE = 'active'\nconst ANIMATED = 'animated'\nconst ANIMATION_DURATION = 250\nconst ARIA_DESCRIBEDBY = 'aria-describedby'\nconst ARIA_LABEL = 'aria-label'\nconst CLOSE = 'close'\nconst CLOSE_TITLE = 'Close'\nconst NO_ICON = 'no-icon'\nconst DATA_HIDE = 'data-modal-hide'\nconst DATA_SHOW = 'data-modal-show'\nconst DATA_VISIBLE = 'data-visible'\nconst EMPTY_STRING = ''\nconst ESCAPE = 'escape'\nconst FALSE = 'false'\nconst FOCUSIN = 'focusin'\nconst HIDDEN = 'hidden'\nconst KEYDOWN = 'keydown'\nconst MODAL_LABEL_FALLBACK = 'modal'\nconst PREFERS_REDUCED_MOTION = '(prefers-reduced-motion: reduce)'\nconst SPACE = ' '\nconst SPACE_REGEX = /\\s+/g\nconst STATIC = 'static'\nconst TAB = 'tab'\nconst TRUE = 'true'\n\nconst FOCUSABLE_SELECTORS = [\n '[contenteditable]',\n '[tabindex=\"0\"]:not([disabled])',\n 'a[href]',\n 'audio[controls]',\n 'button:not([disabled])',\n 'iframe',\n \"input:not([disabled]):not([type='hidden'])\",\n 'select:not([disabled])',\n 'summary',\n 'textarea:not([disabled])',\n 'video[controls]',\n].join(',')\n\n// ====================\n// The component\n// ====================\n\nexport class ModalWindow extends HTMLElement {\n // Element references (set during build).\n _buttonClose:HTMLButtonElement|null = null\n _modal:HTMLDialogElement|null = null\n _modalOverlay:HTMLDivElement|null = null\n _modalScroll:HTMLDivElement|null = null\n _modalContent:HTMLDivElement|null = null\n _focusTrap1:HTMLSpanElement|null = null\n _focusTrap2:HTMLSpanElement|null = null\n _heading:HTMLElement|null = null\n\n static TAG:string = 'modal-window'\n\n // State.\n _activeElement:HTMLElement|null = null\n _isActive = false\n _isAnimated = true\n _isBuilt = false\n _isHideShow = false\n _isStatic = false\n _timerForHide:number|undefined\n _timerForShow:number|undefined\n _closable:boolean = true\n _showIcon:boolean = true\n\n // =======================\n // Lifecycle: constructor.\n // =======================\n\n constructor () {\n super()\n this._bind()\n }\n\n // ============================\n // Helper: build modal structure.\n // ============================\n\n _buildModal (contentNodes:Node[]) {\n // Create focus trap\n const createFocusTrap = () => {\n const trap = document.createElement('span')\n trap.setAttribute('aria-hidden', 'true')\n trap.setAttribute('data-modal-focus-trap', '')\n trap.tabIndex = 0\n return trap\n }\n\n // Create scroll container\n const scroll = document.createElement('div')\n scroll.setAttribute('data-modal-scroll', '')\n this._modalScroll = scroll\n\n // Create overlay\n const overlay = document.createElement('div')\n overlay.setAttribute('data-modal-overlay', '')\n this._modalOverlay = overlay\n\n // Create dialog\n const dialog = document.createElement('dialog')\n dialog.setAttribute('aria-modal', 'true')\n dialog.setAttribute('data-modal-dialog', '')\n dialog.tabIndex = -1\n this._modal = dialog\n\n // Create close button if closable and icon should be shown\n if (this._closable && this._showIcon) {\n const closeBtn = document.createElement('button')\n closeBtn.setAttribute('data-modal-close', '')\n closeBtn.type = 'button'\n closeBtn.innerHTML = '×'\n dialog.appendChild(closeBtn)\n this._buttonClose = closeBtn\n }\n\n // Create content wrapper\n const content = document.createElement('div')\n content.setAttribute('data-modal-content', '')\n this._modalContent = content\n\n // Move content nodes into the content wrapper\n contentNodes.forEach(node => {\n content.appendChild(node)\n })\n\n dialog.appendChild(content)\n\n // Create focus traps\n this._focusTrap1 = createFocusTrap()\n this._focusTrap2 = createFocusTrap()\n\n // Assemble structure\n overlay.appendChild(dialog)\n scroll.appendChild(this._focusTrap1)\n scroll.appendChild(overlay)\n scroll.appendChild(this._focusTrap2)\n\n // Add to component\n this.appendChild(scroll)\n }\n\n // ============================\n // Lifecycle: watch attributes.\n // ============================\n\n static get observedAttributes () {\n return [ACTIVE, ANIMATED, ARIA_DESCRIBEDBY, CLOSE, STATIC]\n }\n\n // ==============================\n // Lifecycle: attributes changed.\n // ==============================\n\n attributeChangedCallback (name: string, oldValue: string, newValue: string) {\n // Different old/new values?\n if (oldValue !== newValue) {\n // Changed [active=\"\u2026\"] value?\n if (name === ACTIVE) {\n this._setActiveFlag()\n }\n\n // Changed [animated=\"\u2026\"] value?\n if (name === ANIMATED) {\n this._setAnimationFlag()\n }\n\n // Changed [aria-describedby=\"\u2026\"] value?\n if (name === ARIA_DESCRIBEDBY) {\n this._setModalDescription()\n }\n\n // Changed [close=\"\u2026\"] value?\n if (name === CLOSE) {\n this._setCloseTitle()\n }\n\n // Changed [static=\"\u2026\"] value?\n if (name === STATIC) {\n this._setStaticFlag()\n }\n }\n }\n\n // ===========================\n // Lifecycle: component mount.\n // ===========================\n\n connectedCallback () {\n // Build modal structure once.\n if (!this._isBuilt) {\n this._closable = this.getAttribute('closable') !== 'false'\n this._showIcon = !this.hasAttribute(NO_ICON)\n\n // Get heading for aria-label.\n this._heading = this.querySelector('h1, h2, h3, h4, h5, h6')\n\n // Collect all child nodes.\n const contentNodes = Array.from(this.childNodes)\n\n // Build the modal structure.\n this._buildModal(contentNodes)\n\n // Set animation flag.\n this._setAnimationFlag()\n\n // Set close title.\n this._setCloseTitle()\n\n // Set modal label.\n this._setModalLabel()\n\n // Set modal description.\n this._setModalDescription()\n\n // Set static flag.\n this._setStaticFlag()\n\n // Set active flag.\n this._setActiveFlag()\n\n this._isBuilt = true\n }\n\n this._addEvents()\n }\n\n // =============================\n // Lifecycle: component unmount.\n // =============================\n\n disconnectedCallback () {\n this._removeEvents()\n }\n\n // ============================\n // Helper: bind `this` context.\n // ============================\n\n _bind () {\n const propertyNames = Object.getOwnPropertyNames(\n Object.getPrototypeOf(this)\n ) as (keyof ModalWindow)[]\n\n propertyNames.forEach((name) => {\n // Bind functions.\n if (typeof this[name] === 'function') {\n // @ts-expect-error bind\n this[name] = this[name].bind(this)\n }\n })\n }\n\n // ===================\n // Helper: add events.\n // ===================\n\n _addEvents () {\n // Prevent doubles.\n this._removeEvents()\n\n document.addEventListener(FOCUSIN, this._handleFocusIn)\n document.addEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.addEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.addEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ======================\n // Helper: remove events.\n // ======================\n\n _removeEvents () {\n document.removeEventListener(FOCUSIN, this._handleFocusIn)\n document.removeEventListener(KEYDOWN, this._handleKeyDown)\n\n if (this._buttonClose) {\n this._buttonClose.removeEventListener('click', this._handleClickClose)\n }\n if (this._modalOverlay) {\n this._modalOverlay.removeEventListener('click', this._handleClickOverlay)\n }\n }\n\n // ===========================\n // Helper: set animation flag.\n // ===========================\n\n _setAnimationFlag () {\n this._isAnimated = this.getAttribute(ANIMATED) !== FALSE\n }\n\n // ========================\n // Helper: add close title.\n // ========================\n\n _setCloseTitle () {\n // Get title.\n const title = this.getAttribute(CLOSE) || CLOSE_TITLE\n\n // Set title.\n if (this._buttonClose) {\n this._buttonClose.title = title\n this._buttonClose.setAttribute(ARIA_LABEL, title)\n }\n }\n\n // ========================\n // Helper: add modal label.\n // ========================\n\n _setModalLabel () {\n // Set later.\n let label = MODAL_LABEL_FALLBACK\n\n // Heading exists?\n if (this._heading) {\n // Get text.\n label = this._heading.textContent || label\n label = label.trim().replace(SPACE_REGEX, SPACE)\n }\n\n // Set label.\n if (this._modal) {\n this._modal.setAttribute(ARIA_LABEL, label)\n }\n }\n\n // ==============================\n // Helper: set modal description.\n // ==============================\n\n _setModalDescription () {\n if (!this._modal) return\n\n const describedBy = this.getAttribute(ARIA_DESCRIBEDBY)\n\n if (describedBy) {\n this._modal.setAttribute(ARIA_DESCRIBEDBY, describedBy)\n } else {\n this._modal.removeAttribute(ARIA_DESCRIBEDBY)\n }\n }\n\n // ========================\n // Helper: set active flag.\n // ========================\n\n _setActiveFlag () {\n // Get flag.\n const isActive = this.getAttribute(ACTIVE) === TRUE\n\n // Set flag.\n this._isActive = isActive\n\n // Set display.\n this._toggleModalDisplay(() => {\n // Focus modal?\n if (this._isActive) {\n this._focusModal()\n }\n })\n }\n\n // ========================\n // Helper: set static flag.\n // ========================\n\n _setStaticFlag () {\n this._isStatic = this.getAttribute(STATIC) === TRUE\n }\n\n // ======================\n // Helper: focus element.\n // ======================\n\n _focusElement (element: HTMLElement) {\n window.requestAnimationFrame(() => {\n if (typeof element.focus === 'function') {\n element.focus()\n }\n })\n }\n\n // ====================\n // Helper: focus modal.\n // ====================\n\n _focusModal () {\n window.requestAnimationFrame(() => {\n if (this._modal) {\n this._modal.focus()\n }\n if (this._modalScroll) {\n this._modalScroll.scrollTo(0, 0)\n }\n })\n }\n\n // =============================\n // Helper: detect outside modal.\n // =============================\n\n _isOutsideModal (element?: HTMLElement) {\n // Early exit.\n if (!this._isActive || !element || !this._modal) {\n return false\n }\n\n // Has element?\n const hasElement = this.contains(element) || this._modal.contains(element)\n\n // Get boolean.\n const bool = !hasElement\n\n // Expose boolean.\n return bool\n }\n\n // ===========================\n // Helper: detect motion pref.\n // ===========================\n\n _isMotionOkay () {\n // Get pref.\n const { matches } = window.matchMedia(PREFERS_REDUCED_MOTION)\n\n // Expose boolean.\n return this._isAnimated && !matches\n }\n\n // =====================\n // Helper: toggle modal.\n // =====================\n\n _toggleModalDisplay (callback: () => void) {\n if (!this._modalScroll) return\n\n // @ts-expect-error boolean\n this.setAttribute(ACTIVE, this._isActive)\n\n // Get booleans.\n const isModalVisible = this._modalScroll.getAttribute(DATA_VISIBLE) === TRUE\n const isMotionOkay = this._isMotionOkay()\n\n // Get delay.\n const delay = isMotionOkay ? ANIMATION_DURATION : 0\n\n // Get scrollbar width.\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n\n // Get active element.\n const activeElement = document.activeElement as HTMLElement\n\n // Cache active element?\n if (this._isActive && activeElement) {\n this._activeElement = activeElement\n }\n\n // =============\n // Modal active?\n // =============\n\n if (this._isActive) {\n // Show modal.\n this._modalScroll.setAttribute(DATA_VISIBLE, TRUE)\n\n // Hide scrollbar.\n document.documentElement.style.overflow = HIDDEN\n\n // Add placeholder?\n if (scrollbarWidth) {\n document.documentElement.style.paddingRight = `${scrollbarWidth}px`\n }\n\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_SHOW, TRUE)\n }\n\n // Fire callback.\n callback()\n\n // Await CSS animation.\n this._timerForShow = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForShow)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_SHOW)\n }, delay)\n } else if (isModalVisible) {\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.setAttribute(DATA_HIDE, TRUE)\n }\n\n // Fire callback?\n callback()\n\n // Await CSS animation.\n this._timerForHide = window.setTimeout(() => {\n // Clear.\n clearTimeout(this._timerForHide)\n\n // Remove flag.\n this._isHideShow = false\n this._modalScroll?.removeAttribute(DATA_HIDE)\n\n // Hide modal.\n this._modalScroll?.setAttribute(DATA_VISIBLE, FALSE)\n\n // Show scrollbar.\n document.documentElement.style.overflow = EMPTY_STRING\n\n // Remove placeholder.\n document.documentElement.style.paddingRight = EMPTY_STRING\n\n // Delay.\n }, delay)\n }\n }\n\n // =====================\n // Event: overlay click.\n // =====================\n\n _handleClickOverlay (event: MouseEvent) {\n if (this._isHideShow || this._isStatic) return\n if (!this._closable) return\n\n // Get layer.\n const target = event.target as HTMLElement\n\n // Outside modal? (clicked directly on overlay, not dialog)\n if (target === this._modalOverlay) {\n this.close()\n }\n }\n\n // ====================\n // Event: close button click.\n // ====================\n\n _handleClickClose () {\n this.close()\n }\n\n // =========================\n // Event: focus in document.\n // =========================\n\n _handleFocusIn () {\n if (!this._isActive || !this._modal) return\n\n const activeElement = document.activeElement as HTMLElement\n\n // Get booleans.\n const isFocusTrap1 = activeElement === this._focusTrap1\n const isFocusTrap2 = activeElement === this._focusTrap2\n\n // Get focusable elements in modal.\n const focusList = Array.from(\n this._modal.querySelectorAll(FOCUSABLE_SELECTORS)\n ) as HTMLElement[]\n\n // Get first & last items.\n const focusItemFirst = focusList[0]\n const focusItemLast = focusList[focusList.length - 1]\n\n // Focus trap: above?\n if (isFocusTrap1 && focusItemLast) {\n this._focusElement(focusItemLast)\n\n // Focus trap: below?\n } else if (isFocusTrap2 && focusItemFirst) {\n this._focusElement(focusItemFirst)\n\n // Outside modal?\n } else if (this._isOutsideModal(activeElement)) {\n this._focusModal()\n }\n }\n\n // =================\n // Event: key press.\n // =================\n\n _handleKeyDown ({ key }:KeyboardEvent) {\n if (!this._isActive) return\n\n key = key.toLowerCase()\n\n // Escape key?\n if (\n key === ESCAPE &&\n !this._isHideShow &&\n !this._isStatic &&\n this._closable\n ) {\n this.close()\n }\n\n // Tab key?\n if (key === TAB) {\n this._handleFocusIn()\n }\n }\n\n // =================\n // Public: open modal.\n // =================\n\n open () {\n this._isActive = true\n this._toggleModalDisplay(() => {\n this._focusModal()\n })\n }\n\n // =================\n // Public: close modal.\n // =================\n\n close () {\n this._isActive = false\n this._toggleModalDisplay(() => {\n if (this._activeElement) {\n this._focusElement(this._activeElement)\n }\n })\n }\n}\n\ndefine(ModalWindow.TAG, ModalWindow)\n"],
5
+ "mappings": ";;AAAA,SAAS,cAAc;AA0BvB,MAAM,SAAS;AACf,MAAM,WAAW;AACjB,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,aAAa;AACnB,MAAM,QAAQ;AACd,MAAM,cAAc;AACpB,MAAM,UAAU;AAChB,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,SAAS;AACf,MAAM,QAAQ;AACd,MAAM,UAAU;AAChB,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB;AAC/B,MAAM,QAAQ;AACd,MAAM,cAAc;AACpB,MAAM,SAAS;AACf,MAAM,MAAM;AACZ,MAAM,OAAO;AAEb,MAAM,sBAAsB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,EAAE,KAAK,GAAG;AAMH,MAAM,oBAAoB,YAAY;AAAA,EArE7C,OAqE6C;AAAA;AAAA;AAAA;AAAA,EAEzC,eAAsC;AAAA,EACtC,SAAgC;AAAA,EAChC,gBAAoC;AAAA,EACpC,eAAmC;AAAA,EACnC,gBAAoC;AAAA,EACpC,cAAmC;AAAA,EACnC,cAAmC;AAAA,EACnC,WAA4B;AAAA,EAE5B,OAAO,MAAa;AAAA;AAAA,EAGpB,iBAAkC;AAAA,EAClC,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,YAAoB;AAAA,EACpB,YAAoB;AAAA;AAAA;AAAA;AAAA,EAMpB,cAAe;AACX,UAAM;AACN,SAAK,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAMA,YAAa,cAAqB;AAE9B,UAAM,kBAAkB,6BAAM;AAC1B,YAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,WAAK,aAAa,eAAe,MAAM;AACvC,WAAK,aAAa,yBAAyB,EAAE;AAC7C,WAAK,WAAW;AAChB,aAAO;AAAA,IACX,GANwB;AASxB,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,aAAa,qBAAqB,EAAE;AAC3C,SAAK,eAAe;AAGpB,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,aAAa,sBAAsB,EAAE;AAC7C,SAAK,gBAAgB;AAGrB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,aAAa,cAAc,MAAM;AACxC,WAAO,aAAa,qBAAqB,EAAE;AAC3C,WAAO,WAAW;AAClB,SAAK,SAAS;AAGd,QAAI,KAAK,aAAa,KAAK,WAAW;AAClC,YAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,eAAS,aAAa,oBAAoB,EAAE;AAC5C,eAAS,OAAO;AAChB,eAAS,YAAY;AACrB,aAAO,YAAY,QAAQ;AAC3B,WAAK,eAAe;AAAA,IACxB;AAGA,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,aAAa,sBAAsB,EAAE;AAC7C,SAAK,gBAAgB;AAGrB,iBAAa,QAAQ,UAAQ;AACzB,cAAQ,YAAY,IAAI;AAAA,IAC5B,CAAC;AAED,WAAO,YAAY,OAAO;AAG1B,SAAK,cAAc,gBAAgB;AACnC,SAAK,cAAc,gBAAgB;AAGnC,YAAQ,YAAY,MAAM;AAC1B,WAAO,YAAY,KAAK,WAAW;AACnC,WAAO,YAAY,OAAO;AAC1B,WAAO,YAAY,KAAK,WAAW;AAGnC,SAAK,YAAY,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,qBAAsB;AAC7B,WAAO,CAAC,QAAQ,UAAU,kBAAkB,OAAO,MAAM;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAMA,yBAA0B,MAAc,UAAkB,UAAkB;AAExE,QAAI,aAAa,UAAU;AAEvB,UAAI,SAAS,QAAQ;AACjB,aAAK,eAAe;AAAA,MACxB;AAGA,UAAI,SAAS,UAAU;AACnB,aAAK,kBAAkB;AAAA,MAC3B;AAGA,UAAI,SAAS,kBAAkB;AAC3B,aAAK,qBAAqB;AAAA,MAC9B;AAGA,UAAI,SAAS,OAAO;AAChB,aAAK,eAAe;AAAA,MACxB;AAGA,UAAI,SAAS,QAAQ;AACjB,aAAK,eAAe;AAAA,MACxB;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAqB;AAEjB,QAAI,CAAC,KAAK,UAAU;AAChB,WAAK,YAAY,KAAK,aAAa,UAAU,MAAM;AACnD,WAAK,YAAY,CAAC,KAAK,aAAa,OAAO;AAG3C,WAAK,WAAW,KAAK,cAAc,wBAAwB;AAG3D,YAAM,eAAe,MAAM,KAAK,KAAK,UAAU;AAG/C,WAAK,YAAY,YAAY;AAG7B,WAAK,kBAAkB;AAGvB,WAAK,eAAe;AAGpB,WAAK,eAAe;AAGpB,WAAK,qBAAqB;AAG1B,WAAK,eAAe;AAGpB,WAAK,eAAe;AAEpB,WAAK,WAAW;AAAA,IACpB;AAEA,SAAK,WAAW;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAwB;AACpB,SAAK,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAMA,QAAS;AACL,UAAM,gBAAgB,OAAO;AAAA,MACzB,OAAO,eAAe,IAAI;AAAA,IAC9B;AAEA,kBAAc,QAAQ,CAAC,SAAS;AAE5B,UAAI,OAAO,KAAK,IAAI,MAAM,YAAY;AAElC,aAAK,IAAI,IAAI,KAAK,IAAI,EAAE,KAAK,IAAI;AAAA,MACrC;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAMA,aAAc;AAEV,SAAK,cAAc;AAEnB,aAAS,iBAAiB,SAAS,KAAK,cAAc;AACtD,aAAS,iBAAiB,SAAS,KAAK,cAAc;AAEtD,QAAI,KAAK,cAAc;AACnB,WAAK,aAAa,iBAAiB,SAAS,KAAK,iBAAiB;AAAA,IACtE;AACA,QAAI,KAAK,eAAe;AACpB,WAAK,cAAc,iBAAiB,SAAS,KAAK,mBAAmB;AAAA,IACzE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAiB;AACb,aAAS,oBAAoB,SAAS,KAAK,cAAc;AACzD,aAAS,oBAAoB,SAAS,KAAK,cAAc;AAEzD,QAAI,KAAK,cAAc;AACnB,WAAK,aAAa,oBAAoB,SAAS,KAAK,iBAAiB;AAAA,IACzE;AACA,QAAI,KAAK,eAAe;AACpB,WAAK,cAAc,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,IAC5E;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAqB;AACjB,SAAK,cAAc,KAAK,aAAa,QAAQ,MAAM;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAkB;AAEd,UAAM,QAAQ,KAAK,aAAa,KAAK,KAAK;AAG1C,QAAI,KAAK,cAAc;AACnB,WAAK,aAAa,QAAQ;AAC1B,WAAK,aAAa,aAAa,YAAY,KAAK;AAAA,IACpD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAkB;AAEd,QAAI,QAAQ;AAGZ,QAAI,KAAK,UAAU;AAEf,cAAQ,KAAK,SAAS,eAAe;AACrC,cAAQ,MAAM,KAAK,EAAE,QAAQ,aAAa,KAAK;AAAA,IACnD;AAGA,QAAI,KAAK,QAAQ;AACb,WAAK,OAAO,aAAa,YAAY,KAAK;AAAA,IAC9C;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAwB;AACpB,QAAI,CAAC,KAAK,OAAQ;AAElB,UAAM,cAAc,KAAK,aAAa,gBAAgB;AAEtD,QAAI,aAAa;AACb,WAAK,OAAO,aAAa,kBAAkB,WAAW;AAAA,IAC1D,OAAO;AACH,WAAK,OAAO,gBAAgB,gBAAgB;AAAA,IAChD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAkB;AAEd,UAAM,WAAW,KAAK,aAAa,MAAM,MAAM;AAG/C,SAAK,YAAY;AAGjB,SAAK,oBAAoB,MAAM;AAE3B,UAAI,KAAK,WAAW;AAChB,aAAK,YAAY;AAAA,MACrB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAkB;AACd,SAAK,YAAY,KAAK,aAAa,MAAM,MAAM;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAMA,cAAe,SAAsB;AACjC,WAAO,sBAAsB,MAAM;AAC/B,UAAI,OAAO,QAAQ,UAAU,YAAY;AACrC,gBAAQ,MAAM;AAAA,MAClB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAMA,cAAe;AACX,WAAO,sBAAsB,MAAM;AAC/B,UAAI,KAAK,QAAQ;AACb,aAAK,OAAO,MAAM;AAAA,MACtB;AACA,UAAI,KAAK,cAAc;AACnB,aAAK,aAAa,SAAS,GAAG,CAAC;AAAA,MACnC;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAiB,SAAuB;AAEpC,QAAI,CAAC,KAAK,aAAa,CAAC,WAAW,CAAC,KAAK,QAAQ;AAC7C,aAAO;AAAA,IACX;AAGA,UAAM,aAAa,KAAK,SAAS,OAAO,KAAK,KAAK,OAAO,SAAS,OAAO;AAGzE,UAAM,OAAO,CAAC;AAGd,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAiB;AAEb,UAAM,EAAE,QAAQ,IAAI,OAAO,WAAW,sBAAsB;AAG5D,WAAO,KAAK,eAAe,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAqB,UAAsB;AACvC,QAAI,CAAC,KAAK,aAAc;AAGxB,SAAK,aAAa,QAAQ,KAAK,SAAS;AAGxC,UAAM,iBAAiB,KAAK,aAAa,aAAa,YAAY,MAAM;AACxE,UAAM,eAAe,KAAK,cAAc;AAGxC,UAAM,QAAQ,eAAe,qBAAqB;AAGlD,UAAM,iBAAiB,OAAO,aAAa,SAAS,gBAAgB;AAGpE,UAAM,gBAAgB,SAAS;AAG/B,QAAI,KAAK,aAAa,eAAe;AACjC,WAAK,iBAAiB;AAAA,IAC1B;AAMA,QAAI,KAAK,WAAW;AAEhB,WAAK,aAAa,aAAa,cAAc,IAAI;AAGjD,eAAS,gBAAgB,MAAM,WAAW;AAG1C,UAAI,gBAAgB;AAChB,iBAAS,gBAAgB,MAAM,eAAe,GAAG,cAAc;AAAA,MACnE;AAGA,UAAI,cAAc;AACd,aAAK,cAAc;AACnB,aAAK,aAAa,aAAa,WAAW,IAAI;AAAA,MAClD;AAGA,eAAS;AAGT,WAAK,gBAAgB,OAAO,WAAW,MAAM;AAEzC,qBAAa,KAAK,aAAa;AAG/B,aAAK,cAAc;AACnB,aAAK,cAAc,gBAAgB,SAAS;AAAA,MAChD,GAAG,KAAK;AAAA,IACZ,WAAW,gBAAgB;AAEvB,UAAI,cAAc;AACd,aAAK,cAAc;AACnB,aAAK,aAAa,aAAa,WAAW,IAAI;AAAA,MAClD;AAGA,eAAS;AAGT,WAAK,gBAAgB,OAAO,WAAW,MAAM;AAEzC,qBAAa,KAAK,aAAa;AAG/B,aAAK,cAAc;AACnB,aAAK,cAAc,gBAAgB,SAAS;AAG5C,aAAK,cAAc,aAAa,cAAc,KAAK;AAGnD,iBAAS,gBAAgB,MAAM,WAAW;AAG1C,iBAAS,gBAAgB,MAAM,eAAe;AAAA,MAGlD,GAAG,KAAK;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAqB,OAAmB;AACpC,QAAI,KAAK,eAAe,KAAK,UAAW;AACxC,QAAI,CAAC,KAAK,UAAW;AAGrB,UAAM,SAAS,MAAM;AAGrB,QAAI,WAAW,KAAK,eAAe;AAC/B,WAAK,MAAM;AAAA,IACf;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAqB;AACjB,SAAK,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAkB;AACd,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,OAAQ;AAErC,UAAM,gBAAgB,SAAS;AAG/B,UAAM,eAAe,kBAAkB,KAAK;AAC5C,UAAM,eAAe,kBAAkB,KAAK;AAG5C,UAAM,YAAY,MAAM;AAAA,MACpB,KAAK,OAAO,iBAAiB,mBAAmB;AAAA,IACpD;AAGA,UAAM,iBAAiB,UAAU,CAAC;AAClC,UAAM,gBAAgB,UAAU,UAAU,SAAS,CAAC;AAGpD,QAAI,gBAAgB,eAAe;AAC/B,WAAK,cAAc,aAAa;AAAA,IAGpC,WAAW,gBAAgB,gBAAgB;AACvC,WAAK,cAAc,cAAc;AAAA,IAGrC,WAAW,KAAK,gBAAgB,aAAa,GAAG;AAC5C,WAAK,YAAY;AAAA,IACrB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,eAAgB,EAAE,IAAI,GAAiB;AACnC,QAAI,CAAC,KAAK,UAAW;AAErB,UAAM,IAAI,YAAY;AAGtB,QACI,QAAQ,UACR,CAAC,KAAK,eACN,CAAC,KAAK,aACN,KAAK,WACP;AACE,WAAK,MAAM;AAAA,IACf;AAGA,QAAI,QAAQ,KAAK;AACb,WAAK,eAAe;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,OAAQ;AACJ,SAAK,YAAY;AACjB,SAAK,oBAAoB,MAAM;AAC3B,WAAK,YAAY;AAAA,IACrB,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAMA,QAAS;AACL,SAAK,YAAY;AACjB,SAAK,oBAAoB,MAAM;AAC3B,UAAI,KAAK,gBAAgB;AACrB,aAAK,cAAc,KAAK,cAAc;AAAA,MAC1C;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;AAEA,OAAO,YAAY,KAAK,WAAW;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- @media (prefers-reduced-motion:reduce){*,:after,:before{transition:none!important;animation:none!important}}@keyframes SHOW-OVERLAY{0%{opacity:0}to{opacity:1}}@keyframes SHOW-DIALOG{0%{transform:scale(.95)}to{transform:scale(1)}}@keyframes HIDE-OVERLAY{0%{opacity:1}to{opacity:0}}@keyframes HIDE-DIALOG{0%{transform:scale(1)}to{transform:scale(.95)}}[data-modal-focus-trap]{opacity:0;width:0;height:0;position:fixed;top:0;left:0;overflow:hidden}[data-modal-scroll]{width:100%;height:100%;z-index:var(--modal-overlay-z-index,100000);display:none;position:fixed;top:0;left:0;overflow:hidden auto}[data-modal-scroll][data-visible=true]{display:block}[data-modal-overlay]{background-color:var(--modal-overlay-background-color,#00000080);padding-top:var(--modal-overlay-padding-top,20px);padding-left:var(--modal-overlay-padding-left,20px);padding-right:var(--modal-overlay-padding-right,20px);padding-bottom:var(--modal-overlay-padding-bottom,20px);justify-content:center;align-items:center;width:100%;min-height:100%;display:flex}[data-modal-dialog]{background-color:var(--modal-dialog-background-color,#fff);border-radius:var(--modal-dialog-border-radius,5px);box-shadow:var(--modal-dialog-box-shadow,0 2px 5px 0 #00000080);padding-top:var(--modal-dialog-padding-top,20px);padding-left:var(--modal-dialog-padding-left,20px);padding-right:var(--modal-dialog-padding-right,20px);padding-bottom:var(--modal-dialog-padding-bottom,20px);width:var(--modal-dialog-width,500px);max-width:100%;position:relative}[data-modal-show=true] [data-modal-overlay]{animation-name:SHOW-OVERLAY;animation-duration:.25s}[data-modal-show=true] [data-modal-dialog]{animation-name:SHOW-DIALOG;animation-duration:.25s}[data-modal-hide=true] [data-modal-overlay]{opacity:0;animation-name:HIDE-OVERLAY;animation-duration:.25s}[data-modal-hide=true] [data-modal-dialog]{animation-name:HIDE-DIALOG;animation-duration:.25s;transform:scale(.95)}[data-modal-close]{appearance:none;touch-action:none;user-select:none;color:var(--modal-close-color,#fff);background-color:var(--modal-close-background-color,#000);border-radius:var(--modal-close-border-radius,50%);box-shadow:var(--modal-close-box-shadow,0 0 0 1px #fff);display:var(--modal-close-display,block);cursor:pointer;font-family:var(--modal-close-font-family,"Arial",sans-serif);font-size:var(--modal-close-font-size,23px);text-align:center;line-height:var(--modal-close-line-height,26px);width:var(--modal-close-width,26px);border:0;padding:0;position:absolute;top:0;right:0;transform:translate(40%,-40%)}[data-modal-close]:hover{color:var(--modal-close-color-hover,#000);background-color:var(--modal-close-background-color-hover,#fff);box-shadow:var(--modal-close-box-shadow-hover,0 0 0 1px #000)}@supports selector(:focus-visible){[data-modal-close]:focus-visible{color:var(--modal-close-color-hover,#000);background-color:var(--modal-close-background-color-hover,#fff);box-shadow:var(--modal-close-box-shadow-hover,0 0 0 1px #000)}}@supports not selector(:focus-visible){[data-modal-close]:focus{color:var(--modal-close-color-hover,#000);background-color:var(--modal-close-background-color-hover,#fff);box-shadow:var(--modal-close-box-shadow-hover,0 0 0 1px #000)}}
1
+ @media (prefers-reduced-motion:reduce){*,:after,:before{transition:none!important;animation:none!important}}@keyframes SHOW-OVERLAY{0%{opacity:0}to{opacity:1}}@keyframes SHOW-DIALOG{0%{transform:scale(.95)}to{transform:scale(1)}}@keyframes HIDE-OVERLAY{0%{opacity:1}to{opacity:0}}@keyframes HIDE-DIALOG{0%{transform:scale(1)}to{transform:scale(.95)}}[data-modal-focus-trap]{opacity:0;width:0;height:0;position:fixed;top:0;left:0;overflow:hidden}[data-modal-scroll]{width:100%;height:100%;z-index:var(--modal-overlay-z-index,100000);display:none;position:fixed;top:0;left:0;overflow:hidden auto}[data-modal-scroll][data-visible=true]{display:block}[data-modal-overlay]{background-color:var(--modal-overlay-background-color,#00000080);padding-top:var(--modal-overlay-padding-top,20px);padding-left:var(--modal-overlay-padding-left,20px);padding-right:var(--modal-overlay-padding-right,20px);padding-bottom:var(--modal-overlay-padding-bottom,20px);justify-content:center;align-items:center;width:100%;min-height:100%;display:flex}[data-modal-dialog]{background-color:var(--modal-dialog-background-color,#fff);border-radius:var(--modal-dialog-border-radius,0);max-width:none;max-height:none;box-shadow:var(--modal-dialog-box-shadow,0 2px 5px 0 #00000080);padding-top:var(--modal-dialog-padding-top,20px);padding-left:var(--modal-dialog-padding-left,20px);padding-right:var(--modal-dialog-padding-right,20px);padding-bottom:var(--modal-dialog-padding-bottom,20px);width:var(--modal-dialog-width,500px);border:none;max-width:100%;display:block;position:relative}[data-modal-show=true] [data-modal-overlay]{animation-name:SHOW-OVERLAY;animation-duration:.25s}[data-modal-show=true] [data-modal-dialog]{animation-name:SHOW-DIALOG;animation-duration:.25s}[data-modal-hide=true] [data-modal-overlay]{opacity:0;animation-name:HIDE-OVERLAY;animation-duration:.25s}[data-modal-hide=true] [data-modal-dialog]{animation-name:HIDE-DIALOG;animation-duration:.25s;transform:scale(.95)}[data-modal-close]{appearance:none;touch-action:none;user-select:none;color:var(--modal-close-color,#fff);background-color:var(--modal-close-background-color,#000);border-radius:var(--modal-close-border-radius,50%);box-shadow:var(--modal-close-box-shadow,0 0 0 1px #fff);display:var(--modal-close-display,block);cursor:pointer;font-family:var(--modal-close-font-family,"Arial",sans-serif);font-size:var(--modal-close-font-size,23px);text-align:center;line-height:var(--modal-close-line-height,26px);width:var(--modal-close-width,26px);border:0;padding:0;position:absolute;top:0;right:0;transform:translate(40%,-40%)}[data-modal-close]:hover{color:var(--modal-close-color-hover,#000);background-color:var(--modal-close-background-color-hover,#fff);box-shadow:var(--modal-close-box-shadow-hover,0 0 0 1px #000)}@supports selector(:focus-visible){[data-modal-close]:focus-visible{color:var(--modal-close-color-hover,#000);background-color:var(--modal-close-background-color-hover,#fff);box-shadow:var(--modal-close-box-shadow-hover,0 0 0 1px #000)}}@supports not selector(:focus-visible){[data-modal-close]:focus{color:var(--modal-close-color-hover,#000);background-color:var(--modal-close-background-color-hover,#fff);box-shadow:var(--modal-close-box-shadow-hover,0 0 0 1px #000)}}
package/dist/index.min.js CHANGED
@@ -1 +1 @@
1
- var H=Object.defineProperty;var r=(n,t)=>H(n,"name",{value:t,configurable:!0});var F=Object.defineProperty,d=r((n,t)=>F(n,"name",{value:t,configurable:!0}),"__name"),A=class n extends HTMLElement{static{r(this,"WebComponent")}static{d(this,"WebComponent")}static TAG="";TAG="";_globalWildcardListeners=new Set;_namespacedWildcardListeners=new Set;static create(t){let e=class extends n{static{r(this,"CreatedClass")}static{d(this,"CreatedClass")}static TAG=t;TAG=t;render(){throw new Error("`render`should be implemented by children")}};return e.define=function(){return n.define.call(this)},e.event=function(i){return n.event.call(this,i)},e}static define(){u(this.TAG,this)}async attributeChangedCallback(t,e,i){let s=this[`handleChange_${t}`];s&&await s.call(this,e,i)}addEventListener(t,e,i){t===n.event.call(this,"*")?this._namespacedWildcardListeners.add({listener:e,options:i}):t==="*"?e&&this._globalWildcardListeners.add({listener:e,options:i}):super.addEventListener(t,e,i)}_notifyNamespacedWildcardListeners(t){if(this._namespacedWildcardListeners.size===0)return;let e=this.TAG;!e||!t.type.startsWith(`${e}:`)||this._namespacedWildcardListeners.forEach(({listener:i})=>{try{typeof i=="function"?i.call(this,t):i&&typeof i.handleEvent=="function"&&i.handleEvent(t)}catch(s){console.error("Error in namespaced wildcard event listener:",s)}})}_notifyGlobalWildcardListeners(t){this._globalWildcardListeners.size!==0&&this._globalWildcardListeners.forEach(({listener:e})=>{try{typeof e=="function"?e.call(this,t):e&&typeof e.handleEvent=="function"&&e.handleEvent(t)}catch(i){console.error("Error in global wildcard event listener:",i)}})}connectedCallback(){this.render()}qs(t){return this.querySelector(t)}qsa(t){return this.querySelectorAll(t)}static event(t){return p(this.TAG,t)}emit(t,e={}){if(t==="*")throw new Error('Do not emit the literal "*"');let{bubbles:i=!0,cancelable:s=!0,detail:o}=e,a=`${this.TAG}:${t}`,l=new CustomEvent(a,{bubbles:i,cancelable:s,detail:o}),O=this.dispatchEvent(l);return this._notifyNamespacedWildcardListeners(l),O}dispatchEvent(t){let e=super.dispatchEvent(t);return this._notifyGlobalWildcardListeners(t),e}dispatch(t,e={}){let i=new CustomEvent(t,{bubbles:e.bubbles===void 0?!0:e.bubbles,cancelable:e.cancelable===void 0?!0:e.cancelable,detail:e.detail});return this.dispatchEvent(i)}removeEventListener(t,e,i){if(t===n.event.call(this,"*")){if(e&&this._namespacedWildcardListeners){for(let s of this._namespacedWildcardListeners)if(s.listener===e){this._namespacedWildcardListeners.delete(s);break}}}else if(t==="*"){if(e&&this._globalWildcardListeners){for(let s of this._globalWildcardListeners)if(s.listener===e){this._globalWildcardListeners.delete(s);break}}}else super.removeEventListener(t,e,i)}};function p(n,t){return`${n}:${t}`}r(p,"eventName");d(p,"eventName");function L(n){return document.createElement(n).constructor!==HTMLElement}r(L,"isRegistered");d(L,"isRegistered");function u(n,t){window&&"customElements"in window&&(L(n)||customElements.define(n,t))}r(u,"define");d(u,"define");var _="active",f="animated",D=250,h="aria-describedby",T="aria-label",b="close",I="Close",W="no-icon",g="data-modal-hide",C="data-modal-show",E="data-visible",w="",N="escape",y="false",S="focusin",k="hidden",M="keydown",R="modal",B="(prefers-reduced-motion:reduce)",G=" ",x=/\s+/g,v="static",P="tab",c="true",q=["[contenteditable]",'[tabindex="0"]:not([disabled])',"a[href]","audio[controls]","button:not([disabled])","iframe","input:not([disabled]):not([type=hidden])","select:not([disabled])","summary","textarea:not([disabled])","video[controls]"].join(","),m=class extends HTMLElement{static{r(this,"ModalWindow")}_buttonClose=null;_modal=null;_modalOverlay=null;_modalScroll=null;_modalContent=null;_focusTrap1=null;_focusTrap2=null;_heading=null;static TAG="modal-window";_activeElement=null;_isActive=!1;_isAnimated=!0;_isBuilt=!1;_isHideShow=!1;_isStatic=!1;_timerForHide;_timerForShow;_closable=!0;_showIcon=!0;constructor(){super(),this._bind()}_buildModal(t){let e=r(()=>{let l=document.createElement("span");return l.setAttribute("aria-hidden","true"),l.setAttribute("data-modal-focus-trap",""),l.tabIndex=0,l},"createFocusTrap"),i=document.createElement("div");i.setAttribute("data-modal-scroll",""),this._modalScroll=i;let s=document.createElement("div");s.setAttribute("data-modal-overlay",""),this._modalOverlay=s;let o=document.createElement("div");if(o.setAttribute("aria-modal","true"),o.setAttribute("data-modal-dialog",""),o.setAttribute("role","dialog"),o.tabIndex=-1,this._modal=o,this._closable&&this._showIcon){let l=document.createElement("button");l.setAttribute("data-modal-close",""),l.type="button",l.innerHTML="×",o.appendChild(l),this._buttonClose=l}let a=document.createElement("div");a.setAttribute("data-modal-content",""),this._modalContent=a,t.forEach(l=>{a.appendChild(l)}),o.appendChild(a),this._focusTrap1=e(),this._focusTrap2=e(),s.appendChild(o),i.appendChild(this._focusTrap1),i.appendChild(s),i.appendChild(this._focusTrap2),this.appendChild(i)}static get observedAttributes(){return[_,f,h,b,v]}attributeChangedCallback(t,e,i){e!==i&&(t===_&&this._setActiveFlag(),t===f&&this._setAnimationFlag(),t===h&&this._setModalDescription(),t===b&&this._setCloseTitle(),t===v&&this._setStaticFlag())}connectedCallback(){if(!this._isBuilt){this._closable=this.getAttribute("closable")!=="false",this._showIcon=!this.hasAttribute(W),this._heading=this.querySelector("h1,h2,h3,h4,h5,h6");let t=Array.from(this.childNodes);this._buildModal(t),this._setAnimationFlag(),this._setCloseTitle(),this._setModalLabel(),this._setModalDescription(),this._setStaticFlag(),this._setActiveFlag(),this._isBuilt=!0}this._addEvents()}disconnectedCallback(){this._removeEvents()}_bind(){Object.getOwnPropertyNames(Object.getPrototypeOf(this)).forEach(e=>{typeof this[e]=="function"&&(this[e]=this[e].bind(this))})}_addEvents(){this._removeEvents(),document.addEventListener(S,this._handleFocusIn),document.addEventListener(M,this._handleKeyDown),this._buttonClose&&this._buttonClose.addEventListener("click",this._handleClickClose),this._modalOverlay&&this._modalOverlay.addEventListener("click",this._handleClickOverlay)}_removeEvents(){document.removeEventListener(S,this._handleFocusIn),document.removeEventListener(M,this._handleKeyDown),this._buttonClose&&this._buttonClose.removeEventListener("click",this._handleClickClose),this._modalOverlay&&this._modalOverlay.removeEventListener("click",this._handleClickOverlay)}_setAnimationFlag(){this._isAnimated=this.getAttribute(f)!==y}_setCloseTitle(){let t=this.getAttribute(b)||I;this._buttonClose&&(this._buttonClose.title=t,this._buttonClose.setAttribute(T,t))}_setModalLabel(){let t=R;this._heading&&(t=this._heading.textContent||t,t=t.trim().replace(x,G)),this._modal&&this._modal.setAttribute(T,t)}_setModalDescription(){if(!this._modal)return;let t=this.getAttribute(h);t?this._modal.setAttribute(h,t):this._modal.removeAttribute(h)}_setActiveFlag(){let t=this.getAttribute(_)===c;this._isActive=t,this._toggleModalDisplay(()=>{this._isActive&&this._focusModal()})}_setStaticFlag(){this._isStatic=this.getAttribute(v)===c}_focusElement(t){requestAnimationFrame(()=>{typeof t.focus=="function"&&t.focus()})}_focusModal(){requestAnimationFrame(()=>{this._modal&&this._modal.focus(),this._modalScroll&&this._modalScroll.scrollTo(0,0)})}_isOutsideModal(t){return!this._isActive||!t||!this._modal?!1:!(this.contains(t)||this._modal.contains(t))}_isMotionOkay(){let{matches:t}=matchMedia(B);return this._isAnimated&&!t}_toggleModalDisplay(t){if(!this._modalScroll)return;this.setAttribute(_,this._isActive);let e=this._modalScroll.getAttribute(E)===c,i=this._isMotionOkay(),s=i?D:0,o=innerWidth-document.documentElement.clientWidth,a=document.activeElement;this._isActive&&a&&(this._activeElement=a),this._isActive?(this._modalScroll.setAttribute(E,c),document.documentElement.style.overflow=k,o&&(document.documentElement.style.paddingRight=`${o}px`),i&&(this._isHideShow=!0,this._modalScroll.setAttribute(C,c)),t(),this._timerForShow=setTimeout(()=>{clearTimeout(this._timerForShow),this._isHideShow=!1,this._modalScroll?.removeAttribute(C)},s)):e&&(i&&(this._isHideShow=!0,this._modalScroll.setAttribute(g,c)),t(),this._timerForHide=setTimeout(()=>{clearTimeout(this._timerForHide),this._isHideShow=!1,this._modalScroll?.removeAttribute(g),this._modalScroll?.setAttribute(E,y),document.documentElement.style.overflow=w,document.documentElement.style.paddingRight=w},s))}_handleClickOverlay(t){if(this._isHideShow||this._isStatic||!this._closable)return;t.target===this._modalOverlay&&this.close()}_handleClickClose(){this.close()}_handleFocusIn(){if(!this._isActive||!this._modal)return;let t=document.activeElement,e=t===this._focusTrap1,i=t===this._focusTrap2,s=Array.from(this._modal.querySelectorAll(q)),o=s[0],a=s[s.length-1];e&&a?this._focusElement(a):i&&o?this._focusElement(o):this._isOutsideModal(t)&&this._focusModal()}_handleKeyDown({key:t}){this._isActive&&(t=t.toLowerCase(),t===N&&!this._isHideShow&&!this._isStatic&&this._closable&&this.close(),t===P&&this._handleFocusIn())}open(){this._isActive=!0,this._toggleModalDisplay(()=>{this._focusModal()})}close(){this._isActive=!1,this._toggleModalDisplay(()=>{this._activeElement&&this._focusElement(this._activeElement)})}};u(m.TAG,m);export{m as ModalWindow};
1
+ var H=Object.defineProperty;var r=(n,t)=>H(n,"name",{value:t,configurable:!0});var F=Object.defineProperty,d=r((n,t)=>F(n,"name",{value:t,configurable:!0}),"__name"),A=class n extends HTMLElement{static{r(this,"WebComponent")}static{d(this,"WebComponent")}static TAG="";TAG="";_globalWildcardListeners=new Set;_namespacedWildcardListeners=new Set;static create(t){let e=class extends n{static{r(this,"CreatedClass")}static{d(this,"CreatedClass")}static TAG=t;TAG=t;render(){throw new Error("`render`should be implemented by children")}};return e.define=function(){return n.define.call(this)},e.event=function(i){return n.event.call(this,i)},e}static define(){u(this.TAG,this)}async attributeChangedCallback(t,e,i){let s=this[`handleChange_${t}`];s&&await s.call(this,e,i)}addEventListener(t,e,i){t===n.event.call(this,"*")?this._namespacedWildcardListeners.add({listener:e,options:i}):t==="*"?e&&this._globalWildcardListeners.add({listener:e,options:i}):super.addEventListener(t,e,i)}_notifyNamespacedWildcardListeners(t){if(this._namespacedWildcardListeners.size===0)return;let e=this.TAG;!e||!t.type.startsWith(`${e}:`)||this._namespacedWildcardListeners.forEach(({listener:i})=>{try{typeof i=="function"?i.call(this,t):i&&typeof i.handleEvent=="function"&&i.handleEvent(t)}catch(s){console.error("Error in namespaced wildcard event listener:",s)}})}_notifyGlobalWildcardListeners(t){this._globalWildcardListeners.size!==0&&this._globalWildcardListeners.forEach(({listener:e})=>{try{typeof e=="function"?e.call(this,t):e&&typeof e.handleEvent=="function"&&e.handleEvent(t)}catch(i){console.error("Error in global wildcard event listener:",i)}})}connectedCallback(){this.render()}qs(t){return this.querySelector(t)}qsa(t){return this.querySelectorAll(t)}static event(t){return p(this.TAG,t)}emit(t,e={}){if(t==="*")throw new Error('Do not emit the literal "*"');let{bubbles:i=!0,cancelable:s=!0,detail:o}=e,a=`${this.TAG}:${t}`,l=new CustomEvent(a,{bubbles:i,cancelable:s,detail:o}),O=this.dispatchEvent(l);return this._notifyNamespacedWildcardListeners(l),O}dispatchEvent(t){let e=super.dispatchEvent(t);return this._notifyGlobalWildcardListeners(t),e}dispatch(t,e={}){let i=new CustomEvent(t,{bubbles:e.bubbles===void 0?!0:e.bubbles,cancelable:e.cancelable===void 0?!0:e.cancelable,detail:e.detail});return this.dispatchEvent(i)}removeEventListener(t,e,i){if(t===n.event.call(this,"*")){if(e&&this._namespacedWildcardListeners){for(let s of this._namespacedWildcardListeners)if(s.listener===e){this._namespacedWildcardListeners.delete(s);break}}}else if(t==="*"){if(e&&this._globalWildcardListeners){for(let s of this._globalWildcardListeners)if(s.listener===e){this._globalWildcardListeners.delete(s);break}}}else super.removeEventListener(t,e,i)}};function p(n,t){return`${n}:${t}`}r(p,"eventName");d(p,"eventName");function L(n){return document.createElement(n).constructor!==HTMLElement}r(L,"isRegistered");d(L,"isRegistered");function u(n,t){window&&"customElements"in window&&(L(n)||customElements.define(n,t))}r(u,"define");d(u,"define");var _="active",f="animated",D=250,h="aria-describedby",T="aria-label",b="close",I="Close",W="no-icon",g="data-modal-hide",C="data-modal-show",E="data-visible",w="",N="escape",y="false",S="focusin",k="hidden",M="keydown",R="modal",B="(prefers-reduced-motion:reduce)",G=" ",x=/\s+/g,v="static",P="tab",c="true",q=["[contenteditable]",'[tabindex="0"]:not([disabled])',"a[href]","audio[controls]","button:not([disabled])","iframe","input:not([disabled]):not([type=hidden])","select:not([disabled])","summary","textarea:not([disabled])","video[controls]"].join(","),m=class extends HTMLElement{static{r(this,"ModalWindow")}_buttonClose=null;_modal=null;_modalOverlay=null;_modalScroll=null;_modalContent=null;_focusTrap1=null;_focusTrap2=null;_heading=null;static TAG="modal-window";_activeElement=null;_isActive=!1;_isAnimated=!0;_isBuilt=!1;_isHideShow=!1;_isStatic=!1;_timerForHide;_timerForShow;_closable=!0;_showIcon=!0;constructor(){super(),this._bind()}_buildModal(t){let e=r(()=>{let l=document.createElement("span");return l.setAttribute("aria-hidden","true"),l.setAttribute("data-modal-focus-trap",""),l.tabIndex=0,l},"createFocusTrap"),i=document.createElement("div");i.setAttribute("data-modal-scroll",""),this._modalScroll=i;let s=document.createElement("div");s.setAttribute("data-modal-overlay",""),this._modalOverlay=s;let o=document.createElement("dialog");if(o.setAttribute("aria-modal","true"),o.setAttribute("data-modal-dialog",""),o.tabIndex=-1,this._modal=o,this._closable&&this._showIcon){let l=document.createElement("button");l.setAttribute("data-modal-close",""),l.type="button",l.innerHTML="×",o.appendChild(l),this._buttonClose=l}let a=document.createElement("div");a.setAttribute("data-modal-content",""),this._modalContent=a,t.forEach(l=>{a.appendChild(l)}),o.appendChild(a),this._focusTrap1=e(),this._focusTrap2=e(),s.appendChild(o),i.appendChild(this._focusTrap1),i.appendChild(s),i.appendChild(this._focusTrap2),this.appendChild(i)}static get observedAttributes(){return[_,f,h,b,v]}attributeChangedCallback(t,e,i){e!==i&&(t===_&&this._setActiveFlag(),t===f&&this._setAnimationFlag(),t===h&&this._setModalDescription(),t===b&&this._setCloseTitle(),t===v&&this._setStaticFlag())}connectedCallback(){if(!this._isBuilt){this._closable=this.getAttribute("closable")!=="false",this._showIcon=!this.hasAttribute(W),this._heading=this.querySelector("h1,h2,h3,h4,h5,h6");let t=Array.from(this.childNodes);this._buildModal(t),this._setAnimationFlag(),this._setCloseTitle(),this._setModalLabel(),this._setModalDescription(),this._setStaticFlag(),this._setActiveFlag(),this._isBuilt=!0}this._addEvents()}disconnectedCallback(){this._removeEvents()}_bind(){Object.getOwnPropertyNames(Object.getPrototypeOf(this)).forEach(e=>{typeof this[e]=="function"&&(this[e]=this[e].bind(this))})}_addEvents(){this._removeEvents(),document.addEventListener(S,this._handleFocusIn),document.addEventListener(M,this._handleKeyDown),this._buttonClose&&this._buttonClose.addEventListener("click",this._handleClickClose),this._modalOverlay&&this._modalOverlay.addEventListener("click",this._handleClickOverlay)}_removeEvents(){document.removeEventListener(S,this._handleFocusIn),document.removeEventListener(M,this._handleKeyDown),this._buttonClose&&this._buttonClose.removeEventListener("click",this._handleClickClose),this._modalOverlay&&this._modalOverlay.removeEventListener("click",this._handleClickOverlay)}_setAnimationFlag(){this._isAnimated=this.getAttribute(f)!==y}_setCloseTitle(){let t=this.getAttribute(b)||I;this._buttonClose&&(this._buttonClose.title=t,this._buttonClose.setAttribute(T,t))}_setModalLabel(){let t=R;this._heading&&(t=this._heading.textContent||t,t=t.trim().replace(x,G)),this._modal&&this._modal.setAttribute(T,t)}_setModalDescription(){if(!this._modal)return;let t=this.getAttribute(h);t?this._modal.setAttribute(h,t):this._modal.removeAttribute(h)}_setActiveFlag(){let t=this.getAttribute(_)===c;this._isActive=t,this._toggleModalDisplay(()=>{this._isActive&&this._focusModal()})}_setStaticFlag(){this._isStatic=this.getAttribute(v)===c}_focusElement(t){requestAnimationFrame(()=>{typeof t.focus=="function"&&t.focus()})}_focusModal(){requestAnimationFrame(()=>{this._modal&&this._modal.focus(),this._modalScroll&&this._modalScroll.scrollTo(0,0)})}_isOutsideModal(t){return!this._isActive||!t||!this._modal?!1:!(this.contains(t)||this._modal.contains(t))}_isMotionOkay(){let{matches:t}=matchMedia(B);return this._isAnimated&&!t}_toggleModalDisplay(t){if(!this._modalScroll)return;this.setAttribute(_,this._isActive);let e=this._modalScroll.getAttribute(E)===c,i=this._isMotionOkay(),s=i?D:0,o=innerWidth-document.documentElement.clientWidth,a=document.activeElement;this._isActive&&a&&(this._activeElement=a),this._isActive?(this._modalScroll.setAttribute(E,c),document.documentElement.style.overflow=k,o&&(document.documentElement.style.paddingRight=`${o}px`),i&&(this._isHideShow=!0,this._modalScroll.setAttribute(C,c)),t(),this._timerForShow=setTimeout(()=>{clearTimeout(this._timerForShow),this._isHideShow=!1,this._modalScroll?.removeAttribute(C)},s)):e&&(i&&(this._isHideShow=!0,this._modalScroll.setAttribute(g,c)),t(),this._timerForHide=setTimeout(()=>{clearTimeout(this._timerForHide),this._isHideShow=!1,this._modalScroll?.removeAttribute(g),this._modalScroll?.setAttribute(E,y),document.documentElement.style.overflow=w,document.documentElement.style.paddingRight=w},s))}_handleClickOverlay(t){if(this._isHideShow||this._isStatic||!this._closable)return;t.target===this._modalOverlay&&this.close()}_handleClickClose(){this.close()}_handleFocusIn(){if(!this._isActive||!this._modal)return;let t=document.activeElement,e=t===this._focusTrap1,i=t===this._focusTrap2,s=Array.from(this._modal.querySelectorAll(q)),o=s[0],a=s[s.length-1];e&&a?this._focusElement(a):i&&o?this._focusElement(o):this._isOutsideModal(t)&&this._focusModal()}_handleKeyDown({key:t}){this._isActive&&(t=t.toLowerCase(),t===N&&!this._isHideShow&&!this._isStatic&&this._closable&&this.close(),t===P&&this._handleFocusIn())}open(){this._isActive=!0,this._toggleModalDisplay(()=>{this._focusModal()})}close(){this._isActive=!1,this._toggleModalDisplay(()=>{this._activeElement&&this._focusElement(this._activeElement)})}};u(m.TAG,m);export{m as ModalWindow};
package/dist/meta.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "inputs": {
3
3
  "src/index.ts": {
4
- "bytes": 18094,
4
+ "bytes": 18054,
5
5
  "imports": [],
6
6
  "format": "esm"
7
7
  }
@@ -11,7 +11,7 @@
11
11
  "imports": [],
12
12
  "exports": [],
13
13
  "inputs": {},
14
- "bytes": 26248
14
+ "bytes": 26181
15
15
  },
16
16
  "dist/index.js": {
17
17
  "imports": [
@@ -27,10 +27,10 @@
27
27
  "entryPoint": "src/index.ts",
28
28
  "inputs": {
29
29
  "src/index.ts": {
30
- "bytesInOutput": 13105
30
+ "bytesInOutput": 13065
31
31
  }
32
32
  },
33
- "bytes": 13294
33
+ "bytes": 13254
34
34
  }
35
35
  }
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrate-system/dialog",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "description": "Modal dialog window",