@pyreon/vue-compat 0.11.5 → 0.11.6

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/README.md CHANGED
@@ -14,7 +14,7 @@ bun add @pyreon/vue-compat
14
14
  // Replace:
15
15
  // import { ref, computed, watch } from "vue"
16
16
  // With:
17
- import { ref, computed, watch } from "@pyreon/vue-compat"
17
+ import { ref, computed, watch } from '@pyreon/vue-compat'
18
18
 
19
19
  function Counter() {
20
20
  const count = ref(0)
@@ -36,13 +36,13 @@ function Counter() {
36
36
  ### Reactive Objects
37
37
 
38
38
  ```tsx
39
- import { reactive, watchEffect } from "@pyreon/vue-compat"
39
+ import { reactive, watchEffect } from '@pyreon/vue-compat'
40
40
 
41
41
  function UserForm() {
42
- const form = reactive({ name: "", email: "" })
42
+ const form = reactive({ name: '', email: '' })
43
43
 
44
44
  watchEffect(() => {
45
- console.log("form changed:", form.name, form.email)
45
+ console.log('form changed:', form.name, form.email)
46
46
  })
47
47
 
48
48
  return (
@@ -57,7 +57,9 @@ function UserForm() {
57
57
  onInput={(e) => (form.email = e.currentTarget.value)}
58
58
  placeholder="Email"
59
59
  />
60
- <p>Hello, {form.name} ({form.email})</p>
60
+ <p>
61
+ Hello, {form.name} ({form.email})
62
+ </p>
61
63
  </div>
62
64
  )
63
65
  }
@@ -66,16 +68,16 @@ function UserForm() {
66
68
  ### Provide / Inject
67
69
 
68
70
  ```tsx
69
- import { ref, provide, inject, defineComponent } from "@pyreon/vue-compat"
71
+ import { ref, provide, inject, defineComponent } from '@pyreon/vue-compat'
70
72
 
71
- const ThemeKey = Symbol("theme")
73
+ const ThemeKey = Symbol('theme')
72
74
 
73
75
  function ThemeProvider(props: { children: any }) {
74
- const theme = ref("light")
76
+ const theme = ref('light')
75
77
  provide(ThemeKey, theme)
76
78
  return (
77
79
  <div>
78
- <button onClick={() => (theme.value = theme.value === "light" ? "dark" : "light")}>
80
+ <button onClick={() => (theme.value = theme.value === 'light' ? 'dark' : 'light')}>
79
81
  Toggle theme
80
82
  </button>
81
83
  {props.children}
@@ -84,7 +86,7 @@ function ThemeProvider(props: { children: any }) {
84
86
  }
85
87
 
86
88
  function ThemedBox() {
87
- const theme = inject(ThemeKey, ref("light"))
89
+ const theme = inject(ThemeKey, ref('light'))
88
90
  return <div class={`box-${theme.value}`}>Theme: {theme.value}</div>
89
91
  }
90
92
  ```
@@ -92,15 +94,15 @@ function ThemedBox() {
92
94
  ### createApp
93
95
 
94
96
  ```tsx
95
- import { createApp, ref } from "@pyreon/vue-compat"
97
+ import { createApp, ref } from '@pyreon/vue-compat'
96
98
 
97
99
  function App() {
98
- const message = ref("Hello from Pyreon")
100
+ const message = ref('Hello from Pyreon')
99
101
  return <h1>{message.value}</h1>
100
102
  }
101
103
 
102
104
  const app = createApp(App)
103
- app.mount("#app")
105
+ app.mount('#app')
104
106
  ```
105
107
 
106
108
  ## Key Differences from Vue
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 // biome-ignore lint/suspicious/noConfusingVoidType: matches Vue's effect signature\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\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\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 // biome-ignore lint/suspicious/noConfusingVoidType: matches Vue's effect signature\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\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\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 +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 // biome-ignore lint/suspicious/noConfusingVoidType: matches Vue's effect signature\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\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\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":";;;;AA4CA,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;;AAMJ,MAAM,gCAAgB,IAAI,SAAgC;AAG1D,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 // biome-ignore lint/suspicious/noConfusingVoidType: matches Vue's effect signature\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\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\nconst _wrapperCache = new WeakMap<Function, ComponentFn>()\n\n// biome-ignore lint/complexity/noBannedTypes: Function is needed for generic component wrapping\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":";;;;AA4CA,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;;AAMJ,MAAM,gCAAgB,IAAI,SAAgC;AAG1D,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"}
package/package.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
2
  "name": "@pyreon/vue-compat",
3
- "version": "0.11.5",
3
+ "version": "0.11.6",
4
4
  "description": "Vue 3-compatible Composition API shim for Pyreon — write Vue-style code that runs on Pyreon's reactive engine",
5
+ "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/vue-compat#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/pyreon/pyreon/issues"
8
+ },
5
9
  "license": "MIT",
6
10
  "repository": {
7
11
  "type": "git",
8
12
  "url": "https://github.com/pyreon/pyreon.git",
9
13
  "directory": "packages/tools/vue-compat"
10
14
  },
11
- "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/vue-compat#readme",
12
- "bugs": {
13
- "url": "https://github.com/pyreon/pyreon/issues"
14
- },
15
15
  "files": [
16
16
  "lib",
17
17
  "src",
18
18
  "README.md",
19
19
  "LICENSE"
20
20
  ],
21
- "sideEffects": false,
22
21
  "type": "module",
22
+ "sideEffects": false,
23
23
  "main": "./lib/index.js",
24
24
  "module": "./lib/index.js",
25
25
  "types": "./lib/types/index.d.ts",
@@ -40,24 +40,24 @@
40
40
  "types": "./lib/types/jsx-runtime.d.ts"
41
41
  }
42
42
  },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
43
46
  "scripts": {
44
47
  "build": "vl_rolldown_build",
45
48
  "dev": "vl_rolldown_build-watch",
46
49
  "test": "vitest run",
47
50
  "typecheck": "tsc --noEmit",
48
- "lint": "biome check .",
51
+ "lint": "oxlint .",
49
52
  "prepublishOnly": "bun run build"
50
53
  },
51
54
  "dependencies": {
52
- "@pyreon/core": "^0.11.5",
53
- "@pyreon/reactivity": "^0.11.5",
54
- "@pyreon/runtime-dom": "^0.11.5"
55
+ "@pyreon/core": "^0.11.6",
56
+ "@pyreon/reactivity": "^0.11.6",
57
+ "@pyreon/runtime-dom": "^0.11.6"
55
58
  },
56
59
  "devDependencies": {
57
60
  "@happy-dom/global-registrator": "^20.8.3",
58
61
  "happy-dom": "^20.8.3"
59
- },
60
- "publishConfig": {
61
- "access": "public"
62
62
  }
63
63
  }
package/src/index.ts CHANGED
@@ -21,7 +21,7 @@
21
21
  * `import { ref, computed, watch } from "@pyreon/vue-compat"`
22
22
  */
23
23
 
24
- import type { ComponentFn, Props, VNodeChild } from "@pyreon/core"
24
+ import type { ComponentFn, Props, VNodeChild } from '@pyreon/core'
25
25
  import {
26
26
  createContext,
27
27
  Fragment,
@@ -32,7 +32,7 @@ import {
32
32
  pushContext,
33
33
  h as pyreonH,
34
34
  useContext,
35
- } from "@pyreon/core"
35
+ } from '@pyreon/core'
36
36
  import {
37
37
  createStore,
38
38
  effect,
@@ -40,15 +40,15 @@ import {
40
40
  nextTick as pyreonNextTick,
41
41
  type Signal,
42
42
  signal,
43
- } from "@pyreon/reactivity"
44
- import { mount as pyreonMount } from "@pyreon/runtime-dom"
45
- import { getCurrentCtx, getHookIndex } from "./jsx-runtime"
43
+ } from '@pyreon/reactivity'
44
+ import { mount as pyreonMount } from '@pyreon/runtime-dom'
45
+ import { getCurrentCtx, getHookIndex } from './jsx-runtime'
46
46
 
47
47
  // ─── Internal symbols ─────────────────────────────────────────────────────────
48
48
 
49
- const V_IS_REF = Symbol("__v_isRef")
50
- const V_IS_READONLY = Symbol("__v_isReadonly")
51
- const V_RAW = Symbol("__v_raw")
49
+ const V_IS_REF = Symbol('__v_isRef')
50
+ const V_IS_READONLY = Symbol('__v_isReadonly')
51
+ const V_RAW = Symbol('__v_raw')
52
52
 
53
53
  // ─── Ref ──────────────────────────────────────────────────────────────────────
54
54
 
@@ -133,7 +133,7 @@ export function triggerRef<T>(r: Ref<T>): void {
133
133
  */
134
134
  export function isRef(val: unknown): val is Ref {
135
135
  return (
136
- val !== null && typeof val === "object" && (val as Record<symbol, unknown>)[V_IS_REF] === true
136
+ val !== null && typeof val === 'object' && (val as Record<symbol, unknown>)[V_IS_REF] === true
137
137
  )
138
138
  }
139
139
 
@@ -172,8 +172,8 @@ export function computed<T>(
172
172
  const idx = getHookIndex()
173
173
  if (idx < ctx.hooks.length) return ctx.hooks[idx] as ComputedRef<T>
174
174
 
175
- const getter = typeof fnOrOptions === "function" ? fnOrOptions : fnOrOptions.get
176
- const setter = typeof fnOrOptions === "object" ? fnOrOptions.set : undefined
175
+ const getter = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.get
176
+ const setter = typeof fnOrOptions === 'object' ? fnOrOptions.set : undefined
177
177
  const c = pyreonComputed(getter)
178
178
  const { scheduleRerender } = ctx
179
179
  const r = {
@@ -183,7 +183,7 @@ export function computed<T>(
183
183
  },
184
184
  set value(v: T) {
185
185
  if (!setter) {
186
- throw new Error("Cannot set value of a computed ref — computed refs are readonly")
186
+ throw new Error('Cannot set value of a computed ref — computed refs are readonly')
187
187
  }
188
188
  setter(v)
189
189
  scheduleRerender()
@@ -194,8 +194,8 @@ export function computed<T>(
194
194
  }
195
195
 
196
196
  // Outside component
197
- const getter = typeof fnOrOptions === "function" ? fnOrOptions : fnOrOptions.get
198
- const setter = typeof fnOrOptions === "object" ? fnOrOptions.set : undefined
197
+ const getter = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.get
198
+ const setter = typeof fnOrOptions === 'object' ? fnOrOptions.set : undefined
199
199
  const c = pyreonComputed(getter)
200
200
  const r = {
201
201
  [V_IS_REF]: true as const,
@@ -204,7 +204,7 @@ export function computed<T>(
204
204
  },
205
205
  set value(v: T) {
206
206
  if (!setter) {
207
- throw new Error("Cannot set value of a computed ref — computed refs are readonly")
207
+ throw new Error('Cannot set value of a computed ref — computed refs are readonly')
208
208
  }
209
209
  setter(v)
210
210
  },
@@ -664,18 +664,18 @@ interface ComponentOptions<P extends Props = Props> {
664
664
  export function defineComponent<P extends Props = Props>(
665
665
  options: ComponentOptions<P> | ((props: P) => VNodeChild),
666
666
  ): ComponentFn<P> {
667
- if (typeof options === "function") {
667
+ if (typeof options === 'function') {
668
668
  return options as ComponentFn<P>
669
669
  }
670
670
  const comp = (props: P) => {
671
671
  const result = options.setup(props)
672
- if (typeof result === "function") {
672
+ if (typeof result === 'function') {
673
673
  return (result as () => VNodeChild)()
674
674
  }
675
675
  return result
676
676
  }
677
677
  if (options.name) {
678
- Object.defineProperty(comp, "name", { value: options.name })
678
+ Object.defineProperty(comp, 'name', { value: options.name })
679
679
  }
680
680
  return comp as ComponentFn<P>
681
681
  }
@@ -700,7 +700,7 @@ interface App {
700
700
  export function createApp(component: ComponentFn, props?: Props): App {
701
701
  return {
702
702
  mount(el: string | Element): () => void {
703
- const container = typeof el === "string" ? document.querySelector(el) : el
703
+ const container = typeof el === 'string' ? document.querySelector(el) : el
704
704
  if (!container) {
705
705
  throw new Error(`Cannot find mount target: ${el}`)
706
706
  }
@@ -712,4 +712,4 @@ export function createApp(component: ComponentFn, props?: Props): App {
712
712
 
713
713
  // ─── Additional re-exports ────────────────────────────────────────────────────
714
714
 
715
- export { batch } from "@pyreon/reactivity"
715
+ export { batch } from '@pyreon/reactivity'
@@ -1 +1 @@
1
- export { Fragment, jsx, jsxs } from "./jsx-runtime"
1
+ export { Fragment, jsx, jsxs } from './jsx-runtime'
@@ -14,9 +14,9 @@
14
14
  * triggers re-renders.
15
15
  */
16
16
 
17
- import type { ComponentFn, Props, VNode, VNodeChild } from "@pyreon/core"
18
- import { Fragment, h, onUnmount } from "@pyreon/core"
19
- import { runUntracked, signal } from "@pyreon/reactivity"
17
+ import type { ComponentFn, Props, VNode, VNodeChild } from '@pyreon/core'
18
+ import { Fragment, h, onUnmount } from '@pyreon/core'
19
+ import { runUntracked, signal } from '@pyreon/reactivity'
20
20
 
21
21
  export { Fragment }
22
22
 
@@ -71,7 +71,7 @@ function runLayoutEffects(entries: EffectEntry[]): void {
71
71
  for (const entry of entries) {
72
72
  if (entry.cleanup) entry.cleanup()
73
73
  const cleanup = entry.fn()
74
- entry.cleanup = typeof cleanup === "function" ? cleanup : undefined
74
+ entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined
75
75
  }
76
76
  }
77
77
 
@@ -82,7 +82,7 @@ function scheduleEffects(ctx: RenderContext, entries: EffectEntry[]): void {
82
82
  if (ctx.unmounted) return
83
83
  if (entry.cleanup) entry.cleanup()
84
84
  const cleanup = entry.fn()
85
- entry.cleanup = typeof cleanup === "function" ? cleanup : undefined
85
+ entry.cleanup = typeof cleanup === 'function' ? cleanup : undefined
86
86
  }
87
87
  })
88
88
  }
@@ -161,7 +161,7 @@ export function jsx(
161
161
  const { children, ...rest } = props
162
162
  const propsWithKey = (key != null ? { ...rest, key } : rest) as Props
163
163
 
164
- if (typeof type === "function") {
164
+ if (typeof type === 'function') {
165
165
  // Wrap Vue-style component for re-render support
166
166
  const wrapped = wrapCompatComponent(type)
167
167
  const componentProps = children !== undefined ? { ...propsWithKey, children } : propsWithKey
@@ -1,3 +1,3 @@
1
- import { GlobalRegistrator } from "@happy-dom/global-registrator"
1
+ import { GlobalRegistrator } from '@happy-dom/global-registrator'
2
2
 
3
3
  GlobalRegistrator.register()