UNPKG

woby

Version:

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

1 lines 207 kB
{"version":3,"file":"render_to_string-CoO3rHSR.cjs","sources":["../../soby/dist/methods/batch.js","../../soby/dist/methods/is_observable_boolean.js","../../soby/dist/methods/is_observable_frozen.js","../../soby/dist/methods/is_untracked.js","../../soby/dist/objects/memo.js","../../soby/dist/methods/memo.js","../../soby/dist/methods/boolean.js","../../soby/dist/methods/disposed.js","../../soby/dist/methods/resolve.js","../../soby/dist/methods/for.cache.keyed.js","../../soby/dist/objects/suspense.js","../../soby/dist/methods/suspense.js","../../soby/dist/methods/for.cache.unkeyed.js","../../soby/dist/methods/for.js","../../soby/dist/methods/warmup.js","../../soby/dist/methods/switch.js","../../soby/dist/methods/ternary.js","../../soby/dist/methods/observable.js","../../soby/dist/methods/is_observable_writable.js","../../soby/dist/methods/target.js","../../soby/dist/methods/readonly.js","../../soby/dist/methods/selector.js","../../soby/dist/methods/suspended.js","../../soby/dist/methods/tick.js","../../soby/dist/methods/try_catch.js","../../soby/dist/methods/untracked.js","../src/utils/mark.ts","../src/hooks/use_attached.ts","../src/hooks/use_resolved.ts","../src/hooks/use_event_listener.ts","../src/hooks/use_abort_controller.ts","../src/hooks/use_abort_signal.ts","../src/hooks/use_scheduler.ts","../src/hooks/use_animation_frame.ts","../src/hooks/use_animation_loop.ts","../src/hooks/use_context.ts","../src/components/suspense.context.ts","../src/components/suspense.manager.ts","../src/hooks/use_resource.ts","../src/hooks/use_fetch.ts","../src/hooks/use_idle_callback.ts","../src/hooks/use_idle_loop.ts","../src/hooks/use_interval.ts","../src/hooks/use_promise.ts","../src/hooks/use_timeout.ts","../src/hooks/use_mounted.ts","../src/hooks/use_mounted_context.ts","../src/components/error_boundary.ts","../src/components/for.ts","../src/hooks/use_guarded.ts","../src/components/if.ts","../src/components/suspense.ts","../src/components/switch.ts","../src/components/ternary.ts","../src/utils/stylesheets.ts","../src/methods/assign.ts","../src/methods/is_jsx_prop.ts","../src/methods/make.ts","../src/methods/defaults.ts","../src/methods/custom_element.ts","../src/methods/create_context.tsx","../src/methods/create_directive.ts","../src/methods/hmr.ts","../../node_modules/.pnpm/htm@3.1.1/node_modules/htm/dist/htm.module.js","../src/methods/render_to_string.ts"],"sourcesContent":["/* IMPORT */\nimport { setBatch } from '../context.js';\nimport { noop } from '../utils.js';\n/* HELPERS */\nlet counter = 0;\nlet resolve = noop;\n/* MAIN */\nconst batch = async (fn, stack) => {\n if (!counter) {\n setBatch(new Promise(r => resolve = r));\n }\n try {\n counter += 1;\n return await fn();\n }\n finally {\n counter -= 1;\n if (!counter) {\n setBatch(undefined);\n resolve(stack);\n }\n }\n};\n/* MAIN */\nexport default batch;\n","/* IMPORT */\nimport { SYMBOL_OBSERVABLE_BOOLEAN } from '../symbols.js';\nimport { isFunction } from '../utils.js';\n/* MAIN */\nconst isObservableBoolean = (value) => {\n return isFunction(value) && (SYMBOL_OBSERVABLE_BOOLEAN in value);\n};\n/* EXPORT */\nexport default isObservableBoolean;\n","/* IMPORT */\nimport { SYMBOL_OBSERVABLE_FROZEN, SYMBOL_OBSERVABLE_READABLE } from '../symbols.js';\nimport { isFunction } from '../utils.js';\n/* MAIN */\nconst isObservableFrozen = (value) => {\n return isFunction(value) && ((SYMBOL_OBSERVABLE_FROZEN in value) || !!value[SYMBOL_OBSERVABLE_READABLE]?.parent?.disposed);\n};\n/* EXPORT */\nexport default isObservableFrozen;\n","/* IMPORT */\nimport { SYMBOL_UNTRACKED, SYMBOL_UNTRACKED_UNWRAPPED } from '../symbols.js';\nimport { isFunction } from '../utils.js';\n/* MAIN */\nconst isUntracked = (value) => {\n return isFunction(value) && ((SYMBOL_UNTRACKED in value) || (SYMBOL_UNTRACKED_UNWRAPPED in value));\n};\n/* EXPORT */\nexport default isUntracked;\n","/* IMPORT */\nimport { DIRTY_MAYBE_YES, UNAVAILABLE, UNINITIALIZED } from '../constants.js';\nimport Observable from './observable.js';\nimport Observer from './observer.js';\nimport { callStack, Stack } from '../methods/debugger.js';\n/* MAIN */\nclass Memo extends Observer {\n /* CONSTRUCTOR */\n constructor(fn, options) {\n super();\n this.fn = fn;\n this.observable = new Observable(UNINITIALIZED, options, this);\n const { stack } = options ?? { stack: callStack('Memo init') };\n if (options?.sync === true) {\n this.sync = true;\n this.update(stack);\n }\n }\n /* API */\n run(stack) {\n const result = super.refresh(this.fn, stack);\n if (!this.disposed && this.observables.empty()) {\n this.disposed = true;\n }\n if (result !== UNAVAILABLE) {\n this.observable.set(result);\n }\n }\n stale(status, stack) {\n const statusPrev = this.status;\n if (statusPrev >= status)\n return;\n this.status = status;\n if (statusPrev === DIRTY_MAYBE_YES)\n return;\n this.observable.stale(DIRTY_MAYBE_YES, stack);\n }\n}\n/* EXPORT */\nexport default Memo;\n","import isObservableFrozen from './is_observable_frozen.js';\nimport isUntracked from './is_untracked.js';\nimport { frozen, readable } from '../objects/callable.js';\nimport Memo from '../objects/memo.js';\nimport { callStack } from './debugger.js';\n/* IMPORT */\n/* MAIN */\n/**\n * Creates a memoized computed value that automatically tracks its dependencies.\n *\n * Unlike React's useMemo, this function does NOT require a dependency array.\n * Dependencies are automatically tracked when accessed within the memo function\n * using the `$()` syntax.\n *\n * @example\n * ```typescript\n * // ✅ Correct Woby/Soby pattern - no dependency array needed\n * const doubled = memo(() => {\n * return $(count) * 2 // Automatically tracks 'count' as a dependency\n * })\n *\n * // ❌ React pattern - DO NOT use dependency arrays in Woby/Soby\n * const doubled = memo(() => {\n * return $(count) * 2\n * }, [count]) // This array will be ignored!\n * ```\n *\n * @param fn - The function to compute the memoized value. Dependencies are automatically tracked\n * when observables are accessed using `$()` within this function.\n * @param options - Optional memo options (NOT a dependencies array)\n * @returns An observable readonly value that updates when its dependencies change\n *\n * @see {@link effect} for creating side effects\n * @see {@link $} for accessing observable values\n */\nconst memo = (fn, options) => {\n const stack = options?.stack ?? callStack();\n if (isObservableFrozen(fn)) {\n return fn;\n }\n else if (isUntracked(fn)) {\n return frozen(fn(stack));\n }\n else {\n const memo = new Memo(fn, options);\n const observable = readable(memo.observable, stack);\n return observable;\n }\n};\n/* EXPORT */\nexport default memo;\n","/* IMPORT */\nimport isObservableBoolean from './is_observable_boolean.js';\nimport isObservableFrozen from './is_observable_frozen.js';\nimport isUntracked from './is_untracked.js';\nimport memo from './memo.js';\nimport { SYMBOL_OBSERVABLE_BOOLEAN } from '../symbols.js';\nimport { isFunction } from '../utils.js';\n/* MAIN */\nconst boolean = (value) => {\n if (isFunction(value)) {\n if (isObservableFrozen(value) || isUntracked(value)) {\n return !!value();\n }\n else if (isObservableBoolean(value)) {\n return value;\n }\n else {\n const boolean = memo(() => !!value());\n boolean[SYMBOL_OBSERVABLE_BOOLEAN] = true;\n return boolean;\n }\n }\n else {\n return !!value;\n }\n};\n/* EXPORT */\nexport default boolean;\n","/* IMPORT */\nimport cleanup from './cleanup.js';\nimport { readable } from '../objects/callable.js';\nimport Observable from '../objects/observable.js';\n/* MAIN */\nconst disposed = (stack) => {\n const observable = new Observable(false);\n const toggle = () => observable.set(true);\n // Register the cleanup in the current context\n // This ensures that when the context is disposed/re-run, the observable is updated\n cleanup(toggle);\n return readable(observable);\n};\n/* EXPORT */\nexport default disposed;\n","/* IMPORT */\nimport memo from './memo.js';\nimport { frozen } from '../objects/callable.js';\nimport { SYMBOL_OBSERVABLE, SYMBOL_UNTRACKED, SYMBOL_UNTRACKED_UNWRAPPED } from '../symbols.js';\nimport { isFunction } from '../utils.js';\nfunction resolve(value) {\n if (isFunction(value)) {\n if (SYMBOL_UNTRACKED_UNWRAPPED in value) {\n return resolve(value());\n }\n else if (SYMBOL_UNTRACKED in value) {\n return frozen(resolve(value()));\n }\n else if (SYMBOL_OBSERVABLE in value) {\n return value;\n }\n else {\n return memo(() => resolve(value()));\n }\n }\n if (value instanceof Array) {\n const resolved = new Array(value.length);\n for (let i = 0, l = resolved.length; i < l; i++) {\n resolved[i] = resolve(value[i]);\n }\n return resolved;\n }\n else {\n return value;\n }\n}\n/* EXPORT */\nexport default resolve;\n","/* IMPORT */\nimport { OWNER } from '../objects/superroot.js';\nimport { lazySetAdd, lazySetDelete } from '../lazy.js';\nimport cleanup from './cleanup.js';\nimport resolve from './resolve.js';\nimport { frozen, readable } from '../objects/callable.js';\nimport Observable from '../objects/observable.js';\nimport Root from '../objects/root.js';\nimport { SYMBOL_CACHED, SYMBOL_SUSPENSE, SYMBOL_UNCACHED } from '../symbols.js';\nimport { callStack } from './debugger.js';\n/* HELPERS */\nconst DUMMY_INDEX = frozen(-1);\nclass MappedRoot extends Root {\n}\n/* MAIN */\nclass CacheKeyed {\n /* CONSTRUCTOR */\n constructor(fn) {\n /* VARIABLES */\n this.parent = OWNER;\n this.suspense = OWNER.get(SYMBOL_SUSPENSE);\n this.cache = new Map();\n this.bool = false; // The bool is flipped with each iteration, the roots that don't have the updated one are disposed, it's like a cheap counter basically\n this.prevCount = 0; // Number of previous items\n this.reuseCount = 0; // Number of previous items that got reused\n this.nextCount = 0; // Number of next items\n /* API */\n this.cleanup = () => {\n if (!this.prevCount)\n return; // There was nothing before, no need to cleanup\n if (this.prevCount === this.reuseCount)\n return; // All the previous items were reused, no need to cleanup\n const { cache, bool } = this;\n if (!cache.size)\n return; // Nothing to dispose of\n if (this.nextCount) { // Regular cleanup\n cache.forEach((mapped, value) => {\n if (mapped.bool === bool)\n return;\n mapped.dispose(true);\n cache.delete(value);\n });\n }\n else { // There is nothing after, disposing quickly\n this.cache.forEach(mapped => {\n mapped.dispose(true);\n });\n this.cache = new Map();\n }\n };\n this.dispose = () => {\n if (this.suspense) {\n lazySetDelete(this.parent, 'roots', this.roots);\n }\n this.prevCount = this.cache.size;\n this.reuseCount = 0;\n this.nextCount = 0;\n this.cleanup();\n };\n this.before = () => {\n this.bool = !this.bool;\n this.reuseCount = 0;\n this.nextCount = 0;\n };\n this.after = (values) => {\n this.nextCount = values.length;\n this.cleanup();\n this.prevCount = this.nextCount;\n this.reuseCount = 0;\n };\n this.map = (values) => {\n this.before();\n const { cache, bool, fn, fnWithIndex } = this;\n const results = new Array(values.length);\n let resultsCached = true; // Whether all results are cached, if so this enables an optimization\n let resultsUncached = true; // Whether all results are anew, if so this enables an optimization in Voby\n let reuseCount = 0;\n const stack = callStack();\n for (let i = 0, l = values.length; i < l; i++) {\n const value = values[i];\n const cached = cache.get(value);\n if (cached && cached.bool !== bool) {\n resultsUncached = false;\n reuseCount += 1;\n cached.bool = bool;\n cached.index?.set(i);\n results[i] = cached.result; //TSC\n }\n else {\n resultsCached = false;\n const mapped = new MappedRoot(false);\n if (cached) {\n cleanup(() => mapped.dispose(true));\n }\n mapped.wrap(() => {\n let index = DUMMY_INDEX;\n if (fnWithIndex) {\n mapped.index = new Observable(i);\n index = readable(mapped.index, stack);\n }\n const result = results[i] = resolve(fn(value, index));\n mapped.bool = bool;\n mapped.result = result;\n if (!cached) {\n cache.set(value, mapped);\n }\n }, undefined, undefined, stack);\n }\n }\n this.reuseCount = reuseCount;\n this.after(values);\n if (resultsCached) {\n results[SYMBOL_CACHED] = true;\n }\n if (resultsUncached) {\n results[SYMBOL_UNCACHED] = true;\n }\n return results;\n };\n this.roots = () => {\n return Array.from(this.cache.values());\n };\n this.fn = fn;\n this.fnWithIndex = (fn.length > 1);\n if (this.suspense) {\n lazySetAdd(this.parent, 'roots', this.roots);\n }\n }\n}\n/* EXPORT */\nexport default CacheKeyed;\n","/* IMPORT */\nimport { OWNER } from './superroot.js';\nimport { DIRTY_MAYBE_YES, DIRTY_YES } from '../constants.js';\nimport { lazyArrayEach, lazyArrayPush, lazySetEach } from '../lazy.js';\nimport Effect from './effect.js';\nimport Owner from './owner.js';\nimport { SYMBOL_SUSPENSE } from '../symbols.js';\nimport { isFunction } from '../utils.js';\nimport { callStack, Stack } from '../methods/debugger.js';\n/* MAIN */\nclass Suspense extends Owner {\n /* CONSTRUCTOR */\n constructor() {\n super();\n /* VARIABLES */\n this.parent = OWNER;\n this.context = { ...OWNER.context, [SYMBOL_SUSPENSE]: this };\n lazyArrayPush(this.parent, 'suspenses', this);\n this.suspended = (OWNER.get(SYMBOL_SUSPENSE)?.suspended || 0);\n }\n /* API */\n toggle(force) {\n if (!this.suspended && !force)\n return; // Already suspended, this can happen at instantion time\n const suspendedPrev = this.suspended;\n const suspendedNext = suspendedPrev + (force ? 1 : -1);\n this.suspended = suspendedNext;\n if (!!suspendedPrev === !!suspendedNext)\n return; // Same state, nothing to pause or resume\n /* NOTIFYING OBSERVERS, ROOTS AND SUSPENSES */\n const stack = callStack();\n this.observable?.set(!!suspendedNext);\n const notifyOwner = (owner) => {\n lazyArrayEach(owner.contexts, notifyOwner);\n lazyArrayEach(owner.observers, notifyObserver);\n lazyArrayEach(owner.suspenses, notifySuspense);\n lazySetEach(owner.roots, notifyRoot);\n };\n const notifyObserver = (observer) => {\n if (observer instanceof Effect) {\n if (observer.status === DIRTY_MAYBE_YES || observer.status === DIRTY_YES) {\n if (observer.init) {\n observer.update(stack);\n }\n else {\n observer.schedule(stack);\n }\n }\n }\n notifyOwner(observer);\n };\n const notifyRoot = (root) => {\n if (isFunction(root)) {\n root().forEach(notifyOwner);\n }\n else {\n notifyOwner(root);\n }\n };\n const notifySuspense = (suspense) => {\n suspense.toggle(force);\n };\n notifyOwner(this);\n }\n wrap(fn, owner, observer, stack) {\n return super.wrap(fn, this, undefined, stack);\n }\n}\n/* EXPORT */\nexport default Suspense;\n","/* IMPORT */\nimport boolean from './boolean.js';\nimport effect from './effect.js';\nimport get from './get.js';\nimport Suspense from '../objects/suspense.js';\nimport { Stack } from './debugger.js';\n/* MAIN */\nconst suspense = (when, fn, stack) => {\n const suspense = new Suspense();\n const condition = boolean(when);\n const toggle = () => suspense.toggle(get(condition));\n effect(toggle, { sync: true, stack: stack });\n return suspense.wrap(fn, undefined, undefined, stack);\n};\n/* EXPORT */\nexport default suspense;\n","/* IMPORT */\nimport { OWNER } from '../objects/superroot.js';\nimport { lazySetAdd, lazySetDelete } from '../lazy.js';\nimport cleanup from './cleanup.js';\nimport get from './get.js';\nimport memo from './memo.js';\nimport resolve from './resolve.js';\nimport suspense from './suspense.js';\nimport { frozen, readable } from '../objects/callable.js';\nimport Observable from '../objects/observable.js';\nimport Root from '../objects/root.js';\nimport { SYMBOL_CACHED, SYMBOL_SUSPENSE, SYMBOL_UNCACHED } from '../symbols.js';\nimport { callStack } from './debugger.js';\n/* HELPERS */\nconst DUMMY_INDEX = frozen(-1);\nclass MappedRoot extends Root {\n}\n/* MAIN */\n//TODO: Optimize this more\nclass CacheUnkeyed {\n /* CONSTRUCTOR */\n constructor(fn, pooled) {\n /* VARIABLES */\n this.parent = OWNER;\n this.suspense = OWNER.get(SYMBOL_SUSPENSE);\n this.cache = new Map();\n this.pool = [];\n this.poolMaxSize = 0;\n /* API */\n this.cleanup = () => {\n let pooled = 0;\n let poolable = Math.max(0, this.pooled ? this.poolMaxSize - this.pool.length : 0);\n // const stack = callStack()\n this.cache.forEach(mapped => {\n if (poolable > 0 && pooled++ < poolable) {\n mapped.suspended?.set(true);\n this.pool.push(mapped);\n }\n else {\n mapped.dispose(true);\n }\n });\n };\n this.dispose = () => {\n if (this.suspense) {\n lazySetDelete(this.parent, 'roots', this.roots);\n }\n this.cache.forEach(mapped => {\n mapped.dispose(true);\n });\n this.pool.forEach(mapped => {\n mapped.dispose(true);\n });\n };\n this.map = (values) => {\n const { cache, fn, fnWithIndex } = this;\n const cacheNext = new Map();\n const results = new Array(values.length);\n const pool = this.pool;\n const pooled = this.pooled;\n let resultsCached = true; // Whether all results are cached, if so this enables an optimization\n let resultsUncached = true; // Whether all results are anew, if so this enables an optimization in Voby\n let leftovers = [];\n const stack = callStack();\n if (cache.size) {\n for (let i = 0, l = values.length; i < l; i++) {\n const value = values[i];\n const cached = cache.get(value);\n if (cached) {\n resultsUncached = false;\n cache.delete(value);\n cacheNext.set(value, cached);\n cached.index?.set(i);\n results[i] = cached.result; //TSC\n }\n else {\n leftovers.push(i);\n }\n }\n }\n else {\n leftovers = new Array(results.length);\n }\n outer: for (let i = 0, l = leftovers.length; i < l; i++) {\n const index = leftovers[i] || i;\n const value = values[index];\n const isDuplicate = cacheNext.has(value);\n if (!isDuplicate) {\n for (const [key, mapped] of cache.entries()) {\n cache.delete(key);\n cacheNext.set(value, mapped);\n mapped.index?.set(index);\n mapped.value?.set(value);\n results[index] = mapped.result; //TSC\n continue outer;\n }\n }\n resultsCached = false;\n let mapped;\n if (pooled && pool.length) {\n mapped = pool.pop(); //TSC\n mapped.index?.set(index);\n mapped.value?.set(value);\n mapped.suspended?.set(false);\n results[index] = mapped.result; //TSC\n }\n else {\n mapped = new MappedRoot(false);\n mapped.wrap(() => {\n let $index = DUMMY_INDEX;\n if (fnWithIndex) {\n mapped.index = new Observable(index);\n $index = readable(mapped.index, stack);\n }\n const observable = mapped.value = new Observable(value);\n const suspended = pooled ? new Observable(false) : undefined;\n if (suspended)\n suspended.stack = stack;\n const $value = memo(() => get(observable.get())); //TSC\n const result = results[index] = suspended ? suspense(() => suspended.get(), () => resolve(fn($value, $index)), stack) : resolve(fn($value, $index));\n mapped.value = observable;\n mapped.result = result;\n mapped.suspended = suspended;\n }, undefined, undefined, stack);\n }\n if (isDuplicate) { // Expensive, not reusable\n cleanup(() => mapped.dispose(true));\n }\n else { // Cheap, reusable\n cacheNext.set(value, mapped);\n }\n }\n this.poolMaxSize = Math.max(this.poolMaxSize, results.length);\n this.cleanup();\n this.cache = cacheNext;\n if (resultsCached) {\n results[SYMBOL_CACHED] = true;\n }\n if (resultsUncached) {\n results[SYMBOL_UNCACHED] = true;\n }\n return results;\n };\n this.roots = () => {\n return [...this.cache.values(), ...this.pool.values()];\n };\n this.fn = fn;\n this.fnWithIndex = (fn.length > 1);\n this.pooled = pooled;\n if (this.suspense) {\n lazySetAdd(this.parent, 'roots', this.roots);\n }\n }\n}\n/* EXPORT */\nexport default CacheUnkeyed;\n","/* IMPORT */\nimport cleanup from './cleanup.js';\nimport CacheKeyed from './for.cache.keyed.js';\nimport CacheUnkeyed from './for.cache.unkeyed.js';\nimport get from './get.js';\nimport isObservable from './is_observable.js';\nimport isStore from './is_store.js';\nimport memo from './memo.js';\nimport resolve from './resolve.js';\nimport untrack from './untrack.js';\nimport { frozen } from '../objects/callable.js';\nimport { SYMBOL_CACHED, SYMBOL_STORE_VALUES } from '../symbols.js';\nimport { isArray, isEqual } from '../utils.js';\nimport { callStack } from './debugger.js';\nfunction _for(values, fn, fallback = [], options) {\n const stack = callStack();\n if (isArray(values) && !isStore(values)) { // Fast path for plain arrays\n const isUnkeyed = !!options?.unkeyed;\n return frozen(untrack(() => {\n if (values.length) {\n return values.map((value, index) => {\n return resolve(fn(isUnkeyed && !isObservable(value) ? frozen(value) : value, index));\n });\n }\n else {\n return resolve(fallback);\n }\n }));\n }\n else { // Regular path\n const { dispose, map } = options?.unkeyed ? new CacheUnkeyed(fn, !!options.pooled) : new CacheKeyed(fn); //TSC\n cleanup(dispose);\n const value = memo(() => {\n return get(values) ?? [];\n }, {\n equals: (next, prev) => {\n return !!next && !!prev && !next.length && !prev.length && !isStore(next) && !isStore(prev);\n },\n stack\n });\n return memo(() => {\n const array = value();\n if (isStore(array)) {\n array[SYMBOL_STORE_VALUES];\n }\n return untrack(() => {\n const results = map(array);\n return results?.length ? results : resolve(fallback);\n });\n }, {\n equals: (next, prev) => {\n return isArray(next) && !!next[SYMBOL_CACHED] && isArray(prev) && isEqual(next, prev);\n },\n stack\n });\n }\n}\n/* EXPORT */\nexport default _for;\n","/* IMPORT */\nimport untrack from './untrack.js';\n/* MAIN */\n// This function ensures an Observable contains a fresh value, mainly to try to push it into a frozen state, if possible\nconst warmup = (value) => {\n untrack(value);\n return value;\n};\n/* EXPORT */\nexport default warmup;\n","/* IMPORT */\nimport get from './get.js';\nimport isObservableBoolean from './is_observable_boolean.js';\nimport isObservableFrozen from './is_observable_frozen.js';\nimport isUntracked from './is_untracked.js';\nimport memo from './memo.js';\nimport resolve from './resolve.js';\nimport warmup from './warmup.js';\nimport { frozen } from '../objects/callable.js';\nimport { is, isFunction } from '../utils.js';\n/* HELPERS */\nconst match = (condition, values, fallback) => {\n for (let i = 0, l = values.length; i < l; i++) {\n const value = values[i];\n if (value.length === 1)\n return value[0];\n if (is(value[0], condition))\n return value[1];\n }\n return fallback;\n};\nfunction _switch(when, values, fallback) {\n const isDynamic = isFunction(when) && !isObservableFrozen(when) && !isUntracked(when);\n if (isDynamic) {\n if (isObservableBoolean(when)) {\n return memo(() => resolve(match(when(), values, fallback)));\n }\n const value = warmup(memo(() => match(when(), values, fallback)));\n if (isObservableFrozen(value)) {\n return frozen(resolve(value()));\n }\n else {\n return memo(() => resolve(get(value)));\n }\n }\n else {\n const value = match(get(when), values, fallback);\n return frozen(resolve(value));\n }\n}\n/* EXPORT */\nexport default _switch;\n","/* IMPORT */\nimport boolean from './boolean.js';\nimport _switch from './switch.js';\n/* MAIN */\nconst ternary = (when, valueTrue, valueFalse) => {\n const condition = boolean(when);\n return _switch(condition, [[true, valueTrue], [valueFalse]]);\n};\n/* EXPORT */\nexport default ternary;\n","/* IMPORT */\nimport { writable } from '../objects/callable.js';\nimport ObservableClass from '../objects/observable.js';\nimport { callStack } from './debugger.js';\nfunction observable(value, options) {\n const stack = callStack();\n return writable(new ObservableClass(value, options), stack);\n}\n/* EXPORT */\nexport default observable;\n","/* IMPORT */\nimport { SYMBOL_OBSERVABLE_WRITABLE } from '../symbols.js';\nimport { isFunction } from '../utils.js';\n/* MAIN */\nconst isObservableWritable = (value) => {\n return isFunction(value) && (SYMBOL_OBSERVABLE_WRITABLE in value);\n};\n/* EXPORT */\nexport default isObservableWritable;\n","/* IMPORT */\nimport { UNAVAILABLE } from '../constants.js';\nimport { SYMBOL_OBSERVABLE_READABLE, SYMBOL_OBSERVABLE_WRITABLE } from '../symbols.js';\nimport { isFunction } from '../utils.js';\n/* MAIN */\nconst target = (observable) => {\n if (isFunction(observable)) {\n return observable[SYMBOL_OBSERVABLE_READABLE] || observable[SYMBOL_OBSERVABLE_WRITABLE] || UNAVAILABLE;\n }\n else {\n return observable;\n }\n};\n/* EXPORT */\nexport default target;\n","/* IMPORT */\nimport isObservableWritable from './is_observable_writable.js';\nimport target from './target.js';\nimport { readable } from '../objects/callable.js';\n/* MAIN */\nconst readonly = (observable, stack) => {\n if (isObservableWritable(observable)) {\n return readable(target(observable), stack);\n }\n else {\n return observable;\n }\n};\n/* EXPORT */\nexport default readonly;\n","/* IMPORT */\nimport { OBSERVABLE_FALSE, OBSERVABLE_TRUE } from '../constants.js';\nimport cleanup from './cleanup.js';\nimport effect from './effect.js';\nimport isObservableFrozen from './is_observable_frozen.js';\nimport memo from './memo.js';\nimport untrack from './untrack.js';\nimport warmup from './warmup.js';\nimport { readable } from '../objects/callable.js';\nimport Observable from '../objects/observable.js';\nimport { is } from '../utils.js';\n/* HELPERS */\nconst isEqualForSelector = (a, b) => {\n // Treat 0 and -0 as equal for selector purposes\n if ((a === 0 || is(a, -0)) && (b === 0 || is(b, -0)))\n return true;\n return is(a, b);\n};\nimport { callStack, Stack } from './debugger.js';\n/* HELPERS */\nclass DisposableMap extends Map {\n constructor() {\n super(...arguments);\n this.disposed = false;\n }\n}\nclass SelectedObservable extends Observable {\n constructor() {\n super(...arguments);\n this.count = 1;\n }\n /* API */\n call() {\n if (this.selecteds.disposed)\n return;\n this.count -= 1;\n if (this.count)\n return;\n this.selecteds.delete(this.source);\n }\n}\n/* MAIN */\nconst selector = (source) => {\n /* NORMALIZING SOURCE */\n source = warmup(memo(source));\n /* FROZEN SOURCE */\n if (isObservableFrozen(source)) {\n const sourceValue = untrack(source);\n return (value) => {\n return (isEqualForSelector(value, sourceValue)) ? OBSERVABLE_TRUE : OBSERVABLE_FALSE;\n };\n }\n /* SELECTEDS */\n let selecteds = new DisposableMap();\n let selectedValue = untrack(source);\n const stack = callStack();\n effect((stack) => {\n const valuePrev = selectedValue;\n const valueNext = source();\n if (isEqualForSelector(valuePrev, valueNext))\n return;\n selectedValue = valueNext;\n selecteds.get(valuePrev)?.set(false);\n selecteds.get(valueNext)?.set(true);\n }, { suspense: false, sync: true, stack });\n /* CLEANUP ALL */\n const cleanupAll = () => {\n selecteds.disposed = true;\n };\n cleanup(cleanupAll);\n /* SELECTOR */\n return (value) => {\n /* INIT */\n let selected = selecteds.get(value);\n if (selected) {\n selected.count += 1;\n }\n else {\n const isSelected = isEqualForSelector(value, selectedValue);\n selected = new SelectedObservable(isSelected);\n selected.selecteds = selecteds;\n selected.source = value;\n selecteds.set(value, selected);\n }\n /* CLEANUP */\n cleanup(selected);\n /* RETURN */\n return readable(selected);\n };\n};\n/* EXPORT */\nexport default selector;\n","/* IMPORT */\nimport { OBSERVABLE_FALSE } from '../constants.js';\nimport { OWNER } from '../objects/superroot.js';\nimport { readable } from '../objects/callable.js';\nimport Observable from '../objects/observable.js';\nimport { SYMBOL_SUSPENSE } from '../symbols.js';\n/* MAIN */\nconst suspended = (stack) => {\n const suspense = OWNER.get(SYMBOL_SUSPENSE);\n if (!suspense)\n return OBSERVABLE_FALSE;\n const observable = (suspense.observable || (suspense.observable = new Observable(!!suspense.suspended)));\n return readable(observable, stack);\n};\n/* EXPORT */\nexport default suspended;\n","/* IMPORT */\nimport Scheduler from '../objects/scheduler.async.js';\nimport { Stack } from './debugger.js';\n/* MAIN */\nconst tick = (stack) => {\n Scheduler.flush(stack);\n};\n/* EXPORT */\nexport default tick;\n","/* IMPORT */\nimport { OWNER } from '../objects/superroot.js';\nimport memo from './memo.js';\nimport $ from './observable.js';\nimport resolve from './resolve.js';\n/* MAIN */\nconst tryCatch = (value, fn) => {\n const observable = $();\n return memo((stack) => {\n const error = observable();\n if (error) {\n const reset = () => observable(undefined);\n const options = { error, reset };\n return resolve(fn(options));\n }\n else {\n OWNER.errorHandler = observable;\n return resolve(value);\n }\n });\n};\n/* EXPORT */\nexport default tryCatch;\n","/* IMPORT */\nimport untrack from './untrack.js';\nimport { SYMBOL_UNTRACKED } from '../symbols.js';\nimport { isFunction } from '../utils.js';\nfunction untracked(fn) {\n const untracked = isFunction(fn) ? (...args) => untrack(() => fn(...args)) : () => fn;\n untracked[SYMBOL_UNTRACKED] = true;\n return untracked;\n}\n/* EXPORT */\nexport default untracked;\n","import { ObservableMaybe } from \"../types\"\r\nimport { jsx } from \"../jsx-runtime\"\r\nimport { DEBUGGER } from \"soby\"\r\n\r\nexport const mark = (msg: string, ref: ObservableMaybe<Node | null>) => DEBUGGER.verboseComment ?\r\n jsx('comment', { ref, data: msg }) : jsx('text', { ref })","/**\n * Custom Element Implementation for Woby Framework\n * \n * This module provides functionality to create custom HTML elements with reactive properties\n * that integrate seamlessly with the Woby framework's observable system. Custom elements\n * created with this API can be used both in JSX/TSX and directly in HTML.\n * \n * Features:\n * - Automatic attribute to prop mapping\n * - Type conversion for observable props\n * - Nested property support (e.g., 'nested$prop$value' or 'nested.prop.value' in HTML, 'nested$prop$value' in JSX)\n * - Style property support (e.g., 'style$font-size' or 'style.font-size' in HTML, 'style$font-size' in JSX)\n * - Automatic kebab-case to camelCase conversion for all property names\n * - Automatic exclusion of properties with { toHtml: () => undefined } from HTML attributes\n * - Shadow DOM encapsulation with optional stylesheet adoption\n * - Context support for custom elements\n * - Custom serialization using toHtml and fromHtml options\n * \n * Style Encapsulation Options:\n * - ignoreStyle: Set to true to prevent adoption of global stylesheets in shadow DOM\n * \n * @module customElement\n */\n\nimport { $, $$, } from \"../methods/soby\"\nimport { isObservable } from \"soby\"\nimport { useEffect } from \"../hooks\"\nimport { ObservableMaybe } from \"../types\"\nimport { mark } from \"../utils/mark\"\n\nexport const useAttached = (ref?: ObservableMaybe<Node | null>, match?: (parent: Node | null) => boolean) => {\n const isGiven = !!ref\n\n if (!ref)\n ref = $<Node>()\n\n const parent = $<Node | null>(null)\n\n const fn = () => {\n if (!$$(ref)) return\n\n const updateParent = () => {\n let currentParent: Node | null = $$(ref)?.parentNode || null\n\n // If match function is provided, traverse up until match or root\n if (match) {\n while (currentParent) {\n if (match(currentParent)) {\n parent(currentParent)\n return !!currentParent\n }\n // traversed through assignedSlot 1st, \n currentParent = (currentParent as HTMLElement).assignedSlot ?? currentParent.parentNode ?? (currentParent as ShadowRoot).host\n }\n // If no match found, parent remains null\n parent(null)\n return false\n } else {\n // Default behavior: return immediate parent\n parent(currentParent)\n return !!currentParent\n }\n }\n\n // Initial parent check\n if (updateParent()) return\n\n const callback: MutationCallback = (mutationsList, observer) => {\n if (mutationsList[0]?.type === 'childList') {\n // Check nodes that were added\n if (updateParent()) {\n observer.disconnect()\n return\n }\n }\n // Cleanup observer on unmount\n // return () => observer.disconnect()\n }\n\n const observer = new MutationObserver(callback)\n\n // 5. Configuration options\n const config: MutationObserverInit = {\n childList: true, // Crucial: Watch for children being added/removed\n subtree: true // Optional: Watch all descendants, not just direct children\n }\n\n // 6. Start observing\n observer.observe(document, config)\n\n return () => observer.disconnect()\n }\n\n if (isObservable(ref))\n useEffect(fn)\n else\n fn()\n\n // Return the reference node\n return {\n parent,\n mount: isGiven ? undefined : mark('attached', ref),\n ref\n }\n}\n\n\n// export const isLightDom = (node: Node) =>\n// useMemo(() => $$(useAttached(node, (parent): parent is Element => !!parent && 'shadowRoot' in parent).parent))\nexport const useLightDom = (ref?: ObservableMaybe<Node | null>) => {\n // const { parent, mount, ref: r } = useAttached(ref, (parent): parent is Element => (!!(parent as Element).shadowRoot && !!parent.parentElement?.assignedSlot))\n const { parent, mount, ref: r } = useAttached(ref, (parent): parent is Element => !!(parent as Element).assignedSlot)\n // const lightDom = useMemo(() => $$(parent)?.parentElement)\n\n // // Observable to track if slot is assigned\n // const slotAssigned = $<boolean>(false)\n\n // // Effect to observe shadow root and slot changes\n // useEffect(() => {\n // const lightDomElement = $$(lightDom)\n // if (!lightDomElement?.parentElement) return\n\n // const parentElement = lightDomElement.parentElement\n // let shadowRoot: ShadowRoot | null = null\n\n // // Function to check if shadow root is ready\n // const checkShadowRoot = () => {\n // shadowRoot = parentElement.shadowRoot\n // if (shadowRoot) {\n // // Shadow root is ready, now observe for slots\n // observeSlots()\n // return true\n // }\n // return false\n // }\n\n // // Function to observe slots\n // const observeSlots = () => {\n // if (!shadowRoot) return\n\n // // Check if there are already slots\n // const slots = Array.from(shadowRoot.querySelectorAll('slot'))\n // if (slots.length > 0) {\n // // Slots exist, start listening to slot change events\n // listenToSlotChanges(slots)\n // return\n // }\n\n // // No slots yet, observe for when they are added\n // const slotObserver = new MutationObserver((mutations) => {\n // for (const mutation of mutations) {\n // if (mutation.type === 'childList') {\n // mutation.addedNodes.forEach((node) => {\n // if (node.nodeName === 'SLOT') {\n // // Slot added, start listening to slot change events\n // slotObserver.disconnect()\n // listenToSlotChanges([node as HTMLSlotElement])\n // }\n // })\n // }\n // }\n // })\n\n // slotObserver.observe(shadowRoot, { childList: true, subtree: true })\n\n // // Cleanup slot observer\n // return () => slotObserver.disconnect()\n // }\n\n // // Function to listen to slot change events\n // const listenToSlotChanges = (slots: Node[]) => {\n // const slotElements: HTMLSlotElement[] = []\n // for (const slot of slots) {\n // if (slot instanceof HTMLSlotElement) {\n // slotElements.push(slot)\n // // Add event listener for slot change\n // slot.addEventListener('slotchange', () => {\n // // Update slot assigned observable\n // slotAssigned(true)\n // })\n // }\n // }\n\n // // // Initial check for assigned nodes\n // // for (const slot of slotElements) {\n // // if (slot.assignedNodes().length > 0) {\n // // slotAssigned(true)\n // // break\n // // }\n // // }\n // }\n\n // // Check if shadow root is already ready\n // if (!checkShadowRoot()) {\n // // Shadow root not ready yet, observe for when it becomes available\n // const shadowObserver = new MutationObserver(() => {\n // if (checkShadowRoot()) {\n // shadowObserver.disconnect()\n // }\n // })\n\n // shadowObserver.observe(parentElement, { attributes: true })\n\n // // Cleanup shadow observer\n // return () => shadowObserver.disconnect()\n // }\n // })\n\n return { lightDom: parent, mount, ref: r }\n}","\r\n\r\nimport { isObservable } from '../methods/soby'\r\nimport { isArray, isFunction } from '../utils/lang'\r\nimport type { FN, ObservableReadonly } from '../types'\r\n\r\n/* HELPERS */\r\n\r\ntype F<T> = T extends () => infer U ? U : T\r\ntype O<T> = T extends ObservableReadonly<infer U> ? U : T\r\n\r\n\r\n//TODO: Maybe port this to soby, as \"resolved\"\r\n\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8, T9>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8, T9], resolveFunction?: true): [F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>, F<T7>, F<T8>, F<T9>]\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8], resolveFunction?: true): [F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>, F<T7>, F<T8>]\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7>(value: readonly [T1, T2, T3, T4, T5, T6, T7], resolveFunction?: true): [F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>, F<T7>]\r\nexport function useResolved<T1, T2, T3, T4, T5, T6>(value: readonly [T1, T2, T3, T4, T5, T6], resolveFunction?: true): [F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>]\r\nexport function useResolved<T1, T2, T3, T4, T5>(value: readonly [T1, T2, T3, T4, T5], resolveFunction?: true): [F<T1>, F<T2>, F<T3>, F<T4>, F<T5>]\r\nexport function useResolved<T1, T2, T3, T4>(value: readonly [T1, T2, T3, T4], resolveFunction?: true): [F<T1>, F<T2>, F<T3>, F<T4>]\r\nexport function useResolved<T1, T2, T3>(value: readonly [T1, T2, T3], resolveFunction?: true): [F<T1>, F<T2>, F<T3>]\r\nexport function useResolved<T1, T2>(value: readonly [T1, T2], resolveFunction?: true): [F<T1>, F<T2>]\r\nexport function useResolved<T1>(value: readonly [T1], resolveFunction?: true): [F<T1>]\r\nexport function useResolved(value: readonly [], resolveFunction?: true): []\r\n\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8, T9>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8, T9], resolveFunction: false): [O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>, O<T7>, O<T8>, O<T9>]\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8], resolveFunction: false): [O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>, O<T7>, O<T8>]\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7>(value: readonly [T1, T2, T3, T4, T5, T6, T7], resolveFunction: false): [O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>, O<T7>]\r\nexport function useResolved<T1, T2, T3, T4, T5, T6>(value: readonly [T1, T2, T3, T4, T5, T6], resolveFunction: false): [O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>]\r\nexport function useResolved<T1, T2, T3, T4, T5>(value: readonly [T1, T2, T3, T4, T5], resolveFunction: false): [O<T1>, O<T2>, O<T3>, O<T4>, O<T5>]\r\nexport function useResolved<T1, T2, T3, T4>(value: readonly [T1, T2, T3, T4], resolveFunction: false): [O<T1>, O<T2>, O<T3>, O<T4>]\r\nexport function useResolved<T1, T2, T3>(value: readonly [T1, T2, T3], resolveFunction: false): [O<T1>, O<T2>, O<T3>]\r\nexport function useResolved<T1, T2>(value: readonly [T1, T2], resolveFunction: false): [O<T1>, O<T2>]\r\nexport function useResolved<T1>(value: readonly [T1], resolveFunction: false): [O<T1>]\r\nexport function useResolved(value: readonly [], resolveFunction: false): []\r\n\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8, T9, R>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8, T9], callback: FN<[F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>, F<T7>, F<T8>, F<T9>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8, R>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8], callback: FN<[F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>, F<T7>, F<T8>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, R>(value: readonly [T1, T2, T3, T4, T5, T6, T7], callback: FN<[F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>, F<T7>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, R>(value: readonly [T1, T2, T3, T4, T5, T6], callback: FN<[F<T1>, F<T2>, F<T3>, F<T4>, F<T5>, F<T6>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, T3, T4, T5, R>(value: readonly [T1, T2, T3, T4, T5], callback: FN<[F<T1>, F<T2>, F<T3>, F<T4>, F<T5>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, T3, T4, R>(value: readonly [T1, T2, T3, T4], callback: FN<[F<T1>, F<T2>, F<T3>, F<T4>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, T3, R>(value: readonly [T1, T2, T3], callback: FN<[F<T1>, F<T2>, F<T3>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, T2, R>(value: readonly [T1, T2], callback: FN<[F<T1>, F<T2>], R>, resolveFunction?: true): R\r\nexport function useResolved<T1, R>(value: readonly [T1], callback: FN<[F<T1>], R>, resolveFunction?: true): R\r\nexport function useResolved<R>(value: readonly [], callback: FN<[], R>, resolveFunction?: true): R\r\n\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8, T9, R>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8, T9], callback: FN<[O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>, O<T7>, O<T8>, O<T9>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, T8, R>(value: readonly [T1, T2, T3, T4, T5, T6, T7, T8], callback: FN<[O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>, O<T7>, O<T8>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, T7, R>(value: readonly [T1, T2, T3, T4, T5, T6, T7], callback: FN<[O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>, O<T7>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, T3, T4, T5, T6, R>(value: readonly [T1, T2, T3, T4, T5, T6], callback: FN<[O<T1>, O<T2>, O<T3>, O<T4>, O<T5>, O<T6>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, T3, T4, T5, R>(value: readonly [T1, T2, T3, T4, T5], callback: FN<[O<T1>, O<T2>, O<T3>, O<T4>, O<T5>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, T3, T4, R>(value: readonly [T1, T2, T3, T4], callback: FN<[O<T1>, O<T2>, O<T3>, O<T4>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, T3, R>(value: readonly [T1, T2, T3], callback: FN<[O<T1>, O<T2>, O<T3>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, T2, R>(value: readonly [T1, T2], callback: FN<[O<T1>, O<T2>], R>, resolveFunction: false): R\r\nexport function useResolved<T1, R>(value: readonly [T1], callback: FN<[O<T1>], R>, resolveFunction: false): R\r\nexport function useResolved<R>(value: readonly [], callback: FN<[], R>, resolveFunction: false): R\r\n\r\nexport function useResolved<T>(value: T, resolveFunction?: true): F<T>\r\nexport function useResolved<T>(value: T, resolveFunction: false): O<T>\r\n\r\nexport function useResolved<T, R>(value: T, callback: FN<[F<T>], R>, resolveFunction?: true): R\r\nexport func