alien-dom
Version:
Next-generation JSX client renderer with observable data primitives, immediate DOM references, and more.
1,836 lines (1,804 loc) • 124 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// ../node_modules/.pnpm/@alloc+is@3.1.2/node_modules/@alloc/is/dist/is.mjs
var { toString } = Object.prototype;
var isArray = Array.isArray;
var isBoolean = (value) => value === true || value === false;
var isClass = (value) => isFunction(value) && value.toString().startsWith("class ");
var isFunction = isOfType("function");
var isNan = Number.isNaN;
var isNumber = (value) => isNumberLike(value) && !isNan(value);
var isNumberLike = isOfType("number");
var isObject = isOfType("object");
var isObjectOrFunction = (value) => !!value && (isObject(value) || isFunction(value));
var isPromise = isObjectOfType("Promise");
var isPromiseLike = (value) => !!value && isFunction(value.then);
var isString = isOfType("string");
var isPlainObject = (value) => {
if (getObjectType(value) !== "Object") {
return false;
}
const proto = Object.getPrototypeOf(value);
return proto === null || proto === Object.getPrototypeOf({});
};
var isWhat = (value) => value === null ? "null" : isObjectOrFunction(value) ? getObjectType(value) || "Object" : typeof value;
function isOfType(type) {
return (value) => typeof value === type;
}
function isObjectOfType(type) {
return (value) => getObjectType(value) === type;
}
function getObjectType(value) {
const type = toString.call(value).slice(8, -1);
if (type) {
return type;
}
}
// internal/constants.ts
var kElementNodeType = 1;
var kFragmentNodeType = 11;
var kTextNodeType = 3;
var kCommentNodeType = 8;
var kAlienNodeType = Symbol.for("alien:nodeType");
var kShadowRootNodeType = 99;
var kDeferredNodeType = 98;
var kChildrenNodeType = 97;
var kTemplateNodeType = 96;
// internal/duck.ts
function canMatch(node) {
return typeof node.matches == "function";
}
function hasForEach(arg) {
return typeof arg.forEach == "function";
}
function isIterable(arg) {
return typeof arg[Symbol.iterator] == "function";
}
function isArrayLike(obj) {
return isObjectOrFunction(obj) && typeof obj.length === "number" && typeof obj.nodeType !== "number";
}
function hasTagName(node, tagName) {
return node && node.tagName === tagName;
}
function isNode(val) {
return isObjectOrFunction(val) && isNumber(val.nodeType);
}
function isElement(node) {
return node.nodeType === kElementNodeType;
}
function isFragment(node) {
return node.nodeType === kFragmentNodeType;
}
function isTextNode(node) {
return node.nodeType === kTextNodeType;
}
function isComment(node) {
return node.nodeType === kCommentNodeType;
}
function isDocument(node) {
return node.nodeType === 9;
}
// internal/privateSymbol.ts
var hasOwn = Function.call.bind(Object.prototype.hasOwnProperty);
var definePrivateSymbol = (name) => Symbol.for("alien:" + name);
var bindPrivateSymbol = (property) => [
(target) => getPrivate(target, property),
(target, value) => setPrivate(target, property, value)
];
var hasPrivate = (target, property) => hasOwn(target, property);
var getPrivate = (target, property) => (
// Ensure the property is defined on the target directly, so we can avoid a
// prototype lookup when the property is undefined.
hasOwn(target, property) ? target[property] : void 0
);
var setPrivate = (target, property, value) => Object.defineProperty(target, property, {
value,
configurable: true
});
// internal/symbols.ts
var kAlienEffects = definePrivateSymbol("effects");
var kAlienElementKey = definePrivateSymbol("elementKey");
var kAlienElementPosition = definePrivateSymbol("elementPosition");
var kAlienElementTags = definePrivateSymbol("elementTags");
var kAlienFragmentKeys = definePrivateSymbol("fragmentKeys");
var kAlienFragmentNodes = definePrivateSymbol("fragmentNodes");
var kAlienHostProps = definePrivateSymbol("hostProps");
var kAlienInitialContext = definePrivateSymbol("initialContext");
var kAlienMemo = definePrivateSymbol("memo");
var kAlienParentFragment = definePrivateSymbol("parentFragment");
var kAlienRenderFunc = definePrivateSymbol("renderFunc");
var kAlienStateless = definePrivateSymbol("stateless");
var kAlienThunkResult = definePrivateSymbol("thunkResult");
var kAlienUnmountHandler = definePrivateSymbol("unmountHandler");
var [getElementKey, setElementKey] = bindPrivateSymbol(kAlienElementKey);
var [getElementPosition, setElementPosition] = bindPrivateSymbol(
kAlienElementPosition
);
var [getElementTags, setElementTags] = bindPrivateSymbol(kAlienElementTags);
var [getFragmentKeys, setFragmentKeys] = bindPrivateSymbol(kAlienFragmentKeys);
var [getFragmentNodes, setFragmentNodes] = bindPrivateSymbol(kAlienFragmentNodes);
var [getHostProps, setHostProps] = bindPrivateSymbol(kAlienHostProps);
var [getParentFragment, setParentFragment] = bindPrivateSymbol(kAlienParentFragment);
// functions/getElementIdentity.ts
function getElementIdentity(element) {
return getElementKey(element) ?? getElementPosition(element);
}
// internal/binaryInsert.ts
function binaryInsert(array, insertValue, comparator) {
if (array.length === 0 || comparator(array[0], insertValue) >= 0) {
array.splice(0, 0, insertValue);
return array;
} else if (array.length > 0 && comparator(array[array.length - 1], insertValue) <= 0) {
array.splice(array.length, 0, insertValue);
return array;
}
let left = 0, right = array.length;
let leftLast = 0, rightLast = right;
while (left < right) {
const inPos = Math.floor((right + left) / 2);
const compared = comparator(array[inPos], insertValue);
if (compared < 0) {
left = inPos;
} else if (compared > 0) {
right = inPos;
} else {
right = inPos;
left = inPos;
}
if (leftLast === left && rightLast === right) {
break;
}
leftLast = left;
rightLast = right;
}
array.splice(right, 0, insertValue);
return array;
}
// addons/domObserver.ts
var observersByRoot = /* @__PURE__ */ new WeakMap();
function observeDescendants(rootNode) {
let result = observersByRoot.get(rootNode);
if (!result) {
const onAdded = /* @__PURE__ */ new Set();
const onRemoved = /* @__PURE__ */ new Set();
let queued = false;
const added = /* @__PURE__ */ new Set();
const removed = /* @__PURE__ */ new Set();
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of Array.from(mutation.addedNodes)) {
if (isElement(node) || getElementIdentity(node)) {
removed.delete(node) || added.add(node);
}
}
for (const node of Array.from(mutation.removedNodes)) {
if (isElement(node) || getElementIdentity(node)) {
added.delete(node) || removed.add(node);
}
}
}
if (!queued) {
queued = true;
queueMicrotask(() => {
queued = false;
if (!added.size && !removed.size) {
return;
}
const lastAdded = [...added];
const lastRemoved = [...removed];
added.clear();
removed.clear();
lastAdded.forEach((node) => {
onAdded.forEach((listener) => listener(node));
});
lastRemoved.forEach((node) => {
onRemoved.forEach((listener) => listener(node));
});
});
}
});
observer.observe(rootNode, { childList: true, subtree: true });
observersByRoot.set(
rootNode,
result = {
rootNode,
onAdded,
onRemoved,
dispose() {
observer.disconnect();
}
}
);
}
return result;
}
function matchDescendants(target, selector, effect) {
return observeNewDescendants(target, (parentNode) => {
if (isElement(parentNode)) {
parentNode.matches(selector) && effect(parentNode);
parentNode.querySelectorAll(selector).forEach(effect);
}
});
}
function observeNewChildren(target, listener) {
return observeNewDescendants(target, (childNode) => {
if (childNode.parentElement == target) {
listener(childNode);
}
});
}
function observeRemovedChildren(target, listener) {
return observeRemovedDescendants(target, (childNode) => {
if (childNode.parentElement == target) {
listener(childNode);
}
});
}
var observeNewDescendants = /* @__PURE__ */ defineEffectType(
(target, callback) => {
const observer = observeDescendants(target);
observer.onAdded.add(callback);
return () => removeElementListener(observer, "onAdded", callback);
}
);
var observeRemovedDescendants = /* @__PURE__ */ defineEffectType(
(target, callback) => {
const observer = observeDescendants(target);
observer.onRemoved.add(callback);
return () => removeElementListener(observer, "onRemoved", callback);
}
);
var onMount = (target, effect, rootNode = document) => createElementObserver(target, "onAdded", effect, rootNode);
var onUnmount = (target, effect, rootNode = target.getRootNode()) => createElementObserver(target, "onRemoved", effect, rootNode);
var depthFirstBatch = null;
var createElementObserver = /* @__PURE__ */ defineEffectType(
(target, key, effect, rootNode) => {
const self = getCurrentEffect();
if (key == "onAdded" == target.isConnected) {
self?.context?.remove(self);
return effect();
}
let depth = key == "onRemoved" ? getElementDepth(target) : null;
function listener(parentNode) {
if (parentNode === target || parentNode.contains(target)) {
if (self?.context) {
self.context.remove(self);
} else {
dispose();
}
const batch = depthFirstBatch ||= [];
if (!batch.length) {
queueMicrotask(() => {
depthFirstBatch = null;
batch.forEach(([effect2]) => effect2());
});
}
depth ??= getElementDepth(target);
binaryInsert(
batch,
[effect, depth, target, key],
([, a], [, b]) => b - a
);
}
}
const observer = observeDescendants(rootNode);
observer[key].add(listener);
function dispose() {
removeElementListener(observer, key, listener);
}
return dispose;
}
);
function getElementDepth(elem, stopAt) {
let depth = 0;
while (elem.parentElement && elem.parentElement != stopAt) {
depth++;
elem = elem.parentElement;
}
return depth;
}
function removeElementListener(observer, key, listener) {
if (observer[key].delete(listener) && !(observer.onAdded.size + observer.onRemoved.size)) {
observersByRoot.delete(observer.rootNode);
observer.dispose();
}
}
// internal/util.ts
var set = Reflect.set;
var defineProperty = Object.defineProperty;
var noop = () => void 0;
var keys = Object.keys;
function decamelize(s, separator) {
return s.replace(/[A-Z]/g, (match) => separator + match.toLowerCase());
}
function at(arr, index) {
return index < 0 ? arr[arr.length + index] : arr[index];
}
function lastValue(array) {
return array[array.length - 1];
}
function toArray(a) {
return isArray(a) ? a : [a];
}
function forEach(arg, callback) {
if (arg == null)
return;
if (hasForEach(arg)) {
arg.forEach(callback);
} else {
callback(arg);
}
}
function createState(init, params) {
return isClass2(init) ? new init(...params) : init(...params);
}
function isClass2(arg) {
return /^(class[ {]|function [A-Z])/.test(arg.toString());
}
function compareNodeWithTag(node, tag) {
if (tag === Fragment) {
return isFragment(node);
}
if (isString(tag)) {
return compareNodeNames(node.nodeName, tag);
}
if (isTemplateNode(tag)) {
return node.nodeName === tag.template.nodeName;
}
const tags = getElementTags(node);
return tags != null && tags.has(tag);
}
function compareNodeNames(fromNodeName, toNodeName) {
if (fromNodeName !== toNodeName) {
const fromCodeStart = fromNodeName.charCodeAt(0);
const toCodeStart = toNodeName.charCodeAt(0);
if (fromCodeStart <= 90 && toCodeStart >= 97) {
return fromNodeName === toNodeName.toUpperCase();
}
if (toCodeStart <= 90 && fromCodeStart >= 97) {
return toNodeName === fromNodeName.toUpperCase();
}
return false;
}
return true;
}
// core/disposable.ts
function attachDisposer(object, dispose) {
defineProperty(object, "dispose", {
value: dispose,
configurable: true,
enumerable: true
});
return object;
}
function isDisposable(arg) {
return typeof arg.dispose === "function";
}
function createDisposable(args, dispose, thisArg) {
return {
dispose: dispose.bind(thisArg, ...args),
args,
thisArg
};
}
function mergeDisposables(...objects) {
return {
objects,
dispose() {
for (const object of objects) {
object.dispose();
}
}
};
}
// internal/stack.ts
var expectLastValue = (stack, message) => () => {
const value = stack[stack.length - 1];
if (value === null) {
throw Error(message);
}
return value;
};
// internal/global.ts
var currentEffects = [null];
var currentComponent = [null];
var currentNodeStore = [null];
var expectCurrentComponent = expectLastValue(
currentComponent,
"Component instance not found"
);
// internal/linkedList.ts
var LinkedList = class {
first = null;
last = null;
add(item, prepend) {
if (this.first) {
if (prepend) {
item.next = this.first;
this.first.prev = item;
this.first = item;
} else {
item.prev = this.last;
if (this.last) {
this.last.next = item;
}
this.last = item;
}
} else {
this.first = this.last = item;
}
}
remove(item) {
if (item.prev) {
item.prev.next = item.next;
} else {
this.first = item.next;
}
if (item.next) {
item.next.prev = item.prev;
} else {
this.last = item.prev;
}
}
forEach(callback, context) {
let item = this.first;
while (item) {
const { prev } = item;
callback.call(context, item);
item = prev ? item.prev === prev ? item.next : prev.next : item === this.first ? item.next : this.first;
}
}
};
// hooks/internal/useConstructor.ts
function useConstructor(T) {
const component = expectCurrentComponent();
const index = component.nextHookIndex++;
return component.hooks[index] ||= new T();
}
// functions/depsHaveChanged.ts
function depsHaveChanged(deps, prevDeps) {
if (deps === void 0 || prevDeps === void 0 || deps.length !== prevDeps.length) {
return true;
}
if (deps !== prevDeps && deps.length > 0) {
for (let i = 0; i < deps.length; i++)
if (!Object.is(deps[i], prevDeps[i])) {
return true;
}
}
return false;
}
// functions/typeChecking.ts
function isJSXChild(value) {
if (value === null || value === void 0) {
return false;
}
if (typeof value === "function") {
return true;
}
return isNode(value);
}
// core/observable.ts
var kRefType = Symbol.for("refType");
var hooks;
var setObservableHooks = (newHooks) => {
hooks = newHooks || false;
} ;
var unseenAccess = (ref2) => ref2._value;
var nextDebugId = 1;
var access = unseenAccess;
var ReadonlyRef = class {
constructor(_value, debugId) {
this._value = _value;
this.debugId = debugId ?? nextDebugId++;
}
debugId;
_observers = /* @__PURE__ */ new Set();
get _depth() {
return 0;
}
/**
* In addition to adding/removing an observer, computed refs use this method
* to switch between eager and lazy computation mode.
*/
_isObserved(observer, isObserved) {
if (isObserved === this._observers.has(observer)) {
return;
}
if (hooks) {
peek(hooks.isObserved, this, observer, isObserved);
}
if (isObserved) {
this._observers.add(observer);
} else {
this._observers.delete(observer);
}
}
get [kRefType]() {
return "ReadonlyRef";
}
peek() {
return this._value;
}
/**
* Create a `ComputedRef` whose value is derived from `this.value` using the
* given function.
*/
computedMap(compute) {
return computed(() => compute(this.value));
}
computedIf(trueValue, falseValue) {
return computed(
() => this.value ? evaluateInput(trueValue) : falseValue !== void 0 ? evaluateInput(falseValue) : void 0
);
}
/**
* Create a `ComputedRef` that uses the first argument if `this.value` is
* falsy. Otherwise, undefined is used. Function arguments are called within
* the `computed` function.
*/
computedElse(falseValue) {
return computed(() => this.value ? void 0 : evaluateInput(falseValue));
}
};
var Ref = class extends ReadonlyRef {
get [kRefType]() {
return "Ref";
}
set(arg) {
if (isFunction(arg)) {
arg = arg(this.peek());
}
this.value = arg;
return arg;
}
/** Use the negation operator on the current value. */
toggle() {
return this.value = !this.peek();
}
};
function getValue() {
return access(this);
}
function setValue(newValue) {
const oldValue = this._value;
if (newValue !== oldValue) {
this._value = newValue;
this._observers.forEach((observer) => {
observer.observe(this, newValue, oldValue);
updateHasSideEffects ||= !observer.isObservablyPure();
});
if (updateQueue.size > 0) {
scheduleUpdates();
}
}
}
Object.defineProperties(ReadonlyRef.prototype, {
0: { get: getValue },
[Symbol.iterator]: {
value: function* () {
yield this[0];
yield this[1];
}
},
value: {
get: getValue
}
});
Object.defineProperties(Ref.prototype, {
1: {
get() {
return this.set.bind(this);
}
},
value: {
get: getValue,
set: setValue
}
});
function assignPrototype(prototype, newProperties) {
for (const key in newProperties) {
Object.defineProperty(prototype, key, {
value: newProperties[key],
writable: true,
configurable: true
});
}
}
var ReadonlyArrayRef = class extends ReadonlyRef {
get [kRefType]() {
return "ArrayRef";
}
};
var ArrayRef = class extends ReadonlyArrayRef {
_arrayObservers = null;
_produceOperation = noop;
};
var numberRE = /^\d+$/;
var kLengthRef = /* @__PURE__ */ definePrivateSymbol("lengthRef");
var updateLengthRef = (ref2, oldArray, newArray) => {
if (ref2 && oldArray.length !== newArray.length) {
ref2.value = newArray.length;
}
};
var arrayTraps = {
get(target, key) {
if (key === Symbol.iterator) {
return () => target.value[Symbol.iterator]();
}
if (typeof key === "string" && numberRE.test(key)) {
return target._value[+key];
}
if (key === "length") {
if (access === unseenAccess) {
return target._value.length;
}
let lengthRef = getPrivate(target, kLengthRef);
if (!lengthRef) {
setPrivate(
target,
kLengthRef,
lengthRef = new Ref(target._value.length)
);
}
return lengthRef.value;
}
return Reflect.get(target, key);
},
set(target, key, newValue) {
if (typeof key === "string" && numberRE.test(key)) {
const index = +key;
const oldArray = target._value;
const isExpanding = index >= oldArray.length;
if (isExpanding || newValue !== oldArray[index]) {
const newArray = oldArray.slice();
newArray[index] = newValue;
setValue.call(target, newArray);
if (isExpanding) {
updateLengthRef(getPrivate(target, kLengthRef), oldArray, newArray);
}
if (target._arrayObservers) {
notifyArrayObservers(target, { type: "replace", index, newValue });
}
}
return true;
}
if (key === "length") {
const oldArray = target._value;
const delta = newValue - oldArray.length;
if (delta) {
const newArray = oldArray.slice(0, newValue);
if (delta > 0) {
newArray.length = newValue;
}
setValue.call(target, newArray);
updateLengthRef(getPrivate(target, kLengthRef), oldArray, newArray);
if (target._arrayObservers) {
notifyArrayObservers(
target,
newValue > oldArray.length ? { type: "add", index: oldArray.length, count: delta, newArray } : { type: "remove", index: newValue, count: -delta, oldArray }
);
}
}
return true;
}
if (key === "value") {
const oldArray = target._value;
if (newValue !== oldArray) {
setValue.call(target, newValue);
updateLengthRef(getPrivate(target, kLengthRef), oldArray, newValue);
if (target._arrayObservers) {
notifyArrayObservers(target, {
type: "rebase",
newArray: newValue,
oldArray
});
}
}
return true;
}
return Reflect.set(target, key, newValue);
},
has(target, key) {
if (typeof key === "string" && numberRE.test(key)) {
return +key < target._value.length;
}
return Reflect.has(target, key);
}
};
var arrayRef = (init, debugId) => {
arrayRef = (init2, debugId2) => new Proxy(new ArrayRef(init2 || [], debugId2), arrayTraps);
const arrayMutator = (name) => function(...args) {
const oldArray = this._value;
const newArray = oldArray.slice();
const result = newArray[name](...args);
setValue.call(this, newArray);
updateLengthRef(getPrivate(this, kLengthRef), oldArray, newArray);
if (this._arrayObservers) {
const operation = this._produceOperation(name, args, oldArray, newArray);
if (operation) {
notifyArrayObservers(this, operation);
}
}
return result;
};
const arrayEnumerator = (name) => function(...args) {
return this.value[name](...args);
};
const createMethodReducer = (createMethod) => (methods, key) => {
methods[key] = createMethod(key);
return methods;
};
assignPrototype(ArrayRef.prototype, {
[kRefType]: "ArrayRef",
observe(index) {
return computed(
() => this.value[index],
isString(this.debugId) ? `${this.debugId}[${index}]` : void 0
);
},
...[
"copyWithin",
"fill",
"pop",
"push",
"reverse",
"shift",
"sort",
"splice",
"unshift"
].reduce(createMethodReducer(arrayMutator), {}),
...[
"at",
"concat",
"entries",
"every",
"filter",
"find",
"findIndex",
"flat",
"flatMap",
"forEach",
"includes",
"indexOf",
"join",
"keys",
"lastIndexOf",
"map",
"reduce",
"reduceRight",
"slice",
"some",
"values"
].reduce(createMethodReducer(arrayEnumerator), {})
});
return arrayRef(init, debugId);
};
var RefMap = class {
_map;
_sizeRef;
_keysRef;
constructor(entries) {
this._map = new Map(
entries && Array.from(entries, (entry) => [entry[0], ref(entry[1])])
);
this._sizeRef = ref(this._map.size);
this._keysRef = arrayRef(Array.from(this._map.keys()));
}
get size() {
return this._sizeRef.value;
}
get(key) {
return computed(() => {
const value = this._map.get(key);
if (value) {
return value.value;
}
computed(() => this._keysRef.includes(key)).value;
return void 0;
}).value;
}
peek(key) {
return this._map.get(key)?.peek();
}
peekSize() {
return this._sizeRef.peek();
}
set(key, newValue) {
let value = this._map.get(key);
if (value) {
value.value = newValue;
} else {
this._map.set(key, value = ref(newValue));
this._keysRef.push(key);
this._sizeRef.value++;
}
}
delete(key) {
if (this._map.delete(key)) {
const keys2 = this._keysRef.peek();
this._keysRef.splice(keys2.indexOf(key), 1);
this._sizeRef.value--;
}
}
clear() {
this._map.clear();
this._keysRef.length = 0;
this._sizeRef.value = 0;
}
forEach(callback) {
this._map.forEach((value, key) => callback(value.value, key, this));
}
[Symbol.iterator]() {
const keys2 = this._keysRef.value;
let index = 0;
return {
next: () => {
if (index < keys2.length) {
const key = keys2[index++];
const value = this._map.get(key);
return { value: [key, value.peek()], done: false };
}
return { value: void 0, done: true };
}
};
}
};
var passThrough = (result) => result;
var alwaysFalse = () => false;
var nextObserverId = 1;
var Observer = class {
id = nextObserverId++;
refs = /* @__PURE__ */ new Set();
depth = 0;
constructor() {
this.isObservablyPure ||= alwaysFalse;
this.nextCompute ||= noop;
this.didObserve ||= noop;
this.willUpdate ||= noop;
this.onUpdate ||= passThrough;
}
_access(ref2, oldRefs) {
ref2._isObserved(this, true);
oldRefs.delete(ref2);
this.refs.add(ref2);
this.depth = Math.max(this.depth, ref2._depth + 1);
return ref2._value;
}
_update(sync, oldRefs) {
this.refs.clear();
this.depth = 0;
let error;
let result;
try {
result = this.nextCompute(oldRefs);
oldRefs.forEach((ref2) => {
ref2._isObserved(this, false);
});
result = this.onUpdate(result);
} catch (e) {
error = e;
if (!sync) {
console.error(error);
}
}
if (hooks) {
peek(hooks.didUpdate, this, error, result);
}
if (sync) {
if (error)
throw error;
return result;
}
}
/**
* Run the `compute` function synchronously, observing any accessed refs. If
* no `compute` function is provided, the last used `compute` function will be
* reused.
*
* When those refs change, the `compute` function will run again in the next
* microtask (unless you call this method before then).
*/
update(compute) {
updateQueue.delete(this);
const oldRefs = new Set(this.refs);
const parentAccess = access;
access = (ref2) => this._access(ref2, oldRefs);
try {
if (compute) {
this.nextCompute = compute;
}
return this._update(true, oldRefs);
} finally {
access = parentAccess;
}
}
/** Called when a ref has a new value. */
observe(ref2, newValue, oldValue) {
if (hooks) {
hooks.observe(this, ref2, newValue, oldValue);
}
this.didObserve(ref2, newValue, oldValue);
this.scheduleUpdate(ref2, newValue, oldValue);
}
scheduleUpdate(ref2, newValue, oldValue) {
if (!updateQueue.has(this)) {
updateQueue.add(this);
if (ref2) {
this.willUpdate(ref2, newValue, oldValue);
} else {
updateHasSideEffects ||= !this.isObservablyPure();
scheduleUpdates();
}
}
}
/**
* Note: A disposed observer can still be reused.
*/
dispose() {
updateQueue.delete(this);
this.refs.forEach((ref2) => {
ref2._isObserved(this, false);
});
this.refs = /* @__PURE__ */ new Set();
}
/**
* Returns a bound `dispose` method.
*/
get destructor() {
return this.dispose.bind(this);
}
};
var ArrayObserver = class extends Observer {
constructor(target, compute) {
super();
this.target = target;
this.compute = compute;
addArrayObserver(target, this);
}
operations = [];
onOperation(operation) {
forEach(operation, (operation2) => {
if (operation2.type === "rebase") {
this.operations.length = 0;
}
this.operations.push(operation2);
this.scheduleUpdate();
});
}
nextCompute() {
const operations = [...this.operations];
this.operations.length = 0;
this.compute(operations, this.target);
}
dispose() {
super.dispose();
removeArrayObserver(this.target, this);
}
};
/**
* When an `ArrayRef` is observed by an `ArrayObserver` (not to be confused
* with a normal `Observer`), the `ArrayRef` will call this `produceOperation`
* static method to produce the `ArrayOperation` set for a given mutation.
*/
__publicField(ArrayObserver, "produceOperation", (method, args, oldArray, newArray) => {
switch (method) {
case "push":
return args.length > 0 && {
type: "add",
index: oldArray.length,
count: args.length,
newArray
};
case "pop":
return oldArray.length > 0 && {
type: "remove",
index: oldArray.length - 1,
count: 1,
oldArray
};
case "shift":
return oldArray.length > 0 && {
type: "remove",
index: 0,
count: 1,
oldArray
};
case "unshift":
return args.length > 0 && {
type: "add",
index: 0,
count: args.length,
newArray
};
case "splice":
let [start, deleteCount] = args;
if (start < 0) {
start = Math.max(0, oldArray.length + start);
}
const addOperation = args.length > 2 && {
type: "add",
index: start,
count: args.length - 2,
newArray
};
const removeOperation = deleteCount > 0 && {
type: "remove",
index: start,
count: Math.max(0, Math.min(deleteCount, oldArray.length - start)),
oldArray
};
return addOperation && removeOperation ? [removeOperation, addOperation] : addOperation || removeOperation;
case "copyWithin":
case "fill":
case "reverse":
case "sort":
return {
type: "rebase",
oldArray,
newArray
};
}
throw Error("Unknown array method: " + method);
});
function addArrayObserver(ref2, observer) {
ref2._arrayObservers ||= /* @__PURE__ */ new Set();
ref2._arrayObservers.add(observer);
if (ref2._produceOperation === noop) {
ref2._produceOperation = ArrayObserver.produceOperation;
}
}
function removeArrayObserver(ref2, observer) {
ref2._arrayObservers.delete(observer);
if (ref2._arrayObservers.size === 0) {
ref2._arrayObservers = null;
}
}
function notifyArrayObservers(ref2, operation) {
ref2._arrayObservers.forEach((observer) => {
observer.onOperation(operation);
});
}
var emptySymbol = Symbol("empty");
var _ComputedRef = class extends ReadonlyRef {
constructor(compute, debugId) {
super(emptySymbol, debugId);
this.compute = compute;
}
_observer = null;
get _depth() {
return this._observer?.depth ?? 0;
}
_isObserved(observer, isObserved) {
if (isObserved && !this._observer) {
this._observer = new _ComputedRef.Observer(this);
this._observer.update();
}
super._isObserved(observer, isObserved);
if (!isObserved && !this._observers.size) {
this._observer?.dispose();
this._observer = null;
this._value = emptySymbol;
}
}
get [kRefType]() {
return "ComputedRef";
}
get value() {
if (access !== unseenAccess) {
if (this._observer && this._value === emptySymbol) {
this._observer.update();
}
return super.value;
}
return this.peek();
}
/**
* Get the current value without observing it. If the ref is empty, the
* `compute` function will run immediately.
*/
peek() {
if (this._value === emptySymbol) {
if (!this._observer) {
return peek(this.compute);
}
this._observer.update();
}
return this._value;
}
/**
* Clear the current value. If the ref is observed, the `compute` function
* will run again in the next microtask.
*/
clear() {
if (this._observer) {
this._observer.scheduleUpdate();
} else {
this._value = emptySymbol;
}
}
};
var ComputedRef = _ComputedRef;
__publicField(ComputedRef, "Observer", class extends Observer {
constructor(ref2) {
super();
this.ref = ref2;
}
oldValue = emptySymbol;
// The computed ref is cleared immediately upon an observed ref being
// changed to prevent peeks from returning a possibly stale value.
willUpdate() {
this.oldValue = this.ref._value;
this.ref._value = emptySymbol;
}
nextCompute() {
return this.ref.compute();
}
onUpdate(result) {
this.ref._value = this.oldValue;
this.oldValue = void 0;
setValue.call(this.ref, result);
return result;
}
});
var LensRef = class extends Ref {
constructor(source, sink, debugId) {
super(null, debugId);
if (isFunction(source)) {
source = new ComputedRef(source);
}
if (isRef(sink)) {
sink = Reflect.set.bind(Reflect, sink, "value");
}
defineProperty(this, "peek", {
configurable: true,
value: source.peek.bind(source)
});
defineProperty(this, "value", {
configurable: true,
get: Reflect.get.bind(Reflect, source, "value"),
set: sink
});
}
get [kRefType]() {
return "LensRef";
}
};
var TargetObserver = class extends Observer {
constructor(target, onChange) {
super();
this.target = target;
this.onChange = onChange;
}
oldValue = emptySymbol;
willUpdate(_ref, _newValue, oldValue) {
if (this.oldValue === emptySymbol) {
this.oldValue = oldValue;
}
}
nextCompute() {
return access(this.target);
}
onUpdate(newValue) {
if (this.oldValue !== emptySymbol) {
const { oldValue } = this;
this.oldValue = emptySymbol;
if (newValue !== oldValue) {
peek(TargetObserver.onChange, this, newValue, oldValue);
}
}
}
static onChange(observer, newValue, oldValue) {
observer.onChange(newValue, oldValue, observer.target);
}
};
var updateQueue = /* @__PURE__ */ new Set();
var updateScheduled = false;
var updateHasSideEffects = false;
function scheduleUpdates() {
if (!updateScheduled) {
updateScheduled = true;
queueMicrotask(processUpdates);
}
}
function sortObservers(a, b) {
if (a.depth < b.depth) {
return -1;
}
if (b.depth < a.depth) {
return 1;
}
return a.id - b.id;
}
function processUpdates() {
updateScheduled = false;
const devError = Error("Cycle detected");
let skipPureObservers = false;
let currentObserver;
let oldRefs;
const parentAccess = access;
access = (ref2) => currentObserver._access(ref2, oldRefs);
const update = (observer) => {
if (skipPureObservers && observer.isObservablyPure()) {
return;
}
if (updateQueue.delete(observer)) {
oldRefs = new Set(observer.refs);
currentObserver = observer;
currentObserver._update(false, oldRefs);
}
};
for (let loops = 0; updateQueue.size > 0; loops++) {
if (loops > 100) {
updateQueue.clear();
throw devError || Error("Cycle detected");
}
if (updateQueue.size) {
skipPureObservers = updateHasSideEffects;
updateHasSideEffects = false;
const updatedObservers = [...updateQueue].sort(sortObservers);
updatedObservers.forEach(update);
}
}
access = parentAccess;
}
function collectAccessedRefs(fn, accessedRefs) {
const parentAccess = access;
access = (ref2) => {
accessedRefs.add(ref2);
return parentAccess(ref2);
};
try {
return fn();
} finally {
access = parentAccess;
}
}
var ref = (value, debugId) => new Ref(value, debugId);
var refMap = (entries) => new RefMap(entries);
var computed = (compute, debugId) => new ComputedRef(compute, debugId);
var computedEvery = (inputs, debugId) => new ComputedRef(() => inputs.every(evaluateInput), debugId);
var computedSome = (inputs, debugId) => new ComputedRef(() => inputs.some(evaluateInput), debugId);
var lens = (compute, set2, debugId) => new LensRef(compute, set2, debugId);
function observe(arg1, arg2) {
let observer;
if (isFunction(arg1)) {
observer = new Observer();
observer.update(arg1);
} else {
observer = new TargetObserver(arg1, arg2);
observer.update();
}
return observer;
}
var observeArrayOperations = (arrayRef2, handler) => new ArrayObserver(arrayRef2, handler);
function isReadonlyRef(arg) {
return isRef(arg) && !Object.getOwnPropertyDescriptor(arg, "value").set;
}
function isRef(value) {
return Boolean(value) && value[kRefType] !== void 0;
}
function isArrayRef(value) {
return Boolean(value) && value[kRefType] === "ArrayRef";
}
function guardRef(value, guard) {
return isRef(value) ? guard(value.peek()) : guard(value);
}
function peek(arg1, ...rest) {
if (access === unseenAccess) {
return isFunction(arg1) ? arg1(...rest) : arg1[rest[0]];
}
const parentAccess = access;
access = unseenAccess;
try {
if (isFunction(arg1)) {
return arg1(...rest);
}
return arg1[rest[0]];
} finally {
access = parentAccess;
}
}
var unref = (arg) => isRef(arg) ? arg.value : arg;
var evaluateInput = (arg) => unref(isFunction(arg) ? arg() : arg);
function when(condition, effect) {
const value = condition.peek();
if (value) {
return attachDisposer(
effect ? Promise.resolve().then(() => effect(value)) : Promise.resolve(value),
noop
);
}
let observer;
return attachDisposer(
new Promise((resolve, reject) => {
observer = observe(condition, (value2) => {
if (!value2)
return;
observer.dispose();
if (effect) {
try {
resolve(effect(value2));
} catch (error) {
reject(error);
}
} else {
resolve(value2);
}
});
}),
() => {
observer.dispose();
}
);
}
// hooks/useDepsArray.ts
function useDepsArray(deps) {
const component = expectCurrentComponent();
const index = component.nextHookIndex++;
const prevDeps = component.hooks[index];
component.hooks[index] = deps;
return depsHaveChanged(deps, prevDeps);
}
// internal/onceMounted.ts
var pendingCallbacks = /* @__PURE__ */ new WeakMap();
function onceMounted(node, callback) {
if (node.isConnected) {
callback(node);
} else {
const callbacks = pendingCallbacks.get(node);
if (callbacks) {
if (isFunction(callbacks)) {
pendingCallbacks.set(node, /* @__PURE__ */ new Set([callbacks, callback]));
} else {
callbacks.add(callback);
}
} else {
pendingCallbacks.set(node, callback);
}
return () => {
const callbacks2 = pendingCallbacks.get(node);
if (isFunction(callbacks2)) {
pendingCallbacks.delete(node);
} else if (callbacks2) {
callbacks2.delete(callback);
if (callbacks2.size === 0) {
pendingCallbacks.delete(node);
}
}
};
}
}
function notifyMounted(node) {
if (node.isConnected) {
notifyMountedRecursive(node);
} else if (isFragment(node)) {
const childNodes = getFragmentNodes(node);
if (childNodes) {
for (const childNode of childNodes)
if (childNode?.isConnected) {
notifyMountedRecursive(childNode);
}
}
}
}
function notifyMountedRecursive(node) {
const callbacks = pendingCallbacks.get(node);
if (callbacks) {
pendingCallbacks.delete(node);
if (isFunction(callbacks)) {
try {
callbacks(node);
} catch (error) {
console.error(error);
}
} else {
for (const callback of callbacks) {
try {
callback(node);
} catch (error) {
console.error(error);
}
}
}
}
if (isElement(node)) {
for (let i = 0; i < node.childNodes.length; i++) {
notifyMountedRecursive(node.childNodes[i]);
}
}
}
// internal/elementProxy.ts
var kElementProxyType = Symbol.for("ElementProxy");
var InternalElementProxy = class {
/** The element that was set. */
_element = null;
/**
* Pending effects that will be called when an element is set. They exist when
* `onceElementExists` is called before an element has been set.
*/
_pendingEffects = null;
constructor(effect) {
if (effect) {
onceElementExists(this, effect);
}
}
get [kElementProxyType]() {
return true;
}
toElement() {
return this._element;
}
setElement(element) {
const pendingEffects = this._pendingEffects;
this._pendingEffects = null;
this._element = element;
if (element) {
pendingEffects?.forEach((effect) => effect(element));
}
}
// This must be named `dispose` for HMR to clear it on updates.
dispose() {
this._pendingEffects = null;
}
};
function onceElementExists(ref2, effect) {
let dispose;
if (ref2._element) {
return effect(ref2._element);
}
const pendingEffect = (element) => {
dispose = effect(element);
};
const pendingEffects = ref2._pendingEffects ||= /* @__PURE__ */ new Set();
pendingEffects.add(pendingEffect);
return () => {
pendingEffects.delete(pendingEffect);
dispose?.();
};
}
// addons/elementProxy.ts
function createElementProxy(effect) {
const ref2 = new InternalElementProxy(effect);
return new Proxy(ref2, {
get(target, prop) {
if (prop === kElementProxyType) {
return true;
}
if (ref2._element && prop in ref2._element) {
const value = ref2._element[prop];
return typeof value === "function" ? value.bind(ref2._element) : value;
}
return target[prop];
},
set(target, prop, value) {
if (ref2._element && prop in ref2._element) {
target = ref2._element;
}
return Reflect.set(target, prop, value);
}
});
}
var isElementProxy = (arg) => !!(arg && arg[kElementProxyType]);
// core/unmount.ts
function unmount(node, skipRemove, keepComponent) {
if (isElementProxy(node)) {
node = node.toElement();
}
if (node?.isConnected) {
if (isFragment(node)) {
const childNodes = getFragmentNodes(node) || Array.from(node.childNodes);
for (let i = childNodes.length - 1; i >= 0; i--) {
const childNode = childNodes[i];
if (childNode) {
unmountTree(childNode, skipRemove);
}
}
} else {
unmountTree(node, skipRemove, keepComponent);
}
}
}
function unmountTree(node, skipRemove, keepComponent) {
if (!skipRemove) {
node.remove();
}
if (isElement(node)) {
for (let childNode = node.lastChild; childNode; childNode = childNode.previousSibling) {
unmountTree(childNode, true);
}
const hostProps = getHostProps(node);
hostProps?.unmount();
}
const effects = getPrivate(node, kAlienEffects);
effects?.disable(true);
const tags = getElementTags(node);
if (tags) {
for (const component of tags.values()) {
if (component === keepComponent)
break;
component.dispose();
}
}
const unmountHandler = getPrivate(node, kAlienUnmountHandler);
unmountHandler?.();
}
// core/mount.ts
function mount(parent, node) {
while (parent.lastChild) {
unmount(parent.lastChild);
}
mountLastChild(parent, node);
}
function mountLastChild(parent, node) {
const wasConnected = node.isConnected;
parent.appendChild(node);
if (!wasConnected) {
notifyMounted(node);
}
}
function mountFirstChild(parent, node) {
const wasConnected = node.isConnected;
parent.insertBefore(node, parent.firstChild);
if (!wasConnected) {
notifyMounted(node);
}
}
function mountBeforeNode(sibling, node) {
const wasConnected = node.isConnected;
sibling.before(node);
if (!wasConnected) {
notifyMounted(node);
}
}
function mountAfterNode(sibling, node) {
const wasConnected = node.isConnected;
sibling.after(node);
if (!wasConnected) {
notifyMounted(node);
}
}
function mountReplacementNode(oldNode, newNode) {
const wasConnected = newNode.isConnected;
oldNode.replaceWith(newNode);
unmount(oldNode, true);
if (!wasConnected) {
notifyMounted(newNode);
}
}
// internal/fromElementThunk.ts
function fromElementThunk(thunk, keepDeferred) {
if (!hasPrivate(thunk, kAlienThunkResult)) {
const component = lastValue(currentComponent);
if (!component) {
return thunk();
}
defineProperty(thunk, kAlienThunkResult, {
get() {
let result = component.newMemos ? component.newMemos.get(thunk) : void 0;
if (result === void 0) {
result = thunk();
if (isDeferredNode(result)) {
if (keepDeferred) {
return result;
}
result = evaluateDeferredNode(result);
}
component.newMemos ||= /* @__PURE__ */ new Map();
component.newMemos.set(thunk, result);
}
return result;
}
});
}
return getPrivate(thunk, kAlienThunkResult);
}
// internal/context.ts
var currentContext = /* @__PURE__ */ new Map();
function forwardContext(context, isRerender) {
const oldValues = new Map(currentContext);
context.forEach((value, key) => {
const ref2 = currentContext.get(key);
if (isRerender && ref2) {
context.set(key, ref2);
} else {
currentContext.set(key, value);
}
});
return () => {
context.forEach((_, key) => {
const oldValue = oldValues.get(key);
if (oldValue) {
currentContext.set(key, oldValue);
} else {
currentContext.delete(key);
}
});
};
}
function getContext(context) {
if (context) {
return currentContext.get(context);
}
return currentContext;
}
function setContext(context, value) {
if (context instanceof Map) {
const oldContext = currentContext;
currentContext = context;
return oldContext;
}
const oldValue = currentContext.get(context);
if (value) {
currentContext.set(context, value);
} else {
currentContext.delete(context);
}
return oldValue;
}
// jsx-dom/evaluateChild.ts
function evaluateChild(child) {
if (isDeferredNode(child)) {
child = evaluateDeferredNode(child);
} else {
const key = getElementKey(child);
if (key != null) {
const update = findNodeUpdate(key);
if (update) {
if (isElement(child) && compareNodeWithTag(child, update.tag)) {
morph(child, update);
} else {
child = evaluateDeferredNode(update);
}
}
}
}
return child;
}
function findNodeUpdate(key) {
let update;
let component = lastValue(currentComponent);
if (component) {
do {
if (update = component.updates?.get(key))
break;
} while (component = component.parent);
} else {
const nodeStore = lastValue(currentNodeStore);
update = nodeStore?.getNodeUpdateForKey(key);
}
return update;
}
// jsx-dom/appendChild.ts
function appendChild(child, parent) {
if (child === null) {
return;
}
if (isNode(child)) {
child = evaluateChild(child);
if (isFragment(parent) && !getParentFragment(child)) {
setParentFragment(child, parent);
}
if (hasTagName(parent, "TEMPLATE")) {
parent.content.appendChild(child);
} else {
parent.appendChild(child);
notifyMounted(child);
}
return child;
}
if (isDeferredNode(child)) {
child = evaluateDeferredNode(child);
return appendChild(child, parent);
}
if (isShadowRoot(child)) {
const shadowRoot = parent.attachShadow(child.props);
const ancestorShadowRoot = setContext(
ShadowRootContext,
ref(shadowRoot)
);
try {
for (const shadowChild of child.children) {
appendChild(shadowChild, shadowRoot);
}
} finally {
setContext(ShadowRootContext, ancestorShadowRoot);
}
}
}
// internal/guid.ts
var nextId = Number.MIN_SAFE_INTEGER;
function createGuid(container, key, force, generateId) {
if (!container) {
return nextId += nextId === -1 ? 2 : 1;
}
if (key == null) {
throw Error("A key must be provided when a container is provided");
}
let guid = peek(container, key);
if (!guid || force) {
guid = generateId ? generateId() : nextId += nextId === -1 ? 2 : 1;
}
return guid;
}
// internal/traversal.ts
function findFirstElement(node, end) {
while (node && !isElement(node)) {
if (node === end) {
return null;
}
node = node.nextSibling;
}
return node;
}
function findLastElement(node, start) {
while (node && !isElement(node)) {
if (node === start) {
return null;
}
node = node.previousSibling;
}
return node;
}
// jsx-dom/resolveSelected.ts
function resolveSelected(node) {
if (!node.hasAttribute("multiple")) {
var selectedIndex = -1;
var i = 0;
var curChild = node.firstChild;
var optgroup;
while (curChild) {
if (hasTagName(curChild, "OPTGROUP")) {
optgroup = curChild;
curChild = optgroup.firstChild;
} else {
if (hasTagName(curChild, "OPTION")) {
if (curChild.hasAttribute("selected")) {
selectedIndex = i;
break;
}
i++;
}
curChild = curChild.nextSibling;
if (!curChild && optgroup) {
curChild = optgroup.nextSibling;
optgroup = null;
}
}
}
node.selectedIndex = selectedIndex;
}
}
// morphdom/morphComposite.ts
function morphComposite(fromParentNode, toParentNode) {
const tags = getElementTags(fromParentNode);
const childComponent = tags?.get(toParentNode.tag);
if (childComponent) {
childComponent.replaceProps(toParentNode.props);
toParentNode.context?.forEach((ref2, key) => {
const targetRef = childComponent.context.get(key);
if (targetRef) {
targetRef.value = ref2.peek();
}
});
return fromParentNode;
}
return evaluateDeferredNode(toParentNode);
}
// morphdom/morphChildren.ts
var defaultNextSibling = (node) => node.nextSibling;
function morphChildren(fromParentNode, toChildNodes, component = null, options = {}) {
if (!fromParentNode.childNodes.length) {
if (!toChildNodes || !toChildNodes.length) {
return;
}
} else {
toChildNodes ||= [];
}
const { getFromKey = getElementIdentity, onChildNode = noop } = options;
if (!isArray(toChildNodes)) {
toChildNodes = Array.