@ipxjs/refract 0.3.1 → 0.4.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/README.md +54 -16
- package/package.json +11 -3
- package/src/refract/compat/react-dom-client.ts +27 -0
- package/src/refract/compat/react-dom.ts +42 -0
- package/src/refract/compat/react-jsx-dev-runtime.ts +15 -0
- package/src/refract/compat/react-jsx-runtime.ts +32 -0
- package/src/refract/compat/react.ts +238 -0
- package/src/refract/compat/sharedInternals.ts +212 -0
- package/src/refract/coreRenderer.ts +81 -5
- package/src/refract/dom.ts +41 -3
- package/src/refract/features/hooks.ts +129 -5
- package/src/refract/full.ts +20 -1
- package/src/refract/hooks.ts +9 -0
- package/src/refract/hooksRuntime.ts +22 -3
- package/src/refract/portal.ts +18 -0
- package/src/refract/runtimeExtensions.ts +26 -0
- package/tests/compat.test.ts +177 -0
- package/tests/entrypoints.test.ts +18 -0
- package/tests/keyed.test.ts +1 -1
- package/tests/react-compat-shims.d.ts +4 -0
- package/tests/react-router-smoke.test.ts +72 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Refract
|
|
4
4
|
|
|
5
5
|
A minimal React-like virtual DOM library, written in TypeScript with split entrypoints
|
|
6
|
-
so you can keep bundles small and
|
|
6
|
+
so you can keep bundles small and targeted.
|
|
7
7
|
|
|
8
8
|
Refract implements the core ideas behind React in TypeScript
|
|
9
9
|
- a virtual DOM
|
|
@@ -82,6 +82,44 @@ yarn test
|
|
|
82
82
|
- `refract/full` -- complete API including hooks, context, memo, sanitizer defaults, and devtools integration
|
|
83
83
|
- `refract` -- alias of `refract/full` for backward compatibility
|
|
84
84
|
- Feature entrypoints for custom bundles: `refract/hooks`, `refract/context`, `refract/memo`, `refract/security`, `refract/devtools`
|
|
85
|
+
- Optional React-compat entrypoints (opt-in): `refract/compat/react`, `refract/compat/react-dom`, `refract/compat/react-dom/client`, `refract/compat/react/jsx-runtime`, `refract/compat/react/jsx-dev-runtime`
|
|
86
|
+
|
|
87
|
+
### React Ecosystem Compatibility (Opt-in)
|
|
88
|
+
|
|
89
|
+
Refract now includes an opt-in compatibility layer so you can alias React imports
|
|
90
|
+
for selected ecosystem libraries (for example MUI, `react-router-dom`, and
|
|
91
|
+
`@dnd-kit`) without inflating the default `refract/core` path.
|
|
92
|
+
|
|
93
|
+
Supported compat APIs include:
|
|
94
|
+
- `forwardRef`, `cloneElement`, `Children`, `isValidElement`
|
|
95
|
+
- `useLayoutEffect`, `useInsertionEffect`, `useId`
|
|
96
|
+
- `useSyncExternalStore`, `useImperativeHandle`
|
|
97
|
+
- `createPortal`
|
|
98
|
+
- `createRoot`, `flushSync`, `unstable_batchedUpdates`
|
|
99
|
+
- `jsx/jsxs/jsxDEV` runtime entrypoints
|
|
100
|
+
- React hook dispatcher bridge internals (`__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE`) with optional `registerExternalReactModule(...)` for mixed-runtime environments (tests/Node)
|
|
101
|
+
|
|
102
|
+
Example Vite aliases:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
// vite.config.ts
|
|
106
|
+
import { defineConfig } from "vite";
|
|
107
|
+
|
|
108
|
+
export default defineConfig({
|
|
109
|
+
resolve: {
|
|
110
|
+
alias: {
|
|
111
|
+
react: "refract/compat/react",
|
|
112
|
+
"react-dom": "refract/compat/react-dom",
|
|
113
|
+
"react-dom/client": "refract/compat/react-dom/client",
|
|
114
|
+
"react/jsx-runtime": "refract/compat/react/jsx-runtime",
|
|
115
|
+
"react/jsx-dev-runtime": "refract/compat/react/jsx-dev-runtime",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The compat layer is intentionally separate from core so users who do not need
|
|
122
|
+
React ecosystem compatibility keep the smallest and fastest Refract bundles.
|
|
85
123
|
|
|
86
124
|
## API
|
|
87
125
|
|
|
@@ -181,20 +219,20 @@ The values below are from a local run on February 15, 2026.
|
|
|
181
219
|
|
|
182
220
|
| Framework | JS bundle (raw) | JS bundle (gzip) |
|
|
183
221
|
|---------------------------|----------------:|-----------------:|
|
|
184
|
-
| Refract (`core`) |
|
|
185
|
-
| Refract (`core+hooks`) |
|
|
186
|
-
| Refract (`core+context`) |
|
|
187
|
-
| Refract (`core+memo`) |
|
|
188
|
-
| Refract (`core+security`) |
|
|
189
|
-
| Refract (`refract`) |
|
|
222
|
+
| Refract (`core`) | 8.36 kB | 3.16 kB |
|
|
223
|
+
| Refract (`core+hooks`) | 9.76 kB | 3.65 kB |
|
|
224
|
+
| Refract (`core+context`) | 8.85 kB | 3.38 kB |
|
|
225
|
+
| Refract (`core+memo`) | 9.03 kB | 3.39 kB |
|
|
226
|
+
| Refract (`core+security`) | 9.27 kB | 3.46 kB |
|
|
227
|
+
| Refract (`refract`) | 14.64 kB | 5.34 kB |
|
|
190
228
|
| React | 189.74 kB | 59.52 kB |
|
|
191
229
|
| Preact | 14.46 kB | 5.95 kB |
|
|
192
230
|
|
|
193
231
|
Load-time metrics are machine-dependent, so the benchmark script prints a fresh
|
|
194
232
|
per-run timing table (median, p95, min/max, sd) for every framework.
|
|
195
233
|
|
|
196
|
-
From this snapshot, Refract `core` gzip JS is about
|
|
197
|
-
and the full `refract` entrypoint is about 11.
|
|
234
|
+
From this snapshot, Refract `core` gzip JS is about 18.8x smaller than React,
|
|
235
|
+
and the full `refract` entrypoint is about 11.1x smaller.
|
|
198
236
|
|
|
199
237
|
### Component Combination Benchmarks (Vitest)
|
|
200
238
|
|
|
@@ -204,13 +242,13 @@ Higher `hz` is better.
|
|
|
204
242
|
|
|
205
243
|
| Component usage profile | Mount (hz) | Mount vs base | Reconcile (hz) | Reconcile vs base |
|
|
206
244
|
|-------------------------|------------|---------------|----------------|-------------------|
|
|
207
|
-
| `base` |
|
|
208
|
-
| `memo` |
|
|
209
|
-
| `context` |
|
|
210
|
-
| `fragment` |
|
|
211
|
-
| `keyed` |
|
|
212
|
-
| `memo+context` |
|
|
213
|
-
| `memo+context+keyed` |
|
|
245
|
+
| `base` | 5068.40 | baseline | 4144.37 | baseline |
|
|
246
|
+
| `memo` | 5883.23 | +16.1% | 5154.56 | +24.4% |
|
|
247
|
+
| `context` | 3521.54 | -30.5% | 5063.92 | +22.2% |
|
|
248
|
+
| `fragment` | 4880.23 | -3.7% | 4079.08 | -1.6% |
|
|
249
|
+
| `keyed` | 5763.70 | +13.7% | 4844.23 | +16.9% |
|
|
250
|
+
| `memo+context` | 6173.01 | +21.8% | 5144.98 | +24.1% |
|
|
251
|
+
| `memo+context+keyed` | 5606.73 | +10.6% | 4732.23 | +14.2% |
|
|
214
252
|
|
|
215
253
|
In this run, `memo+context` was the fastest mount profile, while
|
|
216
254
|
`memo` was the fastest reconcile profile.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ipxjs/refract",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A minimal React-like virtual DOM library
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "A minimal React-like virtual DOM library with an optional React compat layer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/refract/index.ts",
|
|
7
7
|
"exports": {
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
"./context": "./src/refract/features/context.ts",
|
|
13
13
|
"./memo": "./src/refract/memo.ts",
|
|
14
14
|
"./security": "./src/refract/features/security.ts",
|
|
15
|
-
"./devtools": "./src/refract/devtools.ts"
|
|
15
|
+
"./devtools": "./src/refract/devtools.ts",
|
|
16
|
+
"./compat/react": "./src/refract/compat/react.ts",
|
|
17
|
+
"./compat/react-dom": "./src/refract/compat/react-dom.ts",
|
|
18
|
+
"./compat/react-dom/client": "./src/refract/compat/react-dom-client.ts",
|
|
19
|
+
"./compat/react/jsx-runtime": "./src/refract/compat/react-jsx-runtime.ts",
|
|
20
|
+
"./compat/react/jsx-dev-runtime": "./src/refract/compat/react-jsx-dev-runtime.ts"
|
|
16
21
|
},
|
|
17
22
|
"scripts": {
|
|
18
23
|
"dev": "vite demo",
|
|
@@ -25,6 +30,9 @@
|
|
|
25
30
|
"devDependencies": {
|
|
26
31
|
"@types/jsdom": "^27.0.0",
|
|
27
32
|
"jsdom": "^28.0.0",
|
|
33
|
+
"react": "^19.2.4",
|
|
34
|
+
"react-dom": "^19.2.4",
|
|
35
|
+
"react-router-dom": "^7.13.0",
|
|
28
36
|
"typescript": "^5.9.3",
|
|
29
37
|
"vite": "^7.3.1",
|
|
30
38
|
"vitest": "^4.0.18"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createElement, Fragment } from "../createElement.js";
|
|
2
|
+
import { render } from "../render.js";
|
|
3
|
+
import { setReactCompatEventMode } from "../dom.js";
|
|
4
|
+
|
|
5
|
+
setReactCompatEventMode(true);
|
|
6
|
+
|
|
7
|
+
export interface RefractCompatRoot {
|
|
8
|
+
render(children: unknown): void;
|
|
9
|
+
unmount(): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createRoot(container: HTMLElement): RefractCompatRoot {
|
|
13
|
+
return {
|
|
14
|
+
render(children: unknown): void {
|
|
15
|
+
render(children as Parameters<typeof render>[0], container);
|
|
16
|
+
},
|
|
17
|
+
unmount(): void {
|
|
18
|
+
render(createElement(Fragment, null), container);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function hydrateRoot(container: HTMLElement, children: unknown): RefractCompatRoot {
|
|
24
|
+
const root = createRoot(container);
|
|
25
|
+
root.render(children);
|
|
26
|
+
return root;
|
|
27
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createElement, Fragment } from "../createElement.js";
|
|
2
|
+
import { flushPendingRenders } from "../coreRenderer.js";
|
|
3
|
+
import { setReactCompatEventMode } from "../dom.js";
|
|
4
|
+
import { createPortal as createPortalImpl } from "../portal.js";
|
|
5
|
+
import type { PortalChild } from "../portal.js";
|
|
6
|
+
import { render } from "../render.js";
|
|
7
|
+
|
|
8
|
+
setReactCompatEventMode(true);
|
|
9
|
+
|
|
10
|
+
export function createPortal(children: PortalChild, container: Node, key?: string | number | null): ReturnType<typeof createPortalImpl> {
|
|
11
|
+
return createPortalImpl(children, container, key);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function unstable_batchedUpdates<T>(callback: () => T): T {
|
|
15
|
+
return callback();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function flushSync<T>(callback: () => T): T {
|
|
19
|
+
const result = callback();
|
|
20
|
+
flushPendingRenders();
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function renderCompat(vnode: unknown, container: HTMLElement): void {
|
|
25
|
+
render(vnode as Parameters<typeof render>[0], container);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function unmountComponentAtNode(container: HTMLElement): boolean {
|
|
29
|
+
render(createElement(Fragment, null), container);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const ReactDomCompat = {
|
|
34
|
+
createPortal,
|
|
35
|
+
flushSync,
|
|
36
|
+
render: renderCompat,
|
|
37
|
+
unstable_batchedUpdates,
|
|
38
|
+
unmountComponentAtNode,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { renderCompat as render };
|
|
42
|
+
export default ReactDomCompat;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Fragment, jsx } from "./react-jsx-runtime.js";
|
|
2
|
+
import type { VNodeType } from "../types.js";
|
|
3
|
+
|
|
4
|
+
type JsxProps = Record<string, unknown> | null | undefined;
|
|
5
|
+
|
|
6
|
+
export function jsxDEV(
|
|
7
|
+
type: VNodeType,
|
|
8
|
+
props: JsxProps,
|
|
9
|
+
key?: string,
|
|
10
|
+
): ReturnType<typeof jsx> {
|
|
11
|
+
return jsx(type, props, key);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { Fragment };
|
|
15
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createElement, Fragment } from "../createElement.js";
|
|
2
|
+
import type { VNode, VNodeType } from "../types.js";
|
|
3
|
+
|
|
4
|
+
type JsxProps = Record<string, unknown> | null | undefined;
|
|
5
|
+
type JsxChild = VNode | string | number | boolean | null | undefined | JsxChild[];
|
|
6
|
+
|
|
7
|
+
function createJsxElement(type: VNodeType, rawProps: JsxProps, key?: string): ReturnType<typeof createElement> {
|
|
8
|
+
const props = { ...(rawProps ?? {}) };
|
|
9
|
+
if (key !== undefined) {
|
|
10
|
+
props.key = key;
|
|
11
|
+
}
|
|
12
|
+
const children = props.children as JsxChild | JsxChild[] | undefined;
|
|
13
|
+
delete props.children;
|
|
14
|
+
|
|
15
|
+
if (children === undefined) {
|
|
16
|
+
return createElement(type, props);
|
|
17
|
+
}
|
|
18
|
+
if (Array.isArray(children)) {
|
|
19
|
+
return createElement(type, props, ...(children as JsxChild[]));
|
|
20
|
+
}
|
|
21
|
+
return createElement(type, props, children as JsxChild);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function jsx(type: VNodeType, props: JsxProps, key?: string): ReturnType<typeof createElement> {
|
|
25
|
+
return createJsxElement(type, props, key);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function jsxs(type: VNodeType, props: JsxProps, key?: string): ReturnType<typeof createElement> {
|
|
29
|
+
return createJsxElement(type, props, key);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Fragment };
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { createElement, Fragment } from "../createElement.js";
|
|
2
|
+
import { memo } from "../memo.js";
|
|
3
|
+
import { createContext } from "../features/context.js";
|
|
4
|
+
import {
|
|
5
|
+
createRef,
|
|
6
|
+
} from "../features/hooks.js";
|
|
7
|
+
import type { Component, Props, VNode } from "../types.js";
|
|
8
|
+
import {
|
|
9
|
+
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
|
10
|
+
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
|
11
|
+
ensureHookDispatcherRuntime,
|
|
12
|
+
registerExternalReactModule,
|
|
13
|
+
resolveDispatcher,
|
|
14
|
+
} from "./sharedInternals.js";
|
|
15
|
+
|
|
16
|
+
const REACT_ELEMENT_TYPE = Symbol.for("react.element");
|
|
17
|
+
type ElementChild = VNode | string | number | boolean | null | undefined | ElementChild[];
|
|
18
|
+
|
|
19
|
+
ensureHookDispatcherRuntime();
|
|
20
|
+
|
|
21
|
+
function normalizeChildren(children: unknown): unknown[] {
|
|
22
|
+
if (children === undefined) return [];
|
|
23
|
+
return Array.isArray(children) ? children : [children];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseChildrenArgs(children: unknown[]): unknown {
|
|
27
|
+
if (children.length === 0) return undefined;
|
|
28
|
+
if (children.length === 1) return children[0];
|
|
29
|
+
return children;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function forwardRef<T, P extends Record<string, unknown> = Record<string, unknown>>(
|
|
33
|
+
render: (props: P, ref: { current: T | null } | ((value: T | null) => void) | null) => VNode,
|
|
34
|
+
): Component {
|
|
35
|
+
const ForwardRefComponent: Component = (props: Props) => {
|
|
36
|
+
const { ref, ...rest } = props as Props & { ref?: { current: T | null } | ((value: T | null) => void) | null };
|
|
37
|
+
return render(rest as unknown as P, ref ?? null);
|
|
38
|
+
};
|
|
39
|
+
return ForwardRefComponent;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function isValidElement(value: unknown): value is VNode {
|
|
43
|
+
return !!value
|
|
44
|
+
&& typeof value === "object"
|
|
45
|
+
&& "type" in (value as Record<string, unknown>)
|
|
46
|
+
&& "props" in (value as Record<string, unknown>);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function cloneElement(
|
|
50
|
+
element: VNode,
|
|
51
|
+
props?: Record<string, unknown> | null,
|
|
52
|
+
...children: unknown[]
|
|
53
|
+
): VNode {
|
|
54
|
+
const mergedProps: Record<string, unknown> = {
|
|
55
|
+
...element.props,
|
|
56
|
+
...(props ?? {}),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
if (children.length > 0) {
|
|
60
|
+
mergedProps.children = normalizeChildren(parseChildrenArgs(children)) as VNode[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (props?.key !== undefined) {
|
|
64
|
+
mergedProps.key = props.key;
|
|
65
|
+
} else if (element.key != null) {
|
|
66
|
+
mergedProps.key = element.key;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const nextChildren = normalizeChildren(mergedProps.children);
|
|
70
|
+
delete mergedProps.children;
|
|
71
|
+
|
|
72
|
+
return createElement(element.type, mergedProps, ...(nextChildren as ElementChild[]));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function childrenToArray(children: unknown): unknown[] {
|
|
76
|
+
if (children === undefined || children === null) return [];
|
|
77
|
+
if (!Array.isArray(children)) return [children];
|
|
78
|
+
const out: unknown[] = [];
|
|
79
|
+
const stack = [...children];
|
|
80
|
+
while (stack.length > 0) {
|
|
81
|
+
const child = stack.shift();
|
|
82
|
+
if (Array.isArray(child)) {
|
|
83
|
+
stack.unshift(...child);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (child === undefined || child === null || typeof child === "boolean") {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
out.push(child);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const Children = {
|
|
95
|
+
map<T>(children: unknown, fn: (child: unknown, index: number) => T): T[] {
|
|
96
|
+
return childrenToArray(children).map(fn);
|
|
97
|
+
},
|
|
98
|
+
forEach(children: unknown, fn: (child: unknown, index: number) => void): void {
|
|
99
|
+
childrenToArray(children).forEach(fn);
|
|
100
|
+
},
|
|
101
|
+
count(children: unknown): number {
|
|
102
|
+
return childrenToArray(children).length;
|
|
103
|
+
},
|
|
104
|
+
toArray(children: unknown): unknown[] {
|
|
105
|
+
return childrenToArray(children);
|
|
106
|
+
},
|
|
107
|
+
only(children: unknown): unknown {
|
|
108
|
+
const array = childrenToArray(children);
|
|
109
|
+
if (array.length !== 1) {
|
|
110
|
+
throw new Error("React.Children.only expected to receive a single React element child.");
|
|
111
|
+
}
|
|
112
|
+
return array[0];
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export function useState<T>(initial: T | (() => T)): [T, (value: T | ((prev: T) => T)) => void] {
|
|
117
|
+
return resolveDispatcher().useState(initial);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function useEffect(effect: () => void | (() => void), deps?: unknown[]): void {
|
|
121
|
+
return resolveDispatcher().useEffect(effect, deps);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function useLayoutEffect(effect: () => void | (() => void), deps?: unknown[]): void {
|
|
125
|
+
return resolveDispatcher().useLayoutEffect(effect, deps);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function useInsertionEffect(effect: () => void | (() => void), deps?: unknown[]): void {
|
|
129
|
+
return resolveDispatcher().useInsertionEffect(effect, deps);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function useRef<T>(initial: T): { current: T } {
|
|
133
|
+
return resolveDispatcher().useRef(initial);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function useMemo<T>(factory: () => T, deps: unknown[]): T {
|
|
137
|
+
return resolveDispatcher().useMemo(factory, deps);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function useCallback<T extends Function>(cb: T, deps: unknown[]): T {
|
|
141
|
+
return resolveDispatcher().useCallback(cb, deps) as T;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function useReducer<S, A, I = S>(
|
|
145
|
+
reducer: (state: S, action: A) => S,
|
|
146
|
+
initialArg: I,
|
|
147
|
+
init?: (arg: I) => S,
|
|
148
|
+
): [S, (action: A) => void] {
|
|
149
|
+
if (init) {
|
|
150
|
+
return resolveDispatcher().useReducer(reducer, initialArg, init) as [S, (action: A) => void];
|
|
151
|
+
}
|
|
152
|
+
return resolveDispatcher().useReducer(reducer, initialArg as unknown as S) as [S, (action: A) => void];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function useSyncExternalStore<T>(
|
|
156
|
+
subscribe: (onStoreChange: () => void) => () => void,
|
|
157
|
+
getSnapshot: () => T,
|
|
158
|
+
getServerSnapshot?: () => T,
|
|
159
|
+
): T {
|
|
160
|
+
return resolveDispatcher().useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function useImperativeHandle<T>(
|
|
164
|
+
ref: { current: T | null } | ((value: T | null) => void) | null | undefined,
|
|
165
|
+
create: () => T,
|
|
166
|
+
deps?: unknown[],
|
|
167
|
+
): void {
|
|
168
|
+
return resolveDispatcher().useImperativeHandle(ref, create, deps);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function useDebugValue(value: unknown): void {
|
|
172
|
+
return resolveDispatcher().useDebugValue(value);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function useContext<T>(context: unknown): T {
|
|
176
|
+
return resolveDispatcher().useContext(context as never) as T;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function useId(): string {
|
|
180
|
+
return resolveDispatcher().useId();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function startTransition(callback: () => void): void {
|
|
184
|
+
callback();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function useTransition(): [boolean, (callback: () => void) => void] {
|
|
188
|
+
return resolveDispatcher().useTransition();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function useDeferredValue<T>(value: T, initialValue?: T): T {
|
|
192
|
+
return resolveDispatcher().useDeferredValue(value, initialValue);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export { createElement, Fragment, createContext, memo };
|
|
196
|
+
export {
|
|
197
|
+
createRef,
|
|
198
|
+
registerExternalReactModule,
|
|
199
|
+
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
|
200
|
+
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export const version = "19.0.0-refract-compat";
|
|
204
|
+
|
|
205
|
+
const ReactCompat = {
|
|
206
|
+
Children,
|
|
207
|
+
Fragment,
|
|
208
|
+
createContext,
|
|
209
|
+
createElement,
|
|
210
|
+
cloneElement,
|
|
211
|
+
createRef,
|
|
212
|
+
forwardRef,
|
|
213
|
+
isValidElement,
|
|
214
|
+
memo,
|
|
215
|
+
registerExternalReactModule,
|
|
216
|
+
startTransition,
|
|
217
|
+
useCallback,
|
|
218
|
+
useContext,
|
|
219
|
+
useDebugValue,
|
|
220
|
+
useDeferredValue,
|
|
221
|
+
useEffect,
|
|
222
|
+
useId,
|
|
223
|
+
useImperativeHandle,
|
|
224
|
+
useInsertionEffect,
|
|
225
|
+
useLayoutEffect,
|
|
226
|
+
useMemo,
|
|
227
|
+
useReducer,
|
|
228
|
+
useRef,
|
|
229
|
+
useState,
|
|
230
|
+
useSyncExternalStore,
|
|
231
|
+
useTransition,
|
|
232
|
+
version,
|
|
233
|
+
$$typeof: REACT_ELEMENT_TYPE,
|
|
234
|
+
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
|
235
|
+
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export default ReactCompat;
|