@pyreon/react-compat 0.1.1 → 0.1.2

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
@@ -10,7 +10,7 @@ bun add @pyreon/react-compat
10
10
 
11
11
  ## Quick Start
12
12
 
13
- ```ts
13
+ ```tsx
14
14
  // Replace:
15
15
  // import { useState, useEffect } from "react"
16
16
  // With:
@@ -25,6 +25,76 @@ function Counter() {
25
25
  }
26
26
  ```
27
27
 
28
+ ### Using Refs and Context
29
+
30
+ ```tsx
31
+ import { useRef, useEffect, createContext, useContext } from "@pyreon/react-compat"
32
+
33
+ const ThemeContext = createContext("light")
34
+
35
+ function ThemeDisplay() {
36
+ const theme = useContext(ThemeContext)
37
+ const divRef = useRef<HTMLDivElement>(null)
38
+
39
+ useEffect(() => {
40
+ console.log("mounted, div is:", divRef.current)
41
+ return () => console.log("unmounted")
42
+ }, [])
43
+
44
+ return <div ref={divRef}>Current theme: {theme}</div>
45
+ }
46
+
47
+ function App() {
48
+ return (
49
+ <ThemeContext.Provider value="dark">
50
+ <ThemeDisplay />
51
+ </ThemeContext.Provider>
52
+ )
53
+ }
54
+ ```
55
+
56
+ ### Reducer Pattern
57
+
58
+ ```tsx
59
+ import { useReducer } from "@pyreon/react-compat"
60
+
61
+ type Action = { type: "increment" } | { type: "decrement" }
62
+
63
+ function reducer(state: number, action: Action) {
64
+ switch (action.type) {
65
+ case "increment": return state + 1
66
+ case "decrement": return state - 1
67
+ }
68
+ }
69
+
70
+ function Counter() {
71
+ const [count, dispatch] = useReducer(reducer, 0)
72
+ return (
73
+ <div>
74
+ <span>{count}</span>
75
+ <button onClick={() => dispatch({ type: "increment" })}>+</button>
76
+ <button onClick={() => dispatch({ type: "decrement" })}>-</button>
77
+ </div>
78
+ )
79
+ }
80
+ ```
81
+
82
+ ### Lazy Loading
83
+
84
+ ```tsx
85
+ import { lazy, Suspense } from "@pyreon/react-compat"
86
+
87
+ const HeavyChart = lazy(() => import("./HeavyChart"))
88
+
89
+ function Dashboard() {
90
+ return (
91
+ <Suspense fallback={<p>Loading chart...</p>}>
92
+ <HeavyChart data={[1, 2, 3]} />
93
+ </Suspense>
94
+ )
95
+ }
96
+ ```
97
+
28
98
  ## Key Differences from React
29
99
 
30
100
  - **No hooks rules.** Call hooks anywhere -- in loops, conditions, nested functions.
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pyreon/react-compat\n *\n * React-compatible hook API that runs on Pyreon's reactive engine.\n *\n * Allows you to write familiar React-style code while getting Pyreon's\n * fine-grained reactivity, built-in router/store, and superior performance.\n *\n * DIFFERENCES FROM REACT:\n * - No hooks rules: call these anywhere in a component, in loops, conditions, etc.\n * - useEffect deps array is IGNORED — Pyreon tracks dependencies automatically.\n * - useCallback/memo are identity functions — no re-renders means no stale closures.\n * - Components run ONCE (setup), not on every render.\n *\n * USAGE:\n * Replace `import { useState, useEffect } from \"react\"` with\n * `import { useState, useEffect } from \"@pyreon/react-compat\"`\n * Replace `import { createRoot } from \"react-dom/client\"` with\n * `import { createRoot } from \"@pyreon/react-compat/dom\"`\n */\n\nexport type { Props, VNode as ReactNode, VNodeChild } from \"@pyreon/core\"\n// Re-export Pyreon's JSX runtime so JSX transforms work the same way\n// Lifecycle\nexport { Fragment, h as createElement, h, onMount as useLayoutEffect } from \"@pyreon/core\"\n\nimport type { CleanupFn, VNodeChild } from \"@pyreon/core\"\nimport {\n createContext,\n createRef,\n ErrorBoundary,\n onErrorCaptured,\n onMount,\n onUnmount,\n onUpdate,\n Portal,\n Suspense,\n useContext,\n} from \"@pyreon/core\"\nimport {\n batch,\n computed,\n createSelector,\n effect,\n getCurrentScope,\n runUntracked,\n signal,\n} from \"@pyreon/reactivity\"\n\n// ─── State ────────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useState`.\n * Returns `[getter, setter]` — call `getter()` to read, `setter(v)` to write.\n *\n * Unlike React: the getter is a signal, so any component or effect that reads\n * it will re-run automatically. No dep arrays needed.\n */\nexport function useState<T>(initial: T | (() => T)): [() => T, (v: T | ((prev: T) => T)) => void] {\n const s = signal<T>(typeof initial === \"function\" ? (initial as () => T)() : initial)\n const setter = (v: T | ((prev: T) => T)) => {\n if (typeof v === \"function\") s.update(v as (prev: T) => T)\n else s.set(v)\n }\n return [s, setter]\n}\n\n// ─── Reducer ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useReducer`.\n */\nexport function useReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initial: S | (() => S),\n): [() => S, (action: A) => void] {\n const s = signal<S>(typeof initial === \"function\" ? (initial as () => S)() : initial)\n const dispatch = (action: A) => s.update((prev) => reducer(prev, action))\n return [s, dispatch]\n}\n\n// ─── Effects ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useEffect`.\n *\n * The `deps` array is IGNORED — Pyreon tracks reactive dependencies automatically.\n * If `deps` is `[]` (mount-only), wrap the body in `runUntracked(() => ...)`.\n *\n * Returns a cleanup the same way React does (return a function from `fn`).\n */\n// biome-ignore lint/suspicious/noConfusingVoidType: void is intentional — callers may return void\nexport function useEffect(fn: () => CleanupFn | void, deps?: unknown[]): void {\n if (deps !== undefined && deps.length === 0) {\n // [] means \"run once on mount\" — use onMount instead of a tracking effect\n onMount((): undefined => {\n const cleanup = runUntracked(fn)\n if (typeof cleanup === \"function\") onUnmount(cleanup)\n })\n } else {\n // No deps or non-empty deps: run reactively (Pyreon auto-tracks).\n // effect() natively supports cleanup: if fn() returns a function,\n // it's called before re-runs and on dispose.\n const e = effect(fn)\n onUnmount(() => {\n e.dispose()\n })\n }\n}\n\n/**\n * Drop-in for React's `useLayoutEffect`.\n * In Pyreon there is no paint distinction — maps to `onMount` (same as useEffect).\n */\nexport { useEffect as useLayoutEffect_ }\n\n// ─── Memoization ─────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useMemo`.\n * The `deps` array is IGNORED — Pyreon's `computed` tracks dependencies automatically.\n * Returns a getter: call `value()` to read the memoized result.\n */\nexport function useMemo<T>(fn: () => T, _deps?: unknown[]): () => T {\n return computed(fn)\n}\n\n/**\n * Drop-in for React's `useCallback`.\n * In Pyreon, components run once so callbacks are never recreated — returns `fn` as-is.\n */\nexport function useCallback<T extends (...args: unknown[]) => unknown>(\n fn: T,\n _deps?: unknown[],\n): T {\n return fn\n}\n\n// ─── Refs ─────────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useRef`.\n * Returns `{ current: T }` — same shape as React's ref object.\n */\nexport function useRef<T>(initial?: T): { current: T | null } {\n const ref = createRef<T>()\n if (initial !== undefined) ref.current = initial as T\n return ref\n}\n\n// ─── Context ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `createContext` + `useContext`.\n * Usage mirrors React: `const Ctx = createContext(defaultValue)`.\n */\nexport { createContext, useContext }\n\n// ─── ID ───────────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useId` — returns a stable unique string per component instance.\n *\n * Uses the component's effectScope as the key so the counter starts at 0 for every\n * component on both server and client — IDs are deterministic and hydration-safe.\n */\nconst _idCounters = new WeakMap<object, number>()\n\nexport function useId(): string {\n const scope = getCurrentScope()\n if (!scope) return `:r${Math.random().toString(36).slice(2, 9)}:`\n const count = _idCounters.get(scope) ?? 0\n _idCounters.set(scope, count + 1)\n return `:r${count.toString(36)}:`\n}\n\n// ─── Optimization ─────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `memo` — wraps a component.\n * In Pyreon, components run once (no re-renders), so memoization is a no-op.\n * Kept for API compatibility when migrating React code.\n */\nexport function memo<P extends Record<string, unknown>>(\n component: (props: P) => VNodeChild,\n): (props: P) => VNodeChild {\n return component\n}\n\n/**\n * Drop-in for React's `useTransition` — no-op in Pyreon (no concurrent mode).\n * Returns `[false, (fn) => fn()]` to keep code runnable without changes.\n */\nexport function useTransition(): [boolean, (fn: () => void) => void] {\n return [false, (fn) => fn()]\n}\n\n/**\n * Drop-in for React's `useDeferredValue` — returns the value as-is in Pyreon.\n */\nexport function useDeferredValue<T>(value: T): T {\n return value\n}\n\n// ─── Batching ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `unstable_batchedUpdates` / React 18's automatic batching.\n * Pyreon's `batch()` does the same thing.\n */\nexport { batch }\n\n// ─── Error boundaries ─────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's error boundary pattern.\n * Return `true` from `handler` to prevent error propagation (like `componentDidCatch`).\n */\nexport { onErrorCaptured as useErrorBoundary }\n\n// ─── Portals ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `createPortal(children, target)`.\n */\nexport function createPortal(children: VNodeChild, target: Element): VNodeChild {\n return Portal({ target, children })\n}\n\n// ─── Imperative handle ────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useImperativeHandle`.\n * In Pyreon, expose methods via a ref prop directly — this is a compatibility shim.\n */\nexport function useImperativeHandle<T>(\n ref: { current: T | null } | null | undefined,\n init: () => T,\n _deps?: unknown[],\n): void {\n onMount((): undefined => {\n if (ref) ref.current = init()\n })\n onUnmount(() => {\n if (ref) ref.current = null\n })\n}\n\n// ─── Selector ─────────────────────────────────────────────────────────────────\n\n/**\n * Pyreon-specific: O(1) equality selector (no React equivalent).\n * Useful for large lists where only the selected item should re-render.\n * @see createSelector in @pyreon/reactivity\n */\nexport { createSelector }\n\n// ─── onUpdate ─────────────────────────────────────────────────────────────────\n\n/** Pyreon-specific lifecycle hook — runs after each reactive update. */\nexport { onMount, onUnmount, onUpdate }\n\n// ─── Suspense / lazy ──────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `lazy()`.\n * Re-exported from `@pyreon/core` — wraps a dynamic import, renders null until\n * the module resolves. Pair with `<Suspense>` to show a fallback during loading.\n */\nexport { lazy } from \"@pyreon/core\"\n\n/**\n * Drop-in for React's `<Suspense>`.\n * Shows `fallback` while a `lazy()` child is still loading.\n */\nexport { Suspense, ErrorBoundary }\n"],"mappings":";;;;;;;;;;;AA0DA,SAAgB,SAAY,SAAsE;CAChG,MAAM,IAAI,OAAU,OAAO,YAAY,aAAc,SAAqB,GAAG,QAAQ;CACrF,MAAM,UAAU,MAA4B;AAC1C,MAAI,OAAO,MAAM,WAAY,GAAE,OAAO,EAAoB;MACrD,GAAE,IAAI,EAAE;;AAEf,QAAO,CAAC,GAAG,OAAO;;;;;AAQpB,SAAgB,WACd,SACA,SACgC;CAChC,MAAM,IAAI,OAAU,OAAO,YAAY,aAAc,SAAqB,GAAG,QAAQ;CACrF,MAAM,YAAY,WAAc,EAAE,QAAQ,SAAS,QAAQ,MAAM,OAAO,CAAC;AACzE,QAAO,CAAC,GAAG,SAAS;;;;;;;;;;AActB,SAAgB,UAAU,IAA4B,MAAwB;AAC5E,KAAI,SAAS,UAAa,KAAK,WAAW,EAExC,eAAyB;EACvB,MAAM,UAAU,aAAa,GAAG;AAChC,MAAI,OAAO,YAAY,WAAY,WAAU,QAAQ;GACrD;MACG;EAIL,MAAM,IAAI,OAAO,GAAG;AACpB,kBAAgB;AACd,KAAE,SAAS;IACX;;;;;;;;AAiBN,SAAgB,QAAW,IAAa,OAA4B;AAClE,QAAO,SAAS,GAAG;;;;;;AAOrB,SAAgB,YACd,IACA,OACG;AACH,QAAO;;;;;;AAST,SAAgB,OAAU,SAAoC;CAC5D,MAAM,MAAM,WAAc;AAC1B,KAAI,YAAY,OAAW,KAAI,UAAU;AACzC,QAAO;;;;;;;;AAmBT,MAAM,8BAAc,IAAI,SAAyB;AAEjD,SAAgB,QAAgB;CAC9B,MAAM,QAAQ,iBAAiB;AAC/B,KAAI,CAAC,MAAO,QAAO,KAAK,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;CAC/D,MAAM,QAAQ,YAAY,IAAI,MAAM,IAAI;AACxC,aAAY,IAAI,OAAO,QAAQ,EAAE;AACjC,QAAO,KAAK,MAAM,SAAS,GAAG,CAAC;;;;;;;AAUjC,SAAgB,KACd,WAC0B;AAC1B,QAAO;;;;;;AAOT,SAAgB,gBAAqD;AACnE,QAAO,CAAC,QAAQ,OAAO,IAAI,CAAC;;;;;AAM9B,SAAgB,iBAAoB,OAAa;AAC/C,QAAO;;;;;AAwBT,SAAgB,aAAa,UAAsB,QAA6B;AAC9E,QAAO,OAAO;EAAE;EAAQ;EAAU,CAAC;;;;;;AASrC,SAAgB,oBACd,KACA,MACA,OACM;AACN,eAAyB;AACvB,MAAI,IAAK,KAAI,UAAU,MAAM;GAC7B;AACF,iBAAgB;AACd,MAAI,IAAK,KAAI,UAAU;GACvB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pyreon/react-compat\n *\n * React-compatible hook API that runs on Pyreon's reactive engine.\n *\n * Allows you to write familiar React-style code while getting Pyreon's\n * fine-grained reactivity, built-in router/store, and superior performance.\n *\n * DIFFERENCES FROM REACT:\n * - No hooks rules: call these anywhere in a component, in loops, conditions, etc.\n * - useEffect deps array is IGNORED — Pyreon tracks dependencies automatically.\n * - useCallback/memo are identity functions — no re-renders means no stale closures.\n * - Components run ONCE (setup), not on every render.\n *\n * USAGE:\n * Replace `import { useState, useEffect } from \"react\"` with\n * `import { useState, useEffect } from \"@pyreon/react-compat\"`\n * Replace `import { createRoot } from \"react-dom/client\"` with\n * `import { createRoot } from \"@pyreon/react-compat/dom\"`\n */\n\nexport type { Props, VNode as ReactNode, VNodeChild } from \"@pyreon/core\"\n// Re-export Pyreon's JSX runtime so JSX transforms work the same way\n// Lifecycle\nexport { Fragment, h as createElement, h, onMount as useLayoutEffect } from \"@pyreon/core\"\n\nimport type { CleanupFn, VNodeChild } from \"@pyreon/core\"\nimport {\n createContext,\n createRef,\n ErrorBoundary,\n onErrorCaptured,\n onMount,\n onUnmount,\n onUpdate,\n Portal,\n Suspense,\n useContext,\n} from \"@pyreon/core\"\nimport {\n batch,\n computed,\n createSelector,\n effect,\n getCurrentScope,\n runUntracked,\n signal,\n} from \"@pyreon/reactivity\"\n\n// ─── State ────────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useState`.\n * Returns `[getter, setter]` — call `getter()` to read, `setter(v)` to write.\n *\n * Unlike React: the getter is a signal, so any component or effect that reads\n * it will re-run automatically. No dep arrays needed.\n */\nexport function useState<T>(initial: T | (() => T)): [() => T, (v: T | ((prev: T) => T)) => void] {\n const s = signal<T>(typeof initial === \"function\" ? (initial as () => T)() : initial)\n const setter = (v: T | ((prev: T) => T)) => {\n if (typeof v === \"function\") s.update(v as (prev: T) => T)\n else s.set(v)\n }\n return [s, setter]\n}\n\n// ─── Reducer ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useReducer`.\n */\nexport function useReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initial: S | (() => S),\n): [() => S, (action: A) => void] {\n const s = signal<S>(typeof initial === \"function\" ? (initial as () => S)() : initial)\n const dispatch = (action: A) => s.update((prev) => reducer(prev, action))\n return [s, dispatch]\n}\n\n// ─── Effects ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useEffect`.\n *\n * The `deps` array is IGNORED — Pyreon tracks reactive dependencies automatically.\n * If `deps` is `[]` (mount-only), wrap the body in `runUntracked(() => ...)`.\n *\n * Returns a cleanup the same way React does (return a function from `fn`).\n */\n// biome-ignore lint/suspicious/noConfusingVoidType: void is intentional — callers may return void\nexport function useEffect(fn: () => CleanupFn | void, deps?: unknown[]): void {\n if (deps !== undefined && deps.length === 0) {\n // [] means \"run once on mount\" — use onMount instead of a tracking effect\n onMount((): undefined => {\n const cleanup = runUntracked(fn)\n if (typeof cleanup === \"function\") onUnmount(cleanup)\n })\n } else {\n // No deps or non-empty deps: run reactively (Pyreon auto-tracks).\n // effect() natively supports cleanup: if fn() returns a function,\n // it's called before re-runs and on dispose.\n const e = effect(fn)\n onUnmount(() => {\n e.dispose()\n })\n }\n}\n\n/**\n * Drop-in for React's `useLayoutEffect`.\n * In Pyreon there is no paint distinction — maps to `onMount` (same as useEffect).\n */\nexport { useEffect as useLayoutEffect_ }\n\n// ─── Memoization ─────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useMemo`.\n * The `deps` array is IGNORED — Pyreon's `computed` tracks dependencies automatically.\n * Returns a getter: call `value()` to read the memoized result.\n */\nexport function useMemo<T>(fn: () => T, _deps?: unknown[]): () => T {\n return computed(fn)\n}\n\n/**\n * Drop-in for React's `useCallback`.\n * In Pyreon, components run once so callbacks are never recreated — returns `fn` as-is.\n */\n// biome-ignore lint/suspicious/noExplicitAny: any is needed for contravariant function params\nexport function useCallback<T extends (...args: any[]) => any>(fn: T, _deps?: unknown[]): T {\n return fn\n}\n\n// ─── Refs ─────────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useRef`.\n * Returns `{ current: T }` — same shape as React's ref object.\n */\nexport function useRef<T>(initial?: T): { current: T | null } {\n const ref = createRef<T>()\n if (initial !== undefined) ref.current = initial as T\n return ref\n}\n\n// ─── Context ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `createContext` + `useContext`.\n * Usage mirrors React: `const Ctx = createContext(defaultValue)`.\n */\nexport { createContext, useContext }\n\n// ─── ID ───────────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useId` — returns a stable unique string per component instance.\n *\n * Uses the component's effectScope as the key so the counter starts at 0 for every\n * component on both server and client — IDs are deterministic and hydration-safe.\n */\nconst _idCounters = new WeakMap<object, number>()\n\nexport function useId(): string {\n const scope = getCurrentScope()\n if (!scope) return `:r${Math.random().toString(36).slice(2, 9)}:`\n const count = _idCounters.get(scope) ?? 0\n _idCounters.set(scope, count + 1)\n return `:r${count.toString(36)}:`\n}\n\n// ─── Optimization ─────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `memo` — wraps a component.\n * In Pyreon, components run once (no re-renders), so memoization is a no-op.\n * Kept for API compatibility when migrating React code.\n */\nexport function memo<P extends Record<string, unknown>>(\n component: (props: P) => VNodeChild,\n): (props: P) => VNodeChild {\n return component\n}\n\n/**\n * Drop-in for React's `useTransition` — no-op in Pyreon (no concurrent mode).\n * Returns `[false, (fn) => fn()]` to keep code runnable without changes.\n */\nexport function useTransition(): [boolean, (fn: () => void) => void] {\n return [false, (fn) => fn()]\n}\n\n/**\n * Drop-in for React's `useDeferredValue` — returns the value as-is in Pyreon.\n */\nexport function useDeferredValue<T>(value: T): T {\n return value\n}\n\n// ─── Batching ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `unstable_batchedUpdates` / React 18's automatic batching.\n * Pyreon's `batch()` does the same thing.\n */\nexport { batch }\n\n// ─── Error boundaries ─────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's error boundary pattern.\n * Return `true` from `handler` to prevent error propagation (like `componentDidCatch`).\n */\nexport { onErrorCaptured as useErrorBoundary }\n\n// ─── Portals ─────────────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `createPortal(children, target)`.\n */\nexport function createPortal(children: VNodeChild, target: Element): VNodeChild {\n return Portal({ target, children })\n}\n\n// ─── Imperative handle ────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `useImperativeHandle`.\n * In Pyreon, expose methods via a ref prop directly — this is a compatibility shim.\n */\nexport function useImperativeHandle<T>(\n ref: { current: T | null } | null | undefined,\n init: () => T,\n _deps?: unknown[],\n): void {\n onMount((): undefined => {\n if (ref) ref.current = init()\n })\n onUnmount(() => {\n if (ref) ref.current = null\n })\n}\n\n// ─── Selector ─────────────────────────────────────────────────────────────────\n\n/**\n * Pyreon-specific: O(1) equality selector (no React equivalent).\n * Useful for large lists where only the selected item should re-render.\n * @see createSelector in @pyreon/reactivity\n */\nexport { createSelector }\n\n// ─── onUpdate ─────────────────────────────────────────────────────────────────\n\n/** Pyreon-specific lifecycle hook — runs after each reactive update. */\nexport { onMount, onUnmount, onUpdate }\n\n// ─── Suspense / lazy ──────────────────────────────────────────────────────────\n\n/**\n * Drop-in for React's `lazy()`.\n * Re-exported from `@pyreon/core` — wraps a dynamic import, renders null until\n * the module resolves. Pair with `<Suspense>` to show a fallback during loading.\n */\nexport { lazy } from \"@pyreon/core\"\n\n/**\n * Drop-in for React's `<Suspense>`.\n * Shows `fallback` while a `lazy()` child is still loading.\n */\nexport { ErrorBoundary, Suspense }\n"],"mappings":";;;;;;;;;;;AA0DA,SAAgB,SAAY,SAAsE;CAChG,MAAM,IAAI,OAAU,OAAO,YAAY,aAAc,SAAqB,GAAG,QAAQ;CACrF,MAAM,UAAU,MAA4B;AAC1C,MAAI,OAAO,MAAM,WAAY,GAAE,OAAO,EAAoB;MACrD,GAAE,IAAI,EAAE;;AAEf,QAAO,CAAC,GAAG,OAAO;;;;;AAQpB,SAAgB,WACd,SACA,SACgC;CAChC,MAAM,IAAI,OAAU,OAAO,YAAY,aAAc,SAAqB,GAAG,QAAQ;CACrF,MAAM,YAAY,WAAc,EAAE,QAAQ,SAAS,QAAQ,MAAM,OAAO,CAAC;AACzE,QAAO,CAAC,GAAG,SAAS;;;;;;;;;;AActB,SAAgB,UAAU,IAA4B,MAAwB;AAC5E,KAAI,SAAS,UAAa,KAAK,WAAW,EAExC,eAAyB;EACvB,MAAM,UAAU,aAAa,GAAG;AAChC,MAAI,OAAO,YAAY,WAAY,WAAU,QAAQ;GACrD;MACG;EAIL,MAAM,IAAI,OAAO,GAAG;AACpB,kBAAgB;AACd,KAAE,SAAS;IACX;;;;;;;;AAiBN,SAAgB,QAAW,IAAa,OAA4B;AAClE,QAAO,SAAS,GAAG;;;;;;AAQrB,SAAgB,YAA+C,IAAO,OAAsB;AAC1F,QAAO;;;;;;AAST,SAAgB,OAAU,SAAoC;CAC5D,MAAM,MAAM,WAAc;AAC1B,KAAI,YAAY,OAAW,KAAI,UAAU;AACzC,QAAO;;;;;;;;AAmBT,MAAM,8BAAc,IAAI,SAAyB;AAEjD,SAAgB,QAAgB;CAC9B,MAAM,QAAQ,iBAAiB;AAC/B,KAAI,CAAC,MAAO,QAAO,KAAK,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;CAC/D,MAAM,QAAQ,YAAY,IAAI,MAAM,IAAI;AACxC,aAAY,IAAI,OAAO,QAAQ,EAAE;AACjC,QAAO,KAAK,MAAM,SAAS,GAAG,CAAC;;;;;;;AAUjC,SAAgB,KACd,WAC0B;AAC1B,QAAO;;;;;;AAOT,SAAgB,gBAAqD;AACnE,QAAO,CAAC,QAAQ,OAAO,IAAI,CAAC;;;;;AAM9B,SAAgB,iBAAoB,OAAa;AAC/C,QAAO;;;;;AAwBT,SAAgB,aAAa,UAAsB,QAA6B;AAC9E,QAAO,OAAO;EAAE;EAAQ;EAAU,CAAC;;;;;;AASrC,SAAgB,oBACd,KACA,MACA,OACM;AACN,eAAyB;AACvB,MAAI,IAAK,KAAI,UAAU,MAAM;GAC7B;AACF,iBAAgB;AACd,MAAI,IAAK,KAAI,UAAU;GACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":"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"}
@@ -33,7 +33,7 @@ declare function useMemo<T>(fn: () => T, _deps?: unknown[]): () => T;
33
33
  * Drop-in for React's `useCallback`.
