UNPKG

@ou-imdt/utils

Version:

Utility library for interactive media development

109 lines (93 loc) 3.46 kB
import { defaultState } from '../Base.js'; // defines a prop to reference a list like elements items export const items = Symbol('items'); // defines a prop to track the index of a list like elements active item export const activeItemIndex = Symbol('activeItemIndex'); // defines a prop to track the availability of a list like elements items export const availableItemFlags = Symbol('availableItemFlags'); // defines a prop to track the selected state of a list like elements items export const selectedItemFlags = Symbol('selectedItemFlags'); // defines a method to move the active item index to the first available item of a list like element export const moveToFirst = Symbol('moveToFirst'); // defines a method to move the active item index to the last available item of a list like element export const moveToLast = Symbol('moveToLast'); // defines a method to move the active item index to the next available item of a list like element export const moveToNext = Symbol('moveToNext'); // defines a method to move the active item index to the previous available item of a list like element export const moveToPrevious = Symbol('moveToPrevious'); // defines a flag to continually loop through items of a list like element export const itemFocusLoop = Symbol('itemFocusLoop'); // defines a prop to hold a reference to the initial items, i.e. during connectedCallback export const initialItems = Symbol('initialItems'); export default (superClass) => class ListMixin extends superClass { static get [defaultState]() { return { ...super[defaultState], [activeItemIndex]: null, [availableItemFlags]: [], [selectedItemFlags]: [], [itemFocusLoop]: false }; } constructor() { super(); } get [items]() { return []; } /** * @param {array} list */ set [items](list) { this.append(...list); // remove DOM ref? } [moveToFirst]() { return this.moveToIndex(0, 1); } [moveToLast]() { return this.moveToIndex(this[items].length - 1, -1); } [moveToNext]() { const index = this[items].length ? (this[activeItemIndex] ?? -1) + 1 : 0; return this.moveToIndex(index, 1); } [moveToPrevious]() { const index = this[items].length ? (this[activeItemIndex] ?? -1) - 1 : this[items].length - 1; return this.moveToIndex(index, 1); } connectedCallback() { super.connectedCallback(); requestAnimationFrame(() => { this[initialItems] = Object.freeze(this[items]); }); } /** * moves the pointer to index provided an item exists at that location * @param {*} index * @param {*} forward * @returns */ moveToIndex(index) { // moveToIndex(index, forward = true) { // const index = this[closestAvailableItemIndex]({ from: value, forward }); if (this[items].length === 0) return; if (typeof this[items][index] === 'undefined') { if (!this[itemFocusLoop]) return false; if (index < 0) return this[moveToLast](); return this[moveToFirst](); } // console.log(`move to index ${index} from ${this[activeItemIndex]}`); this[activeItemIndex] = index; return true; } // sortAscending() { // this[items] = this[items].sort(({ textContent: a }, { textContent: b }) => { // if (a < b) return -1; // if (a > b) return 1; // return 0; // }); // } // sortDescending() { // this[items] = this.sortAscending().reverse(); // } }