@pyreon/vue-compat 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["pyreonComputed","pyreonNextTick","pyreonMount"],"sources":["../src/jsx-runtime.ts","../src/index.ts"],"sourcesContent":["/**\n * Compat JSX runtime for Vue compatibility mode.\n *\n * When `jsxImportSource` is redirected to `@pyreon/vue-compat` (via the vite\n * plugin's `compat: \"vue\"` option), OXC rewrites JSX to import from this file.\n *\n * For component VNodes, we wrap the component function so it returns a reactive\n * accessor — enabling Vue-style re-renders on state change while Pyreon's\n * existing renderer handles all DOM work.\n *\n * Key difference from react/preact compat: the component body runs inside\n * `runUntracked` to prevent `.value` reads (which access underlying signals)\n * from being tracked by the reactive accessor. Only the version signal\n * triggers re-renders.\n */\n\nimport type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'\nimport { Fragment, h, onUnmount } from '@pyreon/core'\nimport { runUntracked, signal } from '@pyreon/reactivity'\n\nexport { Fragment }\n\n// ─── Render context (used by hooks) ──────────────────────────────────────────\n\nexport interface RenderContext {\n hooks: unknown[]\n scheduleRerender: () => void\n /** Effect entries pending execution after render */\n pendingEffects: EffectEntry[]\n /** Layout effect entries pending execution after render */\n pendingLayoutEffects: EffectEntry[]\n /** Set to true when the component is unmounted */\n unmounted: boolean\n /** Callbacks to run on unmount (lifecycle + effect cleanups) */\n unmountCallbacks: (() => void)[]\n}\n\nexport interface EffectEntry {\n fn: () => (() => void) | void\n deps: unknown[] | undefined\n cleanup: (() => void) | undefined\n}\n\nlet _currentCtx: RenderContext | null = null\nlet _hookIndex = 0\n\nexport function getCurrentCtx(): RenderContext | null {\n return _currentCtx\n}\n\nexport function getHookIndex(): number {\n return _hookIndex++\n}\n\nexport function beginRender(ctx: RenderContext): void {\n _currentCtx = ctx\n _hookIndex = 0\n ctx.pendingEffects = []\n ctx.pendingLayoutEffects = []\n}\n\nexport function endRender(): void {\n _currentCtx = null\n _hookIndex = 0\n}\n\n// ─── Effect runners ──────────────────────────────────────────────────────────\n\nfunction runLayoutEffects(entries: EffectEntry[]): void {\n for (const entry of entries) {\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n}\n\nfunction scheduleEffects(ctx: RenderContext, entries: EffectEntry[]): void {\n if (entries.length === 0) return\n queueMicrotask(() => {\n for (const entry of entries) {\n if (ctx.unmounted) return\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n })\n}\n\n// ─── Component wrapping ──────────────────────────────────────────────────────\n\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\nfunction wrapCompatComponent(vueComponent: Function): ComponentFn {\n let wrapped = _wrapperCache.get(vueComponent)\n if (wrapped) return wrapped\n\n // The wrapper returns a reactive accessor (() => VNodeChild) which Pyreon's\n // mountChild treats as a reactive expression via mountReactive.\n wrapped = ((props: Props) => {\n const ctx: RenderContext = {\n hooks: [],\n scheduleRerender: () => {\n // Will be replaced below after version signal is created\n },\n pendingEffects: [],\n pendingLayoutEffects: [],\n unmounted: false,\n unmountCallbacks: [],\n }\n\n const version = signal(0)\n let updateScheduled = false\n\n ctx.scheduleRerender = () => {\n if (ctx.unmounted || updateScheduled) return\n updateScheduled = true\n queueMicrotask(() => {\n updateScheduled = false\n if (!ctx.unmounted) version.set(version.peek() + 1)\n })\n }\n\n // Register cleanup when component unmounts\n onUnmount(() => {\n ctx.unmounted = true\n for (const cb of ctx.unmountCallbacks) cb()\n })\n\n // Return reactive accessor — Pyreon's mountChild calls mountReactive\n return () => {\n version() // tracked read — triggers re-execution when state changes\n beginRender(ctx)\n // runUntracked prevents .value signal reads from being tracked by this accessor —\n // only the version signal should trigger re-renders\n const result = runUntracked(() => (vueComponent as ComponentFn)(props))\n const layoutEffects = ctx.pendingLayoutEffects\n const effects = ctx.pendingEffects\n endRender()\n\n runLayoutEffects(layoutEffects)\n scheduleEffects(ctx, effects)\n\n return result\n }\n }) as unknown as ComponentFn\n\n _wrapperCache.set(vueComponent, wrapped)\n return wrapped\n}\n\n// ─── JSX functions ───────────────────────────────────────────────────────────\n\nexport function jsx(\n type: string | ComponentFn | symbol,\n props: Props & { children?: VNodeChild | VNodeChild[] },\n key?: string | number | null,\n): VNode {\n const { children, ...rest } = props\n const propsWithKey = (key != null ? { ...rest, key } : rest) as Props\n\n if (typeof type === 'function') {\n // Wrap Vue-style component for re-render support\n const wrapped = wrapCompatComponent(type)\n const componentProps = children !== undefined ? { ...propsWithKey, children } : propsWithKey\n return h(wrapped, componentProps)\n }\n\n // DOM element or symbol (Fragment): children go in vnode.children\n const childArray = children === undefined ? [] : Array.isArray(children) ? children : [children]\n\n return h(type, propsWithKey, ...(childArray as VNodeChild[]))\n}\n\nexport const jsxs = jsx\nexport const jsxDEV = jsx\n","/**\n * @pyreon/vue-compat\n *\n * Vue 3-compatible Composition API that runs on Pyreon's reactive engine,\n * using a hook-indexed re-render model.\n *\n * All stateful APIs (ref, computed, reactive, watch, lifecycle hooks, etc.)\n * use hook-indexing to persist state across re-renders. The component body\n * re-executes when state changes (driven by a version signal in the JSX\n * runtime), and hook-indexed calls return the same objects across renders.\n *\n * DIFFERENCES FROM VUE 3:\n * - `deep` option in watch() is ignored — Pyreon tracks dependencies automatically.\n * - `shallowReactive` uses per-property signals (still shallow, but Pyreon-flavored).\n * - `readonly` returns a Proxy that throws on set (not Vue's readonly proxy).\n * - `defineComponent` only supports Composition API (setup function), not Options API.\n * - Components re-execute their body on state change (hook-indexed re-render model).\n *\n * USAGE:\n * Replace `import { ref, computed, watch } from \"vue\"` with\n * `import { ref, computed, watch } from \"@pyreon/vue-compat\"`\n */\n\nimport type { ComponentFn, Props, VNodeChild } from '@pyreon/core'\nimport {\n createContext,\n Fragment,\n onMount,\n onUnmount,\n onUpdate,\n popContext,\n pushContext,\n h as pyreonH,\n useContext,\n} from '@pyreon/core'\nimport {\n createStore,\n effect,\n computed as pyreonComputed,\n nextTick as pyreonNextTick,\n type Signal,\n signal,\n} from '@pyreon/reactivity'\nimport { mount as pyreonMount } from '@pyreon/runtime-dom'\nimport { getCurrentCtx, getHookIndex } from './jsx-runtime'\n\n// ─── Internal symbols ─────────────────────────────────────────────────────────\n\nconst V_IS_REF = Symbol('__v_isRef')\nconst V_IS_READONLY = Symbol('__v_isReadonly')\nconst V_RAW = Symbol('__v_raw')\n\n// ─── Ref ──────────────────────────────────────────────────────────────────────\n\nexport interface Ref<T = unknown> {\n value: T\n readonly [V_IS_REF]: true\n}\n\n/**\n * Creates a reactive ref wrapping the given value.\n * Access via `.value` — reads track, writes trigger.\n *\n * Inside a component: hook-indexed. The setter also calls `scheduleRerender()`.\n * Outside a component: creates a standalone reactive ref.\n */\nexport function ref<T>(value: T): Ref<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Ref<T>\n\n const s = signal(value)\n const { scheduleRerender } = ctx\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return s()\n },\n set value(v: T) {\n s.set(v)\n scheduleRerender()\n },\n /** @internal — access underlying signal for triggerRef */\n _signal: s,\n _scheduleRerender: scheduleRerender,\n }\n ctx.hooks[idx] = r\n return r as Ref<T>\n }\n\n // Outside component\n const s = signal(value)\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return s()\n },\n set value(v: T) {\n s.set(v)\n },\n /** @internal — access underlying signal for triggerRef */\n _signal: s,\n }\n return r as Ref<T>\n}\n\n/**\n * Creates a shallow ref — same as `ref()` in Pyreon since signals are inherently shallow.\n */\nexport function shallowRef<T>(value: T): Ref<T> {\n return ref(value)\n}\n\n/**\n * Force trigger a ref's subscribers, even if the value hasn't changed.\n */\nexport function triggerRef<T>(r: Ref<T>): void {\n const internal = r as Ref<T> & { _signal: Signal<T>; _scheduleRerender?: () => void }\n if (internal._signal) {\n // Force notify by setting the same value with Object.is bypass\n const current = internal._signal.peek()\n internal._signal.set(undefined as T)\n internal._signal.set(current)\n }\n if (internal._scheduleRerender) {\n internal._scheduleRerender()\n }\n}\n\n/**\n * Returns `true` if the value is a ref (created by `ref()` or `computed()`).\n */\nexport function isRef(val: unknown): val is Ref {\n return (\n val !== null && typeof val === 'object' && (val as Record<symbol, unknown>)[V_IS_REF] === true\n )\n}\n\n/**\n * Unwraps a ref: if it has `.value`, return `.value`; otherwise return as-is.\n */\nexport function unref<T>(r: T | Ref<T>): T {\n return isRef(r) ? r.value : r\n}\n\n// ─── Computed ─────────────────────────────────────────────────────────────────\n\nexport interface ComputedRef<T = unknown> extends Ref<T> {\n readonly value: T\n}\n\nexport interface WritableComputedRef<T = unknown> extends Ref<T> {\n value: T\n}\n\n/**\n * Creates a computed ref. Supports both readonly and writable forms.\n *\n * Inside a component: hook-indexed.\n */\nexport function computed<T>(getter: () => T): ComputedRef<T>\nexport function computed<T>(options: {\n get: () => T\n set: (value: T) => void\n}): WritableComputedRef<T>\nexport function computed<T>(\n fnOrOptions: (() => T) | { get: () => T; set: (value: T) => void },\n): ComputedRef<T> | WritableComputedRef<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as ComputedRef<T>\n\n const getter = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.get\n const setter = typeof fnOrOptions === 'object' ? fnOrOptions.set : undefined\n const c = pyreonComputed(getter)\n const { scheduleRerender } = ctx\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return c()\n },\n set value(v: T) {\n if (!setter) {\n throw new Error('Cannot set value of a computed ref — computed refs are readonly')\n }\n setter(v)\n scheduleRerender()\n },\n }\n ctx.hooks[idx] = r\n return r as ComputedRef<T>\n }\n\n // Outside component\n const getter = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.get\n const setter = typeof fnOrOptions === 'object' ? fnOrOptions.set : undefined\n const c = pyreonComputed(getter)\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return c()\n },\n set value(v: T) {\n if (!setter) {\n throw new Error('Cannot set value of a computed ref — computed refs are readonly')\n }\n setter(v)\n },\n }\n return r as ComputedRef<T>\n}\n\n// ─── Reactive / Readonly ──────────────────────────────────────────────────────\n\n// WeakMap to track raw objects behind reactive proxies\nconst rawMap = new WeakMap<object, object>()\n\n/**\n * Creates a deeply reactive proxy from a plain object.\n * Backed by Pyreon's `createStore()`.\n *\n * Inside a component: hook-indexed. Proxy wrapper intercepts sets to\n * call `scheduleRerender()`.\n */\nexport function reactive<T extends object>(obj: T): T {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as T\n\n const proxy = createStore(obj)\n rawMap.set(proxy as object, obj)\n const { scheduleRerender } = ctx\n const wrapped = new Proxy(proxy, {\n set(target, key, value, receiver) {\n const result = Reflect.set(target, key, value, receiver)\n scheduleRerender()\n return result\n },\n deleteProperty(target, key) {\n const result = Reflect.deleteProperty(target, key)\n scheduleRerender()\n return result\n },\n })\n rawMap.set(wrapped as object, obj)\n ctx.hooks[idx] = wrapped\n return wrapped as T\n }\n\n // Outside component\n const proxy = createStore(obj)\n rawMap.set(proxy as object, obj)\n return proxy\n}\n\n/**\n * Creates a shallow reactive proxy — same as `reactive()` in Pyreon.\n */\nexport function shallowReactive<T extends object>(obj: T): T {\n return reactive(obj)\n}\n\n/**\n * Returns a readonly proxy that throws on mutation attempts.\n *\n * Inside a component: hook-indexed.\n */\nexport function readonly<T extends object>(obj: T): Readonly<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Readonly<T>\n\n const proxy = _createReadonlyProxy(obj)\n ctx.hooks[idx] = proxy\n return proxy\n }\n\n return _createReadonlyProxy(obj)\n}\n\nfunction _createReadonlyProxy<T extends object>(obj: T): Readonly<T> {\n const proxy = new Proxy(obj, {\n get(target, key) {\n if (key === V_IS_READONLY) return true\n if (key === V_RAW) return target\n return Reflect.get(target, key)\n },\n set(_target, key) {\n // Internal symbols used for identification are allowed\n if (key === V_IS_READONLY || key === V_RAW) return true\n throw new Error(`Cannot set property \"${String(key)}\" on a readonly object`)\n },\n deleteProperty(_target, key) {\n throw new Error(`Cannot delete property \"${String(key)}\" from a readonly object`)\n },\n })\n return proxy as Readonly<T>\n}\n\n/**\n * Returns the raw (unwrapped) object behind a reactive or readonly proxy.\n */\nexport function toRaw<T extends object>(proxy: T): T {\n // Check readonly first\n const readonlyRaw = (proxy as Record<symbol, unknown>)[V_RAW]\n if (readonlyRaw) return readonlyRaw as T\n // Check reactive\n const raw = rawMap.get(proxy as object)\n return (raw as T) ?? proxy\n}\n\n// ─── toRef / toRefs ───────────────────────────────────────────────────────────\n\n/**\n * Creates a ref linked to a property of a reactive object.\n * Reading/writing the ref's `.value` reads/writes the original property.\n *\n * Inside a component: hook-indexed.\n */\nexport function toRef<T extends object, K extends keyof T>(obj: T, key: K): Ref<T[K]> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Ref<T[K]>\n\n const r = _createToRef(obj, key)\n ctx.hooks[idx] = r\n return r\n }\n\n return _createToRef(obj, key)\n}\n\nfunction _createToRef<T extends object, K extends keyof T>(obj: T, key: K): Ref<T[K]> {\n const r = {\n [V_IS_REF]: true as const,\n get value(): T[K] {\n return obj[key]\n },\n set value(newValue: T[K]) {\n obj[key] = newValue\n },\n }\n return r as Ref<T[K]>\n}\n\n/**\n * Converts all properties of a reactive object into individual refs.\n * Each ref is linked to the original property (not a copy).\n *\n * Inside a component: hook-indexed (the entire result, not individual refs).\n */\nexport function toRefs<T extends object>(obj: T): { [K in keyof T]: Ref<T[K]> } {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as { [K in keyof T]: Ref<T[K]> }\n\n const result = {} as { [K in keyof T]: Ref<T[K]> }\n for (const key of Object.keys(obj) as (keyof T)[]) {\n // Create refs directly (not via exported toRef) to avoid extra hook index consumption\n result[key] = _createToRef(obj, key)\n }\n ctx.hooks[idx] = result\n return result\n }\n\n const result = {} as { [K in keyof T]: Ref<T[K]> }\n for (const key of Object.keys(obj) as (keyof T)[]) {\n result[key] = _createToRef(obj, key)\n }\n return result\n}\n\n// ─── Watch ────────────────────────────────────────────────────────────────────\n\nexport interface WatchOptions {\n /** Call the callback immediately with current value. Default: false */\n immediate?: boolean\n /** Ignored in Pyreon — dependencies are tracked automatically. */\n deep?: boolean\n}\n\ntype WatchSource<T> = Ref<T> | (() => T)\n\n/**\n * Watches a reactive source and calls `cb` when it changes.\n *\n * Inside a component: hook-indexed, created once. Disposed on unmount.\n */\nexport function watch<T>(\n source: WatchSource<T>,\n cb: (newValue: T, oldValue: T | undefined) => void,\n options?: WatchOptions,\n): () => void {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as () => void\n\n const getter = isRef(source) ? () => source.value : (source as () => T)\n let oldValue: T | undefined\n let initialized = false\n\n if (options?.immediate) {\n oldValue = undefined\n const current = getter()\n cb(current, oldValue)\n oldValue = current\n initialized = true\n }\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n const newValue = getter()\n if (initialized) {\n cb(newValue, oldValue)\n }\n oldValue = newValue\n initialized = true\n } finally {\n running = false\n }\n })\n\n const stop = () => e.dispose()\n ctx.hooks[idx] = stop\n ctx.unmountCallbacks.push(stop)\n return stop\n }\n\n // Outside component\n const getter = isRef(source) ? () => source.value : (source as () => T)\n let oldValue: T | undefined\n let initialized = false\n\n if (options?.immediate) {\n oldValue = undefined\n const current = getter()\n cb(current, oldValue)\n oldValue = current\n initialized = true\n }\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n const newValue = getter()\n if (initialized) {\n cb(newValue, oldValue)\n }\n oldValue = newValue\n initialized = true\n } finally {\n running = false\n }\n })\n\n return () => e.dispose()\n}\n\n/**\n * Runs the given function reactively — re-executes whenever its tracked\n * dependencies change.\n *\n * Inside a component: hook-indexed, created once. Disposed on unmount.\n */\nexport function watchEffect(fn: () => void): () => void {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as () => void\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n fn()\n } finally {\n running = false\n }\n })\n const stop = () => e.dispose()\n ctx.hooks[idx] = stop\n ctx.unmountCallbacks.push(stop)\n return stop\n }\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n fn()\n } finally {\n running = false\n }\n })\n return () => e.dispose()\n}\n\n// ─── Lifecycle ────────────────────────────────────────────────────────────────\n\n/**\n * Registers a callback to run after the component is mounted.\n * Hook-indexed: only registered on first render.\n */\nexport function onMounted(fn: () => void): void {\n const ctx = getCurrentCtx()\n if (!ctx) {\n // Fallback: use Pyreon's lifecycle directly (e.g., inside defineComponent without jsx-runtime)\n onMount(() => {\n fn()\n })\n return\n }\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return // Already registered\n ctx.hooks[idx] = true\n // Schedule to run after render via microtask\n ctx.pendingEffects.push({\n fn: () => {\n fn()\n return undefined\n },\n deps: [],\n cleanup: undefined,\n })\n}\n\n/**\n * Registers a callback to run when the component is unmounted.\n * Hook-indexed: only registered on first render.\n */\nexport function onUnmounted(fn: () => void): void {\n const ctx = getCurrentCtx()\n if (!ctx) {\n onUnmount(fn)\n return\n }\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return // Already registered\n ctx.hooks[idx] = true\n ctx.unmountCallbacks.push(fn)\n}\n\n/**\n * Registers a callback to run after a reactive update (not on initial mount).\n * Hook-indexed: registered once, fires on each re-render.\n */\nexport function onUpdated(fn: () => void): void {\n const ctx = getCurrentCtx()\n if (!ctx) {\n onUpdate(fn)\n return\n }\n const idx = getHookIndex()\n if (idx >= ctx.hooks.length) {\n // First render — just mark as registered, don't fire\n ctx.hooks[idx] = true\n return\n }\n // Re-render — schedule the callback\n ctx.pendingEffects.push({\n fn: () => {\n fn()\n return undefined\n },\n deps: undefined,\n cleanup: undefined,\n })\n}\n\n/**\n * Registers a callback to run before mount.\n * In Pyreon there is no pre-mount phase — maps to `onMounted()`.\n */\nexport function onBeforeMount(fn: () => void): void {\n onMounted(fn)\n}\n\n/**\n * Registers a callback to run before unmount.\n * In Pyreon there is no pre-unmount phase — maps to `onUnmounted()`.\n */\nexport function onBeforeUnmount(fn: () => void): void {\n onUnmounted(fn)\n}\n\n// ─── nextTick ─────────────────────────────────────────────────────────────────\n\n/**\n * Returns a Promise that resolves after all pending reactive updates have flushed.\n */\nexport function nextTick(): Promise<void> {\n return pyreonNextTick()\n}\n\n// ─── Provide / Inject ─────────────────────────────────────────────────────────\n\n// Registry of string/symbol keys to Pyreon context objects (created lazily)\nconst _contextRegistry = new Map<string | symbol, ReturnType<typeof createContext>>()\n\nfunction getOrCreateContext<T>(key: string | symbol, defaultValue?: T) {\n if (!_contextRegistry.has(key)) {\n _contextRegistry.set(key, createContext<T>(defaultValue as T))\n }\n return _contextRegistry.get(key) as ReturnType<typeof createContext<T>>\n}\n\n/**\n * Provides a value to all descendant components.\n *\n * Inside a component: hook-indexed, pushed once. Popped on unmount.\n */\nexport function provide<T>(key: string | symbol, value: T): void {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return // Already provided\n ctx.hooks[idx] = true\n const vueCtx = getOrCreateContext<T>(key)\n pushContext(new Map([[vueCtx.id, value]]))\n ctx.unmountCallbacks.push(() => popContext())\n return\n }\n // Outside component — use Pyreon's provide directly\n const vueCtx = getOrCreateContext<T>(key)\n pushContext(new Map([[vueCtx.id, value]]))\n}\n\n/**\n * Injects a value provided by an ancestor component.\n */\nexport function inject<T>(key: string | symbol, defaultValue?: T): T | undefined {\n const ctx = getOrCreateContext<T>(key)\n const value = useContext(ctx)\n return value !== undefined ? value : defaultValue\n}\n\n// ─── defineComponent ──────────────────────────────────────────────────────────\n\ninterface ComponentOptions<P extends Props = Props> {\n /** The setup function — called once during component initialization. */\n setup: (props: P) => (() => VNodeChild) | VNodeChild\n /** Optional name for debugging. */\n name?: string\n}\n\n/**\n * Defines a component using Vue 3 Composition API style.\n * Only supports the `setup()` function — Options API is not supported.\n */\nexport function defineComponent<P extends Props = Props>(\n options: ComponentOptions<P> | ((props: P) => VNodeChild),\n): ComponentFn<P> {\n if (typeof options === 'function') {\n return options as ComponentFn<P>\n }\n const comp = (props: P) => {\n const result = options.setup(props)\n if (typeof result === 'function') {\n return (result as () => VNodeChild)()\n }\n return result\n }\n if (options.name) {\n Object.defineProperty(comp, 'name', { value: options.name })\n }\n return comp as ComponentFn<P>\n}\n\n// ─── h ────────────────────────────────────────────────────────────────────────\n\n/**\n * Re-export of Pyreon's `h()` function for creating VNodes.\n */\nexport { Fragment, pyreonH as h }\n\n// ─── createApp ────────────────────────────────────────────────────────────────\n\ninterface App {\n /** Mount the application into a DOM element. Returns an unmount function. */\n mount(el: string | Element): () => void\n}\n\n/**\n * Creates a Pyreon application instance — Vue 3 `createApp()` compatible.\n */\nexport function createApp(component: ComponentFn, props?: Props): App {\n return {\n mount(el: string | Element): () => void {\n const container = typeof el === 'string' ? document.querySelector(el) : el\n if (!container) {\n throw new Error(`Cannot find mount target: ${el}`)\n }\n const vnode = pyreonH(component, props ?? null)\n return pyreonMount(vnode, container)\n },\n }\n}\n\n// ─── Additional re-exports ────────────────────────────────────────────────────\n\nexport { batch } from '@pyreon/reactivity'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["pyreonComputed","pyreonNextTick","pyreonMount"],"sources":["../src/jsx-runtime.ts","../src/index.ts"],"sourcesContent":["/**\n * Compat JSX runtime for Vue compatibility mode.\n *\n * When `jsxImportSource` is redirected to `@pyreon/vue-compat` (via the vite\n * plugin's `compat: \"vue\"` option), OXC rewrites JSX to import from this file.\n *\n * For component VNodes, we wrap the component function so it returns a reactive\n * accessor — enabling Vue-style re-renders on state change while Pyreon's\n * existing renderer handles all DOM work.\n *\n * Key difference from react/preact compat: the component body runs inside\n * `runUntracked` to prevent `.value` reads (which access underlying signals)\n * from being tracked by the reactive accessor. Only the version signal\n * triggers re-renders.\n */\n\nimport type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'\nimport { Fragment, h, onUnmount } from '@pyreon/core'\nimport { runUntracked, signal } from '@pyreon/reactivity'\n\nexport { Fragment }\n\n// ─── Render context (used by hooks) ──────────────────────────────────────────\n\nexport interface RenderContext {\n hooks: unknown[]\n scheduleRerender: () => void\n /** Effect entries pending execution after render */\n pendingEffects: EffectEntry[]\n /** Layout effect entries pending execution after render */\n pendingLayoutEffects: EffectEntry[]\n /** Set to true when the component is unmounted */\n unmounted: boolean\n /** Callbacks to run on unmount (lifecycle + effect cleanups) */\n unmountCallbacks: (() => void)[]\n}\n\nexport interface EffectEntry {\n fn: () => (() => void) | void\n deps: unknown[] | undefined\n cleanup: (() => void) | undefined\n}\n\nlet _currentCtx: RenderContext | null = null\nlet _hookIndex = 0\n\nexport function getCurrentCtx(): RenderContext | null {\n return _currentCtx\n}\n\nexport function getHookIndex(): number {\n return _hookIndex++\n}\n\nexport function beginRender(ctx: RenderContext): void {\n _currentCtx = ctx\n _hookIndex = 0\n ctx.pendingEffects = []\n ctx.pendingLayoutEffects = []\n}\n\nexport function endRender(): void {\n _currentCtx = null\n _hookIndex = 0\n}\n\n// ─── Effect runners ──────────────────────────────────────────────────────────\n\nfunction runLayoutEffects(entries: EffectEntry[]): void {\n for (const entry of entries) {\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n}\n\nfunction scheduleEffects(ctx: RenderContext, entries: EffectEntry[]): void {\n if (entries.length === 0) return\n queueMicrotask(() => {\n for (const entry of entries) {\n if (ctx.unmounted) return\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n })\n}\n\n// ─── Component wrapping ──────────────────────────────────────────────────────\n\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\nfunction wrapCompatComponent(vueComponent: Function): ComponentFn {\n let wrapped = _wrapperCache.get(vueComponent)\n if (wrapped) return wrapped\n\n // The wrapper returns a reactive accessor (() => VNodeChild) which Pyreon's\n // mountChild treats as a reactive expression via mountReactive.\n wrapped = ((props: Props) => {\n const ctx: RenderContext = {\n hooks: [],\n scheduleRerender: () => {\n // Will be replaced below after version signal is created\n },\n pendingEffects: [],\n pendingLayoutEffects: [],\n unmounted: false,\n unmountCallbacks: [],\n }\n\n const version = signal(0)\n let updateScheduled = false\n\n ctx.scheduleRerender = () => {\n if (ctx.unmounted || updateScheduled) return\n updateScheduled = true\n queueMicrotask(() => {\n updateScheduled = false\n if (!ctx.unmounted) version.set(version.peek() + 1)\n })\n }\n\n // Register cleanup when component unmounts\n onUnmount(() => {\n ctx.unmounted = true\n for (const cb of ctx.unmountCallbacks) cb()\n })\n\n // Return reactive accessor — Pyreon's mountChild calls mountReactive\n return () => {\n version() // tracked read — triggers re-execution when state changes\n beginRender(ctx)\n // runUntracked prevents .value signal reads from being tracked by this accessor —\n // only the version signal should trigger re-renders\n const result = runUntracked(() => (vueComponent as ComponentFn)(props))\n const layoutEffects = ctx.pendingLayoutEffects\n const effects = ctx.pendingEffects\n endRender()\n\n runLayoutEffects(layoutEffects)\n scheduleEffects(ctx, effects)\n\n return result\n }\n }) as unknown as ComponentFn\n\n _wrapperCache.set(vueComponent, wrapped)\n return wrapped\n}\n\n// ─── JSX functions ───────────────────────────────────────────────────────────\n\nexport function jsx(\n type: string | ComponentFn | symbol,\n props: Props & { children?: VNodeChild | VNodeChild[] },\n key?: string | number | null,\n): VNode {\n const { children, ...rest } = props\n const propsWithKey = (key != null ? { ...rest, key } : rest) as Props\n\n if (typeof type === 'function') {\n // Wrap Vue-style component for re-render support\n const wrapped = wrapCompatComponent(type)\n const componentProps = children !== undefined ? { ...propsWithKey, children } : propsWithKey\n return h(wrapped, componentProps)\n }\n\n // DOM element: convert Vue ref ({ value }) to callback ref for Pyreon's runtime-dom\n if (typeof type === 'string' && propsWithKey.ref != null) {\n const r = propsWithKey.ref\n if (\n typeof r === 'object' &&\n r !== null &&\n (r as Record<symbol, unknown>)[Symbol.for('__v_isRef')] === true\n ) {\n const vueRef = r as { value: unknown }\n propsWithKey.ref = (el: Element | null) => {\n vueRef.value = el\n }\n }\n }\n\n // DOM element or symbol (Fragment): children go in vnode.children\n const childArray = children === undefined ? [] : Array.isArray(children) ? children : [children]\n\n return h(type, propsWithKey, ...(childArray as VNodeChild[]))\n}\n\nexport const jsxs = jsx\nexport const jsxDEV = jsx\n","/**\n * @pyreon/vue-compat\n *\n * Vue 3-compatible Composition API that runs on Pyreon's reactive engine,\n * using a hook-indexed re-render model.\n *\n * All stateful APIs (ref, computed, reactive, watch, lifecycle hooks, etc.)\n * use hook-indexing to persist state across re-renders. The component body\n * re-executes when state changes (driven by a version signal in the JSX\n * runtime), and hook-indexed calls return the same objects across renders.\n *\n * DIFFERENCES FROM VUE 3:\n * - `deep` option in watch() is ignored — Pyreon tracks dependencies automatically.\n * - `shallowReactive` uses per-property signals (still shallow, but Pyreon-flavored).\n * - `readonly` returns a Proxy that throws on set (not Vue's readonly proxy).\n * - `defineComponent` only supports Composition API (setup function), not Options API.\n * - Components re-execute their body on state change (hook-indexed re-render model).\n *\n * USAGE:\n * Replace `import { ref, computed, watch } from \"vue\"` with\n * `import { ref, computed, watch } from \"@pyreon/vue-compat\"`\n */\n\nimport type { ComponentFn, Props, VNodeChild } from '@pyreon/core'\nimport {\n createContext,\n Fragment,\n onMount,\n onUnmount,\n onUpdate,\n popContext,\n Portal,\n pushContext,\n h as pyreonH,\n useContext,\n} from '@pyreon/core'\nimport {\n createStore,\n effect,\n computed as pyreonComputed,\n nextTick as pyreonNextTick,\n type Signal,\n signal,\n} from '@pyreon/reactivity'\nimport { mount as pyreonMount } from '@pyreon/runtime-dom'\nimport { getCurrentCtx, getHookIndex } from './jsx-runtime'\n\n// ─── Internal symbols ─────────────────────────────────────────────────────────\n\nconst V_IS_REF = Symbol.for('__v_isRef')\nconst V_IS_READONLY = Symbol('__v_isReadonly')\nconst V_SKIP = Symbol('__v_skip')\nconst V_RAW = Symbol('__v_raw')\n\n// ─── Ref ──────────────────────────────────────────────────────────────────────\n\nexport interface Ref<T = unknown> {\n value: T\n readonly [V_IS_REF]: true\n}\n\n/**\n * Creates a reactive ref wrapping the given value.\n * Access via `.value` — reads track, writes trigger.\n *\n * Inside a component: hook-indexed. The setter also calls `scheduleRerender()`.\n * Outside a component: creates a standalone reactive ref.\n */\nexport function ref<T>(value: T): Ref<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Ref<T>\n\n const s = signal(value)\n const { scheduleRerender } = ctx\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return s()\n },\n set value(v: T) {\n s.set(v)\n scheduleRerender()\n },\n /** @internal — access underlying signal for triggerRef */\n _signal: s,\n _scheduleRerender: scheduleRerender,\n }\n ctx.hooks[idx] = r\n return r as Ref<T>\n }\n\n // Outside component\n const s = signal(value)\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return s()\n },\n set value(v: T) {\n s.set(v)\n },\n /** @internal — access underlying signal for triggerRef */\n _signal: s,\n }\n return r as Ref<T>\n}\n\n/**\n * Creates a shallow ref — same as `ref()` in Pyreon since signals are inherently shallow.\n */\nexport function shallowRef<T>(value: T): Ref<T> {\n return ref(value)\n}\n\n/**\n * Force trigger a ref's subscribers, even if the value hasn't changed.\n */\nexport function triggerRef<T>(r: Ref<T>): void {\n const internal = r as Ref<T> & { _signal: Signal<T>; _scheduleRerender?: () => void }\n if (internal._signal) {\n // Force notify by setting the same value with Object.is bypass\n const current = internal._signal.peek()\n internal._signal.set(undefined as T)\n internal._signal.set(current)\n }\n if (internal._scheduleRerender) {\n internal._scheduleRerender()\n }\n}\n\n/**\n * Returns `true` if the value is a ref (created by `ref()` or `computed()`).\n */\nexport function isRef(val: unknown): val is Ref {\n return (\n val !== null && typeof val === 'object' && (val as Record<symbol, unknown>)[V_IS_REF] === true\n )\n}\n\n/**\n * Unwraps a ref: if it has `.value`, return `.value`; otherwise return as-is.\n */\nexport function unref<T>(r: T | Ref<T>): T {\n return isRef(r) ? r.value : r\n}\n\n/**\n * Unwraps a ref, calls a getter, or returns the value as-is.\n * Vue 3.3+ API for normalizing ref/getter/value inputs.\n */\nexport function toValue<T>(source: Ref<T> | (() => T) | T): T {\n if (isRef(source)) return source.value\n if (typeof source === 'function') return (source as () => T)()\n return source\n}\n\n// ─── Computed ─────────────────────────────────────────────────────────────────\n\nexport interface ComputedRef<T = unknown> extends Ref<T> {\n readonly value: T\n}\n\nexport interface WritableComputedRef<T = unknown> extends Ref<T> {\n value: T\n}\n\n/**\n * Creates a computed ref. Supports both readonly and writable forms.\n *\n * Inside a component: hook-indexed.\n */\nexport function computed<T>(getter: () => T): ComputedRef<T>\nexport function computed<T>(options: {\n get: () => T\n set: (value: T) => void\n}): WritableComputedRef<T>\nexport function computed<T>(\n fnOrOptions: (() => T) | { get: () => T; set: (value: T) => void },\n): ComputedRef<T> | WritableComputedRef<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as ComputedRef<T>\n\n const getter = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.get\n const setter = typeof fnOrOptions === 'object' ? fnOrOptions.set : undefined\n const c = pyreonComputed(getter)\n const { scheduleRerender } = ctx\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return c()\n },\n set value(v: T) {\n if (!setter) {\n throw new Error('Cannot set value of a computed ref — computed refs are readonly')\n }\n setter(v)\n scheduleRerender()\n },\n }\n ctx.hooks[idx] = r\n return r as ComputedRef<T>\n }\n\n // Outside component\n const getter = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.get\n const setter = typeof fnOrOptions === 'object' ? fnOrOptions.set : undefined\n const c = pyreonComputed(getter)\n const r = {\n [V_IS_REF]: true as const,\n get value(): T {\n return c()\n },\n set value(v: T) {\n if (!setter) {\n throw new Error('Cannot set value of a computed ref — computed refs are readonly')\n }\n setter(v)\n },\n }\n return r as ComputedRef<T>\n}\n\n// ─── Reactive / Readonly ──────────────────────────────────────────────────────\n\n// WeakMap to track raw objects behind reactive proxies\nconst rawMap = new WeakMap<object, object>()\n\n/**\n * Creates a deeply reactive proxy from a plain object.\n * Backed by Pyreon's `createStore()`.\n *\n * Inside a component: hook-indexed. Proxy wrapper intercepts sets to\n * call `scheduleRerender()`.\n */\nexport function reactive<T extends object>(obj: T): T {\n if ((obj as Record<symbol, boolean>)[V_SKIP]) return obj\n\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as T\n\n const proxy = createStore(obj)\n rawMap.set(proxy as object, obj)\n const { scheduleRerender } = ctx\n const wrapped = new Proxy(proxy, {\n set(target, key, value, receiver) {\n const result = Reflect.set(target, key, value, receiver)\n scheduleRerender()\n return result\n },\n deleteProperty(target, key) {\n const result = Reflect.deleteProperty(target, key)\n scheduleRerender()\n return result\n },\n })\n rawMap.set(wrapped as object, obj)\n ctx.hooks[idx] = wrapped\n return wrapped as T\n }\n\n // Outside component\n const proxy = createStore(obj)\n rawMap.set(proxy as object, obj)\n return proxy\n}\n\n/**\n * Creates a shallow reactive proxy — same as `reactive()` in Pyreon.\n */\nexport function shallowReactive<T extends object>(obj: T): T {\n return reactive(obj)\n}\n\n/**\n * Returns a readonly proxy that throws on mutation attempts.\n *\n * Inside a component: hook-indexed.\n */\nexport function readonly<T extends object>(obj: T): Readonly<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Readonly<T>\n\n const proxy = _createReadonlyProxy(obj)\n ctx.hooks[idx] = proxy\n return proxy\n }\n\n return _createReadonlyProxy(obj)\n}\n\n/**\n * Returns a shallow readonly proxy — only top-level properties throw on set.\n * Nested objects are NOT wrapped in readonly (unlike `readonly()`).\n */\nexport function shallowReadonly<T extends object>(obj: T): Readonly<T> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Readonly<T>\n\n const proxy = _createShallowReadonlyProxy(obj)\n ctx.hooks[idx] = proxy\n return proxy\n }\n\n return _createShallowReadonlyProxy(obj)\n}\n\nfunction _createShallowReadonlyProxy<T extends object>(obj: T): Readonly<T> {\n const proxy = new Proxy(obj, {\n get(target, key) {\n if (key === V_IS_READONLY) return true\n if (key === V_RAW) return target\n return Reflect.get(target, key)\n // NO recursive wrapping — shallow\n },\n set(_target, key) {\n if (key === V_IS_READONLY || key === V_RAW) return true\n throw new Error(`Cannot set property \"${String(key)}\" on a readonly object`)\n },\n deleteProperty(_target, key) {\n throw new Error(`Cannot delete property \"${String(key)}\" from a readonly object`)\n },\n })\n return proxy as Readonly<T>\n}\n\nfunction _createReadonlyProxy<T extends object>(obj: T): Readonly<T> {\n const proxy = new Proxy(obj, {\n get(target, key) {\n if (key === V_IS_READONLY) return true\n if (key === V_RAW) return target\n const value = Reflect.get(target, key)\n // Recursively wrap nested objects in readonly\n if (value !== null && typeof value === 'object' && !isRef(value)) {\n return _createReadonlyProxy(value as object)\n }\n return value\n },\n set(_target, key) {\n // Internal symbols used for identification are allowed\n if (key === V_IS_READONLY || key === V_RAW) return true\n throw new Error(`Cannot set property \"${String(key)}\" on a readonly object`)\n },\n deleteProperty(_target, key) {\n throw new Error(`Cannot delete property \"${String(key)}\" from a readonly object`)\n },\n })\n return proxy as Readonly<T>\n}\n\n/**\n * Returns the raw (unwrapped) object behind a reactive or readonly proxy.\n */\nexport function toRaw<T extends object>(proxy: T): T {\n // Check readonly first\n const readonlyRaw = (proxy as Record<symbol, unknown>)[V_RAW]\n if (readonlyRaw) return readonlyRaw as T\n // Check reactive\n const raw = rawMap.get(proxy as object)\n return (raw as T) ?? proxy\n}\n\n// ─── toRef / toRefs ───────────────────────────────────────────────────────────\n\n/**\n * Creates a ref linked to a property of a reactive object.\n * Reading/writing the ref's `.value` reads/writes the original property.\n *\n * Inside a component: hook-indexed.\n */\nexport function toRef<T extends object, K extends keyof T>(obj: T, key: K): Ref<T[K]> {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as Ref<T[K]>\n\n const r = _createToRef(obj, key)\n ctx.hooks[idx] = r\n return r\n }\n\n return _createToRef(obj, key)\n}\n\nfunction _createToRef<T extends object, K extends keyof T>(obj: T, key: K): Ref<T[K]> {\n const r = {\n [V_IS_REF]: true as const,\n get value(): T[K] {\n return obj[key]\n },\n set value(newValue: T[K]) {\n obj[key] = newValue\n },\n }\n return r as Ref<T[K]>\n}\n\n/**\n * Converts all properties of a reactive object into individual refs.\n * Each ref is linked to the original property (not a copy).\n *\n * Inside a component: hook-indexed (the entire result, not individual refs).\n */\nexport function toRefs<T extends object>(obj: T): { [K in keyof T]: Ref<T[K]> } {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as { [K in keyof T]: Ref<T[K]> }\n\n const result = {} as { [K in keyof T]: Ref<T[K]> }\n for (const key of Object.keys(obj) as (keyof T)[]) {\n // Create refs directly (not via exported toRef) to avoid extra hook index consumption\n result[key] = _createToRef(obj, key)\n }\n ctx.hooks[idx] = result\n return result\n }\n\n const result = {} as { [K in keyof T]: Ref<T[K]> }\n for (const key of Object.keys(obj) as (keyof T)[]) {\n result[key] = _createToRef(obj, key)\n }\n return result\n}\n\n// ─── Watch ────────────────────────────────────────────────────────────────────\n\nexport interface WatchOptions {\n /** Call the callback immediately with current value. Default: false */\n immediate?: boolean\n /** Ignored in Pyreon — dependencies are tracked automatically. */\n deep?: boolean\n /** Accepted for compatibility but not meaningfully differentiated in Pyreon. */\n flush?: 'pre' | 'post' | 'sync'\n}\n\ntype WatchSource<T> = Ref<T> | (() => T)\n\n/**\n * Watches a reactive source (or array of sources) and calls `cb` when it changes.\n *\n * Inside a component: hook-indexed, created once. Disposed on unmount.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function watch<T>(\n source: WatchSource<T>,\n cb: (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void,\n options?: WatchOptions,\n): () => void\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function watch<T extends readonly WatchSource<any>[]>(\n sources: [...T],\n cb: (\n newValues: { [K in keyof T]: T[K] extends WatchSource<infer V> ? V : never },\n oldValues: { [K in keyof T]: T[K] extends WatchSource<infer V> ? V | undefined : never },\n onCleanup: (fn: () => void) => void,\n ) => void,\n options?: WatchOptions,\n): () => void\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function watch<T>(\n source: WatchSource<T> | WatchSource<T>[],\n cb: (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void,\n options?: WatchOptions,\n): () => void {\n // Array of sources — multi-watch\n if (Array.isArray(source)) {\n return _watchArray(\n source as WatchSource<unknown>[],\n cb as (newValue: unknown, oldValue: unknown) => void,\n options,\n )\n }\n return _watchSingle(source as WatchSource<T>, cb, options)\n}\n\nfunction _watchArray(\n sources: WatchSource<unknown>[],\n cb: (newValues: unknown, oldValues: unknown, onCleanup: (fn: () => void) => void) => void,\n options?: WatchOptions,\n): () => void {\n const getters = sources.map((s) => (isRef(s) ? () => (s as Ref).value : (s as () => unknown)))\n\n let cleanupFn: (() => void) | undefined\n const onCleanup = (fn: () => void) => {\n cleanupFn = fn\n }\n\n const runCleanup = () => {\n if (cleanupFn) {\n cleanupFn()\n cleanupFn = undefined\n }\n }\n\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as () => void\n\n let oldValues: unknown[] | undefined\n let initialized = false\n\n if (options?.immediate) {\n const current = getters.map((g) => g())\n cb(current, getters.map(() => undefined), onCleanup)\n oldValues = current\n initialized = true\n }\n\n let running = false\n const combined = pyreonComputed(() => getters.map((g) => g()))\n const e = effect(() => {\n if (running) return\n running = true\n try {\n const newValues = combined()\n if (initialized) {\n runCleanup()\n cb([...newValues], oldValues ? [...oldValues] : getters.map(() => undefined), onCleanup)\n }\n oldValues = [...newValues]\n initialized = true\n } finally {\n running = false\n }\n })\n\n const stop = () => {\n runCleanup()\n e.dispose()\n }\n ctx.hooks[idx] = stop\n ctx.unmountCallbacks.push(stop)\n return stop\n }\n\n // Outside component\n let oldValues: unknown[] | undefined\n let initialized = false\n\n if (options?.immediate) {\n const current = getters.map((g) => g())\n cb(current, getters.map(() => undefined), onCleanup)\n oldValues = current\n initialized = true\n }\n\n let running = false\n const combined = pyreonComputed(() => getters.map((g) => g()))\n const e = effect(() => {\n if (running) return\n running = true\n try {\n const newValues = combined()\n if (initialized) {\n runCleanup()\n cb([...newValues], oldValues ? [...oldValues] : getters.map(() => undefined), onCleanup)\n }\n oldValues = [...newValues]\n initialized = true\n } finally {\n running = false\n }\n })\n\n const stop = () => {\n runCleanup()\n e.dispose()\n }\n if (_currentEffectScope) {\n ;(\n _currentEffectScope as EffectScopeCompat & { _cleanups: (() => void)[] }\n )._cleanups.push(stop)\n }\n return stop\n}\n\nfunction _watchSingle<T>(\n source: WatchSource<T>,\n cb: (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void,\n options?: WatchOptions,\n): () => void {\n let cleanupFn: (() => void) | undefined\n const onCleanup = (fn: () => void) => {\n cleanupFn = fn\n }\n\n const runCleanup = () => {\n if (cleanupFn) {\n cleanupFn()\n cleanupFn = undefined\n }\n }\n\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as () => void\n\n const getter = isRef(source) ? () => source.value : (source as () => T)\n let oldValue: T | undefined\n let initialized = false\n\n if (options?.immediate) {\n oldValue = undefined\n const current = getter()\n cb(current, oldValue, onCleanup)\n oldValue = current\n initialized = true\n }\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n const newValue = getter()\n if (initialized) {\n runCleanup()\n cb(newValue, oldValue, onCleanup)\n }\n oldValue = newValue\n initialized = true\n } finally {\n running = false\n }\n })\n\n const stop = () => {\n runCleanup()\n e.dispose()\n }\n ctx.hooks[idx] = stop\n ctx.unmountCallbacks.push(stop)\n return stop\n }\n\n // Outside component\n const getter = isRef(source) ? () => source.value : (source as () => T)\n let oldValue: T | undefined\n let initialized = false\n\n if (options?.immediate) {\n oldValue = undefined\n const current = getter()\n cb(current, oldValue, onCleanup)\n oldValue = current\n initialized = true\n }\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n const newValue = getter()\n if (initialized) {\n runCleanup()\n cb(newValue, oldValue, onCleanup)\n }\n oldValue = newValue\n initialized = true\n } finally {\n running = false\n }\n })\n\n const stop = () => {\n runCleanup()\n e.dispose()\n }\n if (_currentEffectScope) {\n ;(\n _currentEffectScope as EffectScopeCompat & { _cleanups: (() => void)[] }\n )._cleanups.push(stop)\n }\n return stop\n}\n\n/**\n * Runs the given function reactively — re-executes whenever its tracked\n * dependencies change. Passes an `onCleanup` registration function to the\n * callback, matching Vue 3's `watchEffect((onCleanup) => { ... })` API.\n *\n * Inside a component: hook-indexed, created once. Disposed on unmount.\n */\nexport function watchEffect(\n fn: (onCleanup: (fn: () => void) => void) => void,\n): () => void {\n const ctx = getCurrentCtx()\n\n let cleanupFn: (() => void) | undefined\n const onCleanup = (cleanup: () => void) => {\n cleanupFn = cleanup\n }\n\n const runEffect = () => {\n if (cleanupFn) {\n cleanupFn()\n cleanupFn = undefined\n }\n fn(onCleanup)\n }\n\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return ctx.hooks[idx] as () => void\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n runEffect()\n } finally {\n running = false\n }\n })\n const stop = () => {\n if (cleanupFn) cleanupFn()\n e.dispose()\n }\n ctx.hooks[idx] = stop\n ctx.unmountCallbacks.push(stop)\n return stop\n }\n\n let running = false\n const e = effect(() => {\n if (running) return\n running = true\n try {\n runEffect()\n } finally {\n running = false\n }\n })\n const stop = () => {\n if (cleanupFn) cleanupFn()\n e.dispose()\n }\n // Register with current effect scope if one is active\n if (_currentEffectScope) {\n ;(\n _currentEffectScope as EffectScopeCompat & { _cleanups: (() => void)[] }\n )._cleanups.push(stop)\n }\n return stop\n}\n\n// ─── Lifecycle ────────────────────────────────────────────────────────────────\n\n/**\n * Registers a callback to run after the component is mounted.\n * Hook-indexed: only registered on first render.\n */\nexport function onMounted(fn: () => void): void {\n const ctx = getCurrentCtx()\n if (!ctx) {\n // Fallback: use Pyreon's lifecycle directly (e.g., inside defineComponent without jsx-runtime)\n onMount(() => {\n fn()\n })\n return\n }\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return // Already registered\n ctx.hooks[idx] = true\n // Schedule to run after render via microtask\n ctx.pendingEffects.push({\n fn: () => {\n fn()\n return undefined\n },\n deps: [],\n cleanup: undefined,\n })\n}\n\n/**\n * Registers a callback to run when the component is unmounted.\n * Hook-indexed: only registered on first render.\n */\nexport function onUnmounted(fn: () => void): void {\n const ctx = getCurrentCtx()\n if (!ctx) {\n onUnmount(fn)\n return\n }\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return // Already registered\n ctx.hooks[idx] = true\n ctx.unmountCallbacks.push(fn)\n}\n\n/**\n * Registers a callback to run after a reactive update (not on initial mount).\n * Hook-indexed: registered once, fires on each re-render.\n */\nexport function onUpdated(fn: () => void): void {\n const ctx = getCurrentCtx()\n if (!ctx) {\n onUpdate(fn)\n return\n }\n const idx = getHookIndex()\n if (idx >= ctx.hooks.length) {\n // First render — just mark as registered, don't fire\n ctx.hooks[idx] = true\n return\n }\n // Re-render — schedule the callback\n ctx.pendingEffects.push({\n fn: () => {\n fn()\n return undefined\n },\n deps: undefined,\n cleanup: undefined,\n })\n}\n\n/**\n * Registers a callback to run before mount.\n * In Pyreon there is no pre-mount phase — maps to `onMounted()`.\n */\nexport function onBeforeMount(fn: () => void): void {\n onMounted(fn)\n}\n\n/**\n * Registers a callback to run before unmount.\n * In Pyreon there is no pre-unmount phase — maps to `onUnmounted()`.\n */\nexport function onBeforeUnmount(fn: () => void): void {\n onUnmounted(fn)\n}\n\n// ─── nextTick ─────────────────────────────────────────────────────────────────\n\n/**\n * Returns a Promise that resolves after all pending reactive updates have flushed.\n */\nexport function nextTick(): Promise<void> {\n return pyreonNextTick()\n}\n\n// ─── Provide / Inject ─────────────────────────────────────────────────────────\n\n// Registry of string/symbol keys to Pyreon context objects (created lazily)\nconst _contextRegistry = new Map<string | symbol, ReturnType<typeof createContext>>()\n\nfunction getOrCreateContext<T>(key: string | symbol, defaultValue?: T) {\n if (!_contextRegistry.has(key)) {\n _contextRegistry.set(key, createContext<T>(defaultValue as T))\n }\n return _contextRegistry.get(key) as ReturnType<typeof createContext<T>>\n}\n\n/**\n * Provides a value to all descendant components.\n *\n * Inside a component: hook-indexed, pushed once. Popped on unmount.\n */\nexport function provide<T>(key: string | symbol, value: T): void {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return // Already provided\n ctx.hooks[idx] = true\n const vueCtx = getOrCreateContext<T>(key)\n pushContext(new Map([[vueCtx.id, value]]))\n ctx.unmountCallbacks.push(() => popContext())\n return\n }\n // Outside component — use Pyreon's provide directly\n const vueCtx = getOrCreateContext<T>(key)\n pushContext(new Map([[vueCtx.id, value]]))\n}\n\n/**\n * Injects a value provided by an ancestor component.\n * Supports Vue 3's factory default pattern: `inject(key, () => expensiveDefault, true)`.\n */\nexport function inject<T>(\n key: string | symbol,\n defaultValue?: T | (() => T),\n treatDefaultAsFactory?: boolean,\n): T | undefined {\n const ctx = getOrCreateContext<T>(key)\n const value = useContext(ctx)\n if (value !== undefined) return value\n if (defaultValue === undefined) return undefined\n if (treatDefaultAsFactory && typeof defaultValue === 'function') {\n return (defaultValue as () => T)()\n }\n return defaultValue as T\n}\n\n// ─── defineComponent ──────────────────────────────────────────────────────────\n\ninterface ComponentOptions<P extends Props = Props> {\n /** The setup function — called once during component initialization. */\n setup: (props: P, ctx?: SetupContext) => (() => VNodeChild) | VNodeChild\n /** Optional name for debugging. */\n name?: string\n /** Prop definitions (not validated at runtime, used for type documentation). */\n props?: Record<string, unknown>\n}\n\n/**\n * Defines a component using Vue 3 Composition API style.\n * Only supports the `setup()` function — Options API is not supported.\n */\nexport function defineComponent<P extends Props = Props>(\n options: ComponentOptions<P> | ((props: P) => VNodeChild),\n): ComponentFn<P> {\n if (typeof options === 'function') {\n return options as ComponentFn<P>\n }\n const comp = (props: P) => {\n // Extract children from props for slots\n const children = (props as Record<string, unknown>).children as VNodeChild | undefined\n // Create a minimal SetupContext\n const setupCtx: SetupContext = {\n emit: (event: string, ...args: unknown[]) => {\n const handlerKey = `on${event.charAt(0).toUpperCase()}${event.slice(1)}`\n const handler = (props as Record<string, unknown>)[handlerKey]\n if (typeof handler === 'function') (handler as (...a: unknown[]) => void)(...args)\n },\n slots: {\n default: children !== undefined ? (() => children) : undefined,\n } as Record<string, (() => VNodeChild) | undefined>,\n attrs: props as Record<string, unknown>,\n }\n const result = options.setup(props, setupCtx)\n if (typeof result === 'function') {\n return (result as () => VNodeChild)()\n }\n return result\n }\n if (options.name) {\n Object.defineProperty(comp, 'name', { value: options.name })\n }\n return comp as ComponentFn<P>\n}\n\n// ─── defineAsyncComponent ───────────────────────────────────────────────────\n\n/**\n * Defines an async component that lazily loads on first use.\n * Supports both a bare loader function and an options object with\n * loadingComponent, errorComponent, delay, and timeout.\n *\n * Returns a ComponentFn with a `__loading` property for Suspense integration.\n */\nexport function defineAsyncComponent<P extends Props = Props>(\n loader:\n | (() => Promise<{ default: ComponentFn<P> }>)\n | {\n loader: () => Promise<{ default: ComponentFn<P> }>\n loadingComponent?: ComponentFn\n errorComponent?: ComponentFn\n delay?: number\n timeout?: number\n },\n): ComponentFn<P> & { __loading: () => boolean } {\n const load = typeof loader === 'function' ? loader : loader.loader\n\n const loaded = signal<ComponentFn<P> | null>(null)\n const error = signal<Error | null>(null)\n let promise: Promise<unknown> | null = null\n\n const startLoad = () => {\n if (promise) return\n promise = load().then(\n (mod) => loaded.set(mod.default),\n (err) => error.set(err instanceof Error ? err : new Error(String(err))),\n )\n }\n\n const AsyncComp = ((props: P) => {\n startLoad()\n const err = error()\n if (err) throw err\n const comp = loaded()\n if (!comp) return null\n return comp(props)\n }) as ComponentFn<P> & { __loading: () => boolean }\n\n AsyncComp.__loading = () => {\n const isLoading = loaded() === null && error() === null\n if (isLoading) startLoad()\n return isLoading\n }\n\n return AsyncComp\n}\n\n// ─── h ────────────────────────────────────────────────────────────────────────\n\n/**\n * Re-export of Pyreon's `h()` function for creating VNodes.\n */\nexport { Fragment, pyreonH as h }\n\n// ─── createApp ────────────────────────────────────────────────────────────────\n\ninterface App {\n /** Mount the application into a DOM element. Returns an unmount function. */\n mount(el: string | Element): () => void\n /** Install a plugin. */\n use(plugin: { install: (app: App) => void }): App\n /** Provide a value to the entire app tree. */\n provide<T>(key: string | symbol, value: T): App\n}\n\n/**\n * Creates a Pyreon application instance — Vue 3 `createApp()` compatible.\n */\nexport function createApp(component: ComponentFn, props?: Props): App {\n const provisions: Array<{ key: string | symbol; value: unknown }> = []\n\n const app: App = {\n mount(el: string | Element): () => void {\n const container = typeof el === 'string' ? document.querySelector(el) : el\n if (!container) {\n throw new Error(`Cannot find mount target: ${el}`)\n }\n // Push app-level provisions before mounting\n for (const { key, value } of provisions) {\n const ctx = getOrCreateContext(key)\n pushContext(new Map([[ctx.id, value]]))\n }\n const vnode = pyreonH(component, props ?? null)\n return pyreonMount(vnode, container)\n },\n use(plugin: { install: (app: App) => void }): App {\n plugin.install(app)\n return app\n },\n provide<T>(key: string | symbol, value: T): App {\n provisions.push({ key, value })\n return app\n },\n }\n\n return app\n}\n\n// ─── isReactive / isReadonly / isProxy / markRaw ─────────────────────────────\n\n/**\n * Returns `true` if the value was created by `reactive()`.\n */\nexport function isReactive(value: unknown): boolean {\n return value !== null && typeof value === 'object' && rawMap.has(value as object)\n}\n\n/**\n * Returns `true` if the value was created by `readonly()`.\n */\nexport function isReadonly(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[V_IS_READONLY] === true\n )\n}\n\n/**\n * Returns `true` if the value is either reactive or readonly.\n */\nexport function isProxy(value: unknown): boolean {\n return isReactive(value) || isReadonly(value)\n}\n\n/**\n * Marks an object so that `reactive()` will return it as-is (not wrapped).\n */\nexport function markRaw<T extends object>(obj: T): T {\n ;(obj as Record<symbol, boolean>)[V_SKIP] = true\n return obj\n}\n\n// ─── effectScope / getCurrentScope / onScopeDispose ──────────────────────────\n\nexport interface EffectScopeCompat {\n /** Run a function within this scope. Returns undefined if scope is stopped. */\n run<T>(fn: () => T): T | undefined\n /** Stop the scope and dispose all collected effects/cleanups. */\n stop(): void\n /** Whether the scope is still active. */\n active: boolean\n}\n\nlet _currentEffectScope: EffectScopeCompat | null = null\n\n/**\n * Creates an effect scope that collects reactive effects for grouped disposal.\n *\n * @param detached - If true, the scope is not collected by a parent scope.\n */\nexport function effectScope(detached?: boolean): EffectScopeCompat {\n const cleanups: (() => void)[] = []\n let active = true\n\n const scope: EffectScopeCompat = {\n get active() {\n return active\n },\n run<T>(fn: () => T): T | undefined {\n if (!active) return undefined\n const prev = _currentEffectScope\n _currentEffectScope = scope\n try {\n return fn()\n } finally {\n _currentEffectScope = prev\n }\n },\n stop() {\n if (!active) return\n active = false\n for (const fn of cleanups) fn()\n cleanups.length = 0\n },\n }\n\n // Auto-collect in parent scope unless detached\n if (!detached && _currentEffectScope) {\n const parentCleanups = (_currentEffectScope as EffectScopeCompat & { _cleanups?: (() => void)[] })\n ._cleanups\n if (parentCleanups) parentCleanups.push(() => scope.stop())\n }\n ;(scope as EffectScopeCompat & { _cleanups: (() => void)[] })._cleanups = cleanups\n\n return scope\n}\n\n/**\n * Returns the current active effect scope, or undefined if none.\n */\nexport function getCurrentScope(): EffectScopeCompat | undefined {\n return _currentEffectScope ?? undefined\n}\n\n/**\n * Registers a cleanup function on the current effect scope.\n */\nexport function onScopeDispose(fn: () => void): void {\n if (_currentEffectScope) {\n ;(\n _currentEffectScope as EffectScopeCompat & { _cleanups: (() => void)[] }\n )._cleanups.push(fn)\n }\n}\n\n// ─── onErrorCaptured / onRenderTracked / onRenderTriggered ───────────────────\n\n/**\n * Registers an error capture handler.\n * No direct equivalent in Pyreon — stored but not actively used.\n */\nexport function onErrorCaptured(fn: (err: Error) => boolean | void): void {\n const ctx = getCurrentCtx()\n if (ctx) {\n const idx = getHookIndex()\n if (idx < ctx.hooks.length) return\n ctx.hooks[idx] = fn\n }\n}\n\n/**\n * Dev-only lifecycle hook — no-op in Pyreon.\n */\nexport function onRenderTracked(\n _fn: (event: { key: string; type: string }) => void,\n): void {\n // Dev-only hook — no equivalent in Pyreon\n}\n\n/**\n * Dev-only lifecycle hook — no-op in Pyreon.\n */\nexport function onRenderTriggered(\n _fn: (event: { key: string; type: string }) => void,\n): void {\n // Dev-only hook — no equivalent in Pyreon\n}\n\n// ─── Teleport / KeepAlive ────────────────────────────────────────────────────\n\n/**\n * Teleport — renders children into a different DOM element.\n * Maps to Pyreon's Portal.\n */\nexport function Teleport(props: {\n to: string | Element\n children?: VNodeChild\n}): VNodeChild {\n const target =\n typeof props.to === 'string' ? document.querySelector(props.to) : props.to\n if (!target) return props.children ?? null\n return Portal({ target, children: props.children ?? null })\n}\n\n/**\n * KeepAlive — not supported in Pyreon. Renders children as-is.\n */\nexport function KeepAlive(props: { children?: VNodeChild }): VNodeChild {\n return props.children ?? null\n}\n\n// ─── watchPostEffect / watchSyncEffect ───────────────────────────────────────\n\n/**\n * Runs a watchEffect that flushes after DOM updates.\n * In Pyreon, same as `watchEffect()`.\n */\nexport function watchPostEffect(\n fn: (onCleanup: (fn: () => void) => void) => void,\n): () => void {\n return watchEffect(fn)\n}\n\n/**\n * Runs a watchEffect that flushes synchronously.\n * In Pyreon, same as `watchEffect()`.\n */\nexport function watchSyncEffect(\n fn: (onCleanup: (fn: () => void) => void) => void,\n): () => void {\n return watchEffect(fn)\n}\n\n// ─── customRef ───────────────────────────────────────────────────────────────\n\n/**\n * Creates a customized ref with explicit control over dependency tracking\n * and update triggering.\n */\nexport function customRef<T>(\n factory: (\n track: () => void,\n trigger: () => void,\n ) => { get: () => T; set: (v: T) => void },\n): Ref<T> {\n const s = signal(0)\n const { get, set } = factory(\n () => { s(); return undefined as never }, // track — reading the signal subscribes\n () => s.set(s.peek() + 1), // trigger — bump version to re-notify\n )\n return {\n [V_IS_REF]: true as const,\n get value(): T {\n return get()\n },\n set value(v: T) {\n set(v)\n },\n } as Ref<T>\n}\n\n// ─── version ─────────────────────────────────────────────────────────────────\n\n/**\n * Compatibility version string — indicates Vue 3 API compatibility.\n */\nexport const version = '3.5.0-pyreon'\n\n// ─── Type exports ────────────────────────────────────────────────────────────\n\nexport type { ComponentFn as Component } from '@pyreon/core'\nexport type { VNodeChild as VNode } from '@pyreon/core'\n\n/** Vue-compatible PropType — a callable that returns T. */\nexport type PropType<T> = { (): T }\n\n/** Extract prop types from a component's props definition. */\nexport type ExtractPropTypes<T> = {\n [K in keyof T]: T[K] extends PropType<infer V> ? V : T[K]\n}\n\n/** Vue-compatible emits options type. */\nexport type EmitsOptions = Record<string, (...args: unknown[]) => void>\n\n/** Vue-compatible setup context. */\nexport type SetupContext = {\n emit: (event: string, ...args: unknown[]) => void\n slots: Record<string, (() => VNodeChild) | undefined>\n attrs: Record<string, unknown>\n}\n\n/** Vue-compatible plugin interface. */\nexport type Plugin = { install: (app: App) => void }\n\n/** Vue-compatible directive type (stub). */\nexport type Directive = Record<string, unknown>\n\n/** Vue-compatible injection key with type branding. */\nexport type InjectionKey<T> = symbol & { __type: T }\n\n// ─── Additional re-exports ────────────────────────────────────────────────────\n\nexport { batch } from '@pyreon/reactivity'\n"],"mappings":"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"}
@@ -84,6 +84,15 @@ function jsx(type, props, key) {
84
84
  ...propsWithKey,
85
85
  children
86
86
  } : propsWithKey);
