UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

1 lines 6.79 kB
{"version":3,"file":"modal.cjs","sources":["../../../common/mixins/modal.js"],"sourcesContent":["const 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(el);\n elToFocus?.focus({ preventScroll: true });\n },\n\n async focusElementById (elementId) {\n await this.$nextTick();\n const result = 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 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":[],"mappings":";;AAAA,MAAM,iBAAiB;AACvB,MAAM,gBAAgB,GAAG,cAAc;AACvC,MAAM,wBAAwB;AAiB9B,MAAe,QAAA;AAAA,EACb,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMP,MAAM,yBAA0B,IAAI;AAClC,YAAM,KAAK;AACX,YAAM,oBAAoB,KAAK,sBAAsB,IAAI,IAAI;AAC7D,aAAO,KAAK,sBAAsB,iBAAiB;AAAA,IACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOD,MAAM,kBAAmB,KAAK,KAAK,KAAK;AACtC,YAAM,YAAY,MAAM,KAAK,yBAAyB,EAAE;AACxD,6CAAW,MAAM,EAAE,eAAe,KAAM;AAAA,IACzC;AAAA,IAED,MAAM,iBAAkB,WAAW;;AACjC,YAAM,KAAK;AACX,YAAM,UAAS,UAAK,QAAL,mBAAU,cAAc;AACvC,UAAI,QAAQ;AACV,eAAO,MAAK;AACZ;AAAA,MACD;AAGD,cAAQ,KAAK,wHACgC;AAC7C,YAAM,KAAK;IACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASD,sBAAuB,mBAAmB;AACxC,UAAI,CAAC,kBAAkB,QAAQ;AAC7B;AAAA,MACD;AACD,UAAI,eAAe,kBAAkB,CAAC;AAEtC,UAAI,aAAa,QAAQ,8BAA8B,GAAG;AACxD,uBAAe,kBAAkB,KAAK,QAAM,GAAG,WAAW,GAAG,SAAS,aAAa,IAAI,KAAK;AAAA,MAC7F;AACD,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWD,sBAAuB,KAAK,KAAK,KAAK,0BAA0B,OAAO;AACrE,UAAI,CAAC,GAAI,QAAO;AAChB,YAAM,mBAAmB,CAAC,GAAG,GAAG,iBAAiB,qBAAqB,CAAC;AACvE,aAAO,iBAAiB,OAAO,CAAC,OAAO;AACrC,cAAM,QAAQ,OAAO,iBAAiB,EAAE;AACxC,eAAO,MAAM,iBAAiB,SAAS,MAAM,UAC3C,MAAM,iBAAiB,YAAY,MAAM,YACzC,GAAG,QAAQ,0BAA0B,iBAAiB,aAAa;AAAA,MAC7E,CAAO;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQD,qBAAsB,GAAG,IAAI;AAC3B,YAAM,eAAe,EAAE,QAAQ;AAE/B,UAAI,CAAC,cAAc;AACjB;AAAA,MACD;AAED,YAAM,oBAAoB,KAAK,sBAAsB,EAAE;AACvD,UAAI,CAAC,kBAAkB,QAAQ;AAC7B,UAAE,eAAc;AAChB;AAAA,MACD;AAED,YAAM,wBAAwB,KAAK,sBAAsB,iBAAiB;AAC1E,YAAM,uBAAuB,kBAAkB,kBAAkB,SAAS,CAAC;AAE3E,UAAI,EAAE,UAAU;AACd,YAAI,SAAS,kBAAkB,uBAAuB;AACpD,+BAAqB,MAAK;AAC1B,YAAE,eAAc;AAAA,QACjB;AAAA,MACT,OAAa;AACL,YAAI,SAAS,kBAAkB,sBAAsB;AACnD,gCAAsB,MAAK;AAC3B,YAAE,eAAc;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACH;;"}