UNPKG

woby

Version:

A high-performance framework with fine-grained observable/signal-based reactivity for building rich applications.

1,650 lines (1,649 loc) 93.4 kB
const DEBUGGER = { /** Enable debug mode for detailed logging */ debug: false, /** Enable test mode */ test: false, /** Enable verbose comment debugging */ verboseComment: false, /** Enable context comment debugging */ contextComment: false }; class Stack extends Error { constructor(message = "", startIndex = 0) { super(message); this.name = "Stack"; Object.setPrototypeOf(this, Stack.prototype); if (this.stack) { const stackLines = this.stack.split("\n"); const header = stackLines[0]; const body = stackLines.slice(1 + startIndex); this.stack = [header, ...body].join("\n"); } } } const callStack = (msg) => { if (!DEBUGGER.debug) return void 0; return new Stack(msg ?? "Call Stack"); }; let BATCH; let OBSERVER; const setBatch = (value) => BATCH = value; const setObserver = (value) => OBSERVER = value; const castArray$1 = (value) => { return isArray$1(value) ? value : [value]; }; const castError$1 = (error) => { if (error instanceof Error) return error; if (typeof error === "string") return new Error(error); return new Error("Unknown error"); }; const { is } = Object; const { isArray: isArray$1 } = Array; const isEqual = (a, b) => { if (a.length !== b.length) return false; for (let i = 0, l = a.length; i < l; i++) { const valueA = a[i]; const valueB = b[i]; if (!is(valueA, valueB)) return false; } return true; }; const isFunction$1 = (value) => { return typeof value === "function"; }; const isObject$1 = (value) => { return value !== null && typeof value === "object"; }; const isSymbol = (value) => { return typeof value === "symbol"; }; const noop$1 = (stack, dispose) => { return; }; const nope = () => { return false; }; const SYMBOL_CACHED = Symbol("Cached"); const SYMBOL_OBSERVABLE = Symbol("Observable"); const SYMBOL_OBSERVABLE_BOOLEAN = Symbol("Observable.Boolean"); const SYMBOL_OBSERVABLE_FROZEN = Symbol("Observable.Frozen"); const SYMBOL_OBSERVABLE_READABLE = Symbol("Observable.Readable"); const SYMBOL_OBSERVABLE_WRITABLE = Symbol("Observable.Writable"); const SYMBOL_STORE = Symbol("Store"); const SYMBOL_STORE_KEYS = Symbol("Store.Keys"); const SYMBOL_STORE_OBSERVABLE = Symbol("Store.Observable"); const SYMBOL_STORE_TARGET = Symbol("Store.Target"); const SYMBOL_STORE_VALUES = Symbol("Store.Values"); const SYMBOL_STORE_UNTRACKED = Symbol("Store.Untracked"); const SYMBOL_SUSPENSE$1 = Symbol("Suspense"); const SYMBOL_UNCACHED = Symbol("Uncached"); const SYMBOL_UNTRACKED = Symbol("Untracked"); const SYMBOL_UNTRACKED_UNWRAPPED = Symbol("Untracked.Unwrapped"); function deepResolve(value) { if (isFunction$1(value)) { return deepResolve(value()); } if (value instanceof Array) { const resolved = new Array(value.length); for (let i = 0, l = resolved.length; i < l; i++) { resolved[i] = deepResolve(value[i]); } return resolved; } else { return value; } } function frozenFunction() { if (arguments.length) { throw new Error("A readonly Observable can not be updated"); } else { return this; } } function readableFunction() { if (arguments.length) { throw new Error("A readonly Observable can not be updated"); } else { return this.get(); } } function writableFunction(fn) { if (arguments.length) { if (isFunction$1(fn)) { return this.update(fn); } else { return this.set(fn); } } else { return this.get(); } } const frozen = (value) => { const fn = frozenFunction.bind(value); fn[SYMBOL_OBSERVABLE] = true; fn[SYMBOL_OBSERVABLE_FROZEN] = true; return fn; }; const readable = (value, stack) => { value.stack = stack; const fn = readableFunction.bind(value); fn.valueOf = () => deepResolve(fn); fn.toString = () => fn.valueOf().toString(); fn[SYMBOL_OBSERVABLE] = true; fn[SYMBOL_OBSERVABLE_READABLE] = value; return fn; }; const writable = (value, stack) => { value.stack = stack; const fn = writableFunction.bind(value); fn.valueOf = () => deepResolve(fn); fn.toString = () => fn.valueOf().toString(); fn[SYMBOL_OBSERVABLE] = true; fn[SYMBOL_OBSERVABLE_WRITABLE] = value; return fn; }; const DIRTY_NO = 0; const DIRTY_MAYBE_NO = 1; const DIRTY_MAYBE_YES = 2; const DIRTY_YES = 3; const OBSERVABLE_FALSE = frozen(false); const OBSERVABLE_TRUE = frozen(true); const UNAVAILABLE = new Proxy({}, new Proxy({}, { get() { throw new Error("Unavailable value"); } })); const UNINITIALIZED = function() { }; let Scheduler$2 = class Scheduler { constructor() { this.waiting = []; this.counter = 0; this.locked = false; this.flush = () => { if (this.locked) return; if (this.counter) return; if (!this.waiting.length) return; try { this.locked = true; while (true) { const queue = this.waiting; if (!queue.length) break; this.waiting = []; for (let i = 0, l = queue.length; i < l; i++) { queue[i][0].update(queue[i][1]); } } } finally { this.locked = false; } }; this.wrap = (fn) => { this.counter += 1; fn(); this.counter -= 1; this.flush(); }; this.schedule = (observer, stack) => { this.waiting.push([observer, stack]); }; } }; const SchedulerSync = new Scheduler$2(); class Observable { /* CONSTRUCTOR */ constructor(value, options2, parent) { this.observers = /* @__PURE__ */ new Set(); this.value = value; this.options = options2; if (parent) { this.parent = parent; } if ((options2 == null ? void 0 : options2.equals) !== void 0) { this.equals = options2.equals || nope; } } /* API */ get() { var _a, _b; if (!((_a = this.parent) == null ? void 0 : _a.disposed)) { (_b = this.parent) == null ? void 0 : _b.update(this.stack); OBSERVER == null ? void 0 : OBSERVER.observables.link(this); } return this.value; } set(value) { var _a; if (((_a = this.options) == null ? void 0 : _a.type) !== void 0) { const expectedType = this.options.type; if (typeof expectedType === "string" || typeof expectedType === "function") { try { if (expectedType === "string" || expectedType === String) { if (typeof value !== "string") { throw new TypeError(`Expected value of type 'string', but received '${typeof value}'`); } } else if (expectedType === "number" || expectedType === Number) { if (typeof value !== "number") { throw new TypeError(`Expected value of type 'number', but received '${typeof value}'`); } } else if (expectedType === "boolean" || expectedType === Boolean) { if (typeof value !== "boolean" && typeof value !== "string" && value !== void 0) { throw new TypeError(`Expected value of type 'boolean', 'string', or 'undefined' for boolean, but received '${typeof value}'`); } } else if (expectedType === "function" || expectedType === Function) { if (Array.isArray(value) && typeof value[0] === "function") { } else if (typeof value === "function") { } else { throw new TypeError(`Expected value of type 'function' (as [fn] array or direct function), but received '${typeof value}'`); } } else if (expectedType === "object" || expectedType === Object) { if (typeof value !== "object" || value === null) { throw new TypeError(`Expected value of type 'object', but received '${typeof value}'`); } } else if (expectedType === "symbol" || expectedType === Symbol) { if (typeof value !== "symbol") { throw new TypeError(`Expected value of type 'symbol', but received '${typeof value}'`); } } else if (expectedType === "bigint" || expectedType === BigInt) { if (typeof value !== "bigint") { throw new TypeError(`Expected value of type 'bigint', but received '${typeof value}'`); } } else if (expectedType === "undefined") { if (value !== void 0) { throw new TypeError(`Expected value of type 'undefined', but received '${typeof value}'`); } } else if (typeof expectedType === "function") { const constructorName = expectedType.name; const isBuiltInConstructor = constructorName === "String" || constructorName === "Number" || constructorName === "Boolean" || constructorName === "Function" || constructorName === "Object" || constructorName === "Symbol" || constructorName === "BigInt"; if (constructorName && !isBuiltInConstructor) { if (!(value instanceof expectedType)) { throw new TypeError(`Expected value to be instance of '${constructorName}', but received '${typeof value}'`); } } } } catch (e) { if (!(e instanceof TypeError)) ; else { throw e; } } } } const equals = this.equals || is; const fresh = this.value === UNINITIALIZED || !equals(value, this.value); if (!fresh) return value; this.value = value; this.stack = callStack(); SchedulerSync.counter += 1; this.stale(DIRTY_YES, this.stack); SchedulerSync.counter -= 1; SchedulerSync.flush(); return value; } stale(status, stack) { for (const observer of this.observers) { if (observer.status !== DIRTY_MAYBE_NO || observer.observables.has(this)) { if (observer.sync) { observer.status = Math.max(observer.status, status); SchedulerSync.schedule(observer, stack); } else { observer.stale(status, stack); } } } } update(fn, stack) { const value = fn(this.value); return this.set(value); } } const lazyArrayEach = (arr, fn) => { if (arr instanceof Array) { for (let i = 0, l = arr.length; i < l; i++) { fn(arr[i]); } } else if (arr) { fn(arr); } }; const lazyArrayEachRight = (arr, fn) => { if (arr instanceof Array) { for (let i = arr.length - 1; i >= 0; i--) { fn(arr[i]); } } else if (arr) { fn(arr); } }; const lazyArrayPush = (obj, key, value) => { const arr = obj[key]; if (arr instanceof Array) { arr.push(value); } else if (arr) { obj[key] = [arr, value]; } else { obj[key] = value; } }; const lazySetAdd = (obj, key, value) => { const set = obj[key]; if (set instanceof Set) { set.add(value); } else if (set) { if (value !== set) { const s = /* @__PURE__ */ new Set(); s.add(set); s.add(value); obj[key] = s; } } else { obj[key] = value; } }; const lazySetDelete = (obj, key, value) => { const set = obj[key]; if (set instanceof Set) { set.delete(value); } else if (set === value) { obj[key] = void 0; } }; const lazySetEach = (set, fn) => { if (set instanceof Set) { for (const value of set) { fn(value); } } else if (set) { fn(set); } }; const onCleanup = (cleanup2) => cleanup2.call(cleanup2, callStack()); const onDispose = (owner) => owner.dispose(true); class Owner { constructor() { this.disposed = false; this.cleanups = void 0; this.errorHandler = void 0; this.contexts = void 0; this.observers = void 0; this.roots = void 0; this.suspenses = void 0; } /* API */ catch(error, silent) { var _a; const { errorHandler } = this; if (errorHandler) { errorHandler(error); return true; } else { if ((_a = this.parent) == null ? void 0 : _a.catch(error, true)) return true; if (silent) return false; throw error; } } dispose(deep) { lazyArrayEachRight(this.contexts, onDispose); lazyArrayEachRight(this.observers, onDispose); lazyArrayEachRight(this.suspenses, onDispose); lazyArrayEachRight(this.cleanups, onCleanup); this.cleanups = void 0; this.disposed = deep; this.errorHandler = void 0; this.observers = void 0; this.suspenses = void 0; } get(symbol) { var _a; return (_a = this.context) == null ? void 0 : _a[symbol]; } wrap(fn, owner, observer, stack) { const ownerPrev = OWNER; const observerPrev = OBSERVER; setOwner(owner); setObserver(observer); try { return fn(stack); } catch (error) { this.catch(castError$1(error), false); return UNAVAILABLE; } finally { setOwner(ownerPrev); setObserver(observerPrev); } } } class SuperRoot extends Owner { constructor() { super(...arguments); this.context = {}; } } let SUPER_OWNER = new SuperRoot(); let OWNER = SUPER_OWNER; const setOwner = (value) => OWNER = value; class ObservablesArray { /* CONSTRUCTOR */ constructor(observer) { this.observer = observer; this.observables = []; this.observablesIndex = 0; } /* API */ dispose(deep) { if (deep) { const { observer, observables } = this; for (let i = 0; i < observables.length; i++) { observables[i].observers.delete(observer); } } this.observablesIndex = 0; } postdispose() { const { observer, observables, observablesIndex } = this; const observablesLength = observables.length; if (observablesIndex < observablesLength) { for (let i = observablesIndex; i < observablesLength; i++) { observables[i].observers.delete(observer); } observables.length = observablesIndex; } } empty() { return !this.observables.length; } has(observable) { const index = this.observables.indexOf(observable); return index >= 0 && index < this.observablesIndex; } link(observable) { const { observer, observables, observablesIndex } = this; const observablesLength = observables.length; if (observablesLength > 0) { if (observables[observablesIndex] === observable) { this.observablesIndex += 1; return; } const index = observables.indexOf(observable); if (index >= 0 && index < observablesIndex) { return; } if (observablesIndex < observablesLength - 1) { this.postdispose(); } else if (observablesIndex === observablesLength - 1) { observables[observablesIndex].observers.delete(observer); } } observable.observers.add(observer); observables[this.observablesIndex++] = observable; if (observablesIndex === 128) { observer.observables = new ObservablesSet(observer, observables); } } update(stack) { var _a; const { observables } = this; for (let i = 0, l = observables.length; i < l; i++) { (_a = observables[i].parent) == null ? void 0 : _a.update(stack); } } } class ObservablesSet { /* CONSTRUCTOR */ constructor(observer, observables) { this.observer = observer; this.observables = new Set(observables); } /* API */ dispose(deep) { for (const observable of this.observables) { observable.observers.delete(this.observer); } } postdispose() { return; } empty() { return !this.observables.size; } has(observable) { return this.observables.has(observable); } link(observable) { const { observer, observables } = this; const sizePrev = observables.size; observable.observers.add(observer); const sizeNext = observables.size; if (sizePrev === sizeNext) return; observables.add(observable); } update(stack) { var _a; for (const observable of this.observables) { (_a = observable.parent) == null ? void 0 : _a.update(stack); } } } class Observer extends Owner { /* CONSTRUCTOR */ constructor() { super(); this.parent = OWNER; this.context = OWNER.context; this.status = DIRTY_YES; this.observables = new ObservablesArray(this); if (OWNER !== SUPER_OWNER) { lazyArrayPush(this.parent, "observers", this); } } /* API */ dispose(deep) { this.observables.dispose(deep); super.dispose(deep); } refresh(fn, stack) { this.dispose(false); this.status = DIRTY_MAYBE_NO; try { return this.wrap(fn, this, this, stack); } finally { this.observables.postdispose(); } } run(stack) { throw new Error("Abstract method"); } stale(status, stack) { throw new Error("Abstract method"); } update(stack) { if (this.disposed) return; if (this.status === DIRTY_MAYBE_YES) { this.observables.update(stack); } if (this.status === DIRTY_YES) { this.status = DIRTY_MAYBE_NO; this.run(stack); if (this.status === DIRTY_MAYBE_NO) { this.status = DIRTY_NO; } else { this.update(stack); } } else { this.status = DIRTY_NO; } } } const cleanup = (fn) => { lazyArrayPush(OWNER, "cleanups", fn); }; class Context extends Owner { /* CONSTRUCTOR */ constructor(context2) { super(); this.parent = OWNER; this.context = { ...OWNER.context, ...context2 }; lazyArrayPush(this.parent, "contexts", this); } /* API */ wrap(fn, owner, observer, stack) { return super.wrap(fn, this, void 0, stack); } } function context(symbolOrContext, fn) { if (isSymbol(symbolOrContext)) { return OWNER.context[symbolOrContext]; } else { const stack = callStack(); return new Context(symbolOrContext).wrap(fn || noop$1, void 0, void 0, stack); } } class Scheduler2 { constructor() { this.waiting = []; this.locked = false; this.queued = false; this.flush = (stack) => { if (this.locked) return; if (!this.waiting.length) return; try { this.locked = true; while (true) { const queue = this.waiting; if (!queue.length) break; this.waiting = []; for (let i = 0, l = queue.length; i < l; i++) { queue[i][0].update(queue[i][1]); } } } finally { this.locked = false; } }; this.queue = (stack) => { if (this.queued) return; this.queued = true; this.resolve(stack); }; this.resolve = (stack) => { queueMicrotask(() => { queueMicrotask(() => { if (BATCH) { BATCH.finally(() => this.resolve(stack)); } else { this.queued = false; this.flush(stack); } }); }); }; this.schedule = (effect2, stack) => { this.waiting.push([effect2, stack]); this.queue(stack); }; } } const Scheduler$1 = new Scheduler2(); class Effect extends Observer { /* CONSTRUCTOR */ constructor(fn, options2) { super(); this.fn = fn; if ((options2 == null ? void 0 : options2.suspense) !== false) { const suspense = this.get(SYMBOL_SUSPENSE$1); if (suspense) { this.suspense = suspense; } } if ((options2 == null ? void 0 : options2.sync) === true) { this.sync = true; } const { stack } = options2 ?? { stack: callStack("Effect init") }; if ((options2 == null ? void 0 : options2.sync) === "init") { this.init = true; this.update(stack); } else { this.schedule(stack); } } /* API */ run(stack) { const result = super.refresh(this.fn, stack); if (isFunction$1(result)) { lazyArrayPush(this, "cleanups", result); } } schedule(stack) { var _a; if ((_a = this.suspense) == null ? void 0 : _a.suspended) return; if (this.sync) { this.update(stack); } else { Scheduler$1.schedule(this, stack); } } stale(status, stack) { const statusPrev = this.status; if (statusPrev >= status) return; this.status = status; if (!this.sync || statusPrev !== 2 && statusPrev !== 3) { this.schedule(stack); } } update(stack) { var _a; if ((_a = this.suspense) == null ? void 0 : _a.suspended) return; super.update(stack); } } const effect = (fn, options2) => { const effect2 = new Effect(fn, options2); const dispose = (stack) => effect2.dispose(true); return dispose; }; const isObservable = (value) => { return isFunction$1(value) && SYMBOL_OBSERVABLE in value; }; function get(value, getFunction = true) { const is2 = getFunction ? isFunction$1 : isObservable; if (is2(value)) { return value(); } else { return value; } } const isStore = (value) => { return isObject$1(value) && SYMBOL_STORE in value; }; function untrack(fn) { if (isFunction$1(fn)) { const observerPrev = OBSERVER; if (observerPrev) { try { setObserver(void 0); return fn(); } finally { setObserver(observerPrev); } } else { return fn(); } } else { return fn; } } const isBatching = () => { return !!BATCH || Scheduler$1.queued || Scheduler$1.locked || SchedulerSync.locked; }; class StoreMap extends Map { insert(key, value) { super.set(key, value); return value; } } class StoreCleanable { constructor() { this.count = 0; } listen() { this.count += 1; cleanup(this); } call() { this.count -= 1; if (this.count) return; this.dispose(); } dispose() { } } class StoreKeys extends StoreCleanable { constructor(parent, observable) { super(); this.parent = parent; this.observable = observable; } dispose() { this.parent.keys = void 0; } } class StoreValues extends StoreCleanable { constructor(parent, observable) { super(); this.parent = parent; this.observable = observable; } dispose() { this.parent.values = void 0; } } class StoreHas extends StoreCleanable { constructor(parent, key, observable) { super(); this.parent = parent; this.key = key; this.observable = observable; } dispose() { var _a; (_a = this.parent.has) == null ? void 0 : _a.delete(this.key); } } class StoreProperty extends StoreCleanable { constructor(parent, key, observable, node) { super(); this.parent = parent; this.key = key; this.observable = observable; this.node = node; } dispose() { var _a; (_a = this.parent.properties) == null ? void 0 : _a.delete(this.key); } } const StoreListenersRegular = { /* VARIABLES */ active: 0, listeners: /* @__PURE__ */ new Set(), nodes: /* @__PURE__ */ new Set(), /* API */ prepare: (stack) => { const { listeners, nodes } = StoreListenersRegular; const traversed = /* @__PURE__ */ new Set(); const traverse = (node) => { if (traversed.has(node)) return; traversed.add(node); lazySetEach(node.parents, traverse); lazySetEach(node.listenersRegular, (listener) => { listeners.add(listener); }); }; nodes.forEach(traverse); return () => { listeners.forEach((listener) => { listener(stack); }); }; }, register: (node, stack) => { StoreListenersRegular.nodes.add(node); StoreScheduler.schedule(stack); }, reset: () => { StoreListenersRegular.listeners = /* @__PURE__ */ new Set(); StoreListenersRegular.nodes = /* @__PURE__ */ new Set(); } }; const StoreListenersRoots = { /* VARIABLES */ active: 0, nodes: /* @__PURE__ */ new Map(), /* API */ prepare: () => { const { nodes } = StoreListenersRoots; return () => { nodes.forEach((rootsSet, store2) => { const roots = Array.from(rootsSet); lazySetEach(store2.listenersRoots, (listener) => { listener(roots); }); }); }; }, register: (store2, root, stack) => { const roots = StoreListenersRoots.nodes.get(store2) || /* @__PURE__ */ new Set(); roots.add(root); StoreListenersRoots.nodes.set(store2, roots); StoreScheduler.schedule(stack); }, registerWith: (current, parent, key, stack) => { if (!parent.parents) { const root = (current == null ? void 0 : current.store) || untrack(() => parent.store[key]); StoreListenersRoots.register(parent, root, stack); } else { const traversed = /* @__PURE__ */ new Set(); const traverse = (node) => { if (traversed.has(node)) return; traversed.add(node); lazySetEach(node.parents, (parent2) => { if (!parent2.parents) { StoreListenersRoots.register(parent2, node.store, stack); } traverse(parent2); }); }; traverse(current || parent); } }, reset: () => { StoreListenersRoots.nodes = /* @__PURE__ */ new Map(); } }; const StoreScheduler = { /* VARIABLES */ active: false, /* API */ flush: (stack) => { const flushRegular = StoreListenersRegular.prepare(stack); const flushRoots = StoreListenersRoots.prepare(); StoreScheduler.reset(); flushRegular(stack); flushRoots(stack); }, flushIfNotBatching: (stack) => { if (isBatching()) { if (BATCH) { BATCH.finally(() => StoreScheduler.flushIfNotBatching(stack)); } else { setTimeout(StoreScheduler.flushIfNotBatching, 0); } } else { StoreScheduler.flush(stack); } }, reset: () => { StoreScheduler.active = false; StoreListenersRegular.reset(); StoreListenersRoots.reset(); }, schedule: (stack) => { if (StoreScheduler.active) return; StoreScheduler.active = true; queueMicrotask(() => StoreScheduler.flushIfNotBatching(stack)); } }; const NODES = /* @__PURE__ */ new WeakMap(); const SPECIAL_SYMBOLS = /* @__PURE__ */ new Set([SYMBOL_STORE, SYMBOL_STORE_KEYS, SYMBOL_STORE_OBSERVABLE, SYMBOL_STORE_TARGET, SYMBOL_STORE_VALUES]); const UNREACTIVE_KEYS = /* @__PURE__ */ new Set(["__proto__", "__defineGetter__", "__defineSetter__", "__lookupGetter__", "__lookupSetter__", "prototype", "constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toSource", "toString", "valueOf"]); const STORE_TRAPS = { /* API */ get: (target, key) => { var _a, _b; const stack = callStack("store.get"); if (SPECIAL_SYMBOLS.has(key)) { if (key === SYMBOL_STORE) return true; if (key === SYMBOL_STORE_TARGET) return target; if (key === SYMBOL_STORE_KEYS) { if (isListenable()) { const node2 = getNodeExisting(target); node2.keys || (node2.keys = getNodeKeys(node2)); node2.keys.listen(); node2.keys.observable.stack = stack; node2.keys.observable.get(); } return; } if (key === SYMBOL_STORE_VALUES) { if (isListenable()) { const node2 = getNodeExisting(target); node2.values || (node2.values = getNodeValues(node2)); node2.values.listen(); node2.values.observable.stack = stack; node2.values.observable.get(); } return; } if (key === SYMBOL_STORE_OBSERVABLE) { return (key2) => { var _a2; key2 = typeof key2 === "number" ? String(key2) : key2; const node2 = getNodeExisting(target); const getter2 = (_a2 = node2.getters) == null ? void 0 : _a2.get(key2); if (getter2) return getter2.bind(node2.store); node2.properties || (node2.properties = new StoreMap()); const value2 = target[key2]; const property2 = node2.properties.get(key2) || node2.properties.insert(key2, getNodeProperty(node2, key2, value2)); const options2 = node2.equals ? { equals: node2.equals } : void 0; property2.observable || (property2.observable = getNodeObservable(node2, value2, options2)); const observable = readable(property2.observable, stack); return observable; }; } } if (UNREACTIVE_KEYS.has(key)) return target[key]; const node = getNodeExisting(target); const getter = (_a = node.getters) == null ? void 0 : _a.get(key); const value = getter || target[key]; node.properties || (node.properties = new StoreMap()); const listenable = isListenable(); const proxiable = isProxiable(value); const property = listenable || proxiable ? node.properties.get(key) || node.properties.insert(key, getNodeProperty(node, key, value)) : void 0; if (property == null ? void 0 : property.node) { lazySetAdd(property.node, "parents", node); } if (property && listenable) { const options2 = node.equals ? { equals: node.equals } : void 0; property.listen(); property.observable || (property.observable = getNodeObservable(node, value, options2)); property.observable.stack = stack; property.observable.get(); } if (getter) { return getter.call(node.store); } else { if (typeof value === "function" && value === Array.prototype[key]) { return function() { return value.apply(node.store, arguments); }; } return ((_b = property == null ? void 0 : property.node) == null ? void 0 : _b.store) || value; } }, set: (target, key, value, stack) => { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; value = getTarget(value); const node = getNodeExisting(target); const setter = (_a = node.setters) == null ? void 0 : _a.get(key); if (setter) { setter.call(node.store, value); } else { const targetIsArray = isArray$1(target); const valuePrev = target[key]; const hadProperty = !!valuePrev || key in target; const equals = node.equals || is; if (hadProperty && equals(value, valuePrev) && (key !== "length" || !targetIsArray)) return true; const lengthPrev = targetIsArray && target["length"]; target[key] = value; const lengthNext = targetIsArray && target["length"]; if (targetIsArray && key !== "length" && lengthPrev !== lengthNext) { (_d = (_c = (_b = node.properties) == null ? void 0 : _b.get("length")) == null ? void 0 : _c.observable) == null ? void 0 : _d.set(lengthNext); } (_e = node.values) == null ? void 0 : _e.observable.set(0); if (!hadProperty) { (_f = node.keys) == null ? void 0 : _f.observable.set(0); (_h = (_g = node.has) == null ? void 0 : _g.get(key)) == null ? void 0 : _h.observable.set(true); } const property = (_i = node.properties) == null ? void 0 : _i.get(key); if (property == null ? void 0 : property.node) { lazySetDelete(property.node, "parents", node); } if (property) { (_j = property.observable) == null ? void 0 : _j.set(value); property.node = isProxiable(value) ? NODES.get(value) || getNode(value, key, node) : void 0; } if (property == null ? void 0 : property.node) { lazySetAdd(property.node, "parents", node); } if (StoreListenersRoots.active) { StoreListenersRoots.registerWith(property == null ? void 0 : property.node, node, key, stack); } if (StoreListenersRegular.active) { StoreListenersRegular.register(node, stack); } if (targetIsArray && key === "length") { const lengthPrev2 = Number(valuePrev); const lengthNext2 = Number(value); for (let i = lengthNext2; i < lengthPrev2; i++) { if (i in target) continue; STORE_TRAPS.deleteProperty(target, `${i}`, true); } } } return true; }, deleteProperty: (target, key, _force) => { var _a, _b, _c, _d, _e, _f, _g, _h; const hasProperty = key in target; if (!_force && !hasProperty) return true; const deleted = Reflect.deleteProperty(target, key); if (!deleted) return false; const node = getNodeExisting(target); const stack = callStack(); (_a = node.getters) == null ? void 0 : _a.delete(key); (_b = node.setters) == null ? void 0 : _b.delete(key); (_c = node.keys) == null ? void 0 : _c.observable.set(0); (_d = node.values) == null ? void 0 : _d.observable.set(0); (_f = (_e = node.has) == null ? void 0 : _e.get(key)) == null ? void 0 : _f.observable.set(false); const property = (_g = node.properties) == null ? void 0 : _g.get(key); if (StoreListenersRoots.active) { StoreListenersRoots.registerWith(property == null ? void 0 : property.node, node, key, stack); } if (property == null ? void 0 : property.node) { lazySetDelete(property.node, "parents", node); } if (property) { (_h = property.observable) == null ? void 0 : _h.set(void 0); property.node = void 0; } if (StoreListenersRegular.active) { StoreListenersRegular.register(node, stack); } return true; }, defineProperty: (target, key, descriptor) => { var _a, _b, _c, _d, _e, _f, _g, _h; const node = getNodeExisting(target); const equals = node.equals || is; const hadProperty = key in target; const descriptorPrev = Reflect.getOwnPropertyDescriptor(target, key); const stack = callStack(); if ("value" in descriptor && isStore(descriptor.value)) { descriptor = { ...descriptor, value: getTarget(descriptor.value) }; } if (descriptorPrev && isEqualDescriptor(descriptorPrev, descriptor, equals)) return true; const defined = Reflect.defineProperty(target, key, descriptor); if (!defined) return false; if (!descriptor.get) { (_a = node.getters) == null ? void 0 : _a.delete(key); } else if (descriptor.get) { node.getters || (node.getters = new StoreMap()); node.getters.set(key, descriptor.get); } if (!descriptor.set) { (_b = node.setters) == null ? void 0 : _b.delete(key); } else if (descriptor.set) { node.setters || (node.setters = new StoreMap()); node.setters.set(key, descriptor.set); } if (hadProperty !== !!descriptor.enumerable) { (_c = node.keys) == null ? void 0 : _c.observable.set(0); } (_e = (_d = node.has) == null ? void 0 : _d.get(key)) == null ? void 0 : _e.observable.set(true); const property = (_f = node.properties) == null ? void 0 : _f.get(key); if (StoreListenersRoots.active) { StoreListenersRoots.registerWith(property == null ? void 0 : property.node, node, key, stack); } if (property == null ? void 0 : property.node) { lazySetDelete(property.node, "parents", node); } if (property) { if ("get" in descriptor) { (_g = property.observable) == null ? void 0 : _g.set(descriptor.get); property.node = void 0; } else { const value = descriptor.value; (_h = property.observable) == null ? void 0 : _h.set(value); property.node = isProxiable(value) ? NODES.get(value) || getNode(value, key, node) : void 0; } } if (property == null ? void 0 : property.node) { lazySetAdd(property.node, "parents", node); } if (StoreListenersRoots.active) { StoreListenersRoots.registerWith(property == null ? void 0 : property.node, node, key, stack); } if (StoreListenersRegular.active) { StoreListenersRegular.register(node, stack); } return true; }, has: (target, key) => { if (key === SYMBOL_STORE) return true; if (key === SYMBOL_STORE_TARGET) return true; const value = key in target; if (isListenable()) { const node = getNodeExisting(target); node.has || (node.has = new StoreMap()); const has = node.has.get(key) || node.has.insert(key, getNodeHas(node, key, value)); has.listen(); has.observable.stack = callStack("store.has"); has.observable.get(); } return value; }, ownKeys: (target) => { const keys = Reflect.ownKeys(target); if (isListenable()) { const node = getNodeExisting(target); node.keys || (node.keys = getNodeKeys(node)); node.keys.listen(); node.keys.observable.stack = callStack("store.ownKeys"); node.keys.observable.get(); } return keys; } }; const STORE_UNTRACK_TRAPS = { /* API */ has: (target, key) => { if (key === SYMBOL_STORE_UNTRACKED) return true; return key in target; } }; const getNode = (value, key, parent, equals) => { if (isStore(value)) return getNodeExisting(getTarget(value)); const store2 = isFrozenLike(value, key, parent) ? value : new Proxy(value, STORE_TRAPS); const gettersAndSetters = getGettersAndSetters(value); const node = { parents: parent, store: store2 }; if (gettersAndSetters) { const { getters, setters } = gettersAndSetters; if (getters) node.getters = getters; if (setters) node.setters = setters; } if (equals === false) { node.equals = nope; } else if (equals) { node.equals = equals; } else if (parent == null ? void 0 : parent.equals) { node.equals = parent.equals; } NODES.set(value, node); return node; }; const getNodeExisting = (value) => { const node = NODES.get(value); if (!node) throw new Error("Impossible"); return node; }; const getNodeFromStore = (store2) => { return getNodeExisting(getTarget(store2)); }; const getNodeKeys = (node) => { const observable = getNodeObservable(node, 0, { equals: false }); const keys = new StoreKeys(node, observable); return keys; }; const getNodeValues = (node) => { const observable = getNodeObservable(node, 0, { equals: false }); const values = new StoreValues(node, observable); return values; }; const getNodeHas = (node, key, value) => { const observable = getNodeObservable(node, value); const has = new StoreHas(node, key, observable); return has; }; const getNodeObservable = (node, value, options2) => { return new Observable(value, options2); }; const getNodeProperty = (node, key, value) => { const observable = void 0; const propertyNode = isProxiable(value) ? NODES.get(value) || getNode(value, key, node) : void 0; const property = new StoreProperty(node, key, observable, propertyNode); node.properties || (node.properties = new StoreMap()); node.properties.set(key, property); return property; }; const getGettersAndSetters = (value) => { if (isArray$1(value)) return; let getters; let setters; const keys = Object.keys(value); for (let i = 0, l = keys.length; i < l; i++) { const key = keys[i]; const descriptor = Object.getOwnPropertyDescriptor(value, key); if (!descriptor) continue; const { get: get2, set } = descriptor; if (get2) { getters || (getters = new StoreMap()); getters.set(key, get2); } if (set) { setters || (setters = new StoreMap()); setters.set(key, set); } if (get2 && !set) { setters || (setters = new StoreMap()); setters.set(key, throwNoSetterError); } } if (!getters && !setters) return; return { getters, setters }; }; const getStore = (value, options2) => { if (isStore(value)) return value; const node = NODES.get(value) || getNode(value, void 0, void 0, options2 == null ? void 0 : options2.equals); return node.store; }; const getTarget = (value) => { if (isStore(value)) return value[SYMBOL_STORE_TARGET]; return value; }; const getUntracked = (value) => { if (!isObject$1(value)) return value; if (isUntracked(value)) return value; return new Proxy(value, STORE_UNTRACK_TRAPS); }; const isEqualDescriptor = (a, b, equals) => { return !!a.configurable === !!b.configurable && !!a.enumerable === !!b.enumerable && !!a.writable === !!b.writable && equals(a.value, b.value) && a.get === b.get && a.set === b.set; }; const isFrozenLike = (value, key, parent) => { if (Object.isFrozen(value)) return true; if (!parent || key === void 0) return false; const target = store.unwrap(parent.store); const descriptor = Reflect.getOwnPropertyDescriptor(target, key); if ((descriptor == null ? void 0 : descriptor.configurable) || (descriptor == null ? void 0 : descriptor.writable)) return false; return true; }; const isListenable = () => { return !!OBSERVER; }; const isProxiable = (value) => { if (value === null || typeof value !== "object") return false; if (SYMBOL_STORE in value) return true; if (SYMBOL_STORE_UNTRACKED in value) return false; if (isArray$1(value)) return true; const prototype = Object.getPrototypeOf(value); if (prototype === null) return true; return Object.getPrototypeOf(prototype) === null; }; const isUntracked = (value) => { if (value === null || typeof value !== "object") return false; return SYMBOL_STORE_UNTRACKED in value; }; const throwNoSetterError = () => { throw new TypeError("Cannot set property value of #<Object> which has only a getter"); }; const store = (value, options2) => { if (!isObject$1(value)) return value; if (isUntracked(value)) return value; return getStore(value, options2); }; store.on = (target, listener) => { const targets = isStore(target) ? [target] : castArray$1(target); const selectors = targets.filter(isFunction$1); const nodes = targets.filter(isStore).map(getNodeFromStore); StoreListenersRegular.active += 1; const stack = callStack(); const disposers = selectors.map((selector) => { let inited = false; return effect((stack2) => { if (inited) { StoreListenersRegular.listeners.add(listener); StoreScheduler.schedule(stack2); } inited = true; selector(); }, { suspense: false, sync: true, stack }); }); nodes.forEach((node) => { lazySetAdd(node, "listenersRegular", listener); }); return (stack2) => { StoreListenersRegular.active -= 1; disposers.forEach((disposer) => { disposer(stack2); }); nodes.forEach((node) => { lazySetDelete(node, "listenersRegular", listener); }); }; }; store._onRoots = (target, listener) => { if (!isStore(target)) return noop$1; const node = getNodeFromStore(target); if (node.parents) throw new Error("Only top-level stores are supported"); StoreListenersRoots.active += 1; lazySetAdd(node, "listenersRoots", listener); return () => { StoreListenersRoots.active -= 1; lazySetDelete(node, "listenersRoots", listener); }; }; store.reconcile = /* @__PURE__ */ (() => { const getType = (value) => { if (isArray$1(value)) return 1; if (isProxiable(value)) return 2; return 0; }; const reconcileOuter = (prev, next) => { const uprev = getTarget(prev); const unext = getTarget(next); reconcileInner(prev, next); const prevType = getType(uprev); const nextType = getType(unext); if (prevType === 1 || nextType === 1) { prev.length = next.length; } return prev; }; const reconcileInner = (prev, next) => { const uprev = getTarget(prev); const unext = getTarget(next); const prevKeys = Object.keys(uprev); const nextKeys = Object.keys(unext); for (let i = 0, l = nextKeys.length; i < l; i++) { const key = nextKeys[i]; const prevValue = uprev[key]; const nextValue = unext[key]; if (!is(prevValue, nextValue)) { const prevType = getType(prevValue); const nextType = getType(nextValue); if (prevType && prevType === nextType) { reconcileInner(prev[key], nextValue); if (prevType === 1) { prev[key].length = nextValue.length; } } else { prev[key] = nextValue; } } else if (prevValue === void 0 && !(key in uprev)) { prev[key] = void 0; } } for (let i = 0, l = prevKeys.length; i < l; i++) { const key = prevKeys[i]; if (!(key in unext)) { delete prev[key]; } } return prev; }; const reconcile = (prev, next) => { return untrack(() => { return reconcileOuter(prev, next); }); }; return reconcile; })(); store.untrack = (value) => { return getUntracked(value); }; store.unwrap = (value) => { return getTarget(value); }; const _with = () => { const owner = OWNER; const observer = OBSERVER; return (fn, stack) => { return owner.wrap(() => fn(), owner, observer, stack); }; }; const isSSR = typeof window === "undefined" || typeof document === "undefined" || typeof customElements === "undefined"; const CONTEXTS_DATA = /* @__PURE__ */ new WeakMap(); const DIRECTIVES = {}; const SYMBOL_SUSPENSE = Symbol("Suspense"); const SYMBOL_SUSPENSE_COLLECTOR = Symbol("Suspense.Collector"); const SYMBOL_TEMPLATE_ACCESSOR = Symbol("Template.Accessor"); const SYMBOLS_DIRECTIVES = {}; const SYMBOL_CLONE = Symbol("CloneElement"); const SYMBOL_JSX = Symbol("Jsx"); const SYMBOL_DEFAULT = Symbol("Default"); class SimpleNodeList { constructor(nodes = []) { this.nodes = nodes; } get length() { return this.nodes.length; } item(index) { return this.nodes[index] || null; } [Symbol.iterator]() { return this.nodes[Symbol.iterator](); } } class BaseNode { constructor(nodeType) { this._observers = []; this.nodeType = nodeType; this.attributes = {}; this.childNodes = []; this.parentNode = null; this._mutations = []; } appendChild(child) { const previousSibling = this.childNodes.length > 0 ? this.childNodes[this.childNodes.length - 1] : null; if (child) { child.parentNode = this; } this.childNodes.push(child); this._notifyMutation({ type: "childList", target: this, addedNodes: new SimpleNodeList([child]), removedNodes: new SimpleNodeList([]), previousSibling, nextSibling: null, attributeName: null, attributeNamespace: null, oldValue: null }); return child; } // append(...nodes: any[]) { // nodes.forEach(node => { // // Handle string nodes by converting them to TextNode // if (typeof node === 'string') { // const textNode = new TextNode(node) // this.appendChild(textNode) // } else { // this.appendChild(node) // } // }) // } insertBefore(newNode, referenceNode) { if (referenceNode === null) { return this.appendChild(newNode); } const index = this.childNodes.indexOf(referenceNode); if (index === -1) { throw new Error("Reference node not found"); } const previousSibling = index > 0 ? this.childNodes[index - 1] : null; const nextSibling = referenceNode; if (newNode) { newNode.parentNode = this; } this.childNodes.splice(index, 0, newNode); this._notifyMutation({ type: "childList", target: this, addedNodes: new SimpleNodeList([newNode]), removedNodes: new SimpleNodeList([]), previousSibling, nextSibling, attributeName: null, attributeNamespace: null, oldValue: null }); return newNode; } removeChild(child) { const index = this.childNodes.indexOf(child); if (index === -1) { throw new Error("Child node not found"); } const previousSibling = index > 0 ? this.childNodes[index - 1] : null; const nextSibling = index < this.childNodes.length - 1 ? this.childNodes[index + 1] : null; if (child) { child.parentNode = null; } this.childNodes.splice(index, 1); this._notifyMutation({ type: "childList", target: this, addedNodes: new SimpleNodeList([]), removedNodes: new SimpleNodeList([child]), previousSibling, nextSibling, attributeName: null, attributeNamespace: null, oldValue: null }); return child; } setAttribute(name, value) { const oldValue = this.attributes[name]; const newValue = String(value); this.attributes[name] = newValue; this._notifyMutation({ type: "attributes", target: this, addedNodes: new SimpleNodeList([]), removedNodes: new SimpleNodeList([]), previousSibling: null, nextSibling: null, attributeName: name, attributeNamespace: null, oldValue: oldValue !== void 0 ? oldValue : null }); } removeAttribute(name) { const oldValue = this.attributes[name]; if (oldValue !== void 0) { delete this.attributes[name]; this._notifyMutation({ type: "attributes", target: this, addedNodes: new SimpleNodeList([]), removedNodes: new SimpleNodeList([]), previousSibling: null, nextSibling: null, attributeName: name, attributeNamespace: null, oldValue }); } } // Internal method to notify observers of mutations _notifyMutation(mutation) { this._mutations.push(mutation); this._observers.forEach(({ observer, options: options2 }) => { const filteredMutations = observer["_filterMutations"]([mutation], options2); if (filteredMutations.length > 0) { observer["callback"](filteredMutations, observer); } }); } // Method for MutationObserver to register itself _addObserver(observer, options2) { this._observers.push({ observer, options: options2 }); } // Method for MutationObserver to unregister itself _removeObserver(observer) { const index = this._observers.findIndex((item) => item.observer === observer); if (index !== -1) { this._observers.splice(index, 1); } } } class MutationObserver { constructor(callback) { this.observedElements = /* @__PURE__ */ new Map(); this.pendingMutations = []; this.callback = callback; } observe(target, options2) { this.observedElements.set(target, options2 || {}); target._addObserver(this, options2 || {}); } disconnect() { this.observedElements.forEach((options2, target) => { target._removeObserver(this); }); this.observedElements.clear(); this.pendingMutations = [];