87
+ if (typeof type === "string" && propsWithKey.ref != null) {
88
+ const r = propsWithKey.ref;
89
+ if (typeof r === "object" && r !== null && r[Symbol.for("__v_isRef")] === true) {
90
+ const vueRef = r;
91
+ propsWithKey.ref = (el) => {
92
+ vueRef.value = el;
93
+ };
94
+ }
95
+ }
87
96
  return h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
88
97
  }
89
98
  const jsxs = jsx;
@@ -1 +1 @@
1
- {"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx-runtime.ts"],"sourcesContent":["/**\n * Compat JSX runtime for Vue compatibility mode.\n *\n * When `jsxImportSource` is redirected to `@pyreon/vue-compat` (via the vite\n * plugin's `compat: \"vue\"` option), OXC rewrites JSX to import from this file.\n *\n * For component VNodes, we wrap the component function so it returns a reactive\n * accessor — enabling Vue-style re-renders on state change while Pyreon's\n * existing renderer handles all DOM work.\n *\n * Key difference from react/preact compat: the component body runs inside\n * `runUntracked` to prevent `.value` reads (which access underlying signals)\n * from being tracked by the reactive accessor. Only the version signal\n * triggers re-renders.\n */\n\nimport type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'\nimport { Fragment, h, onUnmount } from '@pyreon/core'\nimport { runUntracked, signal } from '@pyreon/reactivity'\n\nexport { Fragment }\n\n// ─── Render context (used by hooks) ──────────────────────────────────────────\n\nexport interface RenderContext {\n hooks: unknown[]\n scheduleRerender: () => void\n /** Effect entries pending execution after render */\n pendingEffects: EffectEntry[]\n /** Layout effect entries pending execution after render */\n pendingLayoutEffects: EffectEntry[]\n /** Set to true when the component is unmounted */\n unmounted: boolean\n /** Callbacks to run on unmount (lifecycle + effect cleanups) */\n unmountCallbacks: (() => void)[]\n}\n\nexport interface EffectEntry {\n fn: () => (() => void) | void\n deps: unknown[] | undefined\n cleanup: (() => void) | undefined\n}\n\nlet _currentCtx: RenderContext | null = null\nlet _hookIndex = 0\n\nexport function getCurrentCtx(): RenderContext | null {\n return _currentCtx\n}\n\nexport function getHookIndex(): number {\n return _hookIndex++\n}\n\nexport function beginRender(ctx: RenderContext): void {\n _currentCtx = ctx\n _hookIndex = 0\n ctx.pendingEffects = []\n ctx.pendingLayoutEffects = []\n}\n\nexport function endRender(): void {\n _currentCtx = null\n _hookIndex = 0\n}\n\n// ─── Effect runners ──────────────────────────────────────────────────────────\n\nfunction runLayoutEffects(entries: EffectEntry[]): void {\n for (const entry of entries) {\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n}\n\nfunction scheduleEffects(ctx: RenderContext, entries: EffectEntry[]): void {\n if (entries.length === 0) return\n queueMicrotask(() => {\n for (const entry of entries) {\n if (ctx.unmounted) return\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n })\n}\n\n// ─── Component wrapping ──────────────────────────────────────────────────────\n\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\nfunction wrapCompatComponent(vueComponent: Function): ComponentFn {\n let wrapped = _wrapperCache.get(vueComponent)\n if (wrapped) return wrapped\n\n // The wrapper returns a reactive accessor (() => VNodeChild) which Pyreon's\n // mountChild treats as a reactive expression via mountReactive.\n wrapped = ((props: Props) => {\n const ctx: RenderContext = {\n hooks: [],\n scheduleRerender: () => {\n // Will be replaced below after version signal is created\n },\n pendingEffects: [],\n pendingLayoutEffects: [],\n unmounted: false,\n unmountCallbacks: [],\n }\n\n const version = signal(0)\n let updateScheduled = false\n\n ctx.scheduleRerender = () => {\n if (ctx.unmounted || updateScheduled) return\n updateScheduled = true\n queueMicrotask(() => {\n updateScheduled = false\n if (!ctx.unmounted) version.set(version.peek() + 1)\n })\n }\n\n // Register cleanup when component unmounts\n onUnmount(() => {\n ctx.unmounted = true\n for (const cb of ctx.unmountCallbacks) cb()\n })\n\n // Return reactive accessor — Pyreon's mountChild calls mountReactive\n return () => {\n version() // tracked read — triggers re-execution when state changes\n beginRender(ctx)\n // runUntracked prevents .value signal reads from being tracked by this accessor —\n // only the version signal should trigger re-renders\n const result = runUntracked(() => (vueComponent as ComponentFn)(props))\n const layoutEffects = ctx.pendingLayoutEffects\n const effects = ctx.pendingEffects\n endRender()\n\n runLayoutEffects(layoutEffects)\n scheduleEffects(ctx, effects)\n\n return result\n }\n }) as unknown as ComponentFn\n\n _wrapperCache.set(vueComponent, wrapped)\n return wrapped\n}\n\n// ─── JSX functions ───────────────────────────────────────────────────────────\n\nexport function jsx(\n type: string | ComponentFn | symbol,\n props: Props & { children?: VNodeChild | VNodeChild[] },\n key?: string | number | null,\n): VNode {\n const { children, ...rest } = props\n const propsWithKey = (key != null ? { ...rest, key } : rest) as Props\n\n if (typeof type === 'function') {\n // Wrap Vue-style component for re-render support\n const wrapped = wrapCompatComponent(type)\n const componentProps = children !== undefined ? { ...propsWithKey, children } : propsWithKey\n return h(wrapped, componentProps)\n }\n\n // DOM element or symbol (Fragment): children go in vnode.children\n const childArray = children === undefined ? [] : Array.isArray(children) ? children : [children]\n\n return h(type, propsWithKey, ...(childArray as VNodeChild[]))\n}\n\nexport const jsxs = jsx\nexport const jsxDEV = jsx\n"],"mappings":";;;;AA2CA,IAAI,cAAoC;AACxC,IAAI,aAAa;AAUjB,SAAgB,YAAY,KAA0B;AACpD,eAAc;AACd,cAAa;AACb,KAAI,iBAAiB,EAAE;AACvB,KAAI,uBAAuB,EAAE;;AAG/B,SAAgB,YAAkB;AAChC,eAAc;AACd,cAAa;;AAKf,SAAS,iBAAiB,SAA8B;AACtD,MAAK,MAAM,SAAS,SAAS;AAC3B,MAAI,MAAM,QAAS,OAAM,SAAS;EAClC,MAAM,UAAU,MAAM,IAAI;AAC1B,QAAM,UAAU,OAAO,YAAY,aAAa,UAAU;;;AAI9D,SAAS,gBAAgB,KAAoB,SAA8B;AACzE,KAAI,QAAQ,WAAW,EAAG;AAC1B,sBAAqB;AACnB,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,IAAI,UAAW;AACnB,OAAI,MAAM,QAAS,OAAM,SAAS;GAClC,MAAM,UAAU,MAAM,IAAI;AAC1B,SAAM,UAAU,OAAO,YAAY,aAAa,UAAU;;GAE5D;;AAKJ,MAAM,gCAAgB,IAAI,SAAgC;AAE1D,SAAS,oBAAoB,cAAqC;CAChE,IAAI,UAAU,cAAc,IAAI,aAAa;AAC7C,KAAI,QAAS,QAAO;AAIpB,aAAY,UAAiB;EAC3B,MAAM,MAAqB;GACzB,OAAO,EAAE;GACT,wBAAwB;GAGxB,gBAAgB,EAAE;GAClB,sBAAsB,EAAE;GACxB,WAAW;GACX,kBAAkB,EAAE;GACrB;EAED,MAAM,UAAU,OAAO,EAAE;EACzB,IAAI,kBAAkB;AAEtB,MAAI,yBAAyB;AAC3B,OAAI,IAAI,aAAa,gBAAiB;AACtC,qBAAkB;AAClB,wBAAqB;AACnB,sBAAkB;AAClB,QAAI,CAAC,IAAI,UAAW,SAAQ,IAAI,QAAQ,MAAM,GAAG,EAAE;KACnD;;AAIJ,kBAAgB;AACd,OAAI,YAAY;AAChB,QAAK,MAAM,MAAM,IAAI,iBAAkB,KAAI;IAC3C;AAGF,eAAa;AACX,YAAS;AACT,eAAY,IAAI;GAGhB,MAAM,SAAS,mBAAoB,aAA6B,MAAM,CAAC;GACvE,MAAM,gBAAgB,IAAI;GAC1B,MAAM,UAAU,IAAI;AACpB,cAAW;AAEX,oBAAiB,cAAc;AAC/B,mBAAgB,KAAK,QAAQ;AAE7B,UAAO;;;AAIX,eAAc,IAAI,cAAc,QAAQ;AACxC,QAAO;;AAKT,SAAgB,IACd,MACA,OACA,KACO;CACP,MAAM,EAAE,UAAU,GAAG,SAAS;CAC9B,MAAM,eAAgB,OAAO,OAAO;EAAE,GAAG;EAAM;EAAK,GAAG;AAEvD,KAAI,OAAO,SAAS,WAIlB,QAAO,EAFS,oBAAoB,KAAK,EAClB,aAAa,SAAY;EAAE,GAAG;EAAc;EAAU,GAAG,aAC/C;AAMnC,QAAO,EAAE,MAAM,cAAc,GAFV,aAAa,SAAY,EAAE,GAAG,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS,CAEnC;;AAG/D,MAAa,OAAO"}
1
+ {"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx-runtime.ts"],"sourcesContent":["/**\n * Compat JSX runtime for Vue compatibility mode.\n *\n * When `jsxImportSource` is redirected to `@pyreon/vue-compat` (via the vite\n * plugin's `compat: \"vue\"` option), OXC rewrites JSX to import from this file.\n *\n * For component VNodes, we wrap the component function so it returns a reactive\n * accessor — enabling Vue-style re-renders on state change while Pyreon's\n * existing renderer handles all DOM work.\n *\n * Key difference from react/preact compat: the component body runs inside\n * `runUntracked` to prevent `.value` reads (which access underlying signals)\n * from being tracked by the reactive accessor. Only the version signal\n * triggers re-renders.\n */\n\nimport type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'\nimport { Fragment, h, onUnmount } from '@pyreon/core'\nimport { runUntracked, signal } from '@pyreon/reactivity'\n\nexport { Fragment }\n\n// ─── Render context (used by hooks) ──────────────────────────────────────────\n\nexport interface RenderContext {\n hooks: unknown[]\n scheduleRerender: () => void\n /** Effect entries pending execution after render */\n pendingEffects: EffectEntry[]\n /** Layout effect entries pending execution after render */\n pendingLayoutEffects: EffectEntry[]\n /** Set to true when the component is unmounted */\n unmounted: boolean\n /** Callbacks to run on unmount (lifecycle + effect cleanups) */\n unmountCallbacks: (() => void)[]\n}\n\nexport interface EffectEntry {\n fn: () => (() => void) | void\n deps: unknown[] | undefined\n cleanup: (() => void) | undefined\n}\n\nlet _currentCtx: RenderContext | null = null\nlet _hookIndex = 0\n\nexport function getCurrentCtx(): RenderContext | null {\n return _currentCtx\n}\n\nexport function getHookIndex(): number {\n return _hookIndex++\n}\n\nexport function beginRender(ctx: RenderContext): void {\n _currentCtx = ctx\n _hookIndex = 0\n ctx.pendingEffects = []\n ctx.pendingLayoutEffects = []\n}\n\nexport function endRender(): void {\n _currentCtx = null\n _hookIndex = 0\n}\n\n// ─── Effect runners ──────────────────────────────────────────────────────────\n\nfunction runLayoutEffects(entries: EffectEntry[]): void {\n for (const entry of entries) {\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n}\n\nfunction scheduleEffects(ctx: RenderContext, entries: EffectEntry[]): void {\n if (entries.length === 0) return\n queueMicrotask(() => {\n for (const entry of entries) {\n if (ctx.unmounted) return\n if (entry.cleanup) entry.cleanup()\n const cleanup = entry.fn()\n entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined\n }\n })\n}\n\n// ─── Component wrapping ──────────────────────────────────────────────────────\n\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\nfunction wrapCompatComponent(vueComponent: Function): ComponentFn {\n let wrapped = _wrapperCache.get(vueComponent)\n if (wrapped) return wrapped\n\n // The wrapper returns a reactive accessor (() => VNodeChild) which Pyreon's\n // mountChild treats as a reactive expression via mountReactive.\n wrapped = ((props: Props) => {\n const ctx: RenderContext = {\n hooks: [],\n scheduleRerender: () => {\n // Will be replaced below after version signal is created\n },\n pendingEffects: [],\n pendingLayoutEffects: [],\n unmounted: false,\n unmountCallbacks: [],\n }\n\n const version = signal(0)\n let updateScheduled = false\n\n ctx.scheduleRerender = () => {\n if (ctx.unmounted || updateScheduled) return\n updateScheduled = true\n queueMicrotask(() => {\n updateScheduled = false\n if (!ctx.unmounted) version.set(version.peek() + 1)\n })\n }\n\n // Register cleanup when component unmounts\n onUnmount(() => {\n ctx.unmounted = true\n for (const cb of ctx.unmountCallbacks) cb()\n })\n\n // Return reactive accessor — Pyreon's mountChild calls mountReactive\n return () => {\n version() // tracked read — triggers re-execution when state changes\n beginRender(ctx)\n // runUntracked prevents .value signal reads from being tracked by this accessor —\n // only the version signal should trigger re-renders\n const result = runUntracked(() => (vueComponent as ComponentFn)(props))\n const layoutEffects = ctx.pendingLayoutEffects\n const effects = ctx.pendingEffects\n endRender()\n\n runLayoutEffects(layoutEffects)\n scheduleEffects(ctx, effects)\n\n return result\n }\n }) as unknown as ComponentFn\n\n _wrapperCache.set(vueComponent, wrapped)\n return wrapped\n}\n\n// ─── JSX functions ───────────────────────────────────────────────────────────\n\nexport function jsx(\n type: string | ComponentFn | symbol,\n props: Props & { children?: VNodeChild | VNodeChild[] },\n key?: string | number | null,\n): VNode {\n const { children, ...rest } = props\n const propsWithKey = (key != null ? { ...rest, key } : rest) as Props\n\n if (typeof type === 'function') {\n // Wrap Vue-style component for re-render support\n const wrapped = wrapCompatComponent(type)\n const componentProps = children !== undefined ? { ...propsWithKey, children } : propsWithKey\n return h(wrapped, componentProps)\n }\n\n // DOM element: convert Vue ref ({ value }) to callback ref for Pyreon's runtime-dom\n if (typeof type === 'string' && propsWithKey.ref != null) {\n const r = propsWithKey.ref\n if (\n typeof r === 'object' &&\n r !== null &&\n (r as Record<symbol, unknown>)[Symbol.for('__v_isRef')] === true\n ) {\n const vueRef = r as { value: unknown }\n propsWithKey.ref = (el: Element | null) => {\n vueRef.value = el\n }\n }\n }\n\n // DOM element or symbol (Fragment): children go in vnode.children\n const childArray = children === undefined ? [] : Array.isArray(children) ? children : [children]\n\n return h(type, propsWithKey, ...(childArray as VNodeChild[]))\n}\n\nexport const jsxs = jsx\nexport const jsxDEV = jsx\n"],"mappings":";;;;AA2CA,IAAI,cAAoC;AACxC,IAAI,aAAa;AAUjB,SAAgB,YAAY,KAA0B;AACpD,eAAc;AACd,cAAa;AACb,KAAI,iBAAiB,EAAE;AACvB,KAAI,uBAAuB,EAAE;;AAG/B,SAAgB,YAAkB;AAChC,eAAc;AACd,cAAa;;AAKf,SAAS,iBAAiB,SAA8B;AACtD,MAAK,MAAM,SAAS,SAAS;AAC3B,MAAI,MAAM,QAAS,OAAM,SAAS;EAClC,MAAM,UAAU,MAAM,IAAI;AAC1B,QAAM,UAAU,OAAO,YAAY,aAAa,UAAU;;;AAI9D,SAAS,gBAAgB,KAAoB,SAA8B;AACzE,KAAI,QAAQ,WAAW,EAAG;AAC1B,sBAAqB;AACnB,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,IAAI,UAAW;AACnB,OAAI,MAAM,QAAS,OAAM,SAAS;GAClC,MAAM,UAAU,MAAM,IAAI;AAC1B,SAAM,UAAU,OAAO,YAAY,aAAa,UAAU;;GAE5D;;AAKJ,MAAM,gCAAgB,IAAI,SAAgC;AAE1D,SAAS,oBAAoB,cAAqC;CAChE,IAAI,UAAU,cAAc,IAAI,aAAa;AAC7C,KAAI,QAAS,QAAO;AAIpB,aAAY,UAAiB;EAC3B,MAAM,MAAqB;GACzB,OAAO,EAAE;GACT,wBAAwB;GAGxB,gBAAgB,EAAE;GAClB,sBAAsB,EAAE;GACxB,WAAW;GACX,kBAAkB,EAAE;GACrB;EAED,MAAM,UAAU,OAAO,EAAE;EACzB,IAAI,kBAAkB;AAEtB,MAAI,yBAAyB;AAC3B,OAAI,IAAI,aAAa,gBAAiB;AACtC,qBAAkB;AAClB,wBAAqB;AACnB,sBAAkB;AAClB,QAAI,CAAC,IAAI,UAAW,SAAQ,IAAI,QAAQ,MAAM,GAAG,EAAE;KACnD;;AAIJ,kBAAgB;AACd,OAAI,YAAY;AAChB,QAAK,MAAM,MAAM,IAAI,iBAAkB,KAAI;IAC3C;AAGF,eAAa;AACX,YAAS;AACT,eAAY,IAAI;GAGhB,MAAM,SAAS,mBAAoB,aAA6B,MAAM,CAAC;GACvE,MAAM,gBAAgB,IAAI;GAC1B,MAAM,UAAU,IAAI;AACpB,cAAW;AAEX,oBAAiB,cAAc;AAC/B,mBAAgB,KAAK,QAAQ;AAE7B,UAAO;;;AAIX,eAAc,IAAI,cAAc,QAAQ;AACxC,QAAO;;AAKT,SAAgB,IACd,MACA,OACA,KACO;CACP,MAAM,EAAE,UAAU,GAAG,SAAS;CAC9B,MAAM,eAAgB,OAAO,OAAO;EAAE,GAAG;EAAM;EAAK,GAAG;AAEvD,KAAI,OAAO,SAAS,WAIlB,QAAO,EAFS,oBAAoB,KAAK,EAClB,aAAa,SAAY;EAAE,GAAG;EAAc;EAAU,GAAG,aAC/C;AAInC,KAAI,OAAO,SAAS,YAAY,aAAa,OAAO,MAAM;EACxD,MAAM,IAAI,aAAa;AACvB,MACE,OAAO,MAAM,YACb,MAAM,QACL,EAA8B,OAAO,IAAI,YAAY,MAAM,MAC5D;GACA,MAAM,SAAS;AACf,gBAAa,OAAO,OAAuB;AACzC,WAAO,QAAQ;;;;AAQrB,QAAO,EAAE,MAAM,cAAc,GAFV,aAAa,SAAY,EAAE,GAAG,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS,CAEnC;;AAG/D,MAAa,OAAO"}
@@ -1,4 +1,4 @@
1
- import { ComponentFn, Fragment, Props, VNodeChild, h as pyreonH } from "@pyreon/core";
1
+ import { ComponentFn, ComponentFn as Component, Fragment, Props, VNodeChild, VNodeChild as VNode, h as pyreonH } from "@pyreon/core";
2
2
  import { batch } from "@pyreon/reactivity";
