@substrate-system/dialog 0.0.12 → 0.0.14

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/dist/index.cjs CHANGED
@@ -31,9 +31,9 @@ const ARIA_LABEL = "aria-label";
31
31
  const CLOSE = "close";
32
32
  const CLOSE_TITLE = "Close";
33
33
  const NO_ICON = "no-icon";
34
- const DATA_HIDE = "data-modal-hide";
35
- const DATA_SHOW = "data-modal-show";
36
- const DATA_VISIBLE = "data-visible";
34
+ const CLASS_HIDE = "modal-hide";
35
+ const CLASS_SHOW = "modal-show";
36
+ const CLASS_VISIBLE = "modal-visible";
37
37
  const EMPTY_STRING = "";
38
38
  const ESCAPE = "escape";
39
39
  const FALSE = "false";
@@ -100,31 +100,31 @@ class ModalWindow extends HTMLElement {
100
100
  _buildModal(contentNodes) {
101
101
  const createFocusTrap = /* @__PURE__ */ __name(() => {
102
102
  const trap = document.createElement("span");
103
- trap.setAttribute("data-modal-focus-trap", "");
103
+ trap.classList.add("modal-focus-trap");
104
104
  trap.tabIndex = 0;
105
105
  return trap;
106
106
  }, "createFocusTrap");
107
107
  const scroll = document.createElement("div");
108
- scroll.setAttribute("data-modal-scroll", "");
108
+ scroll.classList.add("modal-scroll");
109
109
  this._modalScroll = scroll;
110
110
  const overlay = document.createElement("div");
111
- overlay.setAttribute("data-modal-overlay", "");
111
+ overlay.classList.add("modal-overlay");
112
112
  this._modalOverlay = overlay;
113
113
  const dialog = document.createElement("dialog");
114
114
  dialog.setAttribute("aria-modal", "true");
115
- dialog.setAttribute("data-modal-dialog", "");
115
+ dialog.classList.add("modal-dialog");
116
116
  dialog.tabIndex = -1;
117
117
  this._modal = dialog;
118
118
  if (this._closable && this._showIcon) {
119
119
  const closeBtn = document.createElement("button");
120
- closeBtn.setAttribute("data-modal-close", "");
120
+ closeBtn.classList.add("modal-close");
121
121
  closeBtn.type = "button";
122
122
  closeBtn.innerHTML = "×";
123
123
  dialog.appendChild(closeBtn);
124
124
  this._buttonClose = closeBtn;
125
125
  }
126
126
  const content = document.createElement("div");
127
- content.setAttribute("data-modal-content", "");
127
+ content.classList.add("modal-content");
128
128
  this._modalContent = content;
129
129
  contentNodes.forEach((node) => {
130
130
  content.appendChild(node);
@@ -339,7 +339,7 @@ class ModalWindow extends HTMLElement {
339
339
  _toggleModalDisplay(callback) {
340
340
  if (!this._modalScroll) return;
341
341
  this.setAttribute(ACTIVE, this._isActive);
342
- const isModalVisible = this._modalScroll.getAttribute(DATA_VISIBLE) === TRUE;
342
+ const isModalVisible = this._modalScroll.classList.contains(CLASS_VISIBLE);
343
343
  const isMotionOkay = this._isMotionOkay();
344
344
  const delay = isMotionOkay ? ANIMATION_DURATION : 0;
345
345
  const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
@@ -348,32 +348,32 @@ class ModalWindow extends HTMLElement {
348
348
  this._activeElement = activeElement;
349
349
  }
350
350
  if (this._isActive) {
351
- this._modalScroll.setAttribute(DATA_VISIBLE, TRUE);
351
+ this._modalScroll.classList.add(CLASS_VISIBLE);
352
352
  document.documentElement.style.overflow = HIDDEN;
353
353
  if (scrollbarWidth) {
354
354
  document.documentElement.style.paddingRight = `${scrollbarWidth}px`;
355
355
  }
356
356
  if (isMotionOkay) {
357
357
  this._isHideShow = true;
358
- this._modalScroll.setAttribute(DATA_SHOW, TRUE);
358
+ this._modalScroll.classList.add(CLASS_SHOW);
359
359
  }
360
360
  callback();
361
361
  this._timerForShow = window.setTimeout(() => {
362
362
  clearTimeout(this._timerForShow);
363
363
  this._isHideShow = false;
364
- this._modalScroll?.removeAttribute(DATA_SHOW);
364
+ this._modalScroll?.classList.remove(CLASS_SHOW);
365
365
  }, delay);
366
366
  } else if (isModalVisible) {
367
367
  if (isMotionOkay) {
368
368
  this._isHideShow = true;
369
- this._modalScroll.setAttribute(DATA_HIDE, TRUE);
369
+ this._modalScroll.classList.add(CLASS_HIDE);
370
370
  }
371
371
  callback();
372
372
  this._timerForHide = window.setTimeout(() => {
373
373
  clearTimeout(this._timerForHide);
374
374
  this._isHideShow = false;
375
- this._modalScroll?.removeAttribute(DATA_HIDE);
376
- this._modalScroll?.setAttribute(DATA_VISIBLE, FALSE);
375
+ this._modalScroll?.classList.remove(CLASS_HIDE);
376
+ this._modalScroll?.classList.remove(CLASS_VISIBLE);
377
377
  document.documentElement.style.overflow = EMPTY_STRING;
378
378
  document.documentElement.style.paddingRight = EMPTY_STRING;
379
379
  }, delay);
@@ -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 NOCLICK = 'noclick'\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 _noClick:boolean = false\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('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 this._noClick = this.hasAttribute(NOCLICK)\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 || this._noClick) 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 CLASS_HIDE = 'modal-hide'\nconst CLASS_SHOW = 'modal-show'\nconst CLASS_VISIBLE = 'modal-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 NOCLICK = 'noclick'\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 _noClick:boolean = false\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.classList.add('modal-focus-trap')\n trap.tabIndex = 0\n return trap\n }\n\n // Create scroll container\n const scroll = document.createElement('div')\n scroll.classList.add('modal-scroll')\n this._modalScroll = scroll\n\n // Create overlay\n const overlay = document.createElement('div')\n overlay.classList.add('modal-overlay')\n this._modalOverlay = overlay\n\n // Create dialog\n const dialog = document.createElement('dialog')\n dialog.setAttribute('aria-modal', 'true')\n dialog.classList.add('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.classList.add('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.classList.add('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 this._noClick = this.hasAttribute(NOCLICK)\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.classList.contains(CLASS_VISIBLE)\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.classList.add(CLASS_VISIBLE)\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.classList.add(CLASS_SHOW)\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?.classList.remove(CLASS_SHOW)\n }, delay)\n } else if (isModalVisible) {\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.classList.add(CLASS_HIDE)\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?.classList.remove(CLASS_HIDE)\n\n // Hide modal.\n this._modalScroll?.classList.remove(CLASS_VISIBLE)\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 || this._noClick) 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
@@ -45,124 +45,130 @@
45
45
  }
46
46
  }
47
47
 
48
- [data-modal-focus-trap] {
49
- opacity: 0;
50
- width: 0;
51
- height: 0;
52
- position: fixed;
53
- top: 0;
54
- left: 0;
55
- overflow: hidden;
56
- }
57
-
58
- [data-modal-scroll] {
59
- width: 100%;
60
- height: 100%;
61
- z-index: var(--modal-overlay-z-index, 100000);
62
- display: none;
63
- position: fixed;
64
- top: 0;
65
- left: 0;
66
- overflow: hidden auto;
67
- }
68
-
69
- [data-modal-scroll][data-visible="true"] {
70
- display: block;
71
- }
72
-
73
- [data-modal-overlay] {
74
- background-color: var(--modal-overlay-background-color, #00000080);
75
- justify-content: center;
76
- align-items: center;
77
- width: 100%;
78
- min-height: 100%;
79
- display: flex;
80
- }
81
-
82
- [data-modal-dialog] {
83
- background-color: var(--modal-dialog-background-color, #fff);
84
- border-radius: var(--modal-dialog-border-radius, 0);
85
- max-height: none;
86
- box-shadow: var(--modal-dialog-box-shadow, 0 2px 5px 0 #00000080);
87
- padding-top: var(--modal-dialog-padding-top, 20px);
88
- padding-left: var(--modal-dialog-padding-left, 20px);
89
- padding-right: var(--modal-dialog-padding-right, 20px);
90
- padding-bottom: var(--modal-dialog-padding-bottom, 20px);
91
- width: var(--modal-dialog-width, 500px);
92
- border: none;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- [data-modal-show="true"] [data-modal-overlay] {
98
- animation-name: SHOW-OVERLAY;
99
- animation-duration: .25s;
100
- }
48
+ modal-window {
49
+ & .modal-focus-trap {
50
+ opacity: 0;
51
+ width: 0;
52
+ height: 0;
53
+ position: fixed;
54
+ top: 0;
55
+ left: 0;
56
+ overflow: hidden;
57
+ }
101
58
 
102
- [data-modal-show="true"] [data-modal-dialog] {
103
- animation-name: SHOW-DIALOG;
104
- animation-duration: .25s;
105
- }
59
+ & .modal-scroll {
60
+ width: 100%;
61
+ height: 100%;
62
+ z-index: var(--modal-overlay-z-index, 100000);
63
+ display: none;
64
+ position: fixed;
65
+ top: 0;
66
+ left: 0;
67
+ overflow: hidden auto;
68
+
69
+ &.modal-visible {
70
+ display: block;
71
+ }
72
+
73
+ &.modal-show .modal-overlay {
74
+ animation-name: SHOW-OVERLAY;
75
+ animation-duration: .25s;
76
+ }
77
+
78
+ &.modal-show .modal-dialog {
79
+ animation-name: SHOW-DIALOG;
80
+ animation-duration: .25s;
81
+ }
82
+
83
+ &.modal-hide .modal-overlay {
84
+ opacity: 0;
85
+ animation-name: HIDE-OVERLAY;
86
+ animation-duration: .25s;
87
+ }
88
+
89
+ &.modal-hide .modal-dialog {
90
+ animation-name: HIDE-DIALOG;
91
+ animation-duration: .25s;
92
+ transform: scale(.95);
93
+ }
94
+ }
106
95
 
107
- [data-modal-hide="true"] [data-modal-overlay] {
108
- opacity: 0;
109
- animation-name: HIDE-OVERLAY;
110
- animation-duration: .25s;
111
- }
96
+ & .modal-content {
97
+ & > h2 {
98
+ margin-top: 0;
99
+ }
100
+ }
112
101
 
113
- [data-modal-hide="true"] [data-modal-dialog] {
114
- animation-name: HIDE-DIALOG;
115
- animation-duration: .25s;
116
- transform: scale(.95);
117
- }
102
+ & .modal-overlay {
103
+ background-color: var(--modal-overlay-background-color, #00000080);
104
+ justify-content: center;
105
+ align-items: center;
106
+ width: 100%;
107
+ min-height: 100%;
108
+ display: flex;
109
+ }
118
110
 
119
- [data-modal-close] {
120
- appearance: none;
121
- touch-action: none;
122
- user-select: none;
123
- color: var(--modal-close-color, #fff);
124
- background-color: var(--modal-close-background-color, #000);
125
- border-radius: var(--modal-close-border-radius, 50%);
126
- box-shadow: var(--modal-close-box-shadow, 0 0 0 1px #fff);
127
- display: var(--modal-close-display, block);
128
- cursor: pointer;
129
- font-family: var(--modal-close-font-family, "Arial", sans-serif);
130
- font-size: var(--modal-close-font-size, 23px);
131
- text-align: center;
132
- line-height: var(--modal-close-line-height, 26px);
133
- width: var(--modal-close-width, 26px);
134
- border: 0;
135
- padding: 0;
136
- position: absolute;
137
- top: 0;
138
- right: 0;
139
- transform: translate(40%, -40%);
140
- }
111
+ & .modal-dialog {
112
+ background-color: var(--modal-dialog-background-color, #fff);
113
+ border-radius: var(--modal-dialog-border-radius, 0);
114
+ max-height: none;
115
+ box-shadow: var(--modal-dialog-box-shadow, 0 2px 5px 0 #00000080);
116
+ padding-top: var(--modal-dialog-padding-top, 20px);
117
+ padding-left: var(--modal-dialog-padding-left, 20px);
118
+ padding-right: var(--modal-dialog-padding-right, 20px);
119
+ padding-bottom: var(--modal-dialog-padding-bottom, 20px);
120
+ width: var(--modal-dialog-width, 500px);
121
+ border: none;
122
+ display: block;
123
+ position: relative;
124
+ }
141
125
 
142
- [data-modal-close]:hover {
143
- color: var(--modal-close-color-hover, #000);
144
- background-color: var(--modal-close-background-color-hover, #fff);
145
- box-shadow: var(--modal-close-box-shadow-hover, 0 0 0 1px #000);
146
- }
126
+ & .modal-close {
127
+ appearance: none;
128
+ touch-action: none;
129
+ user-select: none;
130
+ color: var(--modal-close-color, #fff);
131
+ background-color: var(--modal-close-background-color, #000);
132
+ border-radius: var(--modal-close-border-radius, 50%);
133
+ box-shadow: var(--modal-close-box-shadow, 0 0 0 1px #fff);
134
+ display: var(--modal-close-display, block);
135
+ cursor: pointer;
136
+ font-family: var(--modal-close-font-family, "Arial", sans-serif);
137
+ font-size: var(--modal-close-font-size, 23px);
138
+ text-align: center;
139
+ line-height: var(--modal-close-line-height, 26px);
140
+ width: var(--modal-close-width, 26px);
141
+ border: 0;
142
+ padding: 0;
143
+ position: absolute;
144
+ top: 0;
145
+ right: 0;
146
+ transform: translate(40%, -40%);
147
+
148
+ &:hover {
149
+ color: var(--modal-close-color-hover, #000);
150
+ background-color: var(--modal-close-background-color-hover, #fff);
151
+ box-shadow: var(--modal-close-box-shadow-hover, 0 0 0 1px #000);
152
+ }
153
+ }
147
154
 
148
- modal-window {
149
155
  & dialog {
150
156
  max-width: 80vw;
151
157
  }
152
- }
153
158
 
154
- @supports selector(:focus-visible) {
155
- [data-modal-close]:focus-visible {
156
- color: var(--modal-close-color-hover, #000);
157
- background-color: var(--modal-close-background-color-hover, #fff);
158
- box-shadow: var(--modal-close-box-shadow-hover, 0 0 0 1px #000);
159
+ @supports selector(:focus-visible) {
160
+ & .modal-close:focus-visible {
161
+ color: var(--modal-close-color-hover, #000);
162
+ background-color: var(--modal-close-background-color-hover, #fff);
163
+ box-shadow: var(--modal-close-box-shadow-hover, 0 0 0 1px #000);
164
+ }
159
165
  }
160
- }
161
166
 
162
- @supports not selector(:focus-visible) {
163
- [data-modal-close]:focus {
164
- color: var(--modal-close-color-hover, #000);
165
- background-color: var(--modal-close-background-color-hover, #fff);
166
- box-shadow: var(--modal-close-box-shadow-hover, 0 0 0 1px #000);
167
+ @supports not selector(:focus-visible) {
168
+ & .modal-close:focus {
169
+ color: var(--modal-close-color-hover, #000);
170
+ background-color: var(--modal-close-background-color-hover, #fff);
171
+ box-shadow: var(--modal-close-box-shadow-hover, 0 0 0 1px #000);
172
+ }
167
173
  }
168
174
  }
package/dist/index.js CHANGED
@@ -9,9 +9,9 @@ const ARIA_LABEL = "aria-label";
9
9
  const CLOSE = "close";
10
10
  const CLOSE_TITLE = "Close";
11
11
  const NO_ICON = "no-icon";
12
- const DATA_HIDE = "data-modal-hide";
13
- const DATA_SHOW = "data-modal-show";
14
- const DATA_VISIBLE = "data-visible";
12
+ const CLASS_HIDE = "modal-hide";
13
+ const CLASS_SHOW = "modal-show";
14
+ const CLASS_VISIBLE = "modal-visible";
15
15
  const EMPTY_STRING = "";
16
16
  const ESCAPE = "escape";
17
17
  const FALSE = "false";
@@ -78,31 +78,31 @@ class ModalWindow extends HTMLElement {
78
78
  _buildModal(contentNodes) {
79
79
  const createFocusTrap = /* @__PURE__ */ __name(() => {
80
80
  const trap = document.createElement("span");
81
- trap.setAttribute("data-modal-focus-trap", "");
81
+ trap.classList.add("modal-focus-trap");
82
82
  trap.tabIndex = 0;
83
83
  return trap;
84
84
  }, "createFocusTrap");
85
85
  const scroll = document.createElement("div");
86
- scroll.setAttribute("data-modal-scroll", "");
86
+ scroll.classList.add("modal-scroll");
87
87
  this._modalScroll = scroll;
88
88
  const overlay = document.createElement("div");
89
- overlay.setAttribute("data-modal-overlay", "");
89
+ overlay.classList.add("modal-overlay");
90
90
  this._modalOverlay = overlay;
91
91
  const dialog = document.createElement("dialog");
92
92
  dialog.setAttribute("aria-modal", "true");
93
- dialog.setAttribute("data-modal-dialog", "");
93
+ dialog.classList.add("modal-dialog");
94
94
  dialog.tabIndex = -1;
95
95
  this._modal = dialog;
96
96
  if (this._closable && this._showIcon) {
97
97
  const closeBtn = document.createElement("button");
98
- closeBtn.setAttribute("data-modal-close", "");
98
+ closeBtn.classList.add("modal-close");
99
99
  closeBtn.type = "button";
100
100
  closeBtn.innerHTML = "×";
101
101
  dialog.appendChild(closeBtn);
102
102
  this._buttonClose = closeBtn;
103
103
  }
104
104
  const content = document.createElement("div");
105
- content.setAttribute("data-modal-content", "");
105
+ content.classList.add("modal-content");
106
106
  this._modalContent = content;
107
107
  contentNodes.forEach((node) => {
108
108
  content.appendChild(node);
@@ -317,7 +317,7 @@ class ModalWindow extends HTMLElement {
317
317
  _toggleModalDisplay(callback) {
318
318
  if (!this._modalScroll) return;
319
319
  this.setAttribute(ACTIVE, this._isActive);
320
- const isModalVisible = this._modalScroll.getAttribute(DATA_VISIBLE) === TRUE;
320
+ const isModalVisible = this._modalScroll.classList.contains(CLASS_VISIBLE);
321
321
  const isMotionOkay = this._isMotionOkay();
322
322
  const delay = isMotionOkay ? ANIMATION_DURATION : 0;
323
323
  const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
@@ -326,32 +326,32 @@ class ModalWindow extends HTMLElement {
326
326
  this._activeElement = activeElement;
327
327
  }
328
328
  if (this._isActive) {
329
- this._modalScroll.setAttribute(DATA_VISIBLE, TRUE);
329
+ this._modalScroll.classList.add(CLASS_VISIBLE);
330
330
  document.documentElement.style.overflow = HIDDEN;
331
331
  if (scrollbarWidth) {
332
332
  document.documentElement.style.paddingRight = `${scrollbarWidth}px`;
333
333
  }
334
334
  if (isMotionOkay) {
335
335
  this._isHideShow = true;
336
- this._modalScroll.setAttribute(DATA_SHOW, TRUE);
336
+ this._modalScroll.classList.add(CLASS_SHOW);
337
337
  }
338
338
  callback();
339
339
  this._timerForShow = window.setTimeout(() => {
340
340
  clearTimeout(this._timerForShow);
341
341
  this._isHideShow = false;
342
- this._modalScroll?.removeAttribute(DATA_SHOW);
342
+ this._modalScroll?.classList.remove(CLASS_SHOW);
343
343
  }, delay);
344
344
  } else if (isModalVisible) {
345
345
  if (isMotionOkay) {
346
346
  this._isHideShow = true;
347
- this._modalScroll.setAttribute(DATA_HIDE, TRUE);
347
+ this._modalScroll.classList.add(CLASS_HIDE);
348
348
  }
349
349
  callback();
350
350
  this._timerForHide = window.setTimeout(() => {
351
351
  clearTimeout(this._timerForHide);
352
352
  this._isHideShow = false;
353
- this._modalScroll?.removeAttribute(DATA_HIDE);
354
- this._modalScroll?.setAttribute(DATA_VISIBLE, FALSE);
353
+ this._modalScroll?.classList.remove(CLASS_HIDE);
354
+ this._modalScroll?.classList.remove(CLASS_VISIBLE);
355
355
  document.documentElement.style.overflow = EMPTY_STRING;
356
356
  document.documentElement.style.paddingRight = EMPTY_STRING;
357
357
  }, delay);
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 NOCLICK = 'noclick'\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 _noClick:boolean = false\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('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 this._noClick = this.hasAttribute(NOCLICK)\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 || this._noClick) 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 CLASS_HIDE = 'modal-hide'\nconst CLASS_SHOW = 'modal-show'\nconst CLASS_VISIBLE = 'modal-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 NOCLICK = 'noclick'\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 _noClick:boolean = false\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.classList.add('modal-focus-trap')\n trap.tabIndex = 0\n return trap\n }\n\n // Create scroll container\n const scroll = document.createElement('div')\n scroll.classList.add('modal-scroll')\n this._modalScroll = scroll\n\n // Create overlay\n const overlay = document.createElement('div')\n overlay.classList.add('modal-overlay')\n this._modalOverlay = overlay\n\n // Create dialog\n const dialog = document.createElement('dialog')\n dialog.setAttribute('aria-modal', 'true')\n dialog.classList.add('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.classList.add('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.classList.add('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 this._noClick = this.hasAttribute(NOCLICK)\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.classList.contains(CLASS_VISIBLE)\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.classList.add(CLASS_VISIBLE)\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.classList.add(CLASS_SHOW)\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?.classList.remove(CLASS_SHOW)\n }, delay)\n } else if (isModalVisible) {\n // Set flag.\n if (isMotionOkay) {\n this._isHideShow = true\n this._modalScroll.classList.add(CLASS_HIDE)\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?.classList.remove(CLASS_HIDE)\n\n // Hide modal.\n this._modalScroll?.classList.remove(CLASS_VISIBLE)\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 || this._noClick) 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
  }
@@ -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);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-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;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)}modal-window{& dialog{max-width:80vw}}@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)}}modal-window{& .modal-focus-trap{opacity:0;width:0;height:0;position:fixed;top:0;left:0;overflow:hidden}& .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;&.modal-visible{display:block}&.modal-show .modal-overlay{animation-name:SHOW-OVERLAY;animation-duration:.25s}&.modal-show .modal-dialog{animation-name:SHOW-DIALOG;animation-duration:.25s}&.modal-hide .modal-overlay{opacity:0;animation-name:HIDE-OVERLAY;animation-duration:.25s}&.modal-hide .modal-dialog{animation-name:HIDE-DIALOG;animation-duration:.25s;transform:scale(.95)}}& .modal-content{&>h2{margin-top:0}}& .modal-overlay{background-color:var(--modal-overlay-background-color,#00000080);justify-content:center;align-items:center;width:100%;min-height:100%;display:flex}& .modal-dialog{background-color:var(--modal-dialog-background-color,#fff);border-radius:var(--modal-dialog-border-radius,0);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;display:block;position:relative}& .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%);&: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)}}& dialog{max-width:80vw}@supports selector(:focus-visible){& .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){& .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",I=250,h="aria-describedby",T="aria-label",b="close",D="Close",W="no-icon",C="data-modal-hide",g="data-modal-show",E="data-visible",w="",N="escape",y="false",S="focusin",k="hidden",M="keydown",R="modal",B="noclick",G="(prefers-reduced-motion:reduce)",x=" ",P=/\s+/g,v="static",q="tab",c="true",K=["[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;_noClick=!1;constructor(){super(),this._bind()}_buildModal(t){let e=r(()=>{let l=document.createElement("span");return 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._noClick=this.hasAttribute(B),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)||D;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(P,x)),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(G);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?I: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(g,c)),t(),this._timerForShow=setTimeout(()=>{clearTimeout(this._timerForShow),this._isHideShow=!1,this._modalScroll?.removeAttribute(g)},s)):e&&(i&&(this._isHideShow=!0,this._modalScroll.setAttribute(C,c)),t(),this._timerForHide=setTimeout(()=>{clearTimeout(this._timerForHide),this._isHideShow=!1,this._modalScroll?.removeAttribute(C),this._modalScroll?.setAttribute(E,y),document.documentElement.style.overflow=w,document.documentElement.style.paddingRight=w},s))}_handleClickOverlay(t){if(this._isHideShow||this._isStatic||this._noClick||!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(K)),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===q&&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 O=Object.defineProperty;var c=(n,t)=>O(n,"name",{value:t,configurable:!0});var H=Object.defineProperty,d=c((n,t)=>H(n,"name",{value:t,configurable:!0}),"__name"),v=class n extends HTMLElement{static{c(this,"WebComponent")}static{d(this,"WebComponent")}static TAG="";TAG="";_globalWildcardListeners=new Set;_namespacedWildcardListeners=new Set;static create(t){let e=class extends n{static{c(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(){h(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 L(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}),M=this.dispatchEvent(l);return this._notifyNamespacedWildcardListeners(l),M}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 L(n,t){return`${n}:${t}`}c(L,"eventName");d(L,"eventName");function p(n){return document.createElement(n).constructor!==HTMLElement}c(p,"isRegistered");d(p,"isRegistered");function h(n,t){window&&"customElements"in window&&(p(n)||customElements.define(n,t))}c(h,"define");d(h,"define");var u="active",m="animated",F=250,r="aria-describedby",A="aria-label",f="close",I="Close",D="no-icon",C="modal-hide",T="modal-show",E="modal-visible",g="",W="escape",N="false",w="focusin",k="hidden",S="keydown",R="modal",B="noclick",G="(prefers-reduced-motion:reduce)",x=" ",P=/\s+/g,b="static",q="tab",y="true",K=["[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(","),_=class extends HTMLElement{static{c(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;_noClick=!1;constructor(){super(),this._bind()}_buildModal(t){let e=c(()=>{let l=document.createElement("span");return l.classList.add("modal-focus-trap"),l.tabIndex=0,l},"createFocusTrap"),i=document.createElement("div");i.classList.add("modal-scroll"),this._modalScroll=i;let s=document.createElement("div");s.classList.add("modal-overlay"),this._modalOverlay=s;let o=document.createElement("dialog");if(o.setAttribute("aria-modal","true"),o.classList.add("modal-dialog"),o.tabIndex=-1,this._modal=o,this._closable&&this._showIcon){let l=document.createElement("button");l.classList.add("modal-close"),l.type="button",l.innerHTML="×",o.appendChild(l),this._buttonClose=l}let a=document.createElement("div");a.classList.add("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[u,m,r,f,b]}attributeChangedCallback(t,e,i){e!==i&&(t===u&&this._setActiveFlag(),t===m&&this._setAnimationFlag(),t===r&&this._setModalDescription(),t===f&&this._setCloseTitle(),t===b&&this._setStaticFlag())}connectedCallback(){if(!this._isBuilt){this._closable=this.getAttribute("closable")!=="false",this._showIcon=!this.hasAttribute(D),this._noClick=this.hasAttribute(B),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(w,this._handleFocusIn),document.addEventListener(S,this._handleKeyDown),this._buttonClose&&this._buttonClose.addEventListener("click",this._handleClickClose),this._modalOverlay&&this._modalOverlay.addEventListener("click",this._handleClickOverlay)}_removeEvents(){document.removeEventListener(w,this._handleFocusIn),document.removeEventListener(S,this._handleKeyDown),this._buttonClose&&this._buttonClose.removeEventListener("click",this._handleClickClose),this._modalOverlay&&this._modalOverlay.removeEventListener("click",this._handleClickOverlay)}_setAnimationFlag(){this._isAnimated=this.getAttribute(m)!==N}_setCloseTitle(){let t=this.getAttribute(f)||I;this._buttonClose&&(this._buttonClose.title=t,this._buttonClose.setAttribute(A,t))}_setModalLabel(){let t=R;this._heading&&(t=this._heading.textContent||t,t=t.trim().replace(P,x)),this._modal&&this._modal.setAttribute(A,t)}_setModalDescription(){if(!this._modal)return;let t=this.getAttribute(r);t?this._modal.setAttribute(r,t):this._modal.removeAttribute(r)}_setActiveFlag(){let t=this.getAttribute(u)===y;this._isActive=t,this._toggleModalDisplay(()=>{this._isActive&&this._focusModal()})}_setStaticFlag(){this._isStatic=this.getAttribute(b)===y}_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(G);return this._isAnimated&&!t}_toggleModalDisplay(t){if(!this._modalScroll)return;this.setAttribute(u,this._isActive);let e=this._modalScroll.classList.contains(E),i=this._isMotionOkay(),s=i?F:0,o=innerWidth-document.documentElement.clientWidth,a=document.activeElement;this._isActive&&a&&(this._activeElement=a),this._isActive?(this._modalScroll.classList.add(E),document.documentElement.style.overflow=k,o&&(document.documentElement.style.paddingRight=`${o}px`),i&&(this._isHideShow=!0,this._modalScroll.classList.add(T)),t(),this._timerForShow=setTimeout(()=>{clearTimeout(this._timerForShow),this._isHideShow=!1,this._modalScroll?.classList.remove(T)},s)):e&&(i&&(this._isHideShow=!0,this._modalScroll.classList.add(C)),t(),this._timerForHide=setTimeout(()=>{clearTimeout(this._timerForHide),this._isHideShow=!1,this._modalScroll?.classList.remove(C),this._modalScroll?.classList.remove(E),document.documentElement.style.overflow=g,document.documentElement.style.paddingRight=g},s))}_handleClickOverlay(t){if(this._isHideShow||this._isStatic||this._noClick||!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(K)),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===W&&!this._isHideShow&&!this._isStatic&&this._closable&&this.close(),t===q&&this._handleFocusIn())}open(){this._isActive=!0,this._toggleModalDisplay(()=>{this._focusModal()})}close(){this._isActive=!1,this._toggleModalDisplay(()=>{this._activeElement&&this._focusElement(this._activeElement)})}};h(_.TAG,_);export{_ as ModalWindow};
package/dist/meta.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "inputs": {
3
3
  "src/index.ts": {
4
- "bytes": 18128,
4
+ "bytes": 18062,
5
5
  "imports": [],
6
6
  "format": "esm"
7
7
  }
@@ -11,7 +11,7 @@
11
11
  "imports": [],
12
12
  "exports": [],
13
13
  "inputs": {},
14
- "bytes": 26305
14
+ "bytes": 26237
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": 13131
30
+ "bytesInOutput": 13065
31
31
  }
32
32
  },
33
- "bytes": 13320
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.12",
3
+ "version": "0.0.14",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "description": "Modal dialog window",
@@ -53,15 +53,13 @@
53
53
  "@typescript-eslint/eslint-plugin": "^8.0.0",
54
54
  "@typescript-eslint/parser": "^8.0.0",
55
55
  "auto-changelog": "^2.5.0",
56
+ "browserslist": "^4.28.1",
56
57
  "esbuild": "^0.27.0",
57
58
  "eslint": "^8.57.0",
58
59
  "eslint-config-standard": "^17.1.0",
59
60
  "lightningcss": "^1.30.2",
60
61
  "lightningcss-cli": "^1.30.2",
61
62
  "markdown-toc": "^1.2.0",
62
- "postcss": "^8.5.2",
63
- "postcss-cli": "^11.0.0",
64
- "postcss-nesting": "^13.0.1",
65
63
  "tap-spec": "^5.0.0",
66
64
  "typedoc": "^0.28.1",
67
65
  "typescript": "^5.7.3",