@uistate/core
Version:
Revolutionary DOM-based state management using CSS custom properties - zero dependencies, potential O(1) updates
79 lines (62 loc) • 2.21 kB
JavaScript
const createEventState = (initial = {}) => {
const store = JSON.parse(JSON.stringify(initial));
const bus = document.createElement("x-store");
bus.style.display = "none";
document.documentElement.appendChild(bus);
return {
get: (path) => {
if (!path) return store;
return path
.split(".")
.reduce(
(obj, prop) =>
obj && obj[prop] !== undefined ? obj[prop] : undefined,
store
);
},
set: (path, value) => {
if(!path) return;
let target = store;
const parts = path.split(".");
const last = parts.pop();
parts.forEach((part) => {
if (!target[part] || typeof target[part] !== "object") {
target[part] = {};
}
target = target[part];
});
target[last] = value;
bus.dispatchEvent(new CustomEvent(path, { detail: value }));
if (parts.length > 0) {
let parentPath = "";
for (const part of parts) {
parentPath = parentPath ? `${parentPath}.${part}` : part;
bus.dispatchEvent(
new CustomEvent(`${parentPath}.*`, {
detail: { path, value },
})
);
}
bus.dispatchEvent(
new CustomEvent("*", {
detail: { path, value},
})
);
}
return value;
},
subscribe: (path, callback) => {
if (!path || typeof callback !== "function") return () => {};
const handler = (e) => callback(e.detail, path);
bus.addEventListener(path, handler);
return () => bus.removeEventListener(path, handler);
},
destroy: () => {
if (bus.parentNode) {
bus.parentNode.removeChild(bus);
}
},
};
};
export default createEventState;
export { createEventState };