@dialpad/dialtone-vue
Version:
Vue component library for Dialpad's design system Dialtone
83 lines (82 loc) • 3.24 kB
JavaScript
const o = ':not(:disabled):not([aria-disabled="true"]):not([role="presentation"])', a = `${o}:not([tabindex="-1"])`, r = "button,[href],input,select,textarea,details,[tabindex]", c = {
methods: {
/**
* get the first focusable element in your component, includes tabindex="-1".
* @param {object} el - optional - ref of dom element to trap focus on.
* will default to the root node of the vue component
*/
async getFirstFocusableElement(e) {
await this.$nextTick();
const t = this._getFocusableElements(e, !0);
return this._getFirstFocusElement(t);
},
/**
* set focus to the first focusable element in your component, includes tabindex="-1".
* @param {object} el - optional - ref of dom element to trap focus on.
* will default to the root node of the vue component
*/
async focusFirstElement(e = this.$el) {
const t = await this.getFirstFocusableElement(e);
t == null || t.focus({ preventScroll: !0 });
},
async focusElementById(e) {
var s;
await this.$nextTick();
const t = (s = this.$el) == null ? void 0 : s.querySelector(e);
if (t) {
t.focus();
return;
}
console.warn('Could not find the element specified in dt-modal prop "initialFocusElement". Defaulting to focusing the first element.'), await this.focusFirstElement();
},
/**
* internal use only.
*
* @param focusableElements - list of focusable elements
* @returns {*} - first DOM element that is focusable.
* @private
*/
_getFirstFocusElement(e) {
if (!e.length)
return;
let t = e[0];
return t.matches('[type="radio"]:not(:checked)') && (t = e.find((s) => s.checked && s.name === t.name) || t), t;
},
/**
* internal use only.
*
* gets all the focusable elements within the component
* and sets the first and last of those elements.
*
* @param {object} el - the root dom element to find focusable elements in.
* @param {bool} includeNegativeTabIndex - will include tabindex="-1" in the list of focusable elements.
*/
_getFocusableElements(e = this.$el, t = !1) {
return e ? [...e.querySelectorAll(r)].filter((n) => {
const i = window.getComputedStyle(n);
return i.getPropertyValue("display") !== "none" && i.getPropertyValue("visibility") !== "hidden" && n.matches(t ? o : a);
}) : [];
},
/**
* tabs to the next element contained within your component, does not include tabindex="-1".
* @param {object} e - keypress event
* @param {object} el - optional - ref of dom element to trap focus on.
* will default to the root node of the vue component
*/
focusTrappedTabPress(e, t) {
if (!(e.key === "Tab"))
return;
const n = this._getFocusableElements(t);
if (!n.length) {
e.preventDefault();
return;
}
const i = this._getFirstFocusElement(n), l = n[n.length - 1];
e.shiftKey ? document.activeElement === i && (l.focus(), e.preventDefault()) : document.activeElement === l && (i.focus(), e.preventDefault());
}
}
};
export {
c as default
};
//# sourceMappingURL=modal.js.map