@xmachines/play-react 1.0.0-beta.18 → 1.0.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@ Bridges TC39 Signal-driven actors to React's render cycle. Business logic stays
13
13
  - Routes action names from spec elements to `actor.send()` via the `actions` prop
14
14
  - Manages per-view UI state in an `@xstate/store` atom (automatic or caller-supplied)
15
15
 
16
- Per [RFC Play v1](https://gitlab.com/xmachin-es/rfc/-/blob/main/src/play-v1.md):
16
+ Per [Play RFC](../docs/rfc/play.md):
17
17
 
18
18
  - **Actor Authority (INV-01):** Guards in the machine decide all state transitions
19
19
  - **Passive Infrastructure (INV-04):** React observes signals and dispatches events — never decides
@@ -260,10 +260,15 @@ function NavBar({ actor }: { actor: ReturnType<typeof createPlayer> }) {
260
260
 
261
261
  Class error boundary that wraps the rendered output. Catches errors thrown during component render and logs them without crashing the full page. `PlayRenderer` wraps its own output in this boundary automatically.
262
262
 
263
+ `componentDidCatch` invokes the `onError` prop (for observability tools) but does **not** re-throw — re-throwing from `componentDidCatch` can unmount the entire React 19 root. `getDerivedStateFromError` handles fallback state transition instead.
264
+
263
265
  ```tsx
264
266
  import { PlayErrorBoundary } from "@xmachines/play-react";
265
267
 
266
- <PlayErrorBoundary fallback={<p>Something went wrong.</p>}>
268
+ <PlayErrorBoundary
269
+ fallback={<p>Something went wrong.</p>}
270
+ onError={(err, info) => Sentry.captureException(err, { extra: info })}
271
+ >
267
272
  <PlayRenderer actor={actor} registry={registry} />
268
273
  </PlayErrorBoundary>;
269
274
  ```
@@ -33,6 +33,10 @@ export interface PlayErrorBoundaryState {
33
33
  * React error boundary protocol. Consumers can attach the `onError` prop to forward
34
34
  * errors to production observability tools (Sentry, Datadog, etc.).
35
35
  *
36
+ * **React 19 safety (Phase 29):** `componentDidCatch` calls `onError` for observability
37
+ * but does NOT re-throw. `getDerivedStateFromError` already sets the fallback state —
38
+ * re-throwing from `componentDidCatch` can unmount the entire React 19 root.
39
+ *
36
40
  * Per CONS-14: Class component pattern works with all React versions (18 and 19).
37
41
  *
38
42
  * @example
@@ -1 +1 @@
1
- {"version":3,"file":"PlayErrorBoundary.d.ts","sourceRoot":"","sources":["../src/PlayErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,8FAA8F;IAC9F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,iBAAkB,SAAQ,KAAK,CAAC,SAAS,CACrD,sBAAsB,EACtB,sBAAsB,CACtB;gBACY,KAAK,EAAE,sBAAsB;IAKzC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,sBAAsB;IAI5D,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAO5D,MAAM,IAAI,KAAK,CAAC,SAAS;CAMlC"}
1
+ {"version":3,"file":"PlayErrorBoundary.d.ts","sourceRoot":"","sources":["../src/PlayErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,8FAA8F;IAC9F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,iBAAkB,SAAQ,KAAK,CAAC,SAAS,CACrD,sBAAsB,EACtB,sBAAsB,CACtB;gBACY,KAAK,EAAE,sBAAsB;IAKzC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,sBAAsB;IAI5D,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAI5D,MAAM,IAAI,KAAK,CAAC,SAAS;CAMlC"}
@@ -4,7 +4,6 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  import React from "react";
7
- import { RendererError } from "./errors.js";
8
7
  /**
9
8
  * React class component error boundary for catching catalog component render errors.
10
9
  *
@@ -12,6 +11,10 @@ import { RendererError } from "./errors.js";
12
11
  * React error boundary protocol. Consumers can attach the `onError` prop to forward
13
12
  * errors to production observability tools (Sentry, Datadog, etc.).
14
13
  *
14
+ * **React 19 safety (Phase 29):** `componentDidCatch` calls `onError` for observability
15
+ * but does NOT re-throw. `getDerivedStateFromError` already sets the fallback state —
16
+ * re-throwing from `componentDidCatch` can unmount the entire React 19 root.
17
+ *
15
18
  * Per CONS-14: Class component pattern works with all React versions (18 and 19).
16
19
  *
17
20
  * @example
@@ -31,9 +34,6 @@ export class PlayErrorBoundary extends React.Component {
31
34
  }
32
35
  componentDidCatch(error, info) {
33
36
  this.props.onError?.(error, info);
34
- throw new RendererError("Component render error caught by PlayErrorBoundary.", {
35
- cause: error,
36
- });
37
37
  }
38
38
  render() {
39
39
  if (this.state.hasError) {
@@ -1 +1 @@
1
- {"version":3,"file":"PlayErrorBoundary.js","sourceRoot":"","sources":["../src/PlayErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA0B5C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK,CAAC,SAG5C;IACA,YAAY,KAA6B;QACxC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC3C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;IAEQ,iBAAiB,CAAC,KAAY,EAAE,IAAqB;QAC7D,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,IAAI,aAAa,CAAC,qDAAqD,EAAE;YAC9E,KAAK,EAAE,KAAK;SACZ,CAAC,CAAC;IACJ,CAAC;IAEQ,MAAM;QACd,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC5B,CAAC;CACD"}
1
+ {"version":3,"file":"PlayErrorBoundary.js","sourceRoot":"","sources":["../src/PlayErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AA0B1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK,CAAC,SAG5C;IACA,YAAY,KAA6B;QACxC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC3C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;IAEQ,iBAAiB,CAAC,KAAY,EAAE,IAAqB;QAC7D,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAEQ,MAAM;QACd,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC5B,CAAC;CACD"}
package/dist/errors.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { PlayError } from "@xmachines/play";
2
2
  /**
3
- * Thrown by `PlayErrorBoundary.componentDidCatch()` when a React component inside
4
- * the boundary throws during rendering.
3
+ * Error class for renderer-level errors in the Play architecture.
5
4
  *
6
- * The original render error is set as `cause`. The `onError` prop callback fires
7
- * before this error is thrown, allowing observability tools to record the incident.
5
+ * **Note (Phase 29):** `PlayErrorBoundary.componentDidCatch()` no longer throws
6
+ * this error. Re-throwing from `componentDidCatch` can unmount the entire React 19
7
+ * root. `RendererError` is retained for programmatic use in custom error handlers
8
+ * and parent boundaries — it is no longer emitted by the built-in boundary itself.
8
9
  *
9
10
  * **Error code:** `PLAY_RENDERER_RENDER_ERROR`
10
11
  *
@@ -12,11 +13,8 @@ import { PlayError } from "@xmachines/play";
12
13
  * ```typescript
13
14
  * import { RendererError } from "@xmachines/play-react/errors";
14
15
  *
15
- * // In a parent error boundary or global handler:
16
- * if (err instanceof RendererError) {
17
- * // err.cause is the original component error
18
- * reportRenderError(err.cause as Error);
19
- * }
16
+ * // Create a RendererError programmatically in a custom boundary:
17
+ * throw new RendererError("Custom render failure", { cause: originalError });
20
18
  * ```
21
19
  */
22
20
  export declare class RendererError extends PlayError {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,SAAQ,SAAS;gBAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAInD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAc,SAAQ,SAAS;gBAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAInD"}
package/dist/errors.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { PlayError } from "@xmachines/play";
2
2
  /**
3
- * Thrown by `PlayErrorBoundary.componentDidCatch()` when a React component inside
4
- * the boundary throws during rendering.
3
+ * Error class for renderer-level errors in the Play architecture.
5
4
  *
6
- * The original render error is set as `cause`. The `onError` prop callback fires
7
- * before this error is thrown, allowing observability tools to record the incident.
5
+ * **Note (Phase 29):** `PlayErrorBoundary.componentDidCatch()` no longer throws
6
+ * this error. Re-throwing from `componentDidCatch` can unmount the entire React 19
7
+ * root. `RendererError` is retained for programmatic use in custom error handlers
8
+ * and parent boundaries — it is no longer emitted by the built-in boundary itself.
8
9
  *
9
10
  * **Error code:** `PLAY_RENDERER_RENDER_ERROR`
10
11
  *
@@ -12,11 +13,8 @@ import { PlayError } from "@xmachines/play";
12
13
  * ```typescript
13
14
  * import { RendererError } from "@xmachines/play-react/errors";
14
15
  *
15
- * // In a parent error boundary or global handler:
16
- * if (err instanceof RendererError) {
17
- * // err.cause is the original component error
18
- * reportRenderError(err.cause as Error);
19
- * }
16
+ * // Create a RendererError programmatically in a custom boundary:
17
+ * throw new RendererError("Custom render failure", { cause: originalError });
20
18
  * ```
21
19
  */
22
20
  export class RendererError extends PlayError {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAS;IAC3C,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CAAC,cAAc,EAAE,4BAA4B,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC7B,CAAC;CACD"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAS;IAC3C,YAAY,OAAe,EAAE,OAAsB;QAClD,KAAK,CAAC,cAAc,EAAE,4BAA4B,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC7B,CAAC;CACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmachines/play-react",
3
- "version": "1.0.0-beta.18",
3
+ "version": "1.0.0-beta.19",
4
4
  "description": "React renderer for XMachines Play architecture with signal-driven rendering",
5
5
  "keywords": [
6
6
  "actor",
@@ -26,6 +26,7 @@
26
26
  "type": "module",
27
27
  "exports": {
28
28
  ".": {
29
+ "source": "./src/index.ts",
29
30
  "types": "./dist/index.d.ts",
30
31
  "import": "./dist/index.js"
31
32
  }
@@ -35,9 +36,7 @@
35
36
  },
36
37
  "scripts": {
37
38
  "build": "tsc --build",
38
- "clean": "rm -rf dist *.tsbuildinfo node_modules/.vite node_modules/.vite-temp",
39
- "typecheck": "tsc --noEmit",
40
- "typecheck:test": "tsc --noEmit -p tsconfig.test.json",
39
+ "clean": "rm -rf dist *.tsbuildinfo coverage .vitest-attachments test/browser/__screenshots__",
41
40
  "typecheck:browser": "tsc --noEmit -p tsconfig.browser.json",
42
41
  "test": "vitest",
43
42
  "test:vitest": "vitest run",
@@ -45,8 +44,8 @@
45
44
  "prepublishOnly": "npm run build"
46
45
  },
47
46
  "dependencies": {
48
- "@xmachines/play-actor": "1.0.0-beta.18",
49
- "@xmachines/play-signals": "1.0.0-beta.18"
47
+ "@xmachines/play-actor": "1.0.0-beta.19",
48
+ "@xmachines/play-signals": "1.0.0-beta.19"
50
49
  },
51
50
  "devDependencies": {
52
51
  "@json-render/core": "^0.16.0",
@@ -57,7 +56,7 @@
57
56
  "@types/node": "^25.5.0",
58
57
  "@types/react": "^19.2.14",
59
58
  "@types/react-dom": "^19.2.3",
60
- "@xmachines/shared": "1.0.0-beta.18",
59
+ "@xmachines/shared": "1.0.0-beta.19",
61
60
  "@xstate/store": ">=3.17.0",
62
61
  "jsdom": "^29.0.1",
63
62
  "react": "^19.2.4",