UNPKG

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
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