@simpreact/simpreact 0.0.7 → 0.0.9

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.
Files changed (81) hide show
  1. package/compat/context.js +3 -3
  2. package/compat/core.js +105 -18
  3. package/compat/dom.js +5 -5
  4. package/compat/hooks.js +18 -3
  5. package/compat/index.d.ts +109 -45
  6. package/compat/jsx-runtime.js +4 -4
  7. package/compat/renderRuntime.js +47 -12
  8. package/component/index.d.ts +6 -7
  9. package/component/index.js +96 -94
  10. package/context/index.d.ts +5 -5
  11. package/context/index.js +27 -17
  12. package/core/createElement.js +14 -17
  13. package/core/flags.js +31 -0
  14. package/core/hostOperations.js +5 -13
  15. package/core/index.d.ts +48 -11
  16. package/core/index.js +4 -2
  17. package/core/internal.d.ts +136 -16
  18. package/core/internal.js +8 -16
  19. package/core/lifecycleEventBus.js +35 -16
  20. package/core/memo.js +4 -1
  21. package/core/mounting.js +70 -150
  22. package/core/mountingChildren.js +11 -29
  23. package/core/patching.js +122 -181
  24. package/core/patchingChildren.js +74 -145
  25. package/core/portal.js +1 -1
  26. package/core/processStack.js +115 -45
  27. package/core/ref.js +1 -0
  28. package/core/rerender.js +20 -22
  29. package/core/runtime.js +10 -2
  30. package/core/unmounting.js +41 -49
  31. package/core/unmountingChildren.js +9 -12
  32. package/core/utils.js +38 -16
  33. package/dom/attach-element-to-dom.js +16 -8
  34. package/dom/events.js +11 -15
  35. package/dom/index.d.ts +6 -5
  36. package/dom/props/attrMaps.js +90 -0
  37. package/dom/props/controlled/select.js +8 -10
  38. package/dom/props/props.js +13 -14
  39. package/hooks/index.d.ts +15 -10
  40. package/hooks/index.js +107 -84
  41. package/package.json +10 -5
  42. package/shared/index.d.ts +10 -6
  43. package/compat/context.d.ts +0 -8
  44. package/compat/core.d.ts +0 -47
  45. package/compat/dom.d.ts +0 -10
  46. package/compat/hooks.d.ts +0 -27
  47. package/compat/jsx-runtime.d.ts +0 -10
  48. package/compat/renderRuntime.d.ts +0 -6
  49. package/core/createElement.d.ts +0 -39
  50. package/core/fragment.d.ts +0 -5
  51. package/core/hostAdapter.d.ts +0 -23
  52. package/core/hostOperations.d.ts +0 -5
  53. package/core/lifecycleEventBus.d.ts +0 -39
  54. package/core/memo.d.ts +0 -8
  55. package/core/mounting.d.ts +0 -7
  56. package/core/mountingChildren.d.ts +0 -4
  57. package/core/patching.d.ts +0 -8
  58. package/core/patchingChildren.d.ts +0 -6
  59. package/core/portal.d.ts +0 -2
  60. package/core/processStack.d.ts +0 -106
  61. package/core/ref.d.ts +0 -18
  62. package/core/rerender.d.ts +0 -4
  63. package/core/runtime.d.ts +0 -17
  64. package/core/unmounting.d.ts +0 -7
  65. package/core/unmountingChildren.d.ts +0 -4
  66. package/core/utils.d.ts +0 -11
  67. package/dom/attach-element-to-dom.d.ts +0 -5
  68. package/dom/domAdapter.d.ts +0 -3
  69. package/dom/events.d.ts +0 -27
  70. package/dom/namespace.d.ts +0 -2
  71. package/dom/props/controlled/index.d.ts +0 -7
  72. package/dom/props/controlled/input.d.ts +0 -7
  73. package/dom/props/controlled/select.d.ts +0 -6
  74. package/dom/props/controlled/textarea.d.ts +0 -6
  75. package/dom/props/dangerInnerHTML.d.ts +0 -7
  76. package/dom/props/index.d.ts +0 -1
  77. package/dom/props/props.d.ts +0 -5
  78. package/dom/props/style.d.ts +0 -1
  79. package/dom/render.d.ts +0 -8
  80. package/shared/lang.d.ts +0 -3
  81. package/shared/utils.d.ts +0 -5