34
34
  * In Pyreon, components run once so callbacks are never recreated — returns `fn` as-is.
35
35
  */
36
- declare function useCallback<T extends (...args: unknown[]) => unknown>(fn: T, _deps?: unknown[]): T;
36
+ declare function useCallback<T extends (...args: any[]) => any>(fn: T, _deps?: unknown[]): T;
37
37
  /**
38
38
  * Drop-in for React's `useRef`.
39
39
  * Returns `{ current: T }` — same shape as React's ref object.
@@ -1 +1 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":";;;;;;AAwEA;;;;;iBAdgB,QAAA,GAAA,CAAY,OAAA,EAAS,CAAA,UAAW,CAAA,WAAY,CAAA,GAAI,CAAA,EAAG,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;;;;iBAcrE,UAAA,MAAA,CACd,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,OAAA,EAAS,CAAA,UAAW,CAAA,WACZ,CAAA,GAAI,MAAA,EAAQ,CAAA;;;;;;;;;iBAiBN,SAAA,CAAU,EAAA,QAAU,SAAA,SAAkB,IAAA;;;;;AAAtD;iBA+BgB,OAAA,GAAA,CAAW,EAAA,QAAU,CAAA,EAAG,KAAA,qBAA0B,CAAA;;;;;iBAQlD,WAAA,eAA0B,IAAA,wBAAA,CACxC,EAAA,EAAI,CAAA,EACJ,KAAA,eACC,CAAA;;;AAXH;;iBAqBgB,MAAA,GAAA,CAAU,OAAA,GAAU,CAAA;EAAM,OAAA,EAAS,CAAA;AAAA;AAAA,iBAwBnC,KAAA,CAAA;AArChB;;;;;AAAA,iBAoDgB,IAAA,WAAe,MAAA,kBAAA,CAC7B,SAAA,GAAY,KAAA,EAAO,CAAA,KAAM,YAAA,IACvB,KAAA,EAAO,CAAA,KAAM,YAAA;;;;;iBAQD,aAAA,CAAA,cAA4B,EAAA;;AAjD5C;;iBAwDgB,gBAAA,GAAA,CAAoB,KAAA,EAAO,CAAA,GAAI,CAAA;;;;iBAyB/B,YAAA,CAAa,QAAA,EAAU,YAAA,EAAY,MAAA,EAAQ,OAAA,GAAU,YAAA;;;;;iBAUrD,mBAAA,GAAA,CACd,GAAA;EAAO,OAAA,EAAS,CAAA;AAAA,sBAChB,IAAA,QAAY,CAAA,EACZ,KAAA"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":";;;;;;AAwEA;;;;;iBAdgB,QAAA,GAAA,CAAY,OAAA,EAAS,CAAA,UAAW,CAAA,WAAY,CAAA,GAAI,CAAA,EAAG,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;;;;iBAcrE,UAAA,MAAA,CACd,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,OAAA,EAAS,CAAA,UAAW,CAAA,WACZ,CAAA,GAAI,MAAA,EAAQ,CAAA;;;;;;;;;iBAiBN,SAAA,CAAU,EAAA,QAAU,SAAA,SAAkB,IAAA;;;;;AAAtD;iBA+BgB,OAAA,GAAA,CAAW,EAAA,QAAU,CAAA,EAAG,KAAA,qBAA0B,CAAA;;;;;iBASlD,WAAA,eAA0B,IAAA,gBAAA,CAAqB,EAAA,EAAI,CAAA,EAAG,KAAA,eAAoB,CAAA;;;AAT1F;;iBAmBgB,MAAA,GAAA,CAAU,OAAA,GAAU,CAAA;EAAM,OAAA,EAAS,CAAA;AAAA;AAAA,iBAwBnC,KAAA,CAAA;AAlChB;;;;;AAAA,iBAiDgB,IAAA,WAAe,MAAA,kBAAA,CAC7B,SAAA,GAAY,KAAA,EAAO,CAAA,KAAM,YAAA,IACvB,KAAA,EAAO,CAAA,KAAM,YAAA;;;;;iBAQD,aAAA,CAAA,cAA4B,EAAA;;AAjD5C;;iBAwDgB,gBAAA,GAAA,CAAoB,KAAA,EAAO,CAAA,GAAI,CAAA;;;;iBAyB/B,YAAA,CAAa,QAAA,EAAU,YAAA,EAAY,MAAA,EAAQ,OAAA,GAAU,YAAA;;;;;iBAUrD,mBAAA,GAAA,CACd,GAAA;EAAO,OAAA,EAAS,CAAA;AAAA,sBAChB,IAAA,QAAY,CAAA,EACZ,KAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/react-compat",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "React-compatible API shim for Pyreon — write React-style hooks that run on Pyreon's reactive engine",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,14 +40,13 @@
40
40
  "dev": "vl_rolldown_build-watch",
41
41
  "test": "vitest run",
42
42
  "typecheck": "tsc --noEmit",
43
- "prepublishOnly": "bun run build",
44
- "prepack": "bun run ../../scripts/resolve-workspace-deps.ts pre",
45
- "postpack": "bun run ../../scripts/resolve-workspace-deps.ts post"
43
+ "lint": "biome check .",
44
+ "prepublishOnly": "bun run build"
46
45
  },
47
46
  "dependencies": {
48
- "@pyreon/core": "^0.1.1",
49
- "@pyreon/reactivity": "^0.1.1",
50
- "@pyreon/runtime-dom": "^0.1.1"
47
+ "@pyreon/core": "workspace:*",
48
+ "@pyreon/reactivity": "workspace:*",
49
+ "@pyreon/runtime-dom": "workspace:*"
51
50
  },
52
51
  "devDependencies": {
53
52
  "@happy-dom/global-registrator": "^20.8.3",
package/src/index.ts CHANGED
@@ -129,10 +129,8 @@ export function useMemo<T>(fn: () => T, _deps?: unknown[]): () => T {
129
129
  * Drop-in for React's `useCallback`.
130
130
  * In Pyreon, components run once so callbacks are never recreated — returns `fn` as-is.
131
131
  */
132
- export function useCallback<T extends (...args: unknown[]) => unknown>(
133
- fn: T,
134
- _deps?: unknown[],
135
- ): T {
132
+ // biome-ignore lint/suspicious/noExplicitAny: any is needed for contravariant function params
133
+ export function useCallback<T extends (...args: any[]) => any>(fn: T, _deps?: unknown[]): T {
136
134
  return fn
137
135
  }
138
136
 
@@ -273,4 +271,4 @@ export { lazy } from "@pyreon/core"
273
271
  * Drop-in for React's `<Suspense>`.
274
272
  * Shows `fallback` while a `lazy()` child is still loading.
275
273
  */
276
- export { Suspense, ErrorBoundary }
274
+ export { ErrorBoundary, Suspense }