@studiometa/js-toolkit
Version:
A set of useful little bits of JavaScript to boost your project! 🚀
163 lines (162 loc) • 4.74 kB
JavaScript
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