3
3
 
4
4
  //#region src/index.d.ts
@@ -31,6 +31,11 @@ declare function isRef(val: unknown): val is Ref;
31
31
  * Unwraps a ref: if it has `.value`, return `.value`; otherwise return as-is.
32
32
  */
33
33
  declare function unref<T>(r: T | Ref<T>): T;
34
+ /**
35
+ * Unwraps a ref, calls a getter, or returns the value as-is.
36
+ * Vue 3.3+ API for normalizing ref/getter/value inputs.
37
+ */
38
+ declare function toValue<T>(source: Ref<T> | (() => T) | T): T;
34
39
  interface ComputedRef<T = unknown> extends Ref<T> {
35
40
  readonly value: T;
36
41
  }
@@ -65,6 +70,11 @@ declare function shallowReactive<T extends object>(obj: T): T;
65
70
  * Inside a component: hook-indexed.
66
71
  */
67
72
  declare function readonly<T extends object>(obj: T): Readonly<T>;
73
+ /**
74
+ * Returns a shallow readonly proxy — only top-level properties throw on set.
75
+ * Nested objects are NOT wrapped in readonly (unlike `readonly()`).
76
+ */
77
+ declare function shallowReadonly<T extends object>(obj: T): Readonly<T>;
68
78
  /**
69
79
  * Returns the raw (unwrapped) object behind a reactive or readonly proxy.
70
80
  */
