@reckona/mreact-compat 0.0.171 → 0.0.173

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 (58) hide show
  1. package/dist/devtools.js +2 -0
  2. package/dist/devtools.js.map +1 -1
  3. package/dist/dom-host-rules.d.ts.map +1 -1
  4. package/dist/dom-host-rules.js +4 -1
  5. package/dist/dom-host-rules.js.map +1 -1
  6. package/dist/dom-props.js +2 -1
  7. package/dist/dom-props.js.map +1 -1
  8. package/dist/element.d.ts +13 -1
  9. package/dist/element.d.ts.map +1 -1
  10. package/dist/element.js +30 -2
  11. package/dist/element.js.map +1 -1
  12. package/dist/fiber-commit.js +2 -1
  13. package/dist/fiber-commit.js.map +1 -1
  14. package/dist/fiber-host.d.ts +1 -1
  15. package/dist/fiber-host.d.ts.map +1 -1
  16. package/dist/fiber-host.js +1 -1
  17. package/dist/fiber-host.js.map +1 -1
  18. package/dist/fiber.d.ts +2 -1
  19. package/dist/fiber.d.ts.map +1 -1
  20. package/dist/fiber.js +2 -0
  21. package/dist/fiber.js.map +1 -1
  22. package/dist/hooks.d.ts +9 -0
  23. package/dist/hooks.d.ts.map +1 -1
  24. package/dist/hooks.js +127 -44
  25. package/dist/hooks.js.map +1 -1
  26. package/dist/host-reconciler.d.ts +2 -0
  27. package/dist/host-reconciler.d.ts.map +1 -1
  28. package/dist/host-reconciler.js +696 -55
  29. package/dist/host-reconciler.js.map +1 -1
  30. package/dist/jsx-dev-runtime.d.ts +3 -1
  31. package/dist/jsx-dev-runtime.d.ts.map +1 -1
  32. package/dist/jsx-dev-runtime.js +3 -1
  33. package/dist/jsx-dev-runtime.js.map +1 -1
  34. package/dist/jsx-runtime.d.ts +4 -2
  35. package/dist/jsx-runtime.d.ts.map +1 -1
  36. package/dist/jsx-runtime.js +9 -1
  37. package/dist/jsx-runtime.js.map +1 -1
  38. package/dist/reactive-prop-cell.d.ts +13 -0
  39. package/dist/reactive-prop-cell.d.ts.map +1 -0
  40. package/dist/reactive-prop-cell.js +36 -0
  41. package/dist/reactive-prop-cell.js.map +1 -0
  42. package/dist/root.d.ts.map +1 -1
  43. package/dist/root.js +8 -5
  44. package/dist/root.js.map +1 -1
  45. package/package.json +3 -3
  46. package/src/devtools.ts +2 -0
  47. package/src/dom-host-rules.ts +4 -1
  48. package/src/dom-props.ts +2 -1
  49. package/src/element.ts +60 -3
  50. package/src/fiber-commit.ts +3 -1
  51. package/src/fiber-host.ts +2 -0
  52. package/src/fiber.ts +4 -0
  53. package/src/hooks.ts +187 -46
  54. package/src/host-reconciler.ts +1031 -70
  55. package/src/jsx-dev-runtime.ts +4 -0
  56. package/src/jsx-runtime.ts +16 -0
  57. package/src/reactive-prop-cell.ts +67 -0
  58. package/src/root.ts +14 -4
@@ -1,5 +1,7 @@
1
1
  import {
2
+ createReactiveDomBlock,
2
3
  Fragment,
4
+ REACTIVE_STATE_BINDING_META,
3
5
  REACTIVE_TEXT_BINDING_META,
4
6
  jsx,
5
7
  } from "./jsx-runtime.js";
