woby
Version:
A high-performance framework with fine-grained observable/signal-based reactivity for building rich applications.
1,407 lines (1,406 loc) • 47.8 kB
JavaScript
import { n as isObject, i as isFunction, k as isString, o as isSVGElement, p as isNode, q as isVoidChild, u as untrack, v as setProps, m as setChild$1, E as get, a8 as isProxy$1, w as SYMBOL_UNTRACKED_UNWRAPPED, Z as SYMBOL_OBSERVABLE_FROZEN, _ as SYMBOL_OBSERVABLE_READABLE, a0 as SYMBOL_OBSERVABLE_WRITABLE, M as createText, G as useRenderEffect, a7 as isArray, N as SYMBOL_UNCACHED, aa as toArray, a9 as fixBigInt, V as isObservable, aj as isNil$1, ad as flatten, ab as castArray, T as useMicrotask, ai as isFunctionReactive, X as store, W as isStore, b8 as SYMBOL_STORE_OBSERVABLE, al as isSVG, aJ as classesToggle, ae as isBoolean, h as assign, K as once, j as indexOf, l as SYMBOL_TEMPLATE_ACCESSOR } from "./setters-Ddu0s6oK.js";
import { a1, a2, a4, S, Y, a3, I, $, U, R, J } from "./setters-Ddu0s6oK.js";
import { m as memo, r as resolve, b as boolean, h as htm, u as useResource, a as useResolved } from "./merge_style-CyMhMoCQ.js";
import { o, E, F, I as I2, S as S2, c, T, z, A, B, C, G, D, d, e, f, g, i, j, k, l, n, p, q, s, t, v, w, x, y } from "./merge_style-CyMhMoCQ.js";
import { r as root } from "./root-B8Ruf358.js";
import { a } from "./render_to_string-DPtjoKMd.js";
import { a as wrapElement, w as wrapCloneElement } from "./wrap_clone_element-CPcdGL7P.js";
var CmdType;
(function(CmdType2) {
CmdType2[CmdType2["Call"] = 0] = "Call";
CmdType2[CmdType2["Set"] = 1] = "Set";
CmdType2[CmdType2["Get"] = 2] = "Get";
CmdType2[CmdType2["Constructor"] = 3] = "Constructor";
})(CmdType || (CmdType = {}));
var SerializeType;
(function(SerializeType2) {
SerializeType2[SerializeType2["Primitive"] = 0] = "Primitive";
SerializeType2[SerializeType2["Object"] = 1] = "Object";
})(SerializeType || (SerializeType = {}));
var ArgEnum;
(function(ArgEnum2) {
ArgEnum2[ArgEnum2["Primitive"] = 0] = "Primitive";
ArgEnum2[ArgEnum2["Object"] = 1] = "Object";
ArgEnum2[ArgEnum2["Callback"] = 2] = "Callback";
ArgEnum2[ArgEnum2["ObjectProperty"] = 3] = "ObjectProperty";
})(ArgEnum || (ArgEnum = {}));
const __TargetSymbol = Symbol("TARGET");
const __ObjectSymbol = Symbol("ID");
const __ArgsSymbol = Symbol("ARGS");
const __IsViaSymbol = Symbol("IsVia");
const IgnoreSymbols = {
[__ArgsSymbol]: __ArgsSymbol,
[__IsViaSymbol]: __IsViaSymbol
};
class ViaClass {
constructor() {
this.finalizationRegistry = typeof FinalizationRegistry === "undefined" ? null : new FinalizationRegistry(this.FinalizeID.bind(this));
this.finalizeTimerId = -1;
this.finalizeIntervalMs = 10;
this.finalizeIdQueue = [];
this.nextObjectId = 1;
this.queue = [];
this.nextGetId = 0;
this.pendingGetResolves = /* @__PURE__ */ new Map();
this.nextFlushId = 0;
this.pendingFlushResolves = /* @__PURE__ */ new Map();
this.isPendingFlush = false;
this.nextCallbackId = 0;
this.callbackToId = /* @__PURE__ */ new Map();
this.idToCallback = /* @__PURE__ */ new Map();
if (!this.finalizationRegistry)
console.warn("[Via.js] No WeakRefs support - will leak memory");
}
FinalizeID(id) {
this.finalizeIdQueue.push(id);
if (this.finalizeTimerId === -1)
this.finalizeTimerId = setTimeout(this.CleanupIDs.bind(this), this.finalizeIntervalMs);
}
CleanupIDs() {
this.finalizeTimerId = -1;
this.postMessage({
"type": "cleanup",
"ids": this.finalizeIdQueue
});
this.finalizeIdQueue.length = 0;
}
getNextObjectId() {
return this.nextObjectId++;
}
addToQueue(d2) {
this.queue.push(d2);
if (!this.isPendingFlush) {
this.isPendingFlush = true;
Promise.resolve().then(this.flush.bind(this));
}
}
// Post the queue to the receiver. Returns a promise which resolves when the receiver
// has finished executing all the commands.
flush() {
this.isPendingFlush = false;
if (!this.queue.length)
return Promise.resolve();
const flushId = this.nextFlushId++;
this.postMessage({
"type": "cmds",
"cmds": this.queue,
"flushId": flushId
});
this.queue.length = 0;
return new Promise((resolve2) => {
this.pendingFlushResolves.set(flushId, resolve2);
});
}
// Called when a message received from the receiver
onMessage(data) {
switch (data.type) {
case "done":
this.onDone(data);
break;
case "callback":
this.onCallback(data);
break;
default:
throw new Error("invalid message type: " + data.type);
}
}
// Called when the receiver has finished a batch of commands passed by a flush.
onDone(data) {
for (const [getId, valueData] of data.getResults) {
const resolve2 = this.pendingGetResolves.get(getId);
if (!resolve2)
throw new Error("invalid get id");
this.pendingGetResolves.delete(getId);
resolve2(this.unwrapArg(valueData));
}
const flushId = data.flushId;
const flushResolve = this.pendingFlushResolves.get(flushId);
if (!flushResolve)
throw new Error("invalid flush id");
this.pendingFlushResolves.delete(flushId);
flushResolve();
}
// Called when a callback is invoked on the receiver and this was forwarded to the controller.
onCallback(data) {
const func = this.idToCallback.get(data.id);
if (!func)
throw new Error("invalid callback id");
const args = data.args.map(this.unwrapArg.bind(this));
func(...args);
}
getCallbackId(func) {
let id = this.callbackToId.get(func);
if (typeof id === "undefined") {
id = this.nextCallbackId++;
this.callbackToId.set(func, id);
this.idToCallback.set(id, func);
}
return id;
}
getIdToCallback(id) {
return this.idToCallback.get(id);
}
viaObjectHandler() {
const THIS = this;
return {
get(target, property, receiver) {
if (property === __ObjectSymbol)
return target[__ObjectSymbol];
else if (IgnoreSymbols[property])
return target[IgnoreSymbols[property]];
return THIS.makeProperty(target[__ObjectSymbol], [property]);
},
set(target, property, value, receiver) {
if (IgnoreSymbols[property])
target[IgnoreSymbols[property]] = value;
else if (typeof property === "symbol")
debugger;
else
THIS.addToQueue([1, target[__ObjectSymbol], [property], THIS.wrapArg(value)]);
return true;
}
};
}
ViaPropertyHandler() {
const THIS = this;
return {
get(target, property, receiver) {
if (property === __TargetSymbol)
return target;
if (IgnoreSymbols[property])
return target[property];
const nextCache = target._nextCache;
const existing = nextCache.get(property);
if (existing)
return existing;
const path = target._path.slice(0);
path.push(property);
const ret = THIS.makeProperty(target[__ObjectSymbol], path);
nextCache.set(property, ret);
return ret;
},
set(target, property, value, receiver) {
if (IgnoreSymbols[property])
target[property] = value;
else {
const path = target._path.slice(0);
path.push(property);
THIS.addToQueue([CmdType.Set, target[__ObjectSymbol], path, THIS.wrapArg(value)]);
}
return true;
},
apply(target, thisArg, argumentsList) {
const returnObjectId = THIS.getNextObjectId();
const args = argumentsList.map(THIS.wrapArg.bind(THIS));
target[__ArgsSymbol] = args.map(toArg);
THIS.addToQueue([CmdType.Call, target[__ObjectSymbol], target._path, args, returnObjectId]);
return THIS._MakeObject(returnObjectId);
},
construct(target, argumentsList, newTarget) {
const returnObjectId = THIS.getNextObjectId();
const args = argumentsList.map(THIS.wrapArg.bind(THIS));
target[__ArgsSymbol] = args.map(toArg);
THIS.addToQueue([CmdType.Constructor, target[__ObjectSymbol], target._path, args, returnObjectId]);
return THIS._MakeObject(returnObjectId);
}
};
}
_MakeObject(id) {
const func = function() {
};
func[__ObjectSymbol] = id;
func[__IsViaSymbol] = true;
const ret = new Proxy(func, this.viaObjectHandler());
if (this.finalizationRegistry)
this.finalizationRegistry.register(ret, id);
return ret;
}
// Wrap an argument to a small array representing the value, object, property or callback for
// posting to the receiver.
wrapArg(arg, _i, _a) {
if (typeof arg === "function") {
const objectId = arg[__ObjectSymbol];
if (typeof objectId === "number")
return [ArgEnum.Object, objectId];
const propertyTarget = arg[__TargetSymbol];
if (propertyTarget)
return [ArgEnum.ObjectProperty, propertyTarget[__ObjectSymbol], propertyTarget._path];
return [ArgEnum.Callback, this.getCallbackId(arg)];
} else if (CanStructuredClone$1(arg)) {
return [ArgEnum.Primitive, arg];
} else
throw new Error("invalid argument");
}
/**
* Unwrap an argument for a callback sent by the receiver.
* @param arr
* @returns
*/
unwrapArg(arr) {
switch (arr[0]) {
case 0:
return arr[1];
case 1:
return this._MakeObject(arr[1]);
default:
throw new Error("invalid arg type");
}
}
// Add a command to the queue representing a get request.
addGet(objectId, path) {
const getId = this.nextGetId++;
this.addToQueue([2, getId, objectId, path]);
return new Promise((resolve2) => {
this.pendingGetResolves.set(getId, resolve2);
});
}
// Return a promise that resolves with the real value of a property, e.g. get(via.document.title).
// This involves a message round-trip, but multiple gets can be requested in parallel, and they will
// all be processed in the same round-trip.
get(proxy) {
if (typeof proxy === "function") {
const objectId = proxy[__ObjectSymbol];
if (typeof objectId === "number")
return this.addGet(objectId, null);
const target = proxy[__TargetSymbol];
if (target)
return this.addGet(target[__ObjectSymbol], target._path);
}
return Promise.resolve(proxy);
}
makeProperty(objectId, path) {
const func = function() {
};
func[__ObjectSymbol] = objectId;
func[__IsViaSymbol] = true;
func._path = path;
func._nextCache = /* @__PURE__ */ new Map();
return new Proxy(func, this.ViaPropertyHandler());
}
}
if (!self.Via)
self.Via = new ViaClass();
self.via = self.Via._MakeObject(0);
self.get = self.Via.get.bind(self.Via);
const isProxy = (proxy) => {
return proxy == null ? false : !!proxy[__IsViaSymbol];
//!!proxy[Symbol.for("__isProxy")]
};
function CanStructuredClone$1(o2) {
const type = typeof o2;
return type === "undefined" || o2 === null || type === "boolean" || type === "number" || type === "bigint" || type === "string" || o2 instanceof Blob || o2 instanceof ArrayBuffer || o2 instanceof ImageData || (Array.isArray(o2) && o2.every((oo) => isProxy(oo)) || Object.keys(o2).every((k2) => CanStructuredClone$1(o2[k2])));
}
const toArg = (arg, _i, _a) => arg[1];
const attributesBoolean = /* @__PURE__ */ new Set(["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"]);
const attributeCamelCasedRe = /e(r[HRWrv]|[Vawy])|Con|l(e[Tcs]|c)|s(eP|y)|a(t[rt]|u|v)|Of|Ex|f[XYa]|gt|hR|d[Pg]|t[TXYd]|[UZq]/;
const attributesCache = {};
const uppercaseRe = /[A-Z]/g;
const normalizeKeySvg = (key) => attributesCache[key] || (attributesCache[key] = attributeCamelCasedRe.test(key) ? key : key.replace(uppercaseRe, (char) => `-${char.toLowerCase()}`));
const isNil = (value) => value === null || value === void 0;
const toKey = (key) => key === "xlinkHref" || key === "xlink:href" ? "href" : normalizeKeySvg(key);
class ViaReceiverClass {
constructor() {
this.idMap = /* @__PURE__ */ new Map([[0, self]]);
this.nextObjectId = -1;
this.callbackToId = /* @__PURE__ */ new Map();
this.idToCallback = /* @__PURE__ */ new Map();
}
// Wrap an argument. This is used for sending values back to the controller. Anything that can be directly
// posted is sent as-is, but any kind of object is represented by its object ID instead.
WrapArg(arg) {
if (CanStructuredClone(arg))
return [SerializeType.Primitive, arg];
else
return [SerializeType.Object, this.ObjectToId(arg)];
}
// Get the real object from an ID.
IdToObject(id) {
const ret = this.idMap.get(id);
if (typeof ret === "undefined")
throw new Error("missing object id: " + id);
return ret;
}
// Allocate new ID for an object on the receiver side.
// The receiver uses negative IDs to prevent ID collisions with the controller.
ObjectToId(object) {
const id = this.nextObjectId--;
this.idMap.set(id, object);
return id;
}
// Get the real value from an ID and a property path, e.g. object ID 0, path ["document", "title"]
// will return window.document.title.
IdToObjectProperty(id, path) {
const ret = this.idMap.get(id);
if (typeof ret === "undefined")
throw new Error("missing object id: " + id);
let base = ret;
for (let i2 = 0, len = path.length; i2 < len; ++i2)
base = base[path[i2]];
return base;
}
// Get a shim function for a given callback ID. This creates a new function that forwards the
// call with its arguments to the controller, where it will run the real callback.
// Callback functions are not re-used to allow them to be garbage collected normally.
GetCallbackShim(id) {
if (this.idToCallback.has(id)) {
return this.idToCallback.get(id);
}
const f2 = (...args) => this.postMessage({
"type": "callback",
"id": id,
"args": args.map(this.WrapArg.bind(this))
});
this.callbackToId.set(f2, id);
this.idToCallback.set(id, f2);
return f2;
}
// Unwrap an argument sent from the controller. Arguments are transported as small arrays indicating
// the type and any object IDs/property paths, so they can be looked up on the receiver side.
UnwrapArg(arr) {
switch (arr[0]) {
case ArgEnum.Primitive:
return arr[1];
case ArgEnum.Object:
return this.IdToObject(arr[1]);
case ArgEnum.Callback:
return this.GetCallbackShim(arr[1]);
case ArgEnum.ObjectProperty:
return this.IdToObjectProperty(arr[1], arr[2]);
default:
throw new Error("invalid arg type");
}
}
// Called when receiving a message from the controller.
OnMessage(data) {
switch (data.type) {
case "cmds":
this.OnCommandsMessage(data);
break;
case "cleanup":
this.OnCleanupMessage(data);
break;
default:
console.error("Unknown message type: " + data.type);
break;
}
}
OnCommandsMessage(data) {
const getResults = [];
data.cmds.forEach((cmd, i2, a5) => {
this.RunCommand(cmd, getResults);
});
this.postMessage({
type: "done",
flushId: data.flushId,
getResults
});
}
RunCommand(arr, getResults) {
const type = arr[0];
switch (type) {
case CmdType.Call:
this.ViaCall(arr[1], arr[2], arr[3], arr[4]);
break;
case CmdType.Set:
this.ViaSet(arr[1], arr[2], arr[3]);
break;
case CmdType.Get:
this.ViaGet(arr[1], arr[2], arr[3], getResults);
break;
case CmdType.Constructor:
this.ViaConstruct(arr[1], arr[2], arr[3], arr[4]);
break;
default:
throw new Error("invalid cmd type: " + type);
}
}
ViaCall(objectId, path, argsData, returnObjectId) {
const obj = this.IdToObject(objectId);
const args = argsData.map(this.UnwrapArg.bind(this));
const methodName = path[path.length - 1];
let base = obj;
for (let i2 = 0, len = path.length - 1; i2 < len; ++i2)
base = base[path[i2]];
if (methodName === "removeEventListener") {
const key = argsData[0][1];
const id = argsData[1][1];
console.log("removeEventListener", key, id);
const f2 = this.idToCallback.get(id);
const ret = base.removeEventListener(key, f2);
this.idToCallback.delete(id);
this.callbackToId.delete(f2);
this.idMap.set(returnObjectId, ret);
} else if (methodName === "setAttribute" && (args[0] === "tabIndex" || base["isSVG"])) {
if (args[0] === "tabIndex") ;
else {
const ret = base.setAttribute(toKey(args[0]), args[1]);
this.idMap.set(returnObjectId, ret);
}
} else {
const ret = base[methodName](...args.map((a5) => Array.isArray(a5) ? [].slice.call(a5) : a5).flat());
this.idMap.set(returnObjectId, ret);
}
}
ViaConstruct(objectId, path, argsData, returnObjectId) {
const obj = this.IdToObject(objectId);
const args = argsData.map(this.UnwrapArg.bind(this));
const methodName = path[path.length - 1];
let base = obj;
for (let i2 = 0, len = path.length - 1; i2 < len; ++i2)
base = base[path[i2]];
const ret = new base[methodName](...args);
this.idMap.set(returnObjectId, ret);
}
ViaSet(objectId, path, valueData) {
const obj = this.IdToObject(objectId);
const value = this.UnwrapArg(valueData);
const propertyName = path[path.length - 1];
let base = obj;
for (let i2 = 0, len = path.length - 1; i2 < len; ++i2)
base = base[path[i2]];
if (propertyName === "tabIndex" && typeof value === "undefined")
base.removeAttribute("tabIndex");
else if (base["isSVG"]) {
const key = toKey(propertyName);
if (isNil(value) || value === false && attributesBoolean.has(key))
base.removeAttribute(key);
else
base.setAttribute(key, String(value));
} else
base[propertyName] = value;
}
ViaGet(getId, objectId, path, getResults) {
const obj = this.IdToObject(objectId);
if (path === null) {
getResults.push([getId, this.WrapArg(obj)]);
return;
}
const propertyName = path[path.length - 1];
let base = obj;
for (let i2 = 0, len = path.length - 1; i2 < len; ++i2)
base = base[path[i2]];
const value = base["isSVG"] ? base.getAttribute(toKey(propertyName)) : base[propertyName];
getResults.push([getId, this.WrapArg(value)]);
}
OnCleanupMessage(data) {
for (const id of data.ids)
this.idMap.delete(id);
}
}
function CanStructuredClone(o2) {
const type = typeof o2;
return type === "undefined" || o2 === null || type === "boolean" || type === "number" || type === "bigint" || type === "string" || o2 instanceof Blob || o2 instanceof ArrayBuffer || o2 instanceof ImageData;
}
self.ViaReceiver = new ViaReceiverClass();
if (typeof via !== "undefined")
var document$1 = via.document;
document$1.createComment;
const createHTMLNode = document$1.createElement;
const createSVGNode = (name) => document$1.createElementNS("http://www.w3.org/2000/svg", name);
document$1.createTextNode;
document$1.createDocumentFragment;
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 i2 = 0, l2 = values.length; i2 < l2; i2++) {
const value = values[i2];
if (value instanceof Node) {
children.push(value);
} else {
FragmentUtils.getChildrenFragmented(value, children);
}
}
} else {
if (values instanceof Node) {
children.push(values);
} else {
FragmentUtils.getChildrenFragmented(values, children);
}
}
return children;
},
getChildren: (thiz) => {
if (!thiz.length) return NOOP_CHILDREN;
if (!thiz.fragmented) return thiz.values;
if (thiz.length === 1) return FragmentUtils.getChildren(thiz.values);
return FragmentUtils.getChildrenFragmented(thiz);
},
pushFragment: (thiz, fragment) => {
FragmentUtils.pushValue(thiz, fragment);
thiz.fragmented = true;
},
pushNode: (thiz, node) => {
FragmentUtils.pushValue(thiz, node);
},
pushValue: (thiz, value) => {
const { values, length } = thiz;
if (length === 0) {
thiz.values = value;
} else if (length === 1) {
thiz.values = [values, value];
} else {
values.push(value);
}
thiz.length += 1;
},
replaceWithNode: (thiz, node) => {
thiz.values = node;
delete thiz.fragmented;
thiz.length = 1;
},
replaceWithFragment: (thiz, fragment) => {
thiz.values = fragment.values;
thiz.fragmented = fragment.fragmented;
thiz.length = fragment.length;
}
};
const IsSvgSymbol = Symbol("isSvg");
IgnoreSymbols[IsSvgSymbol] = IsSvgSymbol;
const createElement = (component, _props, ..._children) => {
const children = _children.length > 1 ? _children : _children.length > 0 ? _children[0] : void 0;
const hasChildren = !isVoidChild(children);
if (hasChildren && isObject(_props) && "children" in _props) {
throw new Error('Providing "children" both as a prop and as rest arguments is forbidden');
}
if (isFunction(component)) {
const props = hasChildren ? { ..._props, children } : _props;
return wrapElement(() => {
return untrack(() => component.call(component, props));
});
} else if (isString(component)) {
const isSVG2 = isSVGElement(component);
const createNode = isSVG2 ? createSVGNode : createHTMLNode;
return wrapElement(() => {
const child = createNode(component);
if (isSVG2) {
child["isSVG"] = true;
child[IsSvgSymbol] = true;
}
const stack = new Error();
untrack(() => {
if (_props) {
setProps(child, _props, stack);
}
if (hasChildren) {
setChild$1(child, children, FragmentUtils.make(), stack);
}
});
return child;
});
} else if (isNode(component)) {
return wrapElement(() => component);
} else {
throw new Error("Invalid component");
}
};
const Dynamic = ({
component,
props
/* , children */
}) => {
if (isFunction(component) || isFunction(props)) {
return memo(() => {
return resolve(createElement(
get(component, false),
get(props)
/* children */
));
});
} else {
return createElement(
component,
props
/* children */
);
}
};
const HTMLValue = Symbol("HtmlValue");
IgnoreSymbols[HTMLValue] = HTMLValue;
const resolveChild = (value, setter, _dynamic, stack) => {
var _a, _b;
const updateElement = (e2, f2, v2, pv) => {
e2.textContent = "";
if (Array.isArray(v2)) {
e2[HTMLValue] = "array";
if (!f2)
e2.parentElement.replaceChildren(e2, ...toArray(v2));
return [e2, ...v2];
} else {
const useE = () => {
if (pv) {
switch (pv[0][HTMLValue]) {
case "element":
pv[0].replaceWith(e2);
break;
case "primitive":
case "array": {
pv.slice(1).forEach((p2) => p2.remove());
break;
}
}
}
};
if (typeof v2 === "symbol") {
e2[HTMLValue] = "symbol";
if (!f2)
e2.parentElement.replaceChildren(e2);
return [e2];
} else {
if (isProxy$1(v2)) {
e2[HTMLValue] = "element";
v2[HTMLValue] = "element";
if (pv) {
switch (pv[0][HTMLValue]) {
case "element":
pv[0].replaceWith(v2);
break;
case "primitive":
case "array":
case "symbol":
case "null":
pv[0].parentElement.replaceChildren(...toArray(v2));
break;
}
}
return [v2];
} else if (!(v2 === void 0 || v2 === null)) {
e2[HTMLValue] = "primitive";
e2.textContent = fixBigInt(v2);
useE();
return [
e2
/* , fixBigInt(v) */
];
} else {
e2[HTMLValue] = "null";
useE();
return [e2];
}
}
}
};
if (isProxy$1(value)) {
return value;
} else if (isFunction(value)) {
if (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)) {
(value[SYMBOL_OBSERVABLE_READABLE] ?? value[SYMBOL_OBSERVABLE_WRITABLE]).stack = stack;
resolveChild(value(), setter, _dynamic, stack);
} else {
const e2 = createText("");
let f2 = true;
let v2;
useRenderEffect((stack2) => {
const pv = v2;
(value[SYMBOL_OBSERVABLE_READABLE] ?? value[SYMBOL_OBSERVABLE_WRITABLE]).stack = stack2;
v2 = resolveChild(value(), null, false, stack2);
v2 = updateElement(e2, f2, v2, pv);
f2 = false;
}, stack);
return v2;
}
} else if (isArray(value)) {
const [values, hasObservables] = resolveArraysAndStatics(value);
values[SYMBOL_UNCACHED] = value[SYMBOL_UNCACHED];
if (hasObservables) {
const e2 = createText("");
let f2 = true;
let v2;
useRenderEffect(() => {
const pv = v2;
v2 = values.map((v22) => resolveChild(v22, null, false, stack)).filter((v22) => typeof v22 !== "undefined");
v2 = updateElement(e2, f2, v2, pv);
f2 = false;
}, stack);
return v2;
} else {
const vs = values.map((v2) => resolveChild(v2, null, false, stack)).filter((v2) => typeof v2 !== "undefined");
return vs;
}
} else {
return value;
}
};
const resolveClass = (classes, resolved = {}) => {
if (isString(classes)) {
classes.split(/\s+/g).filter(Boolean).filter((cls) => {
resolved[cls] = true;
});
} else if (isFunction(classes)) {
resolveClass(classes(), resolved);
} else if (isArray(classes)) {
classes.forEach((cls) => {
resolveClass(cls, resolved);
});
} else if (classes) {
for (const key in classes) {
const value = classes[key];
const isActive = !!get(value);
if (!isActive) continue;
resolved[key] = true;
}
}
return resolved;
};
const resolveStyle = (styles, resolved = {}) => {
if (isString(styles)) {
return styles;
} else if (isFunction(styles)) {
return resolveStyle(styles(), resolved);
} else if (isArray(styles)) {
styles.forEach((style) => {
resolveStyle(style, resolved);
});
} else if (styles) {
for (const key in styles) {
const value = styles[key];
resolved[key] = get(value);
}
}
return resolved;
};
const resolveArraysAndStatics = /* @__PURE__ */ (() => {
const DUMMY_RESOLVED = [];
const resolveArraysAndStaticsInner = (values, resolved, hasObservables) => {
for (let i2 = 0, l2 = values.length; i2 < l2; i2++) {
const value = values[i2];
const type = typeof value;
if (type === "string" || type === "number" || type === "bigint") {
if (resolved === DUMMY_RESOLVED) resolved = values.slice(0, i2);
resolved.push(createText(fixBigInt(value)));
} else if (type === "object" && isArray(value)) {
if (resolved === DUMMY_RESOLVED) resolved = values.slice(0, i2);
hasObservables = resolveArraysAndStaticsInner(value, resolved, hasObservables)[1];
} else if (type === "function" && isObservable(value)) {
if (resolved !== DUMMY_RESOLVED) resolved.push(value);
hasObservables = true;
} else {
if (resolved !== DUMMY_RESOLVED) resolved.push(value);
}
}
if (resolved === DUMMY_RESOLVED) resolved = values;
return [resolved, hasObservables];
};
return (values) => {
return resolveArraysAndStaticsInner(values, DUMMY_RESOLVED, false);
};
})();
const setAttributeStatic = /* @__PURE__ */ (() => {
const attributesBoolean2 = /* @__PURE__ */ new Set(["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"]);
return (element, key, value) => {
if (isNil$1(value) || value === false && attributesBoolean2.has(key)) {
element.removeAttribute(key);
} else {
value = value === true ? "" : String(value);
element.setAttribute(key, value);
}
};
})();
const setAttribute = (element, key, value, stack) => {
if (isFunction(value)) {
if (isObservable(value)) {
useRenderEffect(() => {
setAttributeStatic(element, key, value());
}, stack);
} else {
setAttributeStatic(element, key, value());
}
} else {
setAttributeStatic(element, key, value);
}
};
const setChildStatic = (parent, child, dynamic, stack) => {
if (isVoidChild(child)) return;
if (Array.isArray(child)) {
const children = Array.isArray(child) ? child : [child];
const cs = children.map((c2) => resolveChild(c2, null, false, stack)).flat(Infinity);
parent.replaceChildren(...cs);
} else {
const c2 = resolveChild(child, null, false, stack);
parent.replaceChildren(...[c2].flat(Infinity));
}
};
const setChild = (parent, child, stack) => {
setChildStatic(parent, child, false, stack);
};
const setClassStatic = classesToggle;
const setClass = (element, key, value, stack) => {
if (isFunction(value)) {
if (isObservable(value)) {
useRenderEffect(() => {
setClassStatic(element, key, value());
}, stack);
} else {
setClassStatic(element, key, value());
}
} else {
setClassStatic(element, key, value);
}
};
const setClassBooleanStatic = (element, value, key, keyPrev) => {
if (keyPrev && keyPrev !== true) {
setClassStatic(element, keyPrev, false);
}
if (key && key !== true) {
setClassStatic(element, key, value);
}
};
const setClassBoolean = (element, value, key, stack) => {
if (isFunction(key)) {
if (isObservable(key)) {
let keyPrev;
useRenderEffect(() => {
const keyNext = key();
setClassBooleanStatic(element, value, keyNext, keyPrev);
keyPrev = keyNext;
}, stack);
} else {
setClassBooleanStatic(element, value, key());
}
} else {
setClassBooleanStatic(element, value, key);
}
};
const setClassesStatic = (element, object, objectPrev, stack) => {
if (isString(object)) {
if (isSVG(element)) {
element.setAttribute("class", object);
} else {
element.className = object;
}
} else {
if (objectPrev) {
if (isString(objectPrev)) {
if (objectPrev) {
if (isSVG(element)) {
element.setAttribute("class", "");
} else {
element.className = "";
}
}
} else if (isArray(objectPrev)) {
objectPrev = store(objectPrev, {});
for (let i2 = 0, l2 = objectPrev.length; i2 < l2; i2++) {
if (!objectPrev[i2]) continue;
setClassBoolean(element, false, objectPrev[i2], stack);
}
} else {
objectPrev = store(objectPrev, {});
for (const key in objectPrev) {
if (object && key in object) continue;
setClass(element, key, false, stack);
}
}
}
if (isArray(object)) {
if (isStore(object)) {
for (let i2 = 0, l2 = object.length; i2 < l2; i2++) {
const fn = untrack(() => isFunction(object[i2]) ? object[i2] : object[SYMBOL_STORE_OBSERVABLE](String(i2)));
setClassBoolean(element, true, fn, stack);
}
} else {
for (let i2 = 0, l2 = object.length; i2 < l2; i2++) {
if (!object[i2]) continue;
setClassBoolean(element, true, object[i2], stack);
}
}
} else {
if (isStore(object)) {
for (const key in object) {
const fn = untrack(() => isFunction(object[key]) ? object[key] : object[SYMBOL_STORE_OBSERVABLE](key));
setClass(element, key, fn, stack);
}
} else {
for (const key in object) {
setClass(element, key, object[key], stack);
}
}
}
}
};
const setClasses = (element, object, stack) => {
if (isFunction(object) || isArray(object)) {
let objectPrev;
useRenderEffect(() => {
const objectNext = resolveClass(object);
setClassesStatic(element, objectNext, objectPrev, stack);
objectPrev = objectNext;
}, stack);
} else {
setClassesStatic(element, object, null, stack);
}
};
const setEventStatic = /* @__PURE__ */ (() => {
return (element, event, value) => {
element[event] = value;
};
})();
const setEvent = (element, event, value) => {
setEventStatic(element, event, value);
};
const setHTMLStatic = (element, value) => {
element.innerHTML = String(isNil$1(value) ? "" : value);
};
const setHTML = (element, value, stack) => {
useRenderEffect(() => {
setHTMLStatic(element, get(get(value).__html));
}, stack);
};
const setPropertyStatic = (element, key, value) => {
if (key === "tabIndex" && isBoolean(value)) {
value = value ? 0 : void 0;
}
if (key === "value") {
if (element.tagName === "PROGRESS") {
value ?? (value = null);
} else if (element.tagName === "SELECT" && !element["_$inited"]) {
element["_$inited"] = true;
queueMicrotask(() => element[key] = value);
}
}
try {
element[key] = value;
} catch {
setAttributeStatic(element, key, value);
}
};
const setProperty = (element, key, value, stack) => {
if (isFunction(value) && isFunctionReactive(value)) {
if (isObservable(value)) {
useRenderEffect(() => {
setPropertyStatic(element, key, value());
}, stack);
} else {
setPropertyStatic(element, key, get(value));
}
} else {
setPropertyStatic(element, key, get(value));
}
};
const setRef = (element, value) => {
if (isNil$1(value)) return;
const values = flatten(castArray(value)).filter(Boolean);
if (!values.length) return;
const stack = new Error();
useMicrotask(() => untrack(() => values.forEach((value2) => value2 == null ? void 0 : value2(element))), stack);
};
const setStyleStatic = /* @__PURE__ */ (() => {
const propertyNonDimensionalRe = /^(-|f[lo].*[^se]$|g.{5,}[^ps]$|z|o[pr]|(W.{5})?[lL]i.*(t|mp)$|an|(bo|s).{4}Im|sca|m.{6}[ds]|ta|c.*[st]$|wido|ini)/i;
const propertyNonDimensionalCache = {};
return (element, key, value) => {
if (key.charCodeAt(0) === 45) {
if (isNil$1(value)) {
element.style.removeProperty(key);
} else {
element.style.setProperty(key, String(value));
}
} else if (isNil$1(value)) {
element.style[key] = null;
} else {
element.style[key] = isString(value) || (propertyNonDimensionalCache[key] || (propertyNonDimensionalCache[key] = propertyNonDimensionalRe.test(key))) ? value : `${value}px`;
}
};
})();
const setStyle = (element, key, value, stack) => {
if (isFunction(value) && isFunctionReactive(value)) {
if (isObservable(value)) {
useRenderEffect(() => {
setStyleStatic(element, key, value());
}, stack);
} else {
setStyleStatic(element, key, get(value));
}
} else {
setStyleStatic(element, key, get(value));
}
};
const setStylesStatic = (element, object, objectPrev, stack) => {
if (isString(object)) {
element.setAttribute("style", object);
} else {
if (objectPrev) {
if (isString(objectPrev)) {
if (objectPrev) {
element.style.cssText = "";
}
} else {
objectPrev = store.unwrap(objectPrev);
for (const key in objectPrev) {
if (object && key in object) continue;
setStyleStatic(element, key, null);
}
}
}
if (isStore(object)) {
for (const key in object) {
const fn = untrack(() => isFunction(object[key]) ? object[key] : object[SYMBOL_STORE_OBSERVABLE](key));
setStyle(element, key, fn, stack);
}
} else {
for (const key in object) {
setStyle(element, key, object[key], stack);
}
}
}
};
const setStyles = (element, object, stack) => {
if (isFunction(object) || isArray(object)) {
if (isObservable(object)) {
let objectPrev;
useRenderEffect(() => {
const objectNext = resolveStyle(object);
setStylesStatic(element, objectNext, objectPrev, stack);
objectPrev = objectNext;
}, stack);
} else {
let objectPrev;
useRenderEffect(() => {
const objectNext = resolveStyle(object);
setStylesStatic(element, objectNext, objectPrev, stack);
objectPrev = objectNext;
}, stack);
}
} else {
setStylesStatic(element, get(object), null, stack);
}
};
const render = (child, parent) => {
if (!parent || !(parent instanceof HTMLElement)) throw new Error("Invalid parent node");
parent.textContent = "";
return root((stack, dispose) => {
setChild(parent, child, stack);
return () => {
dispose(stack);
parent.textContent = "";
};
});
};
const Portal = ({ when = true, mount, wrapper, children }) => {
const portal = get(wrapper) || createHTMLNode("div");
if (!(portal instanceof HTMLElement)) throw new Error("Invalid wrapper node");
const condition = boolean(when);
const stack = new Error();
useRenderEffect(() => {
if (!get(condition)) return;
const parent = get(mount) || document.body;
if (!(parent instanceof Element)) throw new Error("Invalid mount node");
parent.insertBefore(portal, null);
return () => {
parent.removeChild(portal);
};
}, stack);
useRenderEffect(() => {
if (!get(condition)) return;
return render(children, portal);
}, stack);
return assign(() => get(condition) || children, { metadata: { portal } });
};
function jsx(component, props, ...children) {
if (typeof children === "string")
return wrapCloneElement(createElement(component, props ?? {}, children), component, props);
if (!props) props = {};
if (typeof children === "string")
Object.assign(props, { children });
return wrapCloneElement(createElement(component, props, props == null ? void 0 : props.key), component, props);
}
const jsxDEV = (component, props, key, isStatic, source, self2) => {
if (key)
Object.assign(props, { key });
return wrapCloneElement(createElement(component, props), component, props);
};
function h$1(component, props, ...children) {
if (children.length || isObject(props) && !isArray(props)) {
if (!props) props = { children };
else props = { ...props, children };
return createElement(component, props);
} else {
return createElement(component, null, props);
}
}
const registry = {};
const h = (type, props, ...children) => createElement(registry[type] || type, props, ...children);
const register = (components) => void assign(registry, components);
const html = assign(htm.bind(h), { register });
const lazy = (fetcher) => {
const fetcherOnce = once(fetcher);
const component = (props) => {
const resource = useResource(fetcherOnce);
return memo(() => {
return useResolved(resource, ({ pending, error, value }) => {
if (pending) return;
if (error) throw error;
const component2 = "default" in value ? value.default : value;
return resolve(createElement(component2, props));
});
});
};
component.preload = () => {
return new Promise((resolve2, reject) => {
const resource = useResource(fetcherOnce);
useResolved(resource, ({ pending, error }) => {
if (pending) return;
if (error) return reject(error);
return resolve2();
});
});
};
return component;
};
const template = (fn) => {
const safePropertyRe = /^[a-z0-9-_]+$/i;
const checkValidProperty = (property) => {
if (isString(property) && safePropertyRe.test(property)) return true;
throw new Error(`Invalid property, only alphanumeric properties are allowed inside templates, received: "${property}"`);
};
const makeAccessor = (actionsWithNodes) => {
return new Proxy({}, {
get(target, prop) {
checkValidProperty(prop);
const accessor = (node, method, key, targetNode) => {
if (key) checkValidProperty(key);
actionsWithNodes.push([node, method, prop, key, targetNode]);
};
const metadata = { [SYMBOL_TEMPLATE_ACCESSOR]: true };
return assign(accessor, metadata);
}
});
};
const makeActionsWithNodesAndTemplate = () => {
const actionsWithNodes = [];
const accessor = makeAccessor(actionsWithNodes);
const component = fn(accessor);
if (isFunction(component)) {
const root2 = component();
if (root2 instanceof Element) {
return { actionsWithNodes, root: root2 };
}
}
throw new Error("Invalid template, it must return a function that returns an Element");
};
const makeActionsWithPaths = (actionsWithNodes) => {
const actionsWithPaths = [];
for (let i2 = 0, l2 = actionsWithNodes.length; i2 < l2; i2++) {
const [node, method, prop, key, targetNode] = actionsWithNodes[i2];
const nodePath = makeNodePath(node);
const targetNodePath = targetNode ? makeNodePath(targetNode) : void 0;
actionsWithPaths.push([nodePath, method, prop, key, targetNodePath]);
}
return actionsWithPaths;
};
const makeNodePath = /* @__PURE__ */ (() => {
let prevNode = null;
let prevPath;
return (node) => {
if (node === prevNode) return prevPath;
const path = [];
let child = node;
let parent = child.parentNode;
while (parent) {
const index = !child.previousSibling ? 0 : !child.nextSibling ? -0 : indexOf(parent.childNodes, child);
path.push(index);
child = parent;
parent = parent.parentNode;
}
prevNode = node;
prevPath = path;
return path;
};
})();
const makeNodePathProperties = (path) => {
const properties = ["root"];
const parts = path.slice().reverse();
for (let i2 = 0, l2 = parts.length; i2 < l2; i2++) {
const part = parts[i2];
if (Object.is(0, part)) {
properties.push("firstChild");
} else if (Object.is(-0, part)) {
properties.push("lastChild");
} else {
properties.push("firstChild");
for (let nsi = 0; nsi < part; nsi++) {
properties.push("nextSibling");
}
}
}
return properties;
};
const makeReviverPaths = (actionsWithPaths) => {
const paths = [];
for (let i2 = 0, l2 = actionsWithPaths.length; i2 < l2; i2++) {
const action = actionsWithPaths[i2];
const nodePath = action[0];
const targetNodePath = action[4];
paths.push(nodePath);
if (targetNodePath) {
paths.push(targetNodePath);
}
}
return paths;
};
const makeReviverVariablesData = (paths, properties) => {
const data = new Array(paths.length);
for (let i2 = 0, l2 = paths.length; i2 < l2; i2++) {
data[i2] = {
path: paths[i2],
properties: properties[i2]
};
}
return data;
};
const makeReviverVariables = (actionsWithPaths) => {
const paths = makeReviverPaths(actionsWithPaths);
const properties = paths.map(makeNodePathProperties);
const data = makeReviverVariablesData(paths, properties);
const assignments = [];
const map = /* @__PURE__ */ new Map();
let variableId = 0;
while (true) {
const datum = data.find((datum2) => datum2.properties.length > 1);
if (!datum) break;
const [current, next] = datum.properties;
const variable = `$${variableId++}`;
const assignment = `const ${variable} = ${current}.${next};`;
assignments.push(assignment);
for (let i2 = 0, l2 = data.length; i2 < l2; i2++) {
const datum2 = data[i2];
const [otherCurrent, otherNext] = datum2.properties;
if (otherCurrent !== current || otherNext !== next) continue;
datum2.properties[0] = variable;
datum2.properties.splice(1, 1);
}
}
for (let i2 = 0, l2 = data.length; i2 < l2; i2++) {
const datum = data[i2];
map.set(datum.path, datum.properties[0]);
}
return { assignments, map };
};
const makeReviverActions = (actionsWithPaths, variables) => {
const actions = [];
for (let i2 = 0, l2 = actionsWithPaths.length; i2 < l2; i2++) {
const [nodePath, method, prop, key, targetNodePath] = actionsWithPaths[i2];
if (targetNodePath) {
actions.push(`this.${method} ( props["${prop}"], ${variables.get(targetNodePath)} );`);
} else if (key) {
actions.push(`this.${method} ( ${variables.get(nodePath)}, "${key}", props["${prop}"] );`);
} else {
actions.push(`this.${method} ( ${variables.get(nodePath)}, props["${prop}"] );`);
}
}
return actions;
};
const makeReviver = (actionsWithPaths) => {
const { assignments, map } = makeReviverVariables(actionsWithPaths);
const actions = makeReviverActions(actionsWithPaths, map);
const fn2 = new Function("root", "props", `${assignments.join("")}${actions.join("")}return root;`);
const apis = { setAttribute, setClasses, setEvent, setHTML, setProperty, setRef, setStyles };
const reviver = fn2.bind(apis);
return reviver;
};
const makeComponent = () => {
const { actionsWithNodes, root: root2 } = makeActionsWithNodesAndTemplate();
const actionsWithPaths = makeActionsWithPaths(actionsWithNodes);
const reviver = makeReviver(actionsWithPaths);
return (props) => {
const clone = root2.cloneNode(true);
return wrapElement(reviver.bind(void 0, clone, props));
};
};
return makeComponent();
};
export {
o as $,
get as $$,
a1 as CONTEXTS_DATA,
a2 as DIRECTIVES,
Dynamic,
E as ErrorBoundary,
F as For,
I2 as If,
Portal,
a4 as SYMBOLS_DIRECTIVES,
S as SYMBOL_CLONE,
Y as SYMBOL_OBSERVABLE,
SYMBOL_OBSERVABLE_FROZEN,
SYMBOL_OBSERVABLE_READABLE,
SYMBOL_OBSERVABLE_WRITABLE,
a3 as SYMBOL_SUSPENSE,
I as SYMBOL_SUSPENSE_COLLECTOR,
SYMBOL_TEMPLATE_ACCESSOR,
SYMBOL_UNCACHED,
$ as SYMBOL_UNTRACKED,
SYMBOL_UNTRACKED_UNWRAPPED,
S2 as Suspense,
c as Switch,
T as Ternary,
z as batch,
A as createContext,
B as createDirective,
createElement,
h$1 as h,
C as hmr,
html,
U as isBatching,
isObservable,
isStore,
jsx,
jsxDEV,
jsx as jsxs,
lazy,
G as mergeStyles,
render,
a as renderToString,
resolve,
store,
template,
D as tick,
untrack,
d as useAbortController,
e as useAbortSignal,
f as useAnimationFrame,
g as useAnimationLoop,
boolean as useBoolean,
R as useCleanup,
i as useContext,
j as useDisposed,
J as useEffect,
k as useEventListener,
l as useFetch,
n as useIdleCallback,
p as useIdleLoop,
q as useInterval,
memo as useMemo,
useMicrotask,
s as usePromise,
t as useReadonly,
useResolved,
useResource,
root as useRoot,
v as useSelector,
w as useSuspended,
x as useTimeout,
y as useUntracked,
wrapCloneElement
};
//# sourceMappingURL=via.es.js.map