@@ -88,21 +98,25 @@ interface WatchOptions {
88
98
  immediate?: boolean;
89
99
  /** Ignored in Pyreon — dependencies are tracked automatically. */
90
100
  deep?: boolean;
101
+ /** Accepted for compatibility but not meaningfully differentiated in Pyreon. */
102
+ flush?: 'pre' | 'post' | 'sync';
91
103
  }
92
104
  type WatchSource<T> = Ref<T> | (() => T);
93
105
  /**
94
- * Watches a reactive source and calls `cb` when it changes.
106
+ * Watches a reactive source (or array of sources) and calls `cb` when it changes.
95
107
  *
96
108
  * Inside a component: hook-indexed, created once. Disposed on unmount.
97
109
  */
98
- declare function watch<T>(source: WatchSource<T>, cb: (newValue: T, oldValue: T | undefined) => void, options?: WatchOptions): () => void;
110
+ declare function watch<T>(source: WatchSource<T>, cb: (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void, options?: WatchOptions): () => void;
111
+ declare function watch<T extends readonly WatchSource<any>[]>(sources: [...T], cb: (newValues: { [K in keyof T]: T[K] extends WatchSource<infer V> ? V : never }, oldValues: { [K in keyof T]: T[K] extends WatchSource<infer V> ? V | undefined : never }, onCleanup: (fn: () => void) => void) => void, options?: WatchOptions): () => void;
99
112
  /**
100
113
  * Runs the given function reactively — re-executes whenever its tracked
101
- * dependencies change.
114
+ * dependencies change. Passes an `onCleanup` registration function to the
115
+ * callback, matching Vue 3's `watchEffect((onCleanup) => { ... })` API.
102
116
  *
103
117
  * Inside a component: hook-indexed, created once. Disposed on unmount.
104
118
  */
105
- declare function watchEffect(fn: () => void): () => void;
119
+ declare function watchEffect(fn: (onCleanup: (fn: () => void) => void) => void): () => void;
106
120
  /**
107
121
  * Registers a callback to run after the component is mounted.
108
122
  * Hook-indexed: only registered on first render.
@@ -140,27 +154,173 @@ declare function nextTick(): Promise<void>;
140
154
  declare function provide<T>(key: string | symbol, value: T): void;
141
155
  /**
142
156
  * Injects a value provided by an ancestor component.
157
+ * Supports Vue 3's factory default pattern: `inject(key, () => expensiveDefault, true)`.
143
158
  */
144
- declare function inject<T>(key: string | symbol, defaultValue?: T): T | undefined;
159
+ declare function inject<T>(key: string | symbol, defaultValue?: T | (() => T), treatDefaultAsFactory?: boolean): T | undefined;
145
160
  interface ComponentOptions<P extends Props = Props> {
146
161
  /** The setup function — called once during component initialization. */
147
- setup: (props: P) => (() => VNodeChild) | VNodeChild;
162
+ setup: (props: P, ctx?: SetupContext) => (() => VNodeChild) | VNodeChild;
148
163
  /** Optional name for debugging. */
149
164
  name?: string;
165
+ /** Prop definitions (not validated at runtime, used for type documentation). */
166
+ props?: Record<string, unknown>;
150
167
  }
151
168
  /**
152
169
  * Defines a component using Vue 3 Composition API style.
153
170
  * Only supports the `setup()` function — Options API is not supported.
154
171
  */
155
172
  declare function defineComponent<P extends Props = Props>(options: ComponentOptions<P> | ((props: P) => VNodeChild)): ComponentFn<P>;
173
+ /**
174
+ * Defines an async component that lazily loads on first use.
175
+ * Supports both a bare loader function and an options object with
176
+ * loadingComponent, errorComponent, delay, and timeout.
177
+ *
178
+ * Returns a ComponentFn with a `__loading` property for Suspense integration.
179
+ */
180
+ declare function defineAsyncComponent<P extends Props = Props>(loader: (() => Promise<{
181
+ default: ComponentFn<P>;
182
+ }>) | {
183
+ loader: () => Promise<{
184
+ default: ComponentFn<P>;
185
+ }>;
186
+ loadingComponent?: ComponentFn;
187
+ errorComponent?: ComponentFn;
188
+ delay?: number;
189
+ timeout?: number;
190
+ }): ComponentFn<P> & {
191
+ __loading: () => boolean;
192
+ };
156
193
  interface App {
157
194
  /** Mount the application into a DOM element. Returns an unmount function. */
158
195
  mount(el: string | Element): () => void;
196
+ /** Install a plugin. */
197
+ use(plugin: {
198
+ install: (app: App) => void;
199
+ }): App;
200
+ /** Provide a value to the entire app tree. */
201
+ provide<T>(key: string | symbol, value: T): App;
159
202
  }
160
203
  /**
161
204
  * Creates a Pyreon application instance — Vue 3 `createApp()` compatible.
162
205
  */
163
206
  declare function createApp(component: ComponentFn, props?: Props): App;
207
+ /**
208
+ * Returns `true` if the value was created by `reactive()`.
209
+ */
210
+ declare function isReactive(value: unknown): boolean;
211
+ /**
212
+ * Returns `true` if the value was created by `readonly()`.
213
+ */
214
+ declare function isReadonly(value: unknown): boolean;
215
+ /**
216
+ * Returns `true` if the value is either reactive or readonly.
217
+ */
218
+ declare function isProxy(value: unknown): boolean;
219
+ /**
220
+ * Marks an object so that `reactive()` will return it as-is (not wrapped).
221
+ */
222
+ declare function markRaw<T extends object>(obj: T): T;
223
+ interface EffectScopeCompat {
224
+ /** Run a function within this scope. Returns undefined if scope is stopped. */
225
+ run<T>(fn: () => T): T | undefined;
226
+ /** Stop the scope and dispose all collected effects/cleanups. */
227
+ stop(): void;
228
+ /** Whether the scope is still active. */
229
+ active: boolean;
230
+ }
231
+ /**
232
+ * Creates an effect scope that collects reactive effects for grouped disposal.
233
+ *
234
+ * @param detached - If true, the scope is not collected by a parent scope.
235
+ */
236
+ declare function effectScope(detached?: boolean): EffectScopeCompat;
237
+ /**
238
+ * Returns the current active effect scope, or undefined if none.
239
+ */
240
+ declare function getCurrentScope(): EffectScopeCompat | undefined;
241
+ /**
242
+ * Registers a cleanup function on the current effect scope.
243
+ */
244
+ declare function onScopeDispose(fn: () => void): void;
245
+ /**
246
+ * Registers an error capture handler.
247
+ * No direct equivalent in Pyreon — stored but not actively used.
248
+ */
249
+ declare function onErrorCaptured(fn: (err: Error) => boolean | void): void;
250
+ /**
251
+ * Dev-only lifecycle hook — no-op in Pyreon.
252
+ */
253
+ declare function onRenderTracked(_fn: (event: {
254
+ key: string;
255
+ type: string;
256
+ }) => void): void;
257
+ /**
258
+ * Dev-only lifecycle hook — no-op in Pyreon.
259
+ */
260
+ declare function onRenderTriggered(_fn: (event: {
261
+ key: string;
262
+ type: string;
263
+ }) => void): void;
264
+ /**
265
+ * Teleport — renders children into a different DOM element.
266
+ * Maps to Pyreon's Portal.
267
+ */
268
+ declare function Teleport(props: {
269
+ to: string | Element;
270
+ children?: VNodeChild;
271
+ }): VNodeChild;
272
+ /**
273
+ * KeepAlive — not supported in Pyreon. Renders children as-is.
274
+ */
275
+ declare function KeepAlive(props: {
276
+ children?: VNodeChild;
277
+ }): VNodeChild;
278
+ /**
279
+ * Runs a watchEffect that flushes after DOM updates.
280
+ * In Pyreon, same as `watchEffect()`.
281
+ */
282
+ declare function watchPostEffect(fn: (onCleanup: (fn: () => void) => void) => void): () => void;
283
+ /**
284
+ * Runs a watchEffect that flushes synchronously.
285
+ * In Pyreon, same as `watchEffect()`.
286
+ */
287
+ declare function watchSyncEffect(fn: (onCleanup: (fn: () => void) => void) => void): () => void;
288
+ /**
289
+ * Creates a customized ref with explicit control over dependency tracking
290
+ * and update triggering.
291
+ */
292
+ declare function customRef<T>(factory: (track: () => void, trigger: () => void) => {
293
+ get: () => T;
294
+ set: (v: T) => void;
295
+ }): Ref<T>;
296
+ /**
297
+ * Compatibility version string — indicates Vue 3 API compatibility.
298
+ */
299
+ declare const version = "3.5.0-pyreon";
300
+ /** Vue-compatible PropType — a callable that returns T. */
301
+ type PropType<T> = {
302
+ (): T;
303
+ };
304
+ /** Extract prop types from a component's props definition. */
305
+ type ExtractPropTypes<T> = { [K in keyof T]: T[K] extends PropType<infer V> ? V : T[K] };
306
+ /** Vue-compatible emits options type. */
307
+ type EmitsOptions = Record<string, (...args: unknown[]) => void>;
308
+ /** Vue-compatible setup context. */
309
+ type SetupContext = {
310
+ emit: (event: string, ...args: unknown[]) => void;
311
+ slots: Record<string, (() => VNodeChild) | undefined>;
312
+ attrs: Record<string, unknown>;
313
+ };
314
+ /** Vue-compatible plugin interface. */
315
+ type Plugin = {
316
+ install: (app: App) => void;
317
+ };
318
+ /** Vue-compatible directive type (stub). */
319
+ type Directive = Record<string, unknown>;
320
+ /** Vue-compatible injection key with type branding. */
321
+ type InjectionKey<T> = symbol & {
322
+ __type: T;
323
+ };
164
324
  //#endregion
165
- export { ComputedRef, Fragment, Ref, WatchOptions, WritableComputedRef, batch, computed, createApp, defineComponent, pyreonH as h, inject, isRef, nextTick, onBeforeMount, onBeforeUnmount, onMounted, onUnmounted, onUpdated, provide, reactive, readonly, ref, shallowReactive, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, watch, watchEffect };
325
+ export { type Component, ComputedRef, Directive, EffectScopeCompat, EmitsOptions, ExtractPropTypes, Fragment, InjectionKey, KeepAlive, Plugin, PropType, Ref, SetupContext, Teleport, type VNode, WatchOptions, WritableComputedRef, batch, computed, createApp, customRef, defineAsyncComponent, defineComponent, effectScope, getCurrentScope, pyreonH as h, inject, isProxy, isReactive, isReadonly, isRef, markRaw, nextTick, onBeforeMount, onBeforeUnmount, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onUnmounted, onUpdated, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, toValue, triggerRef, unref, version, watch, watchEffect, watchPostEffect, watchSyncEffect };
166
326
  //# sourceMappingURL=index2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/index.ts"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"jsx-runtime2.d.ts","names":[],"sources":["../../../src/jsx-runtime.ts"],"mappings":";;;iBAwJgB,GAAA,CACd,IAAA,WAAe,WAAA,WACf,KAAA,EAAO,KAAA;EAAU,QAAA,GAAW,UAAA,GAAa,UAAA;AAAA,GACzC,GAAA,4BACC,KAAA;AAAA,cAiBU,IAAA,SAAI,GAAA"}
1
+ {"version":3,"file":"jsx-runtime2.d.ts","names":[],"sources":["../../../src/jsx-runtime.ts"],"mappings":";;;iBAwJgB,GAAA,CACd,IAAA,WAAe,WAAA,WACf,KAAA,EAAO,KAAA;EAAU,QAAA,GAAW,UAAA,GAAa,UAAA;AAAA,GACzC,GAAA,4BACC,KAAA;AAAA,cAgCU,IAAA,SAAI,GAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/vue-compat",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Vue 3-compatible Composition API shim for Pyreon — write Vue-style code that runs on Pyreon's reactive engine",
5
5
  "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/vue-compat#readme",
6
6
  "bugs": {
@@ -52,9 +52,9 @@
52
52
  "prepublishOnly": "bun run build"
53
53
  },
54
54
  "dependencies": {
55
- "@pyreon/core": "^0.13.0",
56
- "@pyreon/reactivity": "^0.13.0",
57
- "@pyreon/runtime-dom": "^0.13.0"
55
+ "@pyreon/core": "^0.14.0",
56
+ "@pyreon/reactivity": "^0.14.0",
57
+ "@pyreon/runtime-dom": "^0.14.0"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@happy-dom/global-registrator": "^20.8.9",