@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
127 lines (126 loc) • 4.9 kB
JavaScript
import N from "./dom.js";
const _ = "listElementKey is required or the referenced element doesn't exist. Received listElement: ", v = ({
// Role of the list items in the component. This is used to identify the list items
// so you must update this if the role of your list items is anything other than 'option'
listItemRole: h = "option",
// Key of the data prop that will be added to the component.
indexKey: s = "highlightIndex",
idKey: n = "highlightId",
// Key of the method that references the list element.
listElementKey: I = "listRef",
// Optional, Key of the computed prop that references the currently active item element.
activeItemKey: c = "",
// Optional, name of the method that toggles the list visibility. Used for
// opening the list when up or down is pressed.
openMethod: l = null,
// Optional, method to call when the highlightIndex is changed.
afterHighlightMethod: r = null,
// Optional, method to call when the highlightIndex goes past the beginning of the list.
beginningOfListMethod: m = null,
// Optional, method to call when the highlightIndex goes past the end of the list.
endOfListMethod: g = null,
// Scroll the active element into view when highlighted by a keyboard event.
scrollToOnHighlight: d = !0,
// Focus the active element on keyboard navigation.
focusOnKeyboardNavigation: f = !1
} = {}) => ({
mixins: [N],
data() {
return {
[s]: -1,
[n]: "",
scrollToOnHighlight: d,
focusOnKeyboardNavigation: f
};
},
provide() {
return {
highlightId: () => this[n]
};
},
methods: {
// Returns the list element
// this[listElement]() can return a Vue component, in which case we need to target
// the $el property, or it can simply be an html element.
_getListElement() {
var t;
return ((t = this[I]()) == null ? void 0 : t.$el) || this[I]();
},
// Gets the length of all the items in the list, uses the listItemRole param to determine
// whether an element is a list item.
_itemsLength() {
const t = this._getListItemNodes();
return t === null ? 0 : t.length;
},
// Gets all the list item nodes within the list element
_getListItemNodes() {
const t = this._getListElement();
return t ? Array.from(t.querySelectorAll(`[role="${h}"], #sr-only-close-button`)) : (console.error(_, t), null);
},
onUpKey() {
l && this[l](!0), this[s] > 0 ? this.setHighlightIndex(this[s] - 1) : m && this[m](), this.scrollActiveItemIntoViewIfNeeded(), this.focusActiveItemIfNeeded();
},
onDownKey() {
l && this[l](!0), this[s] < this._itemsLength() - 1 ? this.setHighlightIndex(this[s] + 1) : g && this[g](), this.scrollActiveItemIntoViewIfNeeded(), this.focusActiveItemIfNeeded();
},
onHomeKey() {
this.jumpToBeginning(), this.scrollActiveItemIntoViewIfNeeded(), this.focusActiveItemIfNeeded();
},
onEndKey() {
this.jumpToEnd(), this.scrollActiveItemIntoViewIfNeeded(), this.focusActiveItemIfNeeded();
},
onNavigationKey(t) {
const e = this._getListItemNodes(), i = e.filter((o) => o.textContent.trim().toLowerCase().startsWith(t.toLowerCase()));
if (i.length <= 0)
return;
const u = i.findIndex((o) => this[s] === e.indexOf(o)), a = e.indexOf(
u < i.length - 1 ? i[u + 1] : i[0]
);
this.setHighlightIndex(a), this.scrollActiveItemIntoViewIfNeeded(), this.focusActiveItemIfNeeded();
},
isValidLetter(t) {
return t.length > 1 ? !1 : t >= "a" && t <= "z" || t >= "A" && t <= "Z";
},
jumpToBeginning() {
this.setHighlightIndex(0);
},
jumpToEnd() {
this.setHighlightIndex(this._itemsLength() - 1);
},
setHighlightIndex(t) {
this[s] = t, this[n] = this._getItemId(t), this._itemsLength() && r && this[r](t);
},
setHighlightId(t) {
this[n] = t, this[s] = this._getItemIndex(t), this._itemsLength() && r && this[r](this._getItemIndex(t));
},
_getItemIndex(t) {
const e = this._getListElement();
return e ? Array.from(e.querySelectorAll(`[role="${h}"], #sr-only-close-button`)).indexOf(e.querySelector(`#${t}`)) : void 0;
},
_getItemId(t) {
var i;
const e = this._getListElement();
if (e)
return (i = e.querySelectorAll(`[role="${h}"], #sr-only-close-button`)[t]) == null ? void 0 : i.id;
},
scrollActiveItemIntoViewIfNeeded() {
if (!this.scrollToOnHighlight)
return;
const t = this[c];
if (t) {
const e = this._getListElement();
this.scrollElementIntoViewIfNeeded(t, null, null, e);
}
},
focusActiveItemIfNeeded() {
if (!this.focusOnKeyboardNavigation)
return;
const t = this[c];
t && t.focus();
}
}
});
export {
v as default
};
//# sourceMappingURL=keyboard-list-navigation.js.map