{"version":3,"file":"modal.cjs","sources":["../../../common/mixins/modal.js"],"sourcesContent":["import { returnFirstEl } from '@/common/utils';\n\nconst focusableAttrs = ':not(:disabled):not([aria-disabled=\"true\"]):not([role=\"presentation\"])';\nconst tabbableAttrs = `${focusableAttrs}:not([tabindex=\"-1\"])`;\nconst focusableElementsList = `button,[href],input,select,textarea,details,[tabindex]`;\n\n/**\n * This mixin provides the methods to automatically trap tab focus within\n * the component this mixin is on, meaning it is not possible to tab out\n * of the component without dismissing it.\n *\n * Useful for accessibility reasons on things like important actionable alerts.\n *\n * Use focusFirstElement to focus on the first tabbable element within your component, and call\n * focusTrappedTabPress every time tab is pressed to trap tab within this\n * component.\n *\n * Note that focusFirstElement WILL focus elements with tabindex=\"-1\",\n * however focusTrappedTabPress will not.\n * @displayName Modal Mixin\n */\nexport default {\n  methods: {\n    /**\n     * get the first focusable element in your component, includes tabindex=\"-1\".\n     * @param {object} el - optional - ref of dom element to trap focus on.\n     *  will default to the root node of the vue component\n     */\n    async getFirstFocusableElement (el) {\n      await this.$nextTick();\n      const focusableElements = this._getFocusableElements(el, true);\n      return this._getFirstFocusElement(focusableElements);\n    },\n\n    /**\n     * set focus to the first focusable element in your component, includes tabindex=\"-1\".\n     * @param {object} el - optional - ref of dom element to trap focus on.\n     *  will default to the root node of the vue component\n     */\n    async focusFirstElement (el = this.$el) {\n      const elToFocus = await this.getFirstFocusableElement(returnFirstEl(el));\n      elToFocus?.focus({ preventScroll: true });\n    },\n\n    async focusElementById (elementId) {\n      await this.$nextTick();\n      const result = returnFirstEl(this.$el)?.querySelector(elementId);\n      if (result) {\n        result.focus();\n        return;\n      }\n\n      // eslint-disable-next-line no-console\n      console.warn('Could not find the element specified in dt-modal prop \"initialFocusElement\". ' +\n        'Defaulting to focusing the first element.');\n      await this.focusFirstElement();\n    },\n\n    /**\n     * internal use only.\n     *\n     * @param focusableElements - list of focusable elements\n     * @returns {*} - first DOM element that is focusable.\n     * @private\n     */\n    _getFirstFocusElement (focusableElements) {\n      if (!focusableElements.length) {\n        return;\n      }\n      let firstFocusEl = focusableElements[0];\n      // If first element is a checkbox, put focus on the selected checkbox or the first checkbox if none are selected.\n      if (firstFocusEl.matches('[type=\"radio\"]:not(:checked)')) {\n        firstFocusEl = focusableElements.find(el => el.checked && el.name === firstFocusEl.name) || firstFocusEl;\n      }\n      return firstFocusEl;\n    },\n\n    /**\n     * internal use only.\n     *\n     * gets all the focusable elements within the component\n     * and sets the first and last of those elements.\n     *\n     * @param {object} el - the root dom element to find focusable elements in.\n     * @param {bool} includeNegativeTabIndex - will include tabindex=\"-1\" in the list of focusable elements.\n     */\n    _getFocusableElements (el = this.$el, includeNegativeTabIndex = false) {\n      el = returnFirstEl(el);\n      if (!el) return [];\n      const focusableContent = [...el.querySelectorAll(focusableElementsList)];\n      return focusableContent.filter((fc) => {\n        const style = window.getComputedStyle(fc);\n        return style.getPropertyValue('display') !== 'none' &&\n          style.getPropertyValue('visibility') !== 'hidden' &&\n          fc.matches(includeNegativeTabIndex ? focusableAttrs : tabbableAttrs);\n      });\n    },\n\n    /**\n     * tabs to the next element contained within your component, does not include tabindex=\"-1\".\n     * @param {object} e - keypress event\n     * @param {object} el - optional - ref of dom element to trap focus on.\n     *  will default to the root node of the vue component\n     */\n    focusTrappedTabPress (e, el) {\n      const isTabPressed = e.key === 'Tab';\n\n      if (!isTabPressed) {\n        return;\n      }\n\n      const focusableElements = this._getFocusableElements(el);\n      if (!focusableElements.length) {\n        e.preventDefault();\n        return;\n      }\n\n      const firstFocusableElement = this._getFirstFocusElement(focusableElements);\n      const lastFocusableElement = focusableElements[focusableElements.length - 1];\n\n      if (e.shiftKey) {\n        if (document.activeElement === firstFocusableElement) {\n          lastFocusableElement.focus();\n          e.preventDefault();\n        }\n      } else {\n        if (document.activeElement === lastFocusableElement) {\n          firstFocusableElement.focus();\n          e.preventDefault();\n        }\n      }\n    },\n  },\n};\n"],"names":["focusableAttrs","tabbableAttrs","focusableElementsList","Modal","el","focusableElements","elToFocus","returnFirstEl","elementId","result","firstFocusEl","includeNegativeTabIndex","fc","style","firstFocusableElement","lastFocusableElement"],"mappings":"kJAEMA,EAAiB,yEACjBC,EAAgB,GAAGD,CAAc,wBACjCE,EAAwB,yDAiB9BC,EAAe,CACb,QAAS,CAMP,MAAM,yBAA0BC,EAAI,CAClC,MAAM,KAAK,UAAS,EACpB,MAAMC,EAAoB,KAAK,sBAAsBD,EAAI,EAAI,EAC7D,OAAO,KAAK,sBAAsBC,CAAiB,CACrD,EAOA,MAAM,kBAAmBD,EAAK,KAAK,IAAK,CACtC,MAAME,EAAY,MAAM,KAAK,yBAAyBC,EAAAA,cAAcH,CAAE,CAAC,EACvEE,GAAA,MAAAA,EAAW,MAAM,CAAE,cAAe,EAAI,EACxC,EAEA,MAAM,iBAAkBE,EAAW,OACjC,MAAM,KAAK,UAAS,EACpB,MAAMC,GAASF,EAAAA,EAAAA,cAAc,KAAK,GAAG,IAAtBA,YAAAA,EAAyB,cAAcC,GACtD,GAAIC,EAAQ,CACVA,EAAO,MAAK,EACZ,MACF,CAGA,QAAQ,KAAK,wHACgC,EAC7C,MAAM,KAAK,kBAAiB,CAC9B,EASA,sBAAuBJ,EAAmB,CACxC,GAAI,CAACA,EAAkB,OACrB,OAEF,IAAIK,EAAeL,EAAkB,CAAC,EAEtC,OAAIK,EAAa,QAAQ,8BAA8B,IACrDA,EAAeL,EAAkB,KAAKD,GAAMA,EAAG,SAAWA,EAAG,OAASM,EAAa,IAAI,GAAKA,GAEvFA,CACT,EAWA,sBAAuBN,EAAK,KAAK,IAAKO,EAA0B,GAAO,CAErE,OADAP,EAAKG,EAAAA,cAAcH,CAAE,EAChBA,EACoB,CAAC,GAAGA,EAAG,iBAAiBF,CAAqB,CAAC,EAC/C,OAAQU,GAAO,CACrC,MAAMC,EAAQ,OAAO,iBAAiBD,CAAE,EACxC,OAAOC,EAAM,iBAAiB,SAAS,IAAM,QAC3CA,EAAM,iBAAiB,YAAY,IAAM,UACzCD,EAAG,QAAQD,EAA0BX,EAAiBC,CAAa,CACvE,CAAC,EAPe,CAAA,CAQlB,EAQA,qBAAsB,EAAGG,EAAI,CAG3B,GAAI,EAFiB,EAAE,MAAQ,OAG7B,OAGF,MAAMC,EAAoB,KAAK,sBAAsBD,CAAE,EACvD,GAAI,CAACC,EAAkB,OAAQ,CAC7B,EAAE,eAAc,EAChB,MACF,CAEA,MAAMS,EAAwB,KAAK,sBAAsBT,CAAiB,EACpEU,EAAuBV,EAAkBA,EAAkB,OAAS,CAAC,EAEvE,EAAE,SACA,SAAS,gBAAkBS,IAC7BC,EAAqB,MAAK,EAC1B,EAAE,eAAc,GAGd,SAAS,gBAAkBA,IAC7BD,EAAsB,MAAK,EAC3B,EAAE,eAAc,EAGtB,CACJ,CACA"}