{"version":3,"file":"modal.cjs","names":["returnFirstEl"],"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"],"mappings":"qIAEA,IAAM,EAAiB,yEACjB,EAAgB,GAAG,EAAe,uBAClC,EAAwB,yDAiB9B,EAAe,CACb,QAAS,CAMP,MAAM,yBAA0B,EAAI,CAClC,MAAM,KAAK,WAAW,CACtB,IAAM,EAAoB,KAAK,sBAAsB,EAAI,GAAK,CAC9D,OAAO,KAAK,sBAAsB,EAAkB,EAQtD,MAAM,kBAAmB,EAAK,KAAK,IAAK,EACpB,MAAM,KAAK,yBAAyBA,EAAAA,cAAc,EAAG,CAAC,GAC7D,MAAM,CAAE,cAAe,GAAM,CAAC,EAG3C,MAAM,iBAAkB,EAAW,CACjC,MAAM,KAAK,WAAW,CACtB,IAAM,EAASA,EAAAA,cAAc,KAAK,IAAI,EAAE,cAAc,EAAU,CAChE,GAAI,EAAQ,CACV,EAAO,OAAO,CACd,OAIF,QAAQ,KAAK,yHACiC,CAC9C,MAAM,KAAK,mBAAmB,EAUhC,sBAAuB,EAAmB,CACxC,GAAI,CAAC,EAAkB,OACrB,OAEF,IAAI,EAAe,EAAkB,GAKrC,OAHI,EAAa,QAAQ,+BAA+B,GACtD,EAAe,EAAkB,KAAK,GAAM,EAAG,SAAW,EAAG,OAAS,EAAa,KAAK,EAAI,GAEvF,GAYT,sBAAuB,EAAK,KAAK,IAAK,EAA0B,GAAO,CAIrE,MAHA,GAAKA,EAAAA,cAAc,EAAG,CACjB,EACoB,CAAC,GAAG,EAAG,iBAAiB,EAAsB,CAAC,CAChD,OAAQ,GAAO,CACrC,IAAM,EAAQ,OAAO,iBAAiB,EAAG,CACzC,OAAO,EAAM,iBAAiB,UAAU,GAAK,QAC3C,EAAM,iBAAiB,aAAa,GAAK,UACzC,EAAG,QAAQ,EAA0B,EAAiB,EAAc,EACtE,CAPc,EAAE,EAgBpB,qBAAsB,EAAG,EAAI,CAG3B,GAFqB,EAAE,MAAQ,MAG7B,OAGF,IAAM,EAAoB,KAAK,sBAAsB,EAAG,CACxD,GAAI,CAAC,EAAkB,OAAQ,CAC7B,EAAE,gBAAgB,CAClB,OAGF,IAAM,EAAwB,KAAK,sBAAsB,EAAkB,CACrE,EAAuB,EAAkB,EAAkB,OAAS,GAEtE,EAAE,SACA,SAAS,gBAAkB,IAC7B,EAAqB,OAAO,CAC5B,EAAE,gBAAgB,EAGhB,SAAS,gBAAkB,IAC7B,EAAsB,OAAO,CAC7B,EAAE,gBAAgB,GAIzB,CACF"}