stylescape
Version:
Stylescape is a visual identity framework developed by Scape Agency.
247 lines • 8.1 kB
JavaScript
import { getComponent } from "./registry.js";
const instanceStore = new WeakMap();
const config = {
attributePrefix: "data-ss",
autoInitEnabled: true,
observerEnabled: true,
debug: true,
};
let observer = null;
function parseConfig(element, componentName, defaults = {}) {
const result = { ...defaults };
const prefix = `${config.attributePrefix}-${componentName}-`;
const jsonAttr = `${config.attributePrefix}-${componentName}-config`;
const jsonConfig = element.getAttribute(jsonAttr);
if (jsonConfig) {
try {
Object.assign(result, JSON.parse(jsonConfig));
}
catch (e) {
console.warn(`[Stylescape] Invalid JSON config for ${componentName}:`, e);
}
}
Array.from(element.attributes).forEach((attr) => {
if (attr.name.startsWith(prefix) && attr.name !== jsonAttr) {
const key = attr.name
.slice(prefix.length)
.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
let value = attr.value;
if (value === "true")
value = true;
else if (value === "false")
value = false;
else if (!isNaN(Number(value)) && value !== "")
value = Number(value);
result[key] = value;
}
});
return result;
}
function initComponent(element, componentName) {
const entry = getComponent(componentName);
if (!entry) {
if (config.debug) {
console.warn(`[Stylescape] Unknown component: ${componentName}`);
}
return null;
}
let instances = instanceStore.get(element);
if (instances?.has(componentName)) {
if (config.debug) {
console.log(`[Stylescape] Component "${componentName}" already initialized on element`);
}
return instances.get(componentName);
}
const componentConfig = parseConfig(element, componentName, entry.defaults);
try {
const instance = entry.handler(element, componentConfig);
if (!instances) {
instances = new Map();
instanceStore.set(element, instances);
}
instances.set(componentName, instance);
element.setAttribute(`${config.attributePrefix}-${componentName}-initialized`, "true");
if (config.debug) {
console.log(`[Stylescape] Initialized "${componentName}" on`, element);
}
return instance;
}
catch (e) {
console.error(`[Stylescape] Error initializing "${componentName}":`, e);
return null;
}
}
function initElement(element) {
const ssAttr = element.getAttribute(config.attributePrefix);
console.log(`[Stylescape] Processing element:`, {
element: element.tagName,
id: element.id,
dataSs: ssAttr,
});
if (!ssAttr)
return;
if (element.hasAttribute(`${config.attributePrefix}-manual`)) {
console.log(`[Stylescape] Skipping manual element:`, element);
return;
}
const componentNames = ssAttr.trim().split(/\s+/);
console.log(`[Stylescape] Initializing components:`, componentNames);
componentNames.forEach((name) => {
if (name) {
initComponent(element, name.toLowerCase());
}
});
}
export function init(root = document.body) {
console.log("[Stylescape] Auto-init starting...", {
root: root.tagName,
autoInitEnabled: config.autoInitEnabled,
});
if (!config.autoInitEnabled) {
if (config.debug) {
console.log("[Stylescape] Auto-init disabled, skipping");
}
return;
}
const selector = `[${config.attributePrefix}]`;
const elements = root.querySelectorAll(selector);
console.log(`[Stylescape] Found ${elements.length} elements with ${selector}`);
if (root instanceof HTMLElement &&
root.hasAttribute(config.attributePrefix)) {
initElement(root);
}
elements.forEach((element) => initElement(element));
console.log(`[Stylescape] Auto-init complete. Initialized ${elements.length} elements`);
}
export function getInstance(element, componentName) {
const instances = instanceStore.get(element);
if (!instances)
return null;
if (componentName) {
return instances.get(componentName.toLowerCase()) || null;
}
const values = instances.values();
const first = values.next();
return first.done ? null : first.value;
}
export function getAllInstances(element) {
return instanceStore.get(element) || null;
}
export function reinit(element, componentName) {
destroy(element, componentName);
if (componentName) {
initComponent(element, componentName);
}
else {
initElement(element);
}
}
export function destroy(element, componentName) {
const instances = instanceStore.get(element);
if (!instances)
return;
const destroyInstance = (name, instance) => {
if (instance &&
typeof instance.destroy ===
"function") {
try {
instance.destroy();
}
catch (e) {
console.warn(`[Stylescape] Error destroying "${name}":`, e);
}
}
instances.delete(name);
element.removeAttribute(`${config.attributePrefix}-${name}-initialized`);
if (config.debug) {
console.log(`[Stylescape] Destroyed "${name}" on`, element);
}
};
if (componentName) {
const instance = instances.get(componentName.toLowerCase());
if (instance) {
destroyInstance(componentName.toLowerCase(), instance);
}
}
else {
instances.forEach((instance, name) => destroyInstance(name, instance));
instanceStore.delete(element);
}
}
export function observe(root = document.body) {
if (!config.observerEnabled)
return;
if (observer) {
observer.disconnect();
}
observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node instanceof HTMLElement) {
if (node.hasAttribute(config.attributePrefix)) {
initElement(node);
}
const descendants = node.querySelectorAll(`[${config.attributePrefix}]`);
descendants.forEach((el) => initElement(el));
}
});
mutation.removedNodes.forEach((node) => {
if (node instanceof HTMLElement) {
if (instanceStore.has(node)) {
destroy(node);
}
const descendants = node.querySelectorAll(`[${config.attributePrefix}]`);
descendants.forEach((el) => {
if (instanceStore.has(el)) {
destroy(el);
}
});
}
});
});
});
observer.observe(root, {
childList: true,
subtree: true,
});
if (config.debug) {
console.log("[Stylescape] Observer started");
}
}
export function stopObserving() {
if (observer) {
observer.disconnect();
observer = null;
if (config.debug) {
console.log("[Stylescape] Observer stopped");
}
}
}
export function setAutoInit(enabled) {
config.autoInitEnabled = enabled;
}
export function setObserver(enabled) {
config.observerEnabled = enabled;
if (!enabled && observer) {
stopObserving();
}
}
export function setDebug(enabled) {
config.debug = enabled;
}
export function setAttributePrefix(prefix) {
config.attributePrefix = prefix;
}
export function autoStart() {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
init();
observe();
});
}
else {
init();
observe();
}
}
//# sourceMappingURL=autoInit.js.map