@pyreon/preact-compat 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/analysis/hooks.js.html +5406 -0
- package/lib/analysis/jsx-runtime.js.html +5406 -0
- package/lib/analysis/signals.js.html +5406 -0
- package/lib/hooks.js +181 -0
- package/lib/hooks.js.map +1 -0
- package/lib/jsx-runtime.js +88 -0
- package/lib/jsx-runtime.js.map +1 -0
- package/lib/signals.js +57 -0
- package/lib/signals.js.map +1 -0
- package/lib/types/hooks.d.ts +178 -0
- package/lib/types/hooks.d.ts.map +1 -0
- package/lib/types/hooks2.d.ts +47 -0
- package/lib/types/hooks2.d.ts.map +1 -0
- package/lib/types/jsx-runtime.d.ts +87 -0
- package/lib/types/jsx-runtime.d.ts.map +1 -0
- package/lib/types/jsx-runtime2.d.ts +10 -0
- package/lib/types/jsx-runtime2.d.ts.map +1 -0
- package/lib/types/signals.d.ts +57 -0
- package/lib/types/signals.d.ts.map +1 -0
- package/lib/types/signals2.d.ts +35 -0
- package/lib/types/signals2.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/jsx-dev-runtime.ts +1 -0
package/lib/hooks.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { onErrorCaptured, useContext } from "@pyreon/core";
|
|
2
|
+
|
|
3
|
+
//#region src/jsx-runtime.ts
|
|
4
|
+
let _currentCtx = null;
|
|
5
|
+
let _hookIndex = 0;
|
|
6
|
+
function getCurrentCtx() {
|
|
7
|
+
return _currentCtx;
|
|
8
|
+
}
|
|
9
|
+
function getHookIndex() {
|
|
10
|
+
return _hookIndex++;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/hooks.ts
|
|
15
|
+
function requireCtx() {
|
|
16
|
+
const ctx = getCurrentCtx();
|
|
17
|
+
if (!ctx) throw new Error("Hook called outside of a component render");
|
|
18
|
+
return ctx;
|
|
19
|
+
}
|
|
20
|
+
function depsChanged(a, b) {
|
|
21
|
+
if (a === void 0 || b === void 0) return true;
|
|
22
|
+
if (a.length !== b.length) return true;
|
|
23
|
+
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return true;
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Preact-compatible `useState` — returns `[value, setter]`.
|
|
28
|
+
* Triggers a component re-render when the setter is called.
|
|
29
|
+
*/
|
|
30
|
+
function useState(initial) {
|
|
31
|
+
const ctx = requireCtx();
|
|
32
|
+
const idx = getHookIndex();
|
|
33
|
+
if (ctx.hooks.length <= idx) ctx.hooks.push(typeof initial === "function" ? initial() : initial);
|
|
34
|
+
const value = ctx.hooks[idx];
|
|
35
|
+
const setter = (v) => {
|
|
36
|
+
const current = ctx.hooks[idx];
|
|
37
|
+
const next = typeof v === "function" ? v(current) : v;
|
|
38
|
+
if (Object.is(current, next)) return;
|
|
39
|
+
ctx.hooks[idx] = next;
|
|
40
|
+
ctx.scheduleRerender();
|
|
41
|
+
};
|
|
42
|
+
return [value, setter];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Preact-compatible `useEffect` — runs after render when deps change.
|
|
46
|
+
* Returns cleanup on unmount and before re-running.
|
|
47
|
+
*/
|
|
48
|
+
function useEffect(fn, deps) {
|
|
49
|
+
const ctx = requireCtx();
|
|
50
|
+
const idx = getHookIndex();
|
|
51
|
+
if (ctx.hooks.length <= idx) {
|
|
52
|
+
const entry = {
|
|
53
|
+
fn,
|
|
54
|
+
deps,
|
|
55
|
+
cleanup: void 0
|
|
56
|
+
};
|
|
57
|
+
ctx.hooks.push(entry);
|
|
58
|
+
ctx.pendingEffects.push(entry);
|
|
59
|
+
} else {
|
|
60
|
+
const entry = ctx.hooks[idx];
|
|
61
|
+
if (depsChanged(entry.deps, deps)) {
|
|
62
|
+
entry.fn = fn;
|
|
63
|
+
entry.deps = deps;
|
|
64
|
+
ctx.pendingEffects.push(entry);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Preact-compatible `useLayoutEffect` — runs synchronously after DOM mutations.
|
|
70
|
+
*/
|
|
71
|
+
function useLayoutEffect(fn, deps) {
|
|
72
|
+
const ctx = requireCtx();
|
|
73
|
+
const idx = getHookIndex();
|
|
74
|
+
if (ctx.hooks.length <= idx) {
|
|
75
|
+
const entry = {
|
|
76
|
+
fn,
|
|
77
|
+
deps,
|
|
78
|
+
cleanup: void 0
|
|
79
|
+
};
|
|
80
|
+
ctx.hooks.push(entry);
|
|
81
|
+
ctx.pendingLayoutEffects.push(entry);
|
|
82
|
+
} else {
|
|
83
|
+
const entry = ctx.hooks[idx];
|
|
84
|
+
if (depsChanged(entry.deps, deps)) {
|
|
85
|
+
entry.fn = fn;
|
|
86
|
+
entry.deps = deps;
|
|
87
|
+
ctx.pendingLayoutEffects.push(entry);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Preact-compatible `useMemo` — returns the cached value, recomputed when deps change.
|
|
93
|
+
*/
|
|
94
|
+
function useMemo(fn, deps) {
|
|
95
|
+
const ctx = requireCtx();
|
|
96
|
+
const idx = getHookIndex();
|
|
97
|
+
if (ctx.hooks.length <= idx) {
|
|
98
|
+
const value = fn();
|
|
99
|
+
ctx.hooks.push({
|
|
100
|
+
value,
|
|
101
|
+
deps
|
|
102
|
+
});
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
const entry = ctx.hooks[idx];
|
|
106
|
+
if (depsChanged(entry.deps, deps)) {
|
|
107
|
+
entry.value = fn();
|
|
108
|
+
entry.deps = deps;
|
|
109
|
+
}
|
|
110
|
+
return entry.value;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Preact-compatible `useCallback` — returns the cached function when deps haven't changed.
|
|
114
|
+
*/
|
|
115
|
+
function useCallback(fn, deps) {
|
|
116
|
+
return useMemo(() => fn, deps);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Preact-compatible `useRef` — returns `{ current }` persisted across re-renders.
|
|
120
|
+
*/
|
|
121
|
+
function useRef(initial) {
|
|
122
|
+
const ctx = requireCtx();
|
|
123
|
+
const idx = getHookIndex();
|
|
124
|
+
if (ctx.hooks.length <= idx) {
|
|
125
|
+
const ref = { current: initial !== void 0 ? initial : null };
|
|
126
|
+
ctx.hooks.push(ref);
|
|
127
|
+
}
|
|
128
|
+
return ctx.hooks[idx];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Preact-compatible `useReducer` — returns `[state, dispatch]`.
|
|
132
|
+
*/
|
|
133
|
+
function useReducer(reducer, initial) {
|
|
134
|
+
const ctx = requireCtx();
|
|
135
|
+
const idx = getHookIndex();
|
|
136
|
+
if (ctx.hooks.length <= idx) ctx.hooks.push(typeof initial === "function" ? initial() : initial);
|
|
137
|
+
const state = ctx.hooks[idx];
|
|
138
|
+
const dispatch = (action) => {
|
|
139
|
+
const current = ctx.hooks[idx];
|
|
140
|
+
const next = reducer(current, action);
|
|
141
|
+
if (Object.is(current, next)) return;
|
|
142
|
+
ctx.hooks[idx] = next;
|
|
143
|
+
ctx.scheduleRerender();
|
|
144
|
+
};
|
|
145
|
+
return [state, dispatch];
|
|
146
|
+
}
|
|
147
|
+
let _idCounter = 0;
|
|
148
|
+
/**
|
|
149
|
+
* Preact-compatible `useId` — returns a stable unique string per hook call.
|
|
150
|
+
*/
|
|
151
|
+
function useId() {
|
|
152
|
+
const ctx = requireCtx();
|
|
153
|
+
const idx = getHookIndex();
|
|
154
|
+
if (ctx.hooks.length <= idx) ctx.hooks.push(`:r${(_idCounter++).toString(36)}:`);
|
|
155
|
+
return ctx.hooks[idx];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Preact-compatible `memo` — wraps a component to skip re-render when props
|
|
159
|
+
* are shallowly equal.
|
|
160
|
+
*/
|
|
161
|
+
function memo(component, areEqual) {
|
|
162
|
+
const compare = areEqual ?? ((a, b) => {
|
|
163
|
+
const keysA = Object.keys(a);
|
|
164
|
+
const keysB = Object.keys(b);
|
|
165
|
+
if (keysA.length !== keysB.length) return false;
|
|
166
|
+
for (const k of keysA) if (!Object.is(a[k], b[k])) return false;
|
|
167
|
+
return true;
|
|
168
|
+
});
|
|
169
|
+
let prevProps = null;
|
|
170
|
+
let prevResult = null;
|
|
171
|
+
return (props) => {
|
|
172
|
+
if (prevProps !== null && compare(prevProps, props)) return prevResult;
|
|
173
|
+
prevProps = props;
|
|
174
|
+
prevResult = component(props);
|
|
175
|
+
return prevResult;
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//#endregion
|
|
180
|
+
export { memo, useCallback, useContext, useEffect, onErrorCaptured as useErrorBoundary, useId, useLayoutEffect, useMemo, useReducer, useRef, useState };
|
|
181
|
+
//# sourceMappingURL=hooks.js.map
|
package/lib/hooks.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","names":[],"sources":["../src/jsx-runtime.ts","../src/hooks.ts"],"sourcesContent":["/**\n * Compat JSX runtime for Preact compatibility mode.\n *\n * When `jsxImportSource` is redirected to `@pyreon/preact-compat` (via the vite\n * plugin's `compat: \"preact\"` 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 Preact-style re-renders on state change while Pyreon's\n * existing renderer handles all DOM work.\n */\n\nimport type { ComponentFn, Props, VNode, VNodeChild } from \"@pyreon/core\"\nimport { Fragment, h } from \"@pyreon/core\"\nimport { 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}\n\nexport interface EffectEntry {\n // biome-ignore lint/suspicious/noConfusingVoidType: matches Preact'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(preactComponent: Function): ComponentFn {\n let wrapped = _wrapperCache.get(preactComponent)\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 }\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 // Return reactive accessor — Pyreon's mountChild calls mountReactive\n return () => {\n version() // tracked read — triggers re-execution when state changes\n beginRender(ctx)\n const result = (preactComponent 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(preactComponent, 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 Preact-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/preact-compat/hooks\n *\n * Preact-compatible hooks — separate import like `preact/hooks`.\n *\n * Components re-render on state change — just like Preact. Hooks return plain\n * values and use deps arrays for memoization. Existing Preact code works\n * unchanged when paired with `pyreon({ compat: \"preact\" })` in your vite config.\n */\n\nimport type { VNodeChild } from \"@pyreon/core\"\nimport { onErrorCaptured, useContext } from \"@pyreon/core\"\nimport type { EffectEntry } from \"./jsx-runtime\"\nimport { getCurrentCtx, getHookIndex } from \"./jsx-runtime\"\n\nexport { useContext }\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction requireCtx() {\n const ctx = getCurrentCtx()\n if (!ctx) throw new Error(\"Hook called outside of a component render\")\n return ctx\n}\n\nfunction depsChanged(a: unknown[] | undefined, b: unknown[] | undefined): boolean {\n if (a === undefined || b === undefined) return true\n if (a.length !== b.length) return true\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return true\n }\n return false\n}\n\n// ─── useState ────────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useState` — returns `[value, setter]`.\n * Triggers a component re-render when the setter is called.\n */\nexport function useState<T>(initial: T | (() => T)): [T, (v: T | ((prev: T) => T)) => void] {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n ctx.hooks.push(typeof initial === \"function\" ? (initial as () => T)() : initial)\n }\n\n const value = ctx.hooks[idx] as T\n const setter = (v: T | ((prev: T) => T)) => {\n const current = ctx.hooks[idx] as T\n const next = typeof v === \"function\" ? (v as (prev: T) => T)(current) : v\n if (Object.is(current, next)) return\n ctx.hooks[idx] = next\n ctx.scheduleRerender()\n }\n\n return [value, setter]\n}\n\n// ─── useEffect ───────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useEffect` — runs after render when deps change.\n * Returns cleanup on unmount and before re-running.\n */\n// biome-ignore lint/suspicious/noConfusingVoidType: matches Preact's useEffect signature\nexport function useEffect(fn: () => (() => void) | void, deps?: unknown[]): void {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n // First render — always run\n const entry: EffectEntry = { fn, deps, cleanup: undefined }\n ctx.hooks.push(entry)\n ctx.pendingEffects.push(entry)\n } else {\n const entry = ctx.hooks[idx] as EffectEntry\n if (depsChanged(entry.deps, deps)) {\n entry.fn = fn\n entry.deps = deps\n ctx.pendingEffects.push(entry)\n }\n }\n}\n\n// ─── useLayoutEffect ─────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useLayoutEffect` — runs synchronously after DOM mutations.\n */\n// biome-ignore lint/suspicious/noConfusingVoidType: matches Preact's useLayoutEffect signature\nexport function useLayoutEffect(fn: () => (() => void) | void, deps?: unknown[]): void {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n const entry: EffectEntry = { fn, deps, cleanup: undefined }\n ctx.hooks.push(entry)\n ctx.pendingLayoutEffects.push(entry)\n } else {\n const entry = ctx.hooks[idx] as EffectEntry\n if (depsChanged(entry.deps, deps)) {\n entry.fn = fn\n entry.deps = deps\n ctx.pendingLayoutEffects.push(entry)\n }\n }\n}\n\n// ─── useMemo ─────────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useMemo` — returns the cached value, recomputed when deps change.\n */\nexport function useMemo<T>(fn: () => T, deps: unknown[]): T {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n const value = fn()\n ctx.hooks.push({ value, deps })\n return value\n }\n\n const entry = ctx.hooks[idx] as { value: T; deps: unknown[] }\n if (depsChanged(entry.deps, deps)) {\n entry.value = fn()\n entry.deps = deps\n }\n return entry.value\n}\n\n// ─── useCallback ─────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useCallback` — returns the cached function when deps haven't changed.\n */\nexport function useCallback<T extends (...args: never[]) => unknown>(fn: T, deps: unknown[]): T {\n return useMemo(() => fn, deps)\n}\n\n// ─── useRef ──────────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useRef` — returns `{ current }` persisted across re-renders.\n */\nexport function useRef<T>(initial?: T): { current: T | null } {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n const ref = { current: initial !== undefined ? (initial as T) : null }\n ctx.hooks.push(ref)\n }\n\n return ctx.hooks[idx] as { current: T | null }\n}\n\n// ─── useReducer ──────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useReducer` — returns `[state, dispatch]`.\n */\nexport function useReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initial: S | (() => S),\n): [S, (action: A) => void] {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n ctx.hooks.push(typeof initial === \"function\" ? (initial as () => S)() : initial)\n }\n\n const state = ctx.hooks[idx] as S\n const dispatch = (action: A) => {\n const current = ctx.hooks[idx] as S\n const next = reducer(current, action)\n if (Object.is(current, next)) return\n ctx.hooks[idx] = next\n ctx.scheduleRerender()\n }\n\n return [state, dispatch]\n}\n\n// ─── useId ───────────────────────────────────────────────────────────────────\n\nlet _idCounter = 0\n\n/**\n * Preact-compatible `useId` — returns a stable unique string per hook call.\n */\nexport function useId(): string {\n const ctx = requireCtx()\n const idx = getHookIndex()\n\n if (ctx.hooks.length <= idx) {\n ctx.hooks.push(`:r${(_idCounter++).toString(36)}:`)\n }\n\n return ctx.hooks[idx] as string\n}\n\n// ─── Optimization ────────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `memo` — wraps a component to skip re-render when props\n * are shallowly equal.\n */\nexport function memo<P extends Record<string, unknown>>(\n component: (props: P) => VNodeChild,\n areEqual?: (prevProps: P, nextProps: P) => boolean,\n): (props: P) => VNodeChild {\n const compare =\n areEqual ??\n ((a: P, b: P) => {\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n for (const k of keysA) {\n if (!Object.is(a[k], b[k])) return false\n }\n return true\n })\n\n let prevProps: P | null = null\n let prevResult: VNodeChild = null\n\n return (props: P) => {\n if (prevProps !== null && compare(prevProps, props)) {\n return prevResult\n }\n prevProps = props\n prevResult = (component as (p: P) => VNodeChild)(props)\n return prevResult\n }\n}\n\n// ─── useErrorBoundary ────────────────────────────────────────────────────────\n\n/**\n * Preact-compatible `useErrorBoundary`.\n * Wraps Pyreon's `onErrorCaptured`.\n */\nexport { onErrorCaptured as useErrorBoundary }\n"],"mappings":";;;AAqCA,IAAI,cAAoC;AACxC,IAAI,aAAa;AAEjB,SAAgB,gBAAsC;AACpD,QAAO;;AAGT,SAAgB,eAAuB;AACrC,QAAO;;;;;AC1BT,SAAS,aAAa;CACpB,MAAM,MAAM,eAAe;AAC3B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4CAA4C;AACtE,QAAO;;AAGT,SAAS,YAAY,GAA0B,GAAmC;AAChF,KAAI,MAAM,UAAa,MAAM,OAAW,QAAO;AAC/C,KAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,KAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,CAAE,QAAO;AAErC,QAAO;;;;;;AAST,SAAgB,SAAY,SAAgE;CAC1F,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,IACtB,KAAI,MAAM,KAAK,OAAO,YAAY,aAAc,SAAqB,GAAG,QAAQ;CAGlF,MAAM,QAAQ,IAAI,MAAM;CACxB,MAAM,UAAU,MAA4B;EAC1C,MAAM,UAAU,IAAI,MAAM;EAC1B,MAAM,OAAO,OAAO,MAAM,aAAc,EAAqB,QAAQ,GAAG;AACxE,MAAI,OAAO,GAAG,SAAS,KAAK,CAAE;AAC9B,MAAI,MAAM,OAAO;AACjB,MAAI,kBAAkB;;AAGxB,QAAO,CAAC,OAAO,OAAO;;;;;;AAUxB,SAAgB,UAAU,IAA+B,MAAwB;CAC/E,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,KAAK;EAE3B,MAAM,QAAqB;GAAE;GAAI;GAAM,SAAS;GAAW;AAC3D,MAAI,MAAM,KAAK,MAAM;AACrB,MAAI,eAAe,KAAK,MAAM;QACzB;EACL,MAAM,QAAQ,IAAI,MAAM;AACxB,MAAI,YAAY,MAAM,MAAM,KAAK,EAAE;AACjC,SAAM,KAAK;AACX,SAAM,OAAO;AACb,OAAI,eAAe,KAAK,MAAM;;;;;;;AAWpC,SAAgB,gBAAgB,IAA+B,MAAwB;CACrF,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,KAAK;EAC3B,MAAM,QAAqB;GAAE;GAAI;GAAM,SAAS;GAAW;AAC3D,MAAI,MAAM,KAAK,MAAM;AACrB,MAAI,qBAAqB,KAAK,MAAM;QAC/B;EACL,MAAM,QAAQ,IAAI,MAAM;AACxB,MAAI,YAAY,MAAM,MAAM,KAAK,EAAE;AACjC,SAAM,KAAK;AACX,SAAM,OAAO;AACb,OAAI,qBAAqB,KAAK,MAAM;;;;;;;AAU1C,SAAgB,QAAW,IAAa,MAAoB;CAC1D,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,KAAK;EAC3B,MAAM,QAAQ,IAAI;AAClB,MAAI,MAAM,KAAK;GAAE;GAAO;GAAM,CAAC;AAC/B,SAAO;;CAGT,MAAM,QAAQ,IAAI,MAAM;AACxB,KAAI,YAAY,MAAM,MAAM,KAAK,EAAE;AACjC,QAAM,QAAQ,IAAI;AAClB,QAAM,OAAO;;AAEf,QAAO,MAAM;;;;;AAQf,SAAgB,YAAqD,IAAO,MAAoB;AAC9F,QAAO,cAAc,IAAI,KAAK;;;;;AAQhC,SAAgB,OAAU,SAAoC;CAC5D,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,KAAK;EAC3B,MAAM,MAAM,EAAE,SAAS,YAAY,SAAa,UAAgB,MAAM;AACtE,MAAI,MAAM,KAAK,IAAI;;AAGrB,QAAO,IAAI,MAAM;;;;;AAQnB,SAAgB,WACd,SACA,SAC0B;CAC1B,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,IACtB,KAAI,MAAM,KAAK,OAAO,YAAY,aAAc,SAAqB,GAAG,QAAQ;CAGlF,MAAM,QAAQ,IAAI,MAAM;CACxB,MAAM,YAAY,WAAc;EAC9B,MAAM,UAAU,IAAI,MAAM;EAC1B,MAAM,OAAO,QAAQ,SAAS,OAAO;AACrC,MAAI,OAAO,GAAG,SAAS,KAAK,CAAE;AAC9B,MAAI,MAAM,OAAO;AACjB,MAAI,kBAAkB;;AAGxB,QAAO,CAAC,OAAO,SAAS;;AAK1B,IAAI,aAAa;;;;AAKjB,SAAgB,QAAgB;CAC9B,MAAM,MAAM,YAAY;CACxB,MAAM,MAAM,cAAc;AAE1B,KAAI,IAAI,MAAM,UAAU,IACtB,KAAI,MAAM,KAAK,MAAM,cAAc,SAAS,GAAG,CAAC,GAAG;AAGrD,QAAO,IAAI,MAAM;;;;;;AASnB,SAAgB,KACd,WACA,UAC0B;CAC1B,MAAM,UACJ,cACE,GAAM,MAAS;EACf,MAAM,QAAQ,OAAO,KAAK,EAAE;EAC5B,MAAM,QAAQ,OAAO,KAAK,EAAE;AAC5B,MAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAC1C,OAAK,MAAM,KAAK,MACd,KAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,CAAE,QAAO;AAErC,SAAO;;CAGX,IAAI,YAAsB;CAC1B,IAAI,aAAyB;AAE7B,SAAQ,UAAa;AACnB,MAAI,cAAc,QAAQ,QAAQ,WAAW,MAAM,CACjD,QAAO;AAET,cAAY;AACZ,eAAc,UAAmC,MAAM;AACvD,SAAO"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Fragment, h } from "@pyreon/core";
|
|
2
|
+
import { signal } from "@pyreon/reactivity";
|
|
3
|
+
|
|
4
|
+
//#region src/jsx-runtime.ts
|
|
5
|
+
let _currentCtx = null;
|
|
6
|
+
let _hookIndex = 0;
|
|
7
|
+
function beginRender(ctx) {
|
|
8
|
+
_currentCtx = ctx;
|
|
9
|
+
_hookIndex = 0;
|
|
10
|
+
ctx.pendingEffects = [];
|
|
11
|
+
ctx.pendingLayoutEffects = [];
|
|
12
|
+
}
|
|
13
|
+
function endRender() {
|
|
14
|
+
_currentCtx = null;
|
|
15
|
+
_hookIndex = 0;
|
|
16
|
+
}
|
|
17
|
+
function runLayoutEffects(entries) {
|
|
18
|
+
for (const entry of entries) {
|
|
19
|
+
if (entry.cleanup) entry.cleanup();
|
|
20
|
+
const cleanup = entry.fn();
|
|
21
|
+
entry.cleanup = typeof cleanup === "function" ? cleanup : void 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function scheduleEffects(ctx, entries) {
|
|
25
|
+
if (entries.length === 0) return;
|
|
26
|
+
queueMicrotask(() => {
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
if (ctx.unmounted) return;
|
|
29
|
+
if (entry.cleanup) entry.cleanup();
|
|
30
|
+
const cleanup = entry.fn();
|
|
31
|
+
entry.cleanup = typeof cleanup === "function" ? cleanup : void 0;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const _wrapperCache = /* @__PURE__ */ new WeakMap();
|
|
36
|
+
function wrapCompatComponent(preactComponent) {
|
|
37
|
+
let wrapped = _wrapperCache.get(preactComponent);
|
|
38
|
+
if (wrapped) return wrapped;
|
|
39
|
+
wrapped = ((props) => {
|
|
40
|
+
const ctx = {
|
|
41
|
+
hooks: [],
|
|
42
|
+
scheduleRerender: () => {},
|
|
43
|
+
pendingEffects: [],
|
|
44
|
+
pendingLayoutEffects: [],
|
|
45
|
+
unmounted: false
|
|
46
|
+
};
|
|
47
|
+
const version = signal(0);
|
|
48
|
+
let updateScheduled = false;
|
|
49
|
+
ctx.scheduleRerender = () => {
|
|
50
|
+
if (ctx.unmounted || updateScheduled) return;
|
|
51
|
+
updateScheduled = true;
|
|
52
|
+
queueMicrotask(() => {
|
|
53
|
+
updateScheduled = false;
|
|
54
|
+
if (!ctx.unmounted) version.set(version.peek() + 1);
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
return () => {
|
|
58
|
+
version();
|
|
59
|
+
beginRender(ctx);
|
|
60
|
+
const result = preactComponent(props);
|
|
61
|
+
const layoutEffects = ctx.pendingLayoutEffects;
|
|
62
|
+
const effects = ctx.pendingEffects;
|
|
63
|
+
endRender();
|
|
64
|
+
runLayoutEffects(layoutEffects);
|
|
65
|
+
scheduleEffects(ctx, effects);
|
|
66
|
+
return result;
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
_wrapperCache.set(preactComponent, wrapped);
|
|
70
|
+
return wrapped;
|
|
71
|
+
}
|
|
72
|
+
function jsx(type, props, key) {
|
|
73
|
+
const { children, ...rest } = props;
|
|
74
|
+
const propsWithKey = key != null ? {
|
|
75
|
+
...rest,
|
|
76
|
+
key
|
|
77
|
+
} : rest;
|
|
78
|
+
if (typeof type === "function") return h(wrapCompatComponent(type), children !== void 0 ? {
|
|
79
|
+
...propsWithKey,
|
|
80
|
+
children
|
|
81
|
+
} : propsWithKey);
|
|
82
|
+
return h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
|
|
83
|
+
}
|
|
84
|
+
const jsxs = jsx;
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
export { Fragment, jsx, jsxs };
|
|
88
|
+
//# sourceMappingURL=jsx-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx-runtime.ts"],"sourcesContent":["/**\n * Compat JSX runtime for Preact compatibility mode.\n *\n * When `jsxImportSource` is redirected to `@pyreon/preact-compat` (via the vite\n * plugin's `compat: \"preact\"` 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 Preact-style re-renders on state change while Pyreon's\n * existing renderer handles all DOM work.\n */\n\nimport type { ComponentFn, Props, VNode, VNodeChild } from \"@pyreon/core\"\nimport { Fragment, h } from \"@pyreon/core\"\nimport { 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}\n\nexport interface EffectEntry {\n // biome-ignore lint/suspicious/noConfusingVoidType: matches Preact'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(preactComponent: Function): ComponentFn {\n let wrapped = _wrapperCache.get(preactComponent)\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 }\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 // Return reactive accessor — Pyreon's mountChild calls mountReactive\n return () => {\n version() // tracked read — triggers re-execution when state changes\n beginRender(ctx)\n const result = (preactComponent 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(preactComponent, 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 Preact-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":";;;;AAqCA,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,iBAAwC;CACnE,IAAI,UAAU,cAAc,IAAI,gBAAgB;AAChD,KAAI,QAAS,QAAO;AAIpB,aAAY,UAAiB;EAC3B,MAAM,MAAqB;GACzB,OAAO,EAAE;GACT,wBAAwB;GAGxB,gBAAgB,EAAE;GAClB,sBAAsB,EAAE;GACxB,WAAW;GACZ;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,eAAa;AACX,YAAS;AACT,eAAY,IAAI;GAChB,MAAM,SAAU,gBAAgC,MAAM;GACtD,MAAM,gBAAgB,IAAI;GAC1B,MAAM,UAAU,IAAI;AACpB,cAAW;AAEX,oBAAiB,cAAc;AAC/B,mBAAgB,KAAK,QAAQ;AAE7B,UAAO;;;AAIX,eAAc,IAAI,iBAAiB,QAAQ;AAC3C,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/lib/signals.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { batch as pyreonBatch, computed as computed$1, effect as effect$1, signal as signal$1 } from "@pyreon/reactivity";
|
|
2
|
+
|
|
3
|
+
//#region src/signals.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create a Preact-style signal with `.value` accessor.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const count = signal(0)
|
|
9
|
+
* count.value++ // write
|
|
10
|
+
* console.log(count.value) // read (tracked)
|
|
11
|
+
*/
|
|
12
|
+
function signal(initial) {
|
|
13
|
+
const s = signal$1(initial);
|
|
14
|
+
return {
|
|
15
|
+
get value() {
|
|
16
|
+
return s();
|
|
17
|
+
},
|
|
18
|
+
set value(v) {
|
|
19
|
+
s.set(v);
|
|
20
|
+
},
|
|
21
|
+
peek() {
|
|
22
|
+
return s.peek();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create a Preact-style computed with `.value` accessor.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const doubled = computed(() => count.value * 2)
|
|
31
|
+
* console.log(doubled.value)
|
|
32
|
+
*/
|
|
33
|
+
function computed(fn) {
|
|
34
|
+
const c = computed$1(fn);
|
|
35
|
+
return {
|
|
36
|
+
get value() {
|
|
37
|
+
return c();
|
|
38
|
+
},
|
|
39
|
+
peek() {
|
|
40
|
+
return c();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run a side-effect that auto-tracks signal reads.
|
|
46
|
+
* Returns a dispose function.
|
|
47
|
+
*/
|
|
48
|
+
function effect(fn) {
|
|
49
|
+
const e = effect$1(fn);
|
|
50
|
+
return () => {
|
|
51
|
+
e.dispose();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
export { pyreonBatch as batch, computed, effect, signal };
|
|
57
|
+
//# sourceMappingURL=signals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.js","names":["pyreonSignal","pyreonComputed","pyreonEffect"],"sources":["../src/signals.ts"],"sourcesContent":["/**\n * @pyreon/preact-compat/signals\n *\n * Preact Signals compatibility layer (`@preact/signals` style).\n * Wraps Pyreon's signal/computed in `{ value }` accessor objects.\n */\n\nimport type { Effect } from \"@pyreon/reactivity\"\nimport {\n batch as pyreonBatch,\n computed as pyreonComputed,\n effect as pyreonEffect,\n signal as pyreonSignal,\n} from \"@pyreon/reactivity\"\n\n// ─── Signal ──────────────────────────────────────────────────────────────────\n\nexport interface ReadonlySignal<T> {\n readonly value: T\n peek(): T\n}\n\nexport interface WritableSignal<T> extends ReadonlySignal<T> {\n value: T\n}\n\n/**\n * Create a Preact-style signal with `.value` accessor.\n *\n * @example\n * const count = signal(0)\n * count.value++ // write\n * console.log(count.value) // read (tracked)\n */\nexport function signal<T>(initial: T): WritableSignal<T> {\n const s = pyreonSignal<T>(initial)\n return {\n get value(): T {\n return s()\n },\n set value(v: T) {\n s.set(v)\n },\n peek(): T {\n return s.peek()\n },\n }\n}\n\n// ─── Computed ────────────────────────────────────────────────────────────────\n\n/**\n * Create a Preact-style computed with `.value` accessor.\n *\n * @example\n * const doubled = computed(() => count.value * 2)\n * console.log(doubled.value)\n */\nexport function computed<T>(fn: () => T): ReadonlySignal<T> {\n const c = pyreonComputed(fn)\n return {\n get value(): T {\n return c()\n },\n peek(): T {\n // computed doesn't have peek — just read the value untracked\n return c()\n },\n }\n}\n\n// ─── Effect ──────────────────────────────────────────────────────────────────\n\n/**\n * Run a side-effect that auto-tracks signal reads.\n * Returns a dispose function.\n */\n// biome-ignore lint/suspicious/noConfusingVoidType: void is intentional — callers may return void\nexport function effect(fn: () => void | (() => void)): () => void {\n // Pyreon's effect() natively supports cleanup return values\n const e: Effect = pyreonEffect(fn)\n return () => {\n e.dispose()\n }\n}\n\n// ─── Batch ───────────────────────────────────────────────────────────────────\n\n/**\n * Batch multiple signal writes into a single update.\n */\nexport { pyreonBatch as batch }\n"],"mappings":";;;;;;;;;;;AAkCA,SAAgB,OAAU,SAA+B;CACvD,MAAM,IAAIA,SAAgB,QAAQ;AAClC,QAAO;EACL,IAAI,QAAW;AACb,UAAO,GAAG;;EAEZ,IAAI,MAAM,GAAM;AACd,KAAE,IAAI,EAAE;;EAEV,OAAU;AACR,UAAO,EAAE,MAAM;;EAElB;;;;;;;;;AAYH,SAAgB,SAAY,IAAgC;CAC1D,MAAM,IAAIC,WAAe,GAAG;AAC5B,QAAO;EACL,IAAI,QAAW;AACb,UAAO,GAAG;;EAEZ,OAAU;AAER,UAAO,GAAG;;EAEb;;;;;;AAUH,SAAgB,OAAO,IAA2C;CAEhE,MAAM,IAAYC,SAAa,GAAG;AAClC,cAAa;AACX,IAAE,SAAS"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { onErrorCaptured, useContext } from "@pyreon/core";
|
|
2
|
+
function getCurrentCtx() {
|
|
3
|
+
return _currentCtx;
|
|
4
|
+
}
|
|
5
|
+
function getHookIndex() {
|
|
6
|
+
return _hookIndex++;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/hooks.ts
|
|
11
|
+
function requireCtx() {
|
|
12
|
+
const ctx = getCurrentCtx();
|
|
13
|
+
if (!ctx) throw new Error("Hook called outside of a component render");
|
|
14
|
+
return ctx;
|
|
15
|
+
}
|
|
16
|
+
function depsChanged(a, b) {
|
|
17
|
+
if (a === void 0 || b === void 0) return true;
|
|
18
|
+
if (a.length !== b.length) return true;
|
|
19
|
+
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return true;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Preact-compatible `useState` — returns `[value, setter]`.
|
|
24
|
+
* Triggers a component re-render when the setter is called.
|
|
25
|
+
*/
|
|
26
|
+
function useState(initial) {
|
|
27
|
+
const ctx = requireCtx();
|
|
28
|
+
const idx = getHookIndex();
|
|
29
|
+
if (ctx.hooks.length <= idx) ctx.hooks.push(typeof initial === "function" ? initial() : initial);
|
|
30
|
+
const value = ctx.hooks[idx];
|
|
31
|
+
const setter = v => {
|
|
32
|
+
const current = ctx.hooks[idx];
|
|
33
|
+
const next = typeof v === "function" ? v(current) : v;
|
|
34
|
+
if (Object.is(current, next)) return;
|
|
35
|
+
ctx.hooks[idx] = next;
|
|
36
|
+
ctx.scheduleRerender();
|
|
37
|
+
};
|
|
38
|
+
return [value, setter];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Preact-compatible `useEffect` — runs after render when deps change.
|
|
42
|
+
* Returns cleanup on unmount and before re-running.
|
|
43
|
+
*/
|
|
44
|
+
function useEffect(fn, deps) {
|
|
45
|
+
const ctx = requireCtx();
|
|
46
|
+
const idx = getHookIndex();
|
|
47
|
+
if (ctx.hooks.length <= idx) {
|
|
48
|
+
const entry = {
|
|
49
|
+
fn,
|
|
50
|
+
deps,
|
|
51
|
+
cleanup: void 0
|
|
52
|
+
};
|
|
53
|
+
ctx.hooks.push(entry);
|
|
54
|
+
ctx.pendingEffects.push(entry);
|
|
55
|
+
} else {
|
|
56
|
+
const entry = ctx.hooks[idx];
|
|
57
|
+
if (depsChanged(entry.deps, deps)) {
|
|
58
|
+
entry.fn = fn;
|
|
59
|
+
entry.deps = deps;
|
|
60
|
+
ctx.pendingEffects.push(entry);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Preact-compatible `useLayoutEffect` — runs synchronously after DOM mutations.
|
|
66
|
+
*/
|
|
67
|
+
function useLayoutEffect(fn, deps) {
|
|
68
|
+
const ctx = requireCtx();
|
|
69
|
+
const idx = getHookIndex();
|
|
70
|
+
if (ctx.hooks.length <= idx) {
|
|
71
|
+
const entry = {
|
|
72
|
+
fn,
|
|
73
|
+
deps,
|
|
74
|
+
cleanup: void 0
|
|
75
|
+
};
|
|
76
|
+
ctx.hooks.push(entry);
|
|
77
|
+
ctx.pendingLayoutEffects.push(entry);
|
|
78
|
+
} else {
|
|
79
|
+
const entry = ctx.hooks[idx];
|
|
80
|
+
if (depsChanged(entry.deps, deps)) {
|
|
81
|
+
entry.fn = fn;
|
|
82
|
+
entry.deps = deps;
|
|
83
|
+
ctx.pendingLayoutEffects.push(entry);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Preact-compatible `useMemo` — returns the cached value, recomputed when deps change.
|
|
89
|
+
*/
|
|
90
|
+
function useMemo(fn, deps) {
|
|
91
|
+
const ctx = requireCtx();
|
|
92
|
+
const idx = getHookIndex();
|
|
93
|
+
if (ctx.hooks.length <= idx) {
|
|
94
|
+
const value = fn();
|
|
95
|
+
ctx.hooks.push({
|
|
96
|
+
value,
|
|
97
|
+
deps
|
|
98
|
+
});
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
const entry = ctx.hooks[idx];
|
|
102
|
+
if (depsChanged(entry.deps, deps)) {
|
|
103
|
+
entry.value = fn();
|
|
104
|
+
entry.deps = deps;
|
|
105
|
+
}
|
|
106
|
+
return entry.value;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Preact-compatible `useCallback` — returns the cached function when deps haven't changed.
|
|
110
|
+
*/
|
|
111
|
+
function useCallback(fn, deps) {
|
|
112
|
+
return useMemo(() => fn, deps);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Preact-compatible `useRef` — returns `{ current }` persisted across re-renders.
|
|
116
|
+
*/
|
|
117
|
+
function useRef(initial) {
|
|
118
|
+
const ctx = requireCtx();
|
|
119
|
+
const idx = getHookIndex();
|
|
120
|
+
if (ctx.hooks.length <= idx) {
|
|
121
|
+
const ref = {
|
|
122
|
+
current: initial !== void 0 ? initial : null
|
|
123
|
+
};
|
|
124
|
+
ctx.hooks.push(ref);
|
|
125
|
+
}
|
|
126
|
+
return ctx.hooks[idx];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Preact-compatible `useReducer` — returns `[state, dispatch]`.
|
|
130
|
+
*/
|
|
131
|
+
function useReducer(reducer, initial) {
|
|
132
|
+
const ctx = requireCtx();
|
|
133
|
+
const idx = getHookIndex();
|
|
134
|
+
if (ctx.hooks.length <= idx) ctx.hooks.push(typeof initial === "function" ? initial() : initial);
|
|
135
|
+
const state = ctx.hooks[idx];
|
|
136
|
+
const dispatch = action => {
|
|
137
|
+
const current = ctx.hooks[idx];
|
|
138
|
+
const next = reducer(current, action);
|
|
139
|
+
if (Object.is(current, next)) return;
|
|
140
|
+
ctx.hooks[idx] = next;
|
|
141
|
+
ctx.scheduleRerender();
|
|
142
|
+
};
|
|
143
|
+
return [state, dispatch];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Preact-compatible `useId` — returns a stable unique string per hook call.
|
|
147
|
+
*/
|
|
148
|
+
function useId() {
|
|
149
|
+
const ctx = requireCtx();
|
|
150
|
+
const idx = getHookIndex();
|
|
151
|
+
if (ctx.hooks.length <= idx) ctx.hooks.push(`:r${(_idCounter++).toString(36)}:`);
|
|
152
|
+
return ctx.hooks[idx];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Preact-compatible `memo` — wraps a component to skip re-render when props
|
|
156
|
+
* are shallowly equal.
|
|
157
|
+
*/
|
|
158
|
+
function memo(component, areEqual) {
|
|
159
|
+
const compare = areEqual ?? ((a, b) => {
|
|
160
|
+
const keysA = Object.keys(a);
|
|
161
|
+
const keysB = Object.keys(b);
|
|
162
|
+
if (keysA.length !== keysB.length) return false;
|
|
163
|
+
for (const k of keysA) if (!Object.is(a[k], b[k])) return false;
|
|
164
|
+
return true;
|
|
165
|
+
});
|
|
166
|
+
let prevProps = null;
|
|
167
|
+
let prevResult = null;
|
|
168
|
+
return props => {
|
|
169
|
+
if (prevProps !== null && compare(prevProps, props)) return prevResult;
|
|
170
|
+
prevProps = props;
|
|
171
|
+
prevResult = component(props);
|
|
172
|
+
return prevResult;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
export { memo, useCallback, useContext, useEffect, onErrorCaptured as useErrorBoundary, useId, useLayoutEffect, useMemo, useReducer, useRef, useState };
|
|
178
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../../src/jsx-runtime.ts","../../src/hooks.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { VNodeChild, onErrorCaptured, useContext } from "@pyreon/core";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Preact-compatible `useState` — returns `[value, setter]`.
|
|
6
|
+
* Triggers a component re-render when the setter is called.
|
|
7
|
+
*/
|
|
8
|
+
declare function useState<T>(initial: T | (() => T)): [T, (v: T | ((prev: T) => T)) => void];
|
|
9
|
+
/**
|
|
10
|
+
* Preact-compatible `useEffect` — runs after render when deps change.
|
|
11
|
+
* Returns cleanup on unmount and before re-running.
|
|
12
|
+
*/
|
|
13
|
+
declare function useEffect(fn: () => (() => void) | void, deps?: unknown[]): void;
|
|
14
|
+
/**
|
|
15
|
+
* Preact-compatible `useLayoutEffect` — runs synchronously after DOM mutations.
|
|
16
|
+
*/
|
|
17
|
+
declare function useLayoutEffect(fn: () => (() => void) | void, deps?: unknown[]): void;
|
|
18
|
+
/**
|
|
19
|
+
* Preact-compatible `useMemo` — returns the cached value, recomputed when deps change.
|
|
20
|
+
*/
|
|
21
|
+
declare function useMemo<T>(fn: () => T, deps: unknown[]): T;
|
|
22
|
+
/**
|
|
23
|
+
* Preact-compatible `useCallback` — returns the cached function when deps haven't changed.
|
|
24
|
+
*/
|
|
25
|
+
declare function useCallback<T extends (...args: never[]) => unknown>(fn: T, deps: unknown[]): T;
|
|
26
|
+
/**
|
|
27
|
+
* Preact-compatible `useRef` — returns `{ current }` persisted across re-renders.
|
|
28
|
+
*/
|
|
29
|
+
declare function useRef<T>(initial?: T): {
|
|
30
|
+
current: T | null;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Preact-compatible `useReducer` — returns `[state, dispatch]`.
|
|
34
|
+
*/
|
|
35
|
+
declare function useReducer<S, A>(reducer: (state: S, action: A) => S, initial: S | (() => S)): [S, (action: A) => void];
|
|
36
|
+
/**
|
|
37
|
+
* Preact-compatible `useId` — returns a stable unique string per hook call.
|
|
38
|
+
*/
|
|
39
|
+
declare function useId(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Preact-compatible `memo` — wraps a component to skip re-render when props
|
|
42
|
+
* are shallowly equal.
|
|
43
|
+
*/
|
|
44
|
+
declare function memo<P extends Record<string, unknown>>(component: (props: P) => VNodeChild, areEqual?: (prevProps: P, nextProps: P) => boolean): (props: P) => VNodeChild;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { memo, useCallback, useContext, useEffect, onErrorCaptured as useErrorBoundary, useId, useLayoutEffect, useMemo, useReducer, useRef, useState };
|
|
47
|
+
//# sourceMappingURL=hooks2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks2.d.ts","names":[],"sources":["../../src/hooks.ts"],"mappings":";;;;;;;iBAwCgB,QAAA,GAAA,CAAY,OAAA,EAAS,CAAA,UAAW,CAAA,KAAM,CAAA,GAAI,CAAA,EAAG,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;;;;;iBA2B/D,SAAA,CAAU,EAAA,6BAA+B,IAAA;;;;iBAyBzC,eAAA,CAAgB,EAAA,6BAA+B,IAAA;AAzB/D;;;AAAA,iBAgDgB,OAAA,GAAA,CAAW,EAAA,QAAU,CAAA,EAAG,IAAA,cAAkB,CAAA;;AAvB1D;;iBA8CgB,WAAA,eAA0B,IAAA,sBAAA,CAA2B,EAAA,EAAI,CAAA,EAAG,IAAA,cAAkB,CAAA;;;AAvB9F;iBAgCgB,MAAA,GAAA,CAAU,OAAA,GAAU,CAAA;EAAM,OAAA,EAAS,CAAA;AAAA;;;;iBAiBnC,UAAA,MAAA,CACd,OAAA,GAAU,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,CAAA,EAClC,OAAA,EAAS,CAAA,UAAW,CAAA,KAClB,CAAA,GAAI,MAAA,EAAQ,CAAA;;;;iBA2BA,KAAA,CAAA;;;;;iBAiBA,IAAA,WAAe,MAAA,kBAAA,CAC7B,SAAA,GAAY,KAAA,EAAO,CAAA,KAAM,UAAA,EACzB,QAAA,IAAY,SAAA,EAAW,CAAA,EAAG,SAAA,EAAW,CAAA,gBACnC,KAAA,EAAO,CAAA,KAAM,UAAA"}
|