{"version":3,"file":"alert-element-section.min.js","mappings":"yBAOA,MAAMA,qBAAqBC,YA+BjBC,kBAAoBC,KAAKC,aAAaC,KAAKF,MAC3CG,yBAA2BH,KAAKI,oBAAoBF,KAAKF,MAG1D,iBAAAK,GACLL,KAAKM,uBAMLN,KAAKO,aAAa,OAAQ,SAE1BP,KAAKQ,QACP,CAEO,oBAAAC,GACL,MAAMC,EAAUV,KAAKW,WAAWC,cAA2B,cACpD,MAAPF,GAAAA,EAASG,oBAAoB,QAASb,KAAKD,kBAC7C,CAEQ,oBAAAO,GACDN,KAAKW,aACRX,KAAKc,aAAa,CAAEC,KAAM,SAC1Bf,KAAKW,WAAWK,UAAY,4jDAEhC,CAEQ,YAAAf,CAAagB,GAGnBC,aAAalB,KAAKmB,iBAElBC,EAAkBpB,KACpB,CAEQ,mBAAAI,GACNJ,KAAKqB,QAAQC,QAAU,OACvBtB,KAAKmB,gBAAkBI,WAAWH,EAAmB,IAAMpB,KAC7D,CAEQ,MAAAQ,GACN,GAA8B,SAA1BR,KAAKqB,QAAQG,SAAqB,CACpBxB,KAAKW,WAAWC,cAA2B,cACnDa,iBAAiB,QAASzB,KAAKD,kBACzC,CAEA,GAAIC,KAAKqB,QAAQK,UAAW,CAC1B,MAAMA,EAAYC,SAAS3B,KAAKqB,QAAQK,UAAW,KAAO,IAC1DH,WAAWvB,KAAKG,yBAA0BuB,EAC5C,CACF,EAUF,SAASN,EAAkBQ,GACrBA,EAAQC,YACVD,EAAQE,QAEZ,CAQKC,eAAeC,IAAI,kBACtBD,eAAeE,OAAO,gBAAiBpC","sources":["webpack://lange/./sections/alert/alert-element/index.ts"],"sourcesContent":["import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Renders a generic message box. Follows a Bootstrap pattern.\n */\nclass AlertElement extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Which side the alert is aligned to.\n     */\n    alertPosition: 'left' | 'right';\n\n    /**\n     * The severity styling of the alert, following the Bootstrap contextual color names.\n     */\n    alertType: 'danger' | 'dark' | 'info' | 'light' | 'primary' | 'secondary' | 'success' |\n      'warning';\n\n    /**\n     * When 'true' the alert shows a close button that removes the alert when clicked.\n     */\n    closable: string;\n\n    /**\n     * Milliseconds to wait before the alert begins fading out. When unset the alert does not auto\n     * dismiss, and an un-parseable value falls back to a default delay.\n     */\n    fadeDelay: string;\n\n    /**\n     * Set to 'true' to start the fade out animation, after which the alert removes itself. Normally\n     * set internally once the fade delay elapses rather than supplied by the caller.\n     */\n    fadeOut: string;\n  };\n\n  private onCloseClickBound = this.onCloseClick.bind(this);\n  private setFadeOutAttributeBound = this.setFadeOutAttribute.bind(this);\n  private declare fadeRemoveTimer: ReturnType<typeof setTimeout>;\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    // The element applies its own alert role rather than relying on the markup that creates it.\n    // This guarantees every instance announces to assistive technology no matter how it was\n    // authored. Leaving it to each template would let one that omits it silently drop the\n    // announcement.\n    this.setAttribute('role', 'alert');\n\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const closeEl = this.shadowRoot.querySelector<HTMLElement>('.close-cta');\n    closeEl?.removeEventListener('click', this.onCloseClickBound);\n  }\n\n  private initializeShadowRoot() {\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: 'open' });\n      this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n    }\n  }\n\n  private onCloseClick(_event: MouseEvent) {\n    // When the fade out attribute is set, it schedules a remove. Since we are removing immediately\n    // it is important to cancel otherwise that scheduled remove causes a js error.\n    clearTimeout(this.fadeRemoveTimer);\n\n    safeRemoveElement(this);\n  }\n\n  private setFadeOutAttribute() {\n    this.dataset.fadeOut = 'true';\n    this.fadeRemoveTimer = setTimeout(safeRemoveElement, 2000, this);\n  }\n\n  private render() {\n    if (this.dataset.closable === 'true') {\n      const closeEl = this.shadowRoot.querySelector<HTMLElement>('.close-cta');\n      closeEl.addEventListener('click', this.onCloseClickBound);\n    }\n\n    if (this.dataset.fadeDelay) {\n      const fadeDelay = parseInt(this.dataset.fadeDelay, 10) || 5000;\n      setTimeout(this.setFadeOutAttributeBound, fadeDelay);\n    }\n  }\n}\n\n/**\n * This exists as a helper to remove the node that does a check if still connected. This way this\n * callback can be scheduled to run in a way that mitigates an issue where by the time it does run\n * the node has already been removed. When the node has already been detached, trying to remove it\n * again triggers a dom exception (a NotFoundError). We detect the node is already detached by\n * checking that the node has a parent node. If detached then do nothing.\n */\nfunction safeRemoveElement(element: Element) {\n  if (element.parentNode) {\n    element.remove();\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'alert-element': AlertElement;\n  }\n}\n\nif (!customElements.get('alert-element')) {\n  customElements.define('alert-element', AlertElement);\n}\n"],"names":["AlertElement","HTMLElement","onCloseClickBound","this","onCloseClick","bind","setFadeOutAttributeBound","setFadeOutAttribute","connectedCallback","initializeShadowRoot","setAttribute","render","disconnectedCallback","closeEl","shadowRoot","querySelector","removeEventListener","attachShadow","mode","innerHTML","_event","clearTimeout","fadeRemoveTimer","safeRemoveElement","dataset","fadeOut","setTimeout","closable","addEventListener","fadeDelay","parseInt","element","parentNode","remove","customElements","get","define"],"sourceRoot":""}