UNPKG

@sandlada/vue-mdc

Version:

![Vue MDC Logo](https://raw.githubusercontent.com/sandlada/vue-mdc/refs/heads/main/docs/vue-mdc-cover.png)

175 lines (174 loc) 4.89 kB
/** * @license * Copyright 2025 Sandlada & Kai Orion * SPDX-License-Identifier: MIT */ import { onMounted, nextTick } from "vue"; import { isServer } from "../../utils/is-server.js"; const SNavigableController = Symbol("navigableController"); function useNavigable(hostRef, options) { const getTabElements = () => { if (isServer() || !hostRef.value) { return []; } const elements = []; const treewalker = document.createTreeWalker(hostRef.value, NodeFilter.SHOW_ELEMENT); while (treewalker.nextNode()) { if (treewalker.currentNode.hasAttribute("navigation-tab")) { elements.push(treewalker.currentNode); } } return elements; }; const getActiveTabElement = () => { if (isServer() || !hostRef.value) { return null; } const treewalker = document.createTreeWalker(hostRef.value, NodeFilter.SHOW_ELEMENT); while (treewalker.nextNode()) { const node = treewalker.currentNode; if (node.hasAttribute("active-navigation-tab") && node.hasAttribute("navigation-tab")) { return node; } } return null; }; const _isTab = (tabLike) => { return tabLike.hasAttribute("navigation-tab"); }; const _resetTabElementAttribute = () => { if (!hostRef.value) { return; } const treewalker = document.createTreeWalker(hostRef.value, NodeFilter.SHOW_ELEMENT); while (treewalker.nextNode()) { const node = treewalker.currentNode; if (!node.hasAttribute("navigation-tab")) { continue; } if (node.hasAttribute("active-navigation-tab")) { node.removeAttribute("active-navigation-tab"); } } }; const setActiveTabByLabel = (label) => { if (isServer() || !hostRef.value) { return; } _resetTabElementAttribute(); const treewalker = document.createTreeWalker(hostRef.value, NodeFilter.SHOW_ELEMENT); while (treewalker.nextNode()) { const node = treewalker.currentNode; if (!_isTab(node)) { continue; } if (node.hasAttribute("label") && node.getAttribute("label") === label) { if (_dispatchTabChangeEvent(node)) { break; } node.setAttribute("active-navigation-tab", ``); break; } } }; const setActiveTabByOrder = (order) => { if (isServer() || !hostRef.value) { return; } _resetTabElementAttribute(); const treewalker = document.createTreeWalker(hostRef.value, NodeFilter.SHOW_ELEMENT); while (treewalker.nextNode()) { const node = treewalker.currentNode; if (!_isTab(node)) { continue; } if (node.hasAttribute("order") && Number(node.getAttribute("order")) === order) { if (!_dispatchTabChangeEvent(node)) { break; } node.setAttribute("active-navigation-tab", ``); break; } } }; const setActiveTabByElement = (element) => { if (isServer() || !hostRef.value) { return; } _resetTabElementAttribute(); const treewalker = document.createTreeWalker(hostRef.value, NodeFilter.SHOW_ELEMENT); while (treewalker.nextNode()) { const node = treewalker.currentNode; if (!_isTab(node)) { continue; } if (node.isSameNode(element)) { if (!_dispatchTabChangeEvent(node)) { break; } node.setAttribute("active-navigation-tab", ``); break; } } }; const _handleTabClick = (e) => { e.preventDefault(); e.stopPropagation(); const tab = e.currentTarget; setActiveTabByElement(tab); }; const _handleTabChange = (e) => { if (isServer() || !hostRef.value) { return; } e.stopImmediatePropagation(); if (options.handleChange) { options.handleChange(e); } hostRef.value.removeEventListener("change", _handleTabChange); }; const _dispatchTabChangeEvent = (element) => { if (isServer() || !hostRef.value) { return; } const event = new CustomEvent("change", { cancelable: true, bubbles: true }); hostRef.value.addEventListener("change", _handleTabChange); return element.dispatchEvent(event); }; onMounted(() => { if (isServer()) { return; } nextTick(() => { if (!hostRef.value) { return; } const host = hostRef.value; getTabElements().forEach((tab) => { tab.addEventListener("click", _handleTabClick); }); host[SNavigableController] = { getTabElements, getActiveTabElement, setActiveTabByLabel, setActiveTabByOrder, setActiveTabByElement }; }); }); return { getTabElements, getActiveTabElement, setActiveTabByLabel, setActiveTabByOrder, setActiveTabByElement }; } export { SNavigableController, useNavigable }; //# sourceMappingURL=use-navigable.js.map