UNPKG

woby

Version:

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

1,690 lines (1,689 loc) 77.6 kB
"use strict"; 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"); const DEBUGGER = { debug: false, test: 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"); }; 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; }; 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[SYMBOL_OBSERVABLE] = true; fn[SYMBOL_OBSERVABLE_READABLE] = value; return fn; }; const writable = (value, stack) => { value.stack = stack; const fn = writableFunction.bind(value); 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() { }; 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 = exports.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 BATCH; let SUPER_OWNER = new SuperRoot(); let OBSERVER; exports.OWNER = SUPER_OWNER; const setBatch = (value) => BATCH = value; const setObserver = (value) => OBSERVER = value; const setOwner = (value) => exports.OWNER = value; 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; 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) { 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); } } 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 = exports.OWNER; this.context = exports.OWNER.context; this.status = DIRTY_YES; this.observables = new ObservablesArray(this); if (exports.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(exports.OWNER, "cleanups", fn); }; class Context extends Owner { /* CONSTRUCTOR */ constructor(context2) { super(); this.parent = exports.OWNER; this.context = { ...exports.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 exports.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 = exports.OWNER; const observer = OBSERVER; return (fn, stack) => { return owner.wrap(() => fn(stack), owner, observer, stack); }; }; 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 { createComment, createHTMLNode, createSVGNode, createText, createDocumentFragment } = (() => { if (typeof via !== "undefined") { const document2 = via.document; const createComment2 = document2.createComment; const createHTMLNode2 = document2.createElement; const createSVGNode2 = (name) => document2.createElementNS("http://www.w3.org/2000/svg", name); const createText2 = document2.createTextNode; const createDocumentFragment2 = document2.createDocumentFragment; return { createComment: createComment2, createHTMLNode: createHTMLNode2, createSVGNode: createSVGNode2, createText: createText2, createDocumentFragment: createDocumentFragment2 }; } else { const createComment2 = document.createComment.bind(document, ""); const createHTMLNode2 = document.createElement.bind(document); const createSVGNode2 = document.createElementNS.bind(document, "http://www.w3.org/2000/svg"); const createText2 = document.createTextNode.bind(document); const createDocumentFragment2 = document.createDocumentFragment.bind(document); return { createComment: createComment2, createHTMLNode: createHTMLNode2, createSVGNode: createSVGNode2, createText: createText2, createDocumentFragment: createDocumentFragment2 }; } })(); const { assign } = Object; const castArray = (value) => { return isArray(value) ? value : [value]; }; const castError = (exception) => { if (isError(exception)) return exception; if (isString(exception)) return new Error(exception); return new Error("Unknown error"); }; const flatten = (arr) => { for (let i = 0, l = arr.length; i < l; i++) { if (!isArray(arr[i])) continue; return arr.flat(Infinity); } return arr; }; const indexOf = (() => { const _indexOf = Array.prototype.indexOf; return (arr, value) => { return _indexOf.call(arr, value); }; })(); const { isArray } = Array; const isBoolean = (value) => { return typeof value === "boolean"; }; const isComponent = (value) => { return isFunction(value) && SYMBOL_UNTRACKED_UNWRAPPED in value; }; const isError = (value) => { return value instanceof Error; }; const isFalsy = (value) => { return !value; }; const isFunction = (value) => { return typeof value === "function"; }; const isFunctionReactive = (value) => { var _a, _b; return !(SYMBOL_UNTRACKED in value || SYMBOL_UNTRACKED_UNWRAPPED in value || SYMBOL_OBSERVABLE_FROZEN in value || ((_b = (_a = value[SYMBOL_OBSERVABLE_READABLE]) == null ? void 0 : _a.parent) == null ? void 0 : _b.disposed)); }; const isNil = (value) => { return value === null || value === void 0; }; const isNode = (value) => { return value instanceof Node; }; const isObject = (value) => { return typeof value === "object" && value !== null; }; const isPrimitive = (value) => { const t = typeof value; return !(t === "object" || t === "function"); }; const isPromise = (value) => { return value instanceof Promise; }; const isString = (value) => { return typeof value === "string"; }; const isSVG = (value) => { return !!value["isSVG"]; }; const isSVGElement = /* @__PURE__ */ (() => { const svgRe = /^(t(ext$|s)|s[vwy]|g)|^set|tad|ker|p(at|s)|s(to|c$|ca|k)|r(ec|cl)|ew|us|f($|e|s)|cu|n[ei]|l[ty]|[GOP]/; const svgCache = {}; return (element) => { const cached = svgCache[element]; return cached !== void 0 ? cached : svgCache[element] = !element.includes("-") && svgRe.test(element); }; })(); const isTemplateAccessor = (value) => { return isFunction(value) && SYMBOL_TEMPLATE_ACCESSOR in value; }; const isTruthy = (value) => { return !!value; }; const isVoidChild = (value) => { return value === null || value === void 0 || typeof value === "boolean" || typeof value === "symbol"; }; const noop = () => { return; }; const once = (fn) => { let called = false; let result; return () => { if (!called) { called = true; result = fn(); } return result; }; }; const isProxy = (proxy) => { return proxy == null ? false : !!proxy[Symbol.for("__isProxy")]; }; const fixBigInt = (v) => typeof v === "bigint" ? v + "n" : v; const toArray = (v) => [...[v].flat(Infinity)]; const options = { sync: "init", stack: void 0 }; const useRenderEffect = (fn, stack) => { return effect(fn, { ...options, stack }); }; const useCheapDisposed = () => { let disposed = false; const get2 = () => disposed; const set = () => disposed = true; cleanup(set); return get2; }; const useMicrotask = (fn, stack) => { const disposed = useCheapDisposed(); const runWithOwner = _with(); queueMicrotask(() => { if (disposed()) return; runWithOwner(fn, stack); }); }; const classesToggle = (element, classes, force) => { const { className } = element; if (isString(className)) { if (!className) { if (force) { element.className = classes; return; } else { return; } } else if (!force && className === classes) { element.className = ""; return; } } if (classes.includes(" ")) { classes.split(" ").forEach((cls) => { if (!cls.length) return; element.classList.toggle(cls, !!force); }); } else { element.classList.toggle(classes, !!force); } }; const dummyNode = createComment(""); const beforeDummyWrapper = [dummyNode]; const afterDummyWrapper = [dummyNode]; const diff = (parent, before, after, nextSibling) => { if (before === after) return; if (before instanceof Node) { if (after instanceof Node) { if (before.parentNode === parent) { parent.replaceChild(after, before); return; } } beforeDummyWrapper[0] = before; before = beforeDummyWrapper; } if (after instanceof Node) { afterDummyWrapper[0] = after; after = afterDummyWrapper; } const bLength = after.length; let aEnd = before.length; let bEnd = bLength; let aStart = 0; let bStart = 0; let map = null; let removable; while (aStart < aEnd || bStart < bEnd) { if (aEnd === aStart) { const node = bEnd < bLength ? bStart ? after[bStart - 1].nextSibling : after[bEnd - bStart] : nextSibling; if (bStart < bEnd) { if (node) { node.before.apply(node, after.slice(bStart, bEnd)); } else { parent.append.apply(parent, after.slice(bStart, bEnd)); } bStart = bEnd; } } else if (bEnd === bStart) { while (aStart < aEnd) { if (!map || !map.has(before[aStart])) { removable = before[aStart]; if (removable.parentNode === parent) { parent.removeChild(removable); } } aStart++; } } else if (before[aStart] === after[bStart]) { aStart++; bStart++; } else if (before[aEnd - 1] === after[bEnd - 1]) { aEnd--; bEnd--; } else if (before[aStart] === after[bEnd - 1] && after[bStart] === before[aEnd - 1]) { const node = before[--aEnd].nextSibling; parent.insertBefore( after[bStart++], before[aStart++].nextSibling ); parent.insertBefore(after[--bEnd], node); before[aEnd] = after[bEnd]; } else { if (!map) { map = /* @__PURE__ */ new Map(); let i = bStart; while (i < bEnd) map.set(after[i], i++); } if (map.has(before[aStart])) { const index = map.get(before[aStart]); if (bStart < index && index < bEnd) { let i = aStart; let sequence = 1; while (++i < aEnd && i < bEnd && map.get(before[i]) === index + sequence) sequence++; if (sequence > index - bStart) { const node = before[aStart]; if (bStart < index) { if (node) { node.before.apply(node, after.slice(bStart, index)); } else { parent.append.apply(parent, after.slice(bStart, index)); } bStart = index; } } else { parent.replaceChild( after[bStart++], before[aStart++] ); } } else aStart++; } else { removable = before[aStart++]; if (removable.parentNode === parent) { parent.removeChild(removable); } } } } beforeDummyWrapper[0] = dummyNode; afterDummyWrapper[0] = dummyNode; }; const NOOP_CHILDREN = []; const FragmentUtils = { make: () => { return { values: void 0, length: 0 }; }, makeWithNode: (node) => { return { values: node, length: 1 }; }, makeWithFragment: (fragment) => { return { values: fragment, fragmented: true, length: 1 }; }, getChildrenFragmented: (thiz, children = []) => { const { values, length } = thiz; if (!length) return children; if (values instanceof Array) { for (let i = 0, l = values.length; i < l; i++) { const value = values[i]; if (value instanceof Node) { children.push(value); } else { FragmentUtils.getChildrenFragmented(value, children); } }