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
JavaScript
"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);
}
}