(function () { "use strict"; function normalizeSequenceState(sequence) { return { total: Math.max(0, Number(sequence?.total) || 0), currentIndex: Number.isFinite(Number(sequence?.currentIndex)) ? Number(sequence.currentIndex) : -1, previousKey: String(sequence?.previousKey ?? sequence?.previousId ?? "").trim(), nextKey: String(sequence?.nextKey ?? sequence?.nextId ?? "").trim() }; } function isEditableKeyTarget(target) { if (!(target instanceof HTMLElement)) { return false; } return target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement || target.isContentEditable || Boolean(target.closest("[contenteditable='true']")); } function hasOpenModalDialog() { return Boolean(document.querySelector("[role='dialog'][aria-modal='true'][aria-hidden='false']")); } function createSequenceNavigator(config = {}) { const getElements = typeof config.getElements === "function" ? config.getElements : () => ({}); let buttonsBound = false; let keyboardBound = false; function getSequenceState() { return normalizeSequenceState( typeof config.getSequenceState === "function" ? config.getSequenceState() : null ); } function getPrevButton(elements) { return typeof config.getPrevButton === "function" ? config.getPrevButton(elements) : null; } function getNextButton(elements) { return typeof config.getNextButton === "function" ? config.getNextButton(elements) : null; } function getPositionEl(elements) { return typeof config.getPositionEl === "function" ? config.getPositionEl(elements) : null; } function isActive(elements) { return typeof config.isActive === "function" ? config.isActive(elements) !== false : true; } function getTargetKey(sequence, offset) { return offset < 0 ? sequence.previousKey : sequence.nextKey; } function formatPositionText(sequence, elements) { return typeof config.formatPositionText === "function" ? String(config.formatPositionText(sequence, elements) || "") : ""; } function selectTarget(targetKey, elements, offset) { if (!targetKey || typeof config.selectTarget !== "function") { return false; } return config.selectTarget(targetKey, elements, offset) !== false; } function afterSelect(targetKey, elements, offset) { if (typeof config.afterSelect === "function") { config.afterSelect(targetKey, elements, offset); } } function shouldHandleKeyEvent(event, elements) { if (!isActive(elements)) { return false; } if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return false; } if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") { return false; } if (hasOpenModalDialog()) { return false; } return !isEditableKeyTarget(event.target); } function sync(elements = getElements()) { const sequence = getSequenceState(); const previousKey = getTargetKey(sequence, -1); const nextKey = getTargetKey(sequence, 1); const prevButton = getPrevButton(elements); const nextButton = getNextButton(elements); const positionEl = getPositionEl(elements); if (prevButton) { prevButton.disabled = !previousKey; } if (nextButton) { nextButton.disabled = !nextKey; } if (positionEl) { positionEl.textContent = formatPositionText(sequence, elements); } } function step(offset, elements = getElements()) { const sequence = getSequenceState(); const targetKey = getTargetKey(sequence, offset); if (!targetKey) { return false; } const didSelect = selectTarget(targetKey, elements, offset); if (didSelect) { afterSelect(targetKey, elements, offset); } return didSelect; } function bind(elements = getElements()) { if (!buttonsBound) { getPrevButton(elements)?.addEventListener("click", () => { step(-1, getElements()); }); getNextButton(elements)?.addEventListener("click", () => { step(1, getElements()); }); buttonsBound = true; } if (!keyboardBound) { document.addEventListener("keydown", (event) => { const latestElements = getElements(); if (!shouldHandleKeyEvent(event, latestElements)) { return; } const offset = event.key === "ArrowRight" ? 1 : -1; const sequence = getSequenceState(); if (!getTargetKey(sequence, offset)) { return; } event.preventDefault(); step(offset, latestElements); }); keyboardBound = true; } sync(elements); } return { bind, step, sync, getSequenceState }; } window.TarotSequenceNav = { ...(window.TarotSequenceNav || {}), createSequenceNavigator }; })();