package/compat/context.js CHANGED
@@ -1,7 +1,7 @@
1
- import * as SimpReactContext from '../context/index.js';
1
+ import { createCreateContext, createUseContext } from '../context/index.js';
2
2
  import { renderRuntime } from './renderRuntime.js';
3
- export const createContext = SimpReactContext.createCreateContext(renderRuntime);
4
- export const useContext = SimpReactContext.createUseContext(renderRuntime);
3
+ export const createContext = createCreateContext(renderRuntime);
4
+ export const useContext = createUseContext(renderRuntime);
5
5
  export default {
6
6
  createContext,
7
7
  useContext,
package/compat/core.js CHANGED
@@ -1,5 +1,23 @@
1
- import * as SimpReactInternal from '../core/internal.js';
1
+ import { createElement as _createElement, createPortal as _createPortal, Fragment as _Fragment, memo as _memo, } from '../core/index.js';
2
+ import { isFragment, isPortal, withSyncRerender } from '../core/internal.js';
2
3
  import { useCatch, useState } from './hooks.js';
4
+ import { renderRuntime } from './renderRuntime.js';
5
+ // Threads refs through FC elements without polluting string-keyed props.
6
+ // Symbol keys are invisible to `for…in` and Object.keys, so they never
7
+ // accidentally end up on HOST elements via `{...props}` spread.
8
+ export const REF_SYMBOL = Symbol('simpreact.compat.ref');
9
+ // Wraps core createElement to strip `ref` from FC props (matching React's
10
+ // model where ref is not part of the props the component receives).
11
+ export function createElement(type, props, ...args) {
12
+ if (typeof type === 'function' && props != null && 'ref' in props) {
13
+ const { ref, ...restProps } = props;
14
+ if (ref != null) {
15
+ restProps[REF_SYMBOL] = ref;
16
+ }
17
+ return _createElement(type, restProps, ...args);
18
+ }
19
+ return _createElement(type, props, ...args);
20
+ }
3
21
  export const Children = {
4
22
  map(children, fn) {
5
23
  return Children.toArray(children).map(fn);
@@ -39,47 +57,112 @@ export function cloneElement(element, props, ...children) {
39
57
  if (!isValidElement(element)) {
40
58
  throw new Error(`cloneElement: expected a SimpElement, got ${element}`);
41
59
  }
42
- if ((element.flag & SimpReactInternal.SIMP_ELEMENT_FLAG_PORTAL) !== 0) {
60
+ if (isPortal(element)) {
43
61
  throw new Error('cloneElement: the argument must be a SimpElement, but you passed a portal instead.');
44
62
  }
45
- return SimpReactInternal.createElement((element.flag & SimpReactInternal.SIMP_ELEMENT_FLAG_FRAGMENT) !== 0 ? SimpReactInternal.Fragment : element.type, Object.assign({}, element.props, props), arguments.length > 2 ? children : props.children || element.children);
63
+ const mergedProps = Object.assign({}, element.props, props);
64
+ const resolvedChildren = arguments.length > 2 ? children : mergedProps.children !== undefined ? mergedProps.children : element.children;
65
+ return createElement(isFragment(element) ? Fragment : element.type, mergedProps, resolvedChildren);
46
66
  }
47
67
  export function isValidElement(element) {
48
68
  return typeof element === 'object' && element !== null && 'flag' in element;
49
69
  }
50
70
  export function Suspense(props) {
51
- const [isSuspended, setIsSuspended] = useState(false);
71
+ const [pendingCount, setPendingCount] = useState(0);
52
72
  useCatch(error => {
53
73
  if (!(error instanceof Promise)) {
54
74
  throw error;
55
75
  }
56
- if (isSuspended) {
57
- return;
58
- }
59
- setIsSuspended(true);
60
- error.then(() => setIsSuspended(false));
76
+ setPendingCount(c => c + 1);
77
+ error.then(() => setPendingCount(c => c - 1));
61
78
  });
62
- return isSuspended ? props.fallback : props.children;
79
+ return pendingCount > 0 ? props.fallback : props.children;
63
80
  }
64
81
  export function StrictMode(props) {
65
82
  return props.children;
66
83
  }
84
+ // Reads the ref from the Symbol slot so that string-keyed `ref` never
85
+ // appears in the props the inner component receives.
67
86
  export function forwardRef(Component) {
68
87
  return function Forwarded(props) {
69
- return Component(props, props?.ref || null);
88
+ const ref = props?.[REF_SYMBOL] ?? null;
89
+ if (props != null && REF_SYMBOL in props) {
90
+ const { [REF_SYMBOL]: _, ...restProps } = props;
91
+ return Component(restProps, ref);
92
+ }
93
+ return Component(props, ref);
70
94
  };
71
95
  }
72
- export const Fragment = SimpReactInternal.Fragment;
73
- export const createElement = SimpReactInternal.createElement;
74
- export const createPortal = SimpReactInternal.createPortal;
75
- export const memo = SimpReactInternal.memo;
76
- export const flushSync = (value) => value;
96
+ export const version = '18.3.1';
97
+ export const Fragment = _Fragment;
98
+ export const createPortal = _createPortal;
99
+ export const memo = _memo;
100
+ // Minimal React / ReactDOM internals shim for react-dom/test-utils.
101
+ export const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
102
+ ReactCurrentOwner: { current: null },
103
+ ReactCurrentDispatcher: { current: null },
104
+ ReactCurrentBatchConfig: { transition: null },
105
+ // react-dom/test-utils: var EventInternals = SecretInternals.Events; EventInternals[0..4]
106
+ Events: [
107
+ /* getInstanceFromNode */ _node => null,
108
+ /* getNodeFromInstance */ _inst => null,
109
+ /* getFiberCurrentPropsFromNode */ _node => null,
110
+ /* enqueueStateRestore */ () => { },
111
+ /* restoreStateIfNeeded */ () => { },
112
+ ],
113
+ };
114
+ // react-dom/test-utils uses React.unstable_act / React.act for flushing updates.
115
+ export async function unstable_act(callback) {
116
+ const result = callback();
117
+ if (result && typeof result.then === 'function')
118
+ await result;
119
+ await Promise.resolve();
120
+ }
121
+ export { unstable_act as act };
122
+ export function flushSync(callback) {
123
+ let result;
124
+ withSyncRerender(renderRuntime, () => {
125
+ result = callback();
126
+ });
127
+ return result;
128
+ }
129
+ export function lazy(factory) {
130
+ let state = null;
131
+ return function LazyComponent(props) {
132
+ if (state === null) {
133
+ const promise = factory().then(mod => {
134
+ state = { status: 'resolved', component: mod.default };
135
+ }, reason => {
136
+ state = { status: 'rejected', reason };
137
+ });
138
+ state = { status: 'pending', promise };
139
+ }
140
+ if (state.status === 'pending') {
141
+ throw state.promise;
142
+ }
143
+ if (state.status === 'rejected') {
144
+ throw state.reason;
145
+ }
146
+ return createElement(state.component, props);
147
+ };
148
+ }
149
+ // Minimal base class for React-style class components.
150
+ // setState and forceUpdate are no-ops here; the compat renderer overrides
151
+ // them on each instance with real implementations backed by the render queue.
77
152
  export class Component {
78
- constructor() {
79
- throw new Error('Not implemented.');
153
+ constructor(props) {
154
+ this.props = props;
155
+ this.state = {};
156
+ }
157
+ setState(_updater, _callback) { }
158
+ forceUpdate(_callback) { }
159
+ render() {
160
+ throw new Error('Component.render() must be implemented by the subclass.');
80
161
  }
81
162
  }
163
+ Component.prototype.isReactComponent = true;
82
164
  export default {
165
+ version,
83
166
  Children,
84
167
  cloneElement,
85
168
  isValidElement,
@@ -91,5 +174,9 @@ export default {
91
174
  createPortal,
92
175
  memo,
93
176
  flushSync,
177
+ lazy,
94
178
  Component,
179
+ __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
180
+ unstable_act,
181
+ act: unstable_act,
95
182
  };
package/compat/dom.js CHANGED
@@ -1,9 +1,9 @@
1
- import * as SimpReactDOM from '../dom/index.js';
2
- import * as SimpReactShared from '../shared/index.js';
1
+ import { createCreateRoot, createRenderer } from '../dom/index.js';
2
+ import { noop } from '../shared/index.js';
3
3
  import { renderRuntime } from './renderRuntime.js';
4
- export const hydrate = SimpReactShared.noop;
5
- export const render = SimpReactDOM.createRenderer(renderRuntime);
6
- export const createRoot = SimpReactDOM.createCreateRoot(renderRuntime);
4
+ export const hydrate = noop;
5
+ export const render = createRenderer(renderRuntime);
6
+ export const createRoot = createCreateRoot(renderRuntime);
7
7
  export default {
8
8
  hydrate,
9
9
  render,
package/compat/hooks.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createUseCatch, createUseEffect, createUseRef, createUseRerender, createUseState, } from '../hooks/index.js';
2
- import * as SimpReactShared from '../shared/index.js';
1
+ import { createUseCatch, createUseEffect, createUseRef, createUseRerender, createUseState } from '../hooks/index.js';
2
+ import { shallowEqual } from '../shared/index.js';
3
3
  import { renderRuntime } from './renderRuntime.js';
4
4
  export const useRerender = createUseRerender(renderRuntime);
5
5
  export const useState = createUseState(renderRuntime);
@@ -56,7 +56,7 @@ export function useMemo(factory, deps) {
56
56
  deps: undefined,
57
57
  value: undefined,
58
58
  });
59
- if (!SimpReactShared.shallowEqual(ref.current.deps, deps)) {
59
+ if (!shallowEqual(ref.current.deps, deps)) {
60
60
  ref.current.value = factory();
61
61
  ref.current.deps = deps;
62
62
  }
@@ -65,15 +65,30 @@ export function useMemo(factory, deps) {
65
65
  export function useCallback(cb, deps) {
66
66
  return useMemo(() => cb, deps);
67
67
  }
68
+ export function useImperativeHandle(ref, init, deps) {
69
+ useLayoutEffect(() => {
70
+ if (typeof ref === 'function') {
71
+ ref(init());
72
+ }
73
+ else if (ref != null) {
74
+ ref.current = init();
75
+ }
76
+ }, deps);
77
+ }
78
+ export function useDebugValue(_value, _format) { }
68
79
  export default {
69
80
  useSyncExternalStore,
70
81
  useReducer,
71
82
  useId,
72
83
  useMemo,
73
84
  useCallback,
85
+ useImperativeHandle,
86
+ useDebugValue,
74
87
  useState,
75
88
  useEffect,
76
89
  useLayoutEffect,
77
90
  useInsertionEffect,
78
91
  useRef,
92
+ useRerender,
93
+ useCatch,
79
94
  };
package/compat/index.d.ts CHANGED
@@ -1,46 +1,110 @@
1
- export * from './context.js';
2
- export * from './core.js';
3
- export * from './dom.js';
4
- export * from './hooks.js';
5
- export * from './jsx-runtime.js';
6
- export * from './renderRuntime.js';
7
- declare const _default: {
8
- renderRuntime: import("../core/runtime.js").SimpRenderRuntime;
9
- jsx: typeof import("../jsx-runtime/index.js").jsx;
10
- jsxDEV: typeof import("../jsx-runtime/index.js").jsx;
11
- jsxs: typeof import("../jsx-runtime/index.js").jsx;
12
- useSyncExternalStore: typeof import("./hooks.js").useSyncExternalStore;
13
- useReducer: typeof import("./hooks.js").useReducer;
14
- useId: typeof import("./hooks.js").useId;
15
- useMemo: typeof import("./hooks.js").useMemo;
16
- useCallback: typeof import("./hooks.js").useCallback;
17
- useState: import("../hooks/index.js").UseState;
18
- useEffect: (effect: import("../shared/public.js").Effect, deps?: import("../shared/public.js").DependencyList) => void;
19
- useLayoutEffect: (effect: import("../shared/public.js").Effect, deps?: import("../shared/public.js").DependencyList) => void;
20
- useInsertionEffect: (effect: import("../shared/public.js").Effect, deps?: import("../shared/public.js").DependencyList) => void;
21
- useRef: import("../hooks/index.js").UseRef;
22
- hydrate: typeof import("../shared/utils.js").noop;
23
- render: (element: import("../shared/public.js").Nullable<import("../core/createElement.js").SimpElement>, container: import("../shared/public.js").Nullable<Element | DocumentFragment>) => void;
24
- createRoot: (container: Element | DocumentFragment) => import("../dom/render.js").SimpRoot;
25
- Children: {
26
- map(children: import("../core/createElement.js").SimpNode, fn: (child: import("../core/createElement.js").SimpNode, index: number) => import("../core/createElement.js").SimpNode): import("../core/createElement.js").SimpNode[];
27
- forEach(children: import("../core/createElement.js").SimpNode, fn: (child: import("../core/createElement.js").SimpNode, index: number) => void): void;
28
- count(children: import("../core/createElement.js").SimpNode): number;
29
- toArray(children: import("../core/createElement.js").SimpNode): import("../core/createElement.js").SimpNode[];
30
- only(children: import("../core/createElement.js").SimpNode): import("../core/createElement.js").SimpElement;
31
- };
32
- cloneElement: typeof import("./core.js").cloneElement;
33
- isValidElement: typeof import("./core.js").isValidElement;
34
- Suspense: typeof import("./core.js").Suspense;
35
- StrictMode: typeof import("./core.js").StrictMode;
36
- forwardRef: typeof import("./core.js").forwardRef;
37
- Fragment: import("../core/fragment.js").Fragment;
38
- createElement: typeof import("../core/createElement.js").createElement;
39
- createPortal: typeof import("../core/portal.js").createPortal;
40
- memo: typeof import("../core/memo.js").memo;
41
- flushSync: (value: any) => any;
42
- Component: typeof import("./core.js").Component;
43
- createContext: import("../context/index.js").CreateContext;
44
- useContext: import("../context/index.js").UseContext;
1
+ import type { SimpContext } from '../context/index.js';
2
+ import type {
3
+ Attributes,
4
+ FC,
5
+ FunctionalComponent,
6
+ Key,
7
+ Ref,
8
+ RefAttributes,
9
+ RefObject,
10
+ SimpElement,
11
+ SimpNode,
12
+ SimpRenderRuntime,
13
+ } from '../core/index.js';
14
+ import type { SimpRoot } from '../dom/index.js';
15
+ import type { Dispatch, SetStateAction } from '../hooks/index.js';
16
+ import type { DependencyList, Effect, Maybe, Nullable } from '../shared/index.js';
17
+
18
+ export type { SimpContext } from '../context/index.js';
19
+ export type {
20
+ Attributes,
21
+ FC,
22
+ FunctionalComponent,
23
+ Key,
24
+ Ref,
25
+ RefAttributes,
26
+ RefObject,
27
+ SimpElement,
28
+ SimpNode,
29
+ SimpRenderRuntime,
30
+ } from '../core/index.js';
31
+ export type { SimpRoot } from '../dom/index.js';
32
+ export type { Dispatch, SetStateAction } from '../hooks/index.js';
33
+ export type { DependencyList, Effect, Maybe, Nullable } from '../shared/index.js';
34
+
35
+ export declare const renderRuntime: SimpRenderRuntime;
36
+
37
+ export declare function jsx<P = {}>(type: string | FC<P>, props?: P, key?: Maybe<Key>): SimpElement<P>;
38
+ export declare function jsxs<P = {}>(type: string | FC<P>, props?: P, key?: Maybe<Key>): SimpElement<P>;
39
+ export declare function jsxDEV<P = {}>(type: string | FC<P>, props?: P, key?: Maybe<Key>): SimpElement<P>;
40
+
41
+ export declare function useSyncExternalStore<T>(
42
+ subscribe: (callback: () => void) => () => void,
43
+ getSnapshot: () => T
44
+ ): T;
45
+ export declare function useReducer<R extends (state: any, action: any) => any, I>(
46
+ reducer: R,
47
+ initializerArg: I,
48
+ initializer?: (arg: I) => ReturnType<R>
49
+ ): [ReturnType<R>, (action: Parameters<R>[1]) => void];
50
+ export declare function useId(prefix?: string): string;
51
+ export declare function useMemo<T>(factory: () => T, deps: DependencyList): T;
52
+ export declare function useCallback<T>(cb: T, deps: DependencyList): T;
53
+ export declare function useImperativeHandle<T>(
54
+ ref: { current: T | null } | ((value: T | null) => void) | null | undefined,
55
+ init: () => T,
56
+ deps?: DependencyList
57
+ ): void;
58
+ export declare function useDebugValue(value: unknown, format?: (value: unknown) => unknown): void;
59
+ export declare function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
60
+ export declare function useState<S>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
61
+ export declare function useEffect(effect: Effect, deps?: DependencyList): void;
62
+ export declare function useLayoutEffect(effect: Effect, deps?: DependencyList): void;
63
+ export declare function useInsertionEffect(effect: Effect, deps?: DependencyList): void;
64
+ export declare function useRef<T>(initialValue: T): RefObject<T>;
65
+ export declare function useRef<T>(initialValue: T | null): RefObject<T | null>;
66
+ export declare function useRef<T = undefined>(initialValue?: T): RefObject<T | undefined>;
67
+ export declare function useCatch(handler: (error: unknown) => void): void;
68
+
69
+ export declare function hydrate(): void;
70
+ export declare function render(element: SimpElement, parentReference: Nullable<HTMLElement>): void;
71
+ export declare function createRoot(container: Element | DocumentFragment): SimpRoot;
72
+
73
+ export declare const Children: {
74
+ map(children: SimpNode, fn: (child: SimpNode, index: number) => SimpNode): SimpNode[];
75
+ forEach(children: SimpNode, fn: (child: SimpNode, index: number) => void): void;
76
+ count(children: SimpNode): number;
77
+ toArray(children: SimpNode): SimpNode[];
78
+ only(children: SimpNode): SimpElement;
45
79
  };
46
- export default _default;
80
+
81
+ export declare function cloneElement(element: SimpElement, props?: any, ...children: SimpNode[]): SimpElement;
82
+ export declare function isValidElement(element: unknown): element is SimpElement;
83
+ export declare function Suspense(props: { fallback: SimpNode; children: SimpNode }): SimpNode;
84
+ export declare function StrictMode(props: { children: SimpNode }): SimpNode;
85
+ export declare function forwardRef<P, T>(Component: (props: P, ref: Ref<T>) => any): FC;
86
+ export declare function Fragment(props: { children?: SimpNode }): SimpNode;
87
+
88
+ export declare function createElement<P extends {}, T>(
89
+ type: string,
90
+ props?: (RefAttributes<T> & P) | null,
91
+ ...children: SimpNode[]
92
+ ): SimpElement<P>;
93
+ export declare function createElement<P extends {}>(
94
+ type: FunctionalComponent<P>,
95
+ props?: (Attributes & P) | null,
96
+ ...children: SimpNode[]
97
+ ): SimpElement<P>;
98
+
99
+ export declare function createPortal(children: SimpNode, container: any): SimpElement;
100
+
101
+ export declare function memo(Component: FC, compare: (objA: any, objB: any) => boolean): FC;
102
+ export declare function flushSync(value: any): any;
103
+ export declare function lazy<T extends FC<any>>(factory: () => Promise<{ default: T }>): FC<any>;
104
+
105
+ export declare const version: string;
106
+
107
+ export declare class Component {}
108
+
109
+ export declare function createContext<T>(defaultValue: T): SimpContext<T>;
110
+ export declare function useContext<T>(context: SimpContext<T>): T;
@@ -1,7 +1,7 @@
1
- import * as SimpReactJSXRuntime from '../jsx-runtime/index.js';
2
- export const jsx = SimpReactJSXRuntime.jsx;
3
- export const jsxDEV = SimpReactJSXRuntime.jsxDEV;
4
- export const jsxs = SimpReactJSXRuntime.jsxs;
1
+ import { jsx as _jsx, jsxDEV as _jsxDEV, jsxs as _jsxs } from '../jsx-runtime/index.js';
2
+ export const jsx = _jsx;
3
+ export const jsxDEV = _jsxDEV;
4
+ export const jsxs = _jsxs;
5
5
  export default {
6
6
  jsx,
7
7
  jsxDEV,
@@ -1,17 +1,52 @@
1
1
  import { domAdapter } from '../dom/index.js';
2
+ import { createUseEffect, createUseRef, createUseRerender } from '../hooks/index.js';
3
+ import { createRenderRuntime } from '../core/internal.js';
2
4
  import { emptyObject } from '../shared/index.js';
3
- export const renderRuntime = {
4
- hostAdapter: domAdapter,
5
- renderer(component, element) {
6
- return component(element.props || emptyObject);
7
- },
8
- elementToHostMap: new Map(),
9
- renderStack: [],
10
- currentRenderingFCElement: null,
11
- renderPhase: null,
12
- };
5
+ // Lazily assigned after renderRuntime is created to avoid a circular reference
6
+ // at module-evaluation time. All are set before any render can fire.
7
+ let useRef;
8
+ let useRerender;
9
+ let useLayoutEffect;
10
+ export const renderRuntime = createRenderRuntime(domAdapter, function renderer(component, element) {
11
+ const props = element.props || emptyObject;
12
+ const proto = component.prototype;
13
+ if (proto?.isReactComponent || proto?.render) {
14
+ // Persist the instance across re-renders so state is not reset on every
15
+ // render cycle. Hook calls run in the current FC render context.
16
+ const instRef = useRef(null);
17
+ const rerender = useRerender();
18
+ if (instRef.current === null) {
19
+ instRef.current = new component(props);
20
+ if (instRef.current.state == null) {
21
+ instRef.current.state = {};
22
+ }
23
+ }
24
+ const inst = instRef.current;
25
+ inst.props = props;
26
+ // Override the no-op stubs from Component base with real implementations.
27
+ inst.setState = function (updater, callback) {
28
+ const prevState = inst.state;
29
+ const patch = typeof updater === 'function' ? updater(prevState, inst.props) : updater;
30
+ inst.state = Object.assign({}, prevState, patch);
31
+ rerender();
32
+ callback?.();
33
+ };
34
+ inst.forceUpdate = function (callback) {
35
+ rerender();
36
+ callback?.();
37
+ };
38
+ useLayoutEffect(() => {
39
+ if (typeof inst.componentDidMount === 'function') {
40
+ inst.componentDidMount();
41
+ }
42
+ }, []);
43
+ return inst.render();
44
+ }
45
+ return component(props);
46
+ });
47
+ useRef = createUseRef(renderRuntime);
48
+ useRerender = createUseRerender(renderRuntime);
49
+ useLayoutEffect = createUseEffect(renderRuntime);
13
50
  export default {
14
51
  renderRuntime,
15
52
  };
16
- // TODO
17
- window.__SIMP_RUNTIME__ = renderRuntime;
@@ -1,8 +1,5 @@
1
- import type { FC, SimpNode } from '../core/index.js';
2
-
3
- export type Cleanup = () => void;
4
- export type Effect = () => void | Cleanup;
5
- export type DependencyList = readonly unknown[];
1
+ import type { FC, SimpElement, SimpNode } from '../core/index.js';
2
+ import type { DependencyList, Effect } from '../shared/index.js';
6
3
 
7
4
  export interface ComponentRenderContext<S = {}> {
8
5
  state: S;
@@ -11,6 +8,8 @@ export interface ComponentRenderContext<S = {}> {
11
8
  catchers: Array<(error: any) => void>;
12
9
  }
13
10
 
14
- declare function component<P = {}, S = {}>(Component: (props: P, ctx: ComponentRenderContext<S>) => SimpNode): FC<P>;
11
+ export declare function component<P = {}, S = {}>(
12
+ Component: (props: P, ctx: ComponentRenderContext<S>) => SimpNode
13
+ ): FC<P>;
15
14
 
16
- export function componentRenderer(component: FC, element: SimpElement): SimpNode;
15
+ export declare function componentRenderer(component: FC, element: SimpElement): SimpNode;