@xmachines/play-tanstack-react-router 1.0.0-beta.1 → 1.0.0-beta.11
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 +35 -23
- package/dist/route-map.d.ts +26 -56
- package/dist/route-map.d.ts.map +1 -1
- package/dist/route-map.js +18 -87
- package/dist/route-map.js.map +1 -1
- package/package.json +25 -17
- package/.oxfmtrc.json +0 -3
- package/.oxlintrc.json +0 -3
- package/examples/demo/README.md +0 -100
- package/examples/demo/docs/ARCHITECTURE.md +0 -643
- package/examples/demo/docs/INVARIANTS.md +0 -461
- package/examples/demo/docs/SWAP-REACT.md +0 -635
- package/examples/demo/index.html +0 -16
- package/examples/demo/package.json +0 -39
- package/examples/demo/src/App.tsx +0 -148
- package/examples/demo/src/components/About.tsx +0 -49
- package/examples/demo/src/components/Contact.tsx +0 -43
- package/examples/demo/src/components/Dashboard.tsx +0 -46
- package/examples/demo/src/components/DebugPanel.tsx +0 -68
- package/examples/demo/src/components/HeaderNav.tsx +0 -103
- package/examples/demo/src/components/Home.tsx +0 -41
- package/examples/demo/src/components/Login.tsx +0 -82
- package/examples/demo/src/components/Navigation.tsx +0 -262
- package/examples/demo/src/components/Profile.tsx +0 -46
- package/examples/demo/src/components/Register.tsx +0 -109
- package/examples/demo/src/components/Settings.tsx +0 -92
- package/examples/demo/src/components/index.ts +0 -16
- package/examples/demo/src/main.tsx +0 -20
- package/examples/demo/test/actor-authority.test.ts +0 -50
- package/examples/demo/test/browser/__screenshots__/back-button-duplicate.browser.test.tsx/Browser-back-button-navigates-through-unique-history--no-duplicates--1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-button-duplicate.browser.test.tsx/GAP-12--navigation-via-goto---events-creates-single-history-entries-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-button-duplicate.browser.test.tsx/GAP-12--navigation-via-goto---events-creates-single-history-entries-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--After-authentication-flow-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Multiple-rapid-navigations-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Multiple-rapid-navigations-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--URL-stays-in-sync-with-actor-state-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--URL-stays-in-sync-with-actor-state-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Works-correctly-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Works-correctly-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to--about-loads-about-page-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to--contact-loads-contact-page-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to--home-loads-home-page-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to-protected-route-while-authenticated-loads-dashboard-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to-protected-route-while-unauthenticated-redirects-to-login-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/exact-user-scenario.browser.test.tsx/Debug--Print-history-after-each-navigation-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/exact-user-scenario.browser.test.tsx/Debug--Print-history-after-each-navigation-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/exact-user-scenario.browser.test.tsx/EXACT-USER-SCENARIO--home---about---home---contact---home--then-back-3x-should-land-on-about-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/exact-user-scenario.browser.test.tsx/EXACT-USER-SCENARIO--home---about---home---contact---home--then-back-3x-should-land-on-about-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Actor-Authority---infrastructure-cannot-override-guards-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Actor-Authority---infrastructure-cannot-override-guards-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Guards-reject-invalid-navigation-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Guards-reject-invalid-navigation-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-investigation.browser.test.tsx/baseHistory-back---navigation--avoiding-window-history--1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-investigation.browser.test.tsx/baseHistory-back---navigation--avoiding-window-history--2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---authenticated-user-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---authenticated-user-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---unauthenticated-user-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---unauthenticated-user-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-with-guard---authenticated-user-navigates-back-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-with-guard---authenticated-user-navigates-back-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-with-guard---unauthenticated-user-stays-on-public-routes-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-with-guard---unauthenticated-user-stays-on-public-routes-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back---unique-history-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back---unique-history-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Navigate-forward-then-back---unique-history-entries-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Navigate-forward-then-back---unique-history-entries-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Rapid-back-forward-navigation-doesn-t-cause-duplicate-entries-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Rapid-back-forward-navigation-doesn-t-cause-duplicate-entries-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---about-to-home-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---about-to-home-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---contact-to-about-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---contact-to-about-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-forward-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-forward-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-navigation-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-navigation-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/login-flow.browser.test.tsx/E2E--User-can-log-in-and-see-dashboard-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/login-flow.browser.test.tsx/E2E--User-can-log-in-and-see-dashboard-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/navigation.browser.test.tsx/E2E--Navigation-reflects-actor-state-transitions-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/navigation.browser.test.tsx/E2E--Navigation-reflects-actor-state-transitions-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/Browser-back-forward-through-multiple-protected-routes-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/Browser-back-forward-through-multiple-protected-routes-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/Browser-back-navigates-from-dashboard-to-settings--protected-route--1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/Browser-back-navigates-from-dashboard-to-settings--protected-route--2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/RED--Browser-back-forward-through-multiple-protected-routes-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/RED--Browser-back-from-dashboard-to-settings--protected-route--1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/RED--Browser-back-navigates-from-dashboard-to-settings--protected-route--1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-display--account--section-when-navigating-to--settings-account-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-display--account--section-when-navigating-to--settings-account-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-display--general--section-when-navigating-to--settings--no-parameter--1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-display--general--section-when-navigating-to--settings--no-parameter--2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-display--profile--section-when-navigating-to--settings-profile-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-display--profile--section-when-navigating-to--settings-profile-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-update-section-display-when-clicking-section-navigation-buttons-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-parameter.browser.test.tsx/Settings-Parameter-Display-should-update-section-display-when-clicking-section-navigation-buttons-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-query-freeze.browser.test.ts/Settings-with-query-parameters-works-correctly-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/settings-query-freeze.browser.test.ts/Settings-with-section-parameter-works-correctly-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/state-driven.browser.test.ts/DEMO-04--State-Driven-Reset---Browser-back-sends-event-to-actor-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/state-driven.browser.test.ts/DEMO-04--State-Driven-Reset---Browser-back-sends-event-to-actor-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/state-driven.browser.test.ts/DEMO-04b--Browser-navigation-with-SignalSyncedHistory-integration-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/state-driven.browser.test.ts/DEMO-04b--Browser-navigation-with-SignalSyncedHistory-integration-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/tanstack-integration.browser.test.tsx/TanStack-Router-Integration-renders-with-RouterProvider-context-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/tanstack-integration.browser.test.tsx/TanStack-Router-Integration-renders-with-RouterProvider-context-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/test-multiple-back.browser.test.tsx/Multiple-back--Navigate-forward-3x-then-back-3x-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-1--Opening-with--someinvalidstate-stays-at-current-state-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-2--Opening-with--about-renders-About-component--not-Login-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-2b--Opening-with--home-renders-Home-component--not-Login-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-2c--Opening-with--contact-renders-Contact-component--not-Login-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-3--Back-forward-navigation---rendering-syncs-with-URL-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-3--Back-forward-navigation---rendering-syncs-with-URL-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-4--Auth-state-preserved-when-navigating-between-authenticated-anonymous-states-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-4--Auth-state-preserved-when-navigating-between-authenticated-anonymous-states-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-4b--Browser-back-forward-preserves-auth-state-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-4b--Browser-back-forward-preserves-auth-state-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-5--Protected-route-with-play-route-respects-authentication-guard-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/uat-xstate-route-regression.browser.test.ts/UAT-5--Protected-route-with-play-route-respects-authentication-guard-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/user-reported-scenario.browser.test.tsx/User-scenario--home---about---home---contact---home--then-back-3x-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/user-reported-scenario.browser.test.tsx/User-scenario--login---home---about---home---contact---home--then-back-3x-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Browser-back-button-sends-play-route-event-with-correct-state-ID-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Browser-back-button-sends-play-route-event-with-correct-state-ID-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Browser-back-button-sends-xstate-route-event-with-correct-state-ID-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Direct-URL-navigation-sends-play-route-event-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Direct-URL-navigation-sends-xstate-route-event-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Forward-button-sends-play-route-event-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Forward-button-sends-play-route-event-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Forward-button-sends-xstate-route-event-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/GAP-12-fix-preserved--No-duplicate-history-entries-with-play-route-1.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/GAP-12-fix-preserved--No-duplicate-history-entries-with-play-route-2.png +0 -0
- package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Protected-route-sends-xstate-route-with-authentication-guard-1.png +0 -0
- package/examples/demo/test/browser/back-button-duplicate.browser.test.tsx +0 -148
- package/examples/demo/test/browser/back-forward-sync.browser.test.tsx +0 -149
- package/examples/demo/test/browser/direct-navigation.browser.test.ts +0 -146
- package/examples/demo/test/browser/exact-user-scenario.browser.test.tsx +0 -207
- package/examples/demo/test/browser/guard-rejection.browser.test.tsx +0 -52
- package/examples/demo/test/browser/history-investigation.browser.test.tsx +0 -82
- package/examples/demo/test/browser/history-navigation.browser.test.ts +0 -351
- package/examples/demo/test/browser/login-flow.browser.test.tsx +0 -34
- package/examples/demo/test/browser/navigation.browser.test.tsx +0 -34
- package/examples/demo/test/browser/protected-route-navigation.browser.test.tsx +0 -161
- package/examples/demo/test/browser/redirect-url-update.browser.test.tsx +0 -140
- package/examples/demo/test/browser/settings-parameter.browser.test.tsx +0 -164
- package/examples/demo/test/browser/settings-query-freeze.browser.test.ts +0 -141
- package/examples/demo/test/browser/state-driven.browser.test.ts +0 -112
- package/examples/demo/test/browser/tanstack-integration.browser.test.tsx +0 -61
- package/examples/demo/test/browser/uat-xstate-route-regression.browser.test.ts +0 -58
- package/examples/demo/test/browser/xstate-route-events.browser.test.ts +0 -293
- package/examples/demo/test/browser-back-view-rendering.test.ts +0 -104
- package/examples/demo/test/browser-e2e/auth-flow.browser.test.tsx +0 -49
- package/examples/demo/test/invalid-route-redirect.test.ts +0 -40
- package/examples/demo/test/passive-infra.test.ts +0 -35
- package/examples/demo/test/route-parameters.test.ts +0 -539
- package/examples/demo/test/signal-only.test.ts +0 -54
- package/examples/demo/test/strict-separation.test.ts +0 -37
- package/examples/demo/test/test-utils.ts +0 -49
- package/examples/demo/tsconfig.json +0 -21
- package/examples/demo/tsconfig.tsbuildinfo +0 -1
- package/examples/demo/vite.config.ts +0 -13
- package/examples/demo/vitest.browser.config.ts +0 -72
- package/examples/demo/vitest.config.e2e.browser.ts +0 -28
- package/examples/demo/vitest.config.ts +0 -35
- package/src/extract-params.ts +0 -75
- package/src/index.ts +0 -31
- package/src/play-router-provider.tsx +0 -46
- package/src/route-map.ts +0 -158
- package/src/tanstack-router-bridge.ts +0 -135
- package/src/types.ts +0 -26
- package/src/utils.ts +0 -12
- package/test/browser/__screenshots__/signal-synced-history.browser.test.ts/Browser-back-button-sends-route-navigate-event-to-actor-1.png +0 -0
- package/test/browser/__screenshots__/signal-synced-history.browser.test.ts/SignalSyncedHistory-prevents-circular-updates-1.png +0 -0
- package/test/browser/__screenshots__/signal-synced-history.browser.test.ts/SignalSyncedHistory-syncs-actor-route-to-browser-URL-1.png +0 -0
- package/test/browser/signal-synced-history.browser.test.ts +0 -95
- package/test/route-map.test.ts +0 -107
- package/test/tanstack-router-bridge.test.ts +0 -318
- package/test/urlpattern-integration.test.ts +0 -145
- package/tsconfig.json +0 -16
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -35
package/README.md
CHANGED
|
@@ -29,25 +29,15 @@ npm install @xmachines/play-tanstack-react-router @xmachines/play-router @xmachi
|
|
|
29
29
|
|
|
30
30
|
Peer dependencies:
|
|
31
31
|
|
|
32
|
-
- `@tanstack/react-router` `^1.
|
|
32
|
+
- `@tanstack/react-router` `^1.166.7`
|
|
33
33
|
- `react` `^18 || ^19`
|
|
34
|
+
- `xstate` `^5.0.0`
|
|
34
35
|
|
|
35
|
-
##
|
|
36
|
+
## URLPattern Support
|
|
36
37
|
|
|
37
|
-
This package uses the [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) for route pattern matching
|
|
38
|
+
This package uses the [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) for route pattern matching via `@xmachines/play-router`.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
For Node.js test environments or older browsers, install `urlpattern-polyfill`.
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
npm install urlpattern-polyfill
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
if (!globalThis.URLPattern) {
|
|
48
|
-
await import("urlpattern-polyfill");
|
|
49
|
-
}
|
|
50
|
-
```
|
|
40
|
+
URLPattern is available natively on Node.js 24+ and modern browsers (Chrome 95+, Firefox 117+, Safari 16.4+). On older environments, load a polyfill **before** importing this package — see [`@xmachines/play-router` installation](../play-router/README.md#installation) for details.
|
|
51
41
|
|
|
52
42
|
## Quick Start
|
|
53
43
|
|
|
@@ -112,16 +102,35 @@ class TanStackReactRouterBridge implements RouterBridge {
|
|
|
112
102
|
|
|
113
103
|
### `RouteMap` and `createRouteMapFromTree`
|
|
114
104
|
|
|
115
|
-
Map state IDs to URL paths and resolve URLs back to state IDs
|
|
105
|
+
Map state IDs to URL paths and resolve URLs back to state IDs.
|
|
106
|
+
|
|
107
|
+
`RouteMap` extends `BaseRouteMap` from `@xmachines/play-router`, inheriting bucket-indexed
|
|
108
|
+
bidirectional route matching. No routing logic lives in the adapter itself.
|
|
116
109
|
|
|
117
110
|
```ts
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
111
|
+
// RouteMap is a thin subclass of BaseRouteMap — no extra methods
|
|
112
|
+
class RouteMap extends BaseRouteMap {}
|
|
113
|
+
|
|
114
|
+
// Inherited API:
|
|
115
|
+
routeMap.getStateIdByPath(path: string): string | null
|
|
116
|
+
routeMap.getPathByStateId(stateId: string): string | null
|
|
123
117
|
|
|
124
|
-
|
|
118
|
+
// Factory from a machine route tree:
|
|
119
|
+
function createRouteMapFromTree(routeTree: RouteTree): RouteMap
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`getStateIdByPath` returns `null` (not `undefined`) for unmatched paths.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const routeMap = new RouteMap([
|
|
126
|
+
{ stateId: "home", path: "/" },
|
|
127
|
+
{ stateId: "profile", path: "/profile/:userId" },
|
|
128
|
+
{ stateId: "settings", path: "/settings/:section?" },
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
routeMap.getStateIdByPath("/profile/123"); // "profile"
|
|
132
|
+
routeMap.getPathByStateId("home"); // "/"
|
|
133
|
+
routeMap.getStateIdByPath("/unknown"); // null
|
|
125
134
|
```
|
|
126
135
|
|
|
127
136
|
### `PlayRouterProvider`
|
|
@@ -174,4 +183,7 @@ This keeps routing infrastructure passive while preserving business-logic contro
|
|
|
174
183
|
|
|
175
184
|
## License
|
|
176
185
|
|
|
177
|
-
|
|
186
|
+
Copyright (c) 2016 [Mikael Karon](mailto:mikael@karon.se). All rights reserved.
|
|
187
|
+
|
|
188
|
+
This work is licensed under the terms of the MIT license.
|
|
189
|
+
For a copy, see <https://opensource.org/licenses/MIT>.
|
package/dist/route-map.d.ts
CHANGED
|
@@ -10,75 +10,45 @@
|
|
|
10
10
|
* @packageDocumentation
|
|
11
11
|
*/
|
|
12
12
|
import type { RouteTree } from "@xmachines/play-router";
|
|
13
|
+
import { BaseRouteMap } from "@xmachines/play-router";
|
|
13
14
|
/**
|
|
14
|
-
* Mapping between state machine state ID and router path
|
|
15
|
+
* Mapping between state machine state ID and router path.
|
|
16
|
+
*
|
|
17
|
+
* Structurally compatible with `BaseRouteMapping` from `@xmachines/play-router`.
|
|
18
|
+
* Fields are `readonly` — entries are immutable once passed to `RouteMap`.
|
|
15
19
|
*/
|
|
16
20
|
export interface RouteMapping {
|
|
17
|
-
/** State ID from state machine (e.g., "settings.profile") */
|
|
18
|
-
stateId: string;
|
|
19
|
-
/** Router path with optional parameters (e.g., "/settings/:section?") */
|
|
20
|
-
path: string;
|
|
21
|
+
/** State ID from state machine (e.g., `"home"`, `"settings.profile"`) */
|
|
22
|
+
readonly stateId: string;
|
|
23
|
+
/** Router path with optional parameters (e.g., `"/settings/:section?"`) */
|
|
24
|
+
readonly path: string;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
|
-
* Bidirectional route mapper
|
|
27
|
+
* Bidirectional route mapper for TanStack React Router.
|
|
28
|
+
*
|
|
29
|
+
* Extends {@link BaseRouteMap} — all matching logic lives there.
|
|
30
|
+
* This class exists to provide a TanStack React Router-specific type name and to
|
|
31
|
+
* allow future adapter-specific extensions without breaking the shared base.
|
|
24
32
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
33
|
+
* **Inherited API:**
|
|
34
|
+
* - `getStateIdByPath(path): string | null` — path → state ID
|
|
35
|
+
* - `getPathByStateId(stateId): string | null` — state ID → path pattern
|
|
36
|
+
*
|
|
37
|
+
* @extends BaseRouteMap
|
|
27
38
|
*
|
|
28
39
|
* @example
|
|
29
40
|
* ```typescript
|
|
30
|
-
* const
|
|
31
|
-
* { stateId: "home",
|
|
32
|
-
* { stateId: "profile",
|
|
33
|
-
* { stateId: "settings", path: "/settings/:section?" }
|
|
34
|
-
* ];
|
|
35
|
-
*
|
|
36
|
-
* const routeMap = new RouteMap(routes);
|
|
41
|
+
* const routeMap = new RouteMap([
|
|
42
|
+
* { stateId: "home", path: "/" },
|
|
43
|
+
* { stateId: "profile", path: "/profile/:userId" },
|
|
44
|
+
* { stateId: "settings", path: "/settings/:section?" },
|
|
45
|
+
* ]);
|
|
37
46
|
*
|
|
38
47
|
* routeMap.getStateIdByPath("/profile/123"); // "profile"
|
|
39
|
-
* routeMap.getPathByStateId("home");
|
|
48
|
+
* routeMap.getPathByStateId("home"); // "/"
|
|
40
49
|
* ```
|
|
41
50
|
*/
|
|
42
|
-
export declare class RouteMap {
|
|
43
|
-
private stateIdToPath;
|
|
44
|
-
private pathToStateId;
|
|
45
|
-
private patterns;
|
|
46
|
-
/**
|
|
47
|
-
* Create RouteMap from route mappings
|
|
48
|
-
*
|
|
49
|
-
* @param routes - Array of state ID → path mappings
|
|
50
|
-
*/
|
|
51
|
-
constructor(routes: RouteMapping[]);
|
|
52
|
-
/**
|
|
53
|
-
* Get state ID from router path
|
|
54
|
-
*
|
|
55
|
-
* Tries exact match first, then pattern match for parameterized paths.
|
|
56
|
-
*
|
|
57
|
-
* @param path - Router path (e.g., "/profile/123")
|
|
58
|
-
* @returns State ID or null if no match
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```typescript
|
|
62
|
-
* routeMap.getStateIdByPath("/"); // "home" (exact match)
|
|
63
|
-
* routeMap.getStateIdByPath("/profile/123"); // "profile" (pattern match)
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
getStateIdByPath(path: string): string | null;
|
|
67
|
-
/**
|
|
68
|
-
* Get router path from state ID
|
|
69
|
-
*
|
|
70
|
-
* Returns the route pattern with parameter placeholders (not substituted).
|
|
71
|
-
*
|
|
72
|
-
* @param stateId - State machine state ID
|
|
73
|
-
* @returns Router path or null if no match
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```typescript
|
|
77
|
-
* routeMap.getPathByStateId("home"); // "/"
|
|
78
|
-
* routeMap.getPathByStateId("profile"); // "/profile/:userId"
|
|
79
|
-
* ```
|
|
80
|
-
*/
|
|
81
|
-
getPathByStateId(stateId: string): string | null;
|
|
51
|
+
export declare class RouteMap extends BaseRouteMap {
|
|
82
52
|
}
|
|
83
53
|
/**
|
|
84
54
|
* Create RouteMap from RouteTree
|
package/dist/route-map.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-map.d.ts","sourceRoot":"","sources":["../src/route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"route-map.d.ts","sourceRoot":"","sources":["../src/route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,QAAS,SAAQ,YAAY;CAAG;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAcrE"}
|
package/dist/route-map.js
CHANGED
|
@@ -9,102 +9,33 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @packageDocumentation
|
|
11
11
|
*/
|
|
12
|
+
import { BaseRouteMap } from "@xmachines/play-router";
|
|
12
13
|
/**
|
|
13
|
-
* Bidirectional route mapper
|
|
14
|
+
* Bidirectional route mapper for TanStack React Router.
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* Extends {@link BaseRouteMap} — all matching logic lives there.
|
|
17
|
+
* This class exists to provide a TanStack React Router-specific type name and to
|
|
18
|
+
* allow future adapter-specific extensions without breaking the shared base.
|
|
19
|
+
*
|
|
20
|
+
* **Inherited API:**
|
|
21
|
+
* - `getStateIdByPath(path): string | null` — path → state ID
|
|
22
|
+
* - `getPathByStateId(stateId): string | null` — state ID → path pattern
|
|
23
|
+
*
|
|
24
|
+
* @extends BaseRouteMap
|
|
17
25
|
*
|
|
18
26
|
* @example
|
|
19
27
|
* ```typescript
|
|
20
|
-
* const
|
|
21
|
-
* { stateId: "home",
|
|
22
|
-
* { stateId: "profile",
|
|
23
|
-
* { stateId: "settings", path: "/settings/:section?" }
|
|
24
|
-
* ];
|
|
25
|
-
*
|
|
26
|
-
* const routeMap = new RouteMap(routes);
|
|
28
|
+
* const routeMap = new RouteMap([
|
|
29
|
+
* { stateId: "home", path: "/" },
|
|
30
|
+
* { stateId: "profile", path: "/profile/:userId" },
|
|
31
|
+
* { stateId: "settings", path: "/settings/:section?" },
|
|
32
|
+
* ]);
|
|
27
33
|
*
|
|
28
34
|
* routeMap.getStateIdByPath("/profile/123"); // "profile"
|
|
29
|
-
* routeMap.getPathByStateId("home");
|
|
35
|
+
* routeMap.getPathByStateId("home"); // "/"
|
|
30
36
|
* ```
|
|
31
37
|
*/
|
|
32
|
-
export class RouteMap {
|
|
33
|
-
stateIdToPath;
|
|
34
|
-
pathToStateId;
|
|
35
|
-
patterns;
|
|
36
|
-
/**
|
|
37
|
-
* Create RouteMap from route mappings
|
|
38
|
-
*
|
|
39
|
-
* @param routes - Array of state ID → path mappings
|
|
40
|
-
*/
|
|
41
|
-
constructor(routes) {
|
|
42
|
-
this.stateIdToPath = new Map();
|
|
43
|
-
this.pathToStateId = new Map();
|
|
44
|
-
this.patterns = [];
|
|
45
|
-
for (const { stateId, path } of routes) {
|
|
46
|
-
this.stateIdToPath.set(stateId, path);
|
|
47
|
-
// Check if path has parameters
|
|
48
|
-
if (path.includes(":")) {
|
|
49
|
-
// Convert :param and :param? to regex
|
|
50
|
-
const pattern = path
|
|
51
|
-
.replace(/\/:[^/]+\?/g, "(?:/([^/]+))?") // Optional params with optional slash
|
|
52
|
-
.replace(/:[^/]+/g, "([^/]+)"); // Required params
|
|
53
|
-
this.patterns.push({
|
|
54
|
-
pattern: new RegExp(`^${pattern}$`),
|
|
55
|
-
stateId,
|
|
56
|
-
path,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
// Exact match for static paths
|
|
61
|
-
this.pathToStateId.set(path, stateId);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Get state ID from router path
|
|
67
|
-
*
|
|
68
|
-
* Tries exact match first, then pattern match for parameterized paths.
|
|
69
|
-
*
|
|
70
|
-
* @param path - Router path (e.g., "/profile/123")
|
|
71
|
-
* @returns State ID or null if no match
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* routeMap.getStateIdByPath("/"); // "home" (exact match)
|
|
76
|
-
* routeMap.getStateIdByPath("/profile/123"); // "profile" (pattern match)
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
getStateIdByPath(path) {
|
|
80
|
-
// Try exact match first
|
|
81
|
-
const exactMatch = this.pathToStateId.get(path);
|
|
82
|
-
if (exactMatch)
|
|
83
|
-
return exactMatch;
|
|
84
|
-
// Try pattern match
|
|
85
|
-
for (const { pattern, stateId } of this.patterns) {
|
|
86
|
-
if (pattern.test(path))
|
|
87
|
-
return stateId;
|
|
88
|
-
}
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Get router path from state ID
|
|
93
|
-
*
|
|
94
|
-
* Returns the route pattern with parameter placeholders (not substituted).
|
|
95
|
-
*
|
|
96
|
-
* @param stateId - State machine state ID
|
|
97
|
-
* @returns Router path or null if no match
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* routeMap.getPathByStateId("home"); // "/"
|
|
102
|
-
* routeMap.getPathByStateId("profile"); // "/profile/:userId"
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
getPathByStateId(stateId) {
|
|
106
|
-
return this.stateIdToPath.get(stateId) || null;
|
|
107
|
-
}
|
|
38
|
+
export class RouteMap extends BaseRouteMap {
|
|
108
39
|
}
|
|
109
40
|
/**
|
|
110
41
|
* Create RouteMap from RouteTree
|
package/dist/route-map.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-map.js","sourceRoot":"","sources":["../src/route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"route-map.js","sourceRoot":"","sources":["../src/route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAetD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,QAAS,SAAQ,YAAY;CAAG;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAoB;IAC1D,MAAM,MAAM,GAAmB,EAAE,CAAC;IAElC,SAAS,QAAQ,CAAC,IAAe;QAChC,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmachines/play-tanstack-react-router",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.11",
|
|
4
4
|
"description": "TanStack React Router adapter for XMachines Play - synchronizes browser URL with actor state through passive infrastructure",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"routing",
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
],
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"author": "XMachines",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
15
20
|
"type": "module",
|
|
16
21
|
"exports": {
|
|
17
22
|
".": {
|
|
@@ -20,32 +25,35 @@
|
|
|
20
25
|
},
|
|
21
26
|
"./package.json": "./package.json"
|
|
22
27
|
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
23
31
|
"scripts": {
|
|
24
32
|
"build": "tsc --build",
|
|
25
|
-
"clean": "rm -rf dist *.tsbuildinfo",
|
|
33
|
+
"clean": "rm -rf dist *.tsbuildinfo node_modules/.vite node_modules/.vite-temp",
|
|
26
34
|
"typecheck": "tsc --noEmit",
|
|
27
|
-
"test": "vitest
|
|
28
|
-
"test:browser": "vitest
|
|
35
|
+
"test": "vitest",
|
|
36
|
+
"test:browser": "vitest",
|
|
29
37
|
"prepublishOnly": "npm run build"
|
|
30
38
|
},
|
|
31
39
|
"dependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"@xmachines/play-
|
|
34
|
-
"@xmachines/play-
|
|
35
|
-
"
|
|
36
|
-
"xstate": "^5.28.0"
|
|
40
|
+
"@xmachines/play-actor": "1.0.0-beta.11",
|
|
41
|
+
"@xmachines/play-router": "1.0.0-beta.11",
|
|
42
|
+
"@xmachines/play-signals": "1.0.0-beta.11",
|
|
43
|
+
"xstate": "^5.0.0"
|
|
37
44
|
},
|
|
38
45
|
"devDependencies": {
|
|
39
|
-
"@
|
|
40
|
-
"
|
|
46
|
+
"@tanstack/react-router": "^1.167.5",
|
|
47
|
+
"@types/node": "^25.5.0",
|
|
48
|
+
"@xmachines/shared": "1.0.0-beta.11",
|
|
49
|
+
"jsdom": "^29.0.1",
|
|
50
|
+
"typescript": "^5.9.3",
|
|
51
|
+
"vitest": "^4.1.0"
|
|
41
52
|
},
|
|
42
53
|
"peerDependencies": {
|
|
43
54
|
"@tanstack/react-router": "^1.166.7",
|
|
44
|
-
"react": "^18.
|
|
45
|
-
"react-dom": "^18.
|
|
46
|
-
"xstate": "^5.
|
|
47
|
-
},
|
|
48
|
-
"publishConfig": {
|
|
49
|
-
"access": "public"
|
|
55
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
56
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
57
|
+
"xstate": "^5.0.0"
|
|
50
58
|
}
|
|
51
59
|
}
|
package/.oxfmtrc.json
DELETED
package/.oxlintrc.json
DELETED
package/examples/demo/README.md
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# TanStack React Router Demo
|
|
2
|
-
|
|
3
|
-
React + TanStack Router demonstration of Play's actor-authoritative routing and rendering model.
|
|
4
|
-
|
|
5
|
-
## What This Demonstrates
|
|
6
|
-
|
|
7
|
-
- Shared auth machine reused without framework-specific business logic
|
|
8
|
-
- `PlayRouterProvider` renderer-based integration with TanStack Router
|
|
9
|
-
- Shell-driven rendering via `PlayRenderer` with actor-authoritative navigation
|
|
10
|
-
- Non-browser invariant tests plus browser E2E coverage
|
|
11
|
-
|
|
12
|
-
## Running the Demo
|
|
13
|
-
|
|
14
|
-
From this directory (`packages/play-tanstack-react-router/examples/demo`):
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm install
|
|
18
|
-
npm run dev
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Open `http://localhost:3000`.
|
|
22
|
-
|
|
23
|
-
## Step-by-Step Code Flow
|
|
24
|
-
|
|
25
|
-
This demo uses provider-based integration centered on `PlayRouterProvider` and a route map generated from the machine:
|
|
26
|
-
|
|
27
|
-
1. `src/main.tsx` mounts `<App />`.
|
|
28
|
-
2. `src/App.tsx` creates/starts the actor from shared machine + catalog.
|
|
29
|
-
3. `src/App.tsx` builds `routeMap` from `extractMachineRoutes(authMachine)` + `createRouteMapFromTree(routeTree)`.
|
|
30
|
-
4. `PlayRouterProvider` bridges TanStack Router to the actor and renders `Shell` via `renderer(actor, router)`.
|
|
31
|
-
5. `Shell` renders `PlayRenderer`, header/nav, and debug panel from actor state.
|
|
32
|
-
6. Tests in `test/` and `test/browser*/` validate invariant and runtime behavior.
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
// src/App.tsx (shape)
|
|
36
|
-
const routeTree = extractMachineRoutes(authMachine);
|
|
37
|
-
const routeMap = createRouteMapFromTree(routeTree);
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<PlayRouterProvider
|
|
41
|
-
actor={actor}
|
|
42
|
-
router={router}
|
|
43
|
-
routeMap={routeMap}
|
|
44
|
-
renderer={(currentActor, currentRouter) => (
|
|
45
|
-
<Shell actor={currentActor} router={currentRouter} />
|
|
46
|
-
)}
|
|
47
|
-
/>
|
|
48
|
-
);
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
// src/components/Login.tsx (shape)
|
|
53
|
-
<button onClick={() => actor.send({ type: "auth.login", username, password })}>Login</button>
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Shared business logic comes from the common demo machine/catalog module (`authMachine` and `catalog`), so routing decisions remain machine-driven and framework-independent.
|
|
57
|
-
|
|
58
|
-
## Key Files
|
|
59
|
-
|
|
60
|
-
- `src/main.tsx` - React entry point that mounts `<App />`
|
|
61
|
-
- `src/App.tsx` - actor lifecycle, route-map creation, provider wiring, and `Shell` rendering
|
|
62
|
-
- `src/components/` - UI components that send actor events and render state-driven views
|
|
63
|
-
- `test/actor-authority.test.ts` - actor authority and guarded navigation behavior
|
|
64
|
-
- `test/strict-separation.test.ts` - machine/view infrastructure separation contracts
|
|
65
|
-
- `test/browser-e2e/auth-flow.browser.test.tsx` - canonical browser auth flow
|
|
66
|
-
- `test/browser/` - extended browser checks for URL sync, history behavior, and route event flow
|
|
67
|
-
|
|
68
|
-
## Available Scripts
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
npm run dev # Start Vite dev server (http://localhost:3000)
|
|
72
|
-
npm run build # Build production assets
|
|
73
|
-
npm run preview # Preview production build locally
|
|
74
|
-
npm run test # Run Vitest suite
|
|
75
|
-
npm run test:vitest # Explicit Vitest command alias
|
|
76
|
-
npm run test:browser # Browser-focused test run (e2e browser config)
|
|
77
|
-
npm run test:browser:full # Full browser test config run
|
|
78
|
-
npm run test:e2e # Alias to test:browser
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Verification
|
|
82
|
-
|
|
83
|
-
Run the core invariant checks referenced by this demo docs:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
npm run test:vitest -- test/actor-authority.test.ts test/strict-separation.test.ts
|
|
87
|
-
npm run test:browser
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Manual sanity flow:
|
|
91
|
-
|
|
92
|
-
1. Run `npm run dev` and open `http://localhost:3000`.
|
|
93
|
-
2. Attempt protected navigation while logged out and confirm guard-driven behavior.
|
|
94
|
-
3. Log in, then confirm route and view updates stay in sync.
|
|
95
|
-
|
|
96
|
-
## Learn More
|
|
97
|
-
|
|
98
|
-
- [TanStack React Router package README](../../README.md)
|
|
99
|
-
- [Solid Router demo README](../../../play-solid-router/examples/demo/README.md)
|
|
100
|
-
- [TanStack Solid Router demo README](../../../play-tanstack-solid-router/examples/demo/README.md)
|