@@ -17,6 +19,8 @@ import type {
17
19
  export { Fragment };
18
20
  /** Metadata key used by compiled JSX for reactive text bindings. */
19
21
  export { REACTIVE_TEXT_BINDING_META };
22
+ export { REACTIVE_STATE_BINDING_META };
23
+ export { createReactiveDomBlock };
20
24
  /** JSX event and attribute types re-exported by the development JSX runtime. */
21
25
  export type {
22
26
  FormEvent,
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  createElementFromJsxConfig,
3
3
  Fragment,
4
+ REACTIVE_DOM_BLOCK_TYPE,
5
+ REACTIVE_STATE_BINDING_META,
4
6
  REACTIVE_TEXT_BINDING_META,
5
7
  } from "./element.js";
6
8
  import type {
7
9
  ElementType,
10
+ ReactiveDomBlockProps,
11
+ ReactiveDomBlockRender,
8
12
  ReactCompatElement,
9
13
  ReactCompatNode,
10
14
  } from "./element.js";
@@ -13,6 +17,18 @@ import type {
13
17
  export { Fragment };
14
18
  /** Metadata key used by compiled JSX for reactive text bindings. */
15
19
  export { REACTIVE_TEXT_BINDING_META };
20
+ export { REACTIVE_STATE_BINDING_META };
21
+
22
+ export function createReactiveDomBlock<P extends object = Record<string, unknown>>(
23
+ render: ReactiveDomBlockRender<P>,
24
+ blockProps?: P,
25
+ ): ReactCompatElement<ReactiveDomBlockProps> {
26
+ const props: ReactiveDomBlockProps = { render: render as ReactiveDomBlockRender };
27
+ if (blockProps !== undefined) {
28
+ props.blockProps = blockProps as Record<string, unknown>;
29
+ }
30
+ return createElementFromJsxConfig(REACTIVE_DOM_BLOCK_TYPE, props);
31
+ }
16
32
 
17
33
  /** DOM event type with a narrowed currentTarget. */
18
34
  export type JSXEvent<
@@ -0,0 +1,67 @@
1
+ import {
2
+ flushQueuedComputations,
3
+ notifySubscribers,
4
+ trackSource,
5
+ type Source,
6
+ } from "@reckona/mreact-reactive-core/internal";
7
+ import type { ReactiveDomBlockResult } from "./element.js";
8
+
9
+ // A stable reactive box over a component's incoming props, analogous to the
10
+ // native keyed list's KeyedItemCell (packages/reactive-dom/src/bind-list.ts).
11
+ // A reactive-dom-block reads its props through a proxy backed by this cell;
12
+ // when the component re-renders with new props the reconciler swaps the cell's
13
+ // value and notifies, so bound text/attributes update without re-running the
14
+ // block's render closure or reconciling its subtree.
15
+ export interface ReactivePropCell {
16
+ value: Record<string, unknown>;
17
+ source: Source;
18
+ }
19
+
20
+ // What a reactive-dom-block fiber stores in stateNode: the committed node and
21
+ // its dispose, plus the prop cell when the block bridges component props.
22
+ export interface ReactiveDomBlockState extends ReactiveDomBlockResult {
23
+ propCell?: ReactivePropCell | undefined;
24
+ }
25
+
26
+ export function createReactivePropCell(props: Record<string, unknown>): ReactivePropCell {
27
+ return { value: props, source: { subscribers: null } };
28
+ }
29
+
30
+ const PROP_PROXY_HANDLER: ProxyHandler<ReactivePropCell> = {
31
+ get(cell, property) {
32
+ trackSource(cell.source);
33
+ return cell.value[property as string];
34
+ },
35
+ has(cell, property) {
36
+ trackSource(cell.source);
37
+ return property in cell.value;
38
+ },
39
+ ownKeys(cell) {
40
+ trackSource(cell.source);
41
+ return Reflect.ownKeys(cell.value);
42
+ },
43
+ getOwnPropertyDescriptor(cell, property) {
44
+ trackSource(cell.source);
45
+ return Reflect.getOwnPropertyDescriptor(cell.value, property);
46
+ },
47
+ };
48
+
49
+ export function createReactivePropProxy<P extends object>(cell: ReactivePropCell): P {
50
+ return new Proxy(cell, PROP_PROXY_HANDLER) as unknown as P;
51
+ }
52
+
53
+ export function setReactivePropCell(
54
+ cell: ReactivePropCell,
55
+ next: Record<string, unknown>,
56
+ ): void {
57
+ if (Object.is(cell.value, next)) {
58
+ return;
59
+ }
60
+
61
+ cell.value = next;
62
+
63
+ if (cell.source.subscribers !== null) {
64
+ notifySubscribers(cell.source);
65
+ flushQueuedComputations();
66
+ }
67
+ }
package/src/root.ts CHANGED
@@ -35,6 +35,7 @@ import { commitFiberRoot, detachFiberRefs } from "./fiber-commit.js";
35
35
  import {
36
36
  canRenderHostFiber,
37
37
  commitHydratingHostFiberRoot,
38
+ disposeHostFiberResources,
38
39
  renderHydratingHostFiberRoot,
39
40
  renderHostFiberRoot,
40
41
  } from "./fiber-host.js";
@@ -132,6 +133,7 @@ export function createRoot(
132
133
  runtime.currentElement = undefined;
133
134
  runtime.dispose();
134
135
  detachFiberRefs(fiberRoot.current);
136
+ disposeHostFiberResources(fiberRoot.current);
135
137
  runtime.instances.clear();
136
138
  unmountDevToolsRoot(container);
137
139
  clearElementChildren(container);
@@ -164,7 +166,7 @@ function renderHostFiberIntoContainer(
164
166
 
165
167
  fiberRoot.finishedWork = finishedWork;
166
168
  commitFiberRoot(fiberRoot);
167
- collectPortalNodes(fiberRoot.current, runtime);
169
+ collectPortalNodes(fiberRoot.current, runtime, portalSnapshot);
168
170
  removeStalePortalNodes(portalSnapshot, runtime);
169
171
  commitDevToolsRoot(container, fiberRoot);
170
172
  runtime.idMode = "client";
@@ -224,7 +226,7 @@ function renderHydratingHostFiberIntoContainer(
224
226
  fiberRoot.finishedWork = undefined;
225
227
  fiberRoot.workInProgress = undefined;
226
228
  fiberRoot.workInProgressRootRenderLanes = 0;
227
- collectPortalNodes(fiberRoot.current, runtime);
229
+ collectPortalNodes(fiberRoot.current, runtime, portalSnapshot);
228
230
  removeStalePortalNodes(portalSnapshot, runtime);
229
231
  commitDevToolsRoot(container, fiberRoot);
230
232
  runtime.idMode = "client";
@@ -330,6 +332,7 @@ export function hydrateRoot(
330
332
  runtime.currentElement = undefined;
331
333
  runtime.dispose();
332
334
  detachFiberRefs(fiberRoot.current);
335
+ disposeHostFiberResources(fiberRoot.current);
333
336
  runtime.instances.clear();
334
337
  unmountDevToolsRoot(container);
335
338
  clearElementChildren(container);
@@ -472,8 +475,15 @@ function clearElementChildren(element: Element): void {
472
475
  }
473
476
  }
474
477
 
475
- function collectPortalNodes(fiber: Fiber | undefined, runtime: RootRuntime): void {
476
- if (fiber === undefined || runtime.portalContainers.size === 0) {
478
+ function collectPortalNodes(
479
+ fiber: Fiber | undefined,
480
+ runtime: RootRuntime,
481
+ snapshot: PortalRenderSnapshot,
482
+ ): void {
483
+ if (
484
+ fiber === undefined ||
485
+ (runtime.portalContainers.size === 0 && snapshot.containers.size === 0)
486
+ ) {
477
487
  return;
478
488
  }
479
489