UNPKG

@studiometa/js-toolkit

Version:

A set of useful little bits of JavaScript to boost your project! 🚀

163 lines (162 loc) • 4.74 kB
import { isArray, isDefined, SmartQueue, dashCase } from "../utils/index.js"; import { features } from "./features.js"; import { useMutation } from "../services/MutationService.js"; import { getInstanceFromElement } from "../helpers/getInstanceFromElement.js"; let queue; function addToQueue(fn) { if (features.get("blocking")) { fn(); return; } if (!queue) { queue = new SmartQueue(); } return queue.add(fn); } const selectors = /* @__PURE__ */ new Map(); const separator = " "; function getSelector(nameOrSelector) { const { component } = features.get("attributes"); const prefix = features.get("prefix"); const key = prefix + component + nameOrSelector; if (!selectors.has(key)) { const parts = [ // Tag select `${prefix}-${dashCase(nameOrSelector)}`, // Single selector `[${component}="${nameOrSelector}"]`, // Selector in the middle of a list of selectors `[${component}*="${separator}${nameOrSelector}${separator}"]`, // Selector at the end of a list of selectors `[${component}$="${separator}${nameOrSelector}"]`, // Selector at the beginning of a list of selectors `[${component}^="${nameOrSelector}${separator}"]` ]; selectors.set(key, parts.join(",")); } return selectors.get(key); } function getComponentElements(nameOrSelector, element = document) { const selector = getSelector(nameOrSelector); let elements = []; try { elements = Array.from(element.querySelectorAll(selector)); } catch { } if (elements.length === 0 && nameOrSelector[0] === nameOrSelector[0].toLowerCase()) { elements = Array.from(element.querySelectorAll(nameOrSelector)); } return elements; } function eventIsDefinedInConfig(event, config) { return isArray(config.emits) && config.emits.includes(event); } function eventIsNative(event, element) { return isDefined(element[`on${event}`]); } function getEventTarget(instance, event, config) { if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) { return instance.$el; } } function getInstancesStorage() { return globalThis.__JS_TOOLKIT_INSTANCES__ ??= /* @__PURE__ */ new Set(); } function getElementsStorage() { return globalThis.__JS_TOOLKIT_ELEMENTS__ ??= /* @__PURE__ */ new Set(); } function getInstances(ctor) { if (isDefined(ctor)) { const filteredInstances = /* @__PURE__ */ new Set(); for (const instance of getInstancesStorage()) { if (instance instanceof ctor) { filteredInstances.add(instance); } } return filteredInstances; } else { return new Set(getInstancesStorage()); } } function getElements() { return new Set(getElementsStorage()); } function addInstance(instance) { getInstancesStorage().add(instance); getElementsStorage().add(instance.$el); } function deleteInstance(instance) { getInstancesStorage().delete(instance); getElementsStorage().delete(instance.$el); } const registryKey = "__JS_TOOLKIT_REGISTRY__"; function registry() { return globalThis[registryKey] ??= /* @__PURE__ */ new Map(); } function mutationCallback() { addToQueue(() => { for (const [nameOrSelector, ctor] of registry()) { for (const el of getComponentElements(nameOrSelector)) { if (!getInstanceFromElement(el, ctor)) { new ctor(el).$mount(); } } } }); addToQueue(() => { for (const instance of getInstances()) { if (!instance.$el.isConnected) { instance.$terminate(); } } }); } function addToRegistry(nameOrSelector, ctor) { if (registry().has(nameOrSelector)) { return; } registry().set(nameOrSelector, ctor); if (ctor.config?.components) { for (const [selector, childConstructor] of Object.entries(ctor.config?.components)) { if ("$isBase" in childConstructor && childConstructor.$isBase) { addToRegistry(selector, childConstructor); } } } const mutation = useMutation(document, { childList: true, subtree: true }); if (!mutation.has(registryKey)) { mutation.add(registryKey, mutationCallback); } } function findClosestInstance(element, instances) { let closest = null; let minDepth = Infinity; for (const instance of instances) { let depth = 0; let el = element; while (el && el !== instance.$el) { depth++; el = el.parentElement; } if (depth < minDepth) { minDepth = depth; closest = instance; } } return closest; } export { addInstance, addToQueue, addToRegistry, deleteInstance, eventIsDefinedInConfig, eventIsNative, findClosestInstance, getComponentElements, getElements, getEventTarget, getInstances, getSelector }; //# sourceMappingURL=utils.js.map