@xmachines/play-tanstack-react-router 1.0.0-beta.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/.oxfmtrc.json +3 -0
- package/.oxlintrc.json +3 -0
- package/README.md +177 -0
- package/dist/extract-params.d.ts +45 -0
- package/dist/extract-params.d.ts.map +1 -0
- package/dist/extract-params.js +70 -0
- package/dist/extract-params.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/play-router-provider.d.ts +33 -0
- package/dist/play-router-provider.d.ts.map +1 -0
- package/dist/play-router-provider.js +31 -0
- package/dist/play-router-provider.js.map +1 -0
- package/dist/route-map.d.ts +101 -0
- package/dist/route-map.d.ts.map +1 -0
- package/dist/route-map.js +139 -0
- package/dist/route-map.js.map +1 -0
- package/dist/tanstack-router-bridge.d.ts +115 -0
- package/dist/tanstack-router-bridge.d.ts.map +1 -0
- package/dist/tanstack-router-bridge.js +112 -0
- package/dist/tanstack-router-bridge.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +10 -0
- package/dist/utils.js.map +1 -0
- package/examples/demo/README.md +100 -0
- package/examples/demo/docs/ARCHITECTURE.md +643 -0
- package/examples/demo/docs/INVARIANTS.md +461 -0
- package/examples/demo/docs/SWAP-REACT.md +635 -0
- package/examples/demo/index.html +16 -0
- package/examples/demo/package.json +39 -0
- package/examples/demo/src/App.tsx +148 -0
- package/examples/demo/src/components/About.tsx +49 -0
- package/examples/demo/src/components/Contact.tsx +43 -0
- package/examples/demo/src/components/Dashboard.tsx +46 -0
- package/examples/demo/src/components/DebugPanel.tsx +68 -0
- package/examples/demo/src/components/HeaderNav.tsx +103 -0
- package/examples/demo/src/components/Home.tsx +41 -0
- package/examples/demo/src/components/Login.tsx +82 -0
- package/examples/demo/src/components/Navigation.tsx +262 -0
- package/examples/demo/src/components/Profile.tsx +46 -0
- package/examples/demo/src/components/Register.tsx +109 -0
- package/examples/demo/src/components/Settings.tsx +92 -0
- package/examples/demo/src/components/index.ts +16 -0
- package/examples/demo/src/main.tsx +20 -0
- package/examples/demo/test/actor-authority.test.ts +50 -0
- 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 +148 -0
- package/examples/demo/test/browser/back-forward-sync.browser.test.tsx +149 -0
- package/examples/demo/test/browser/direct-navigation.browser.test.ts +146 -0
- package/examples/demo/test/browser/exact-user-scenario.browser.test.tsx +207 -0
- package/examples/demo/test/browser/guard-rejection.browser.test.tsx +52 -0
- package/examples/demo/test/browser/history-investigation.browser.test.tsx +82 -0
- package/examples/demo/test/browser/history-navigation.browser.test.ts +351 -0
- package/examples/demo/test/browser/login-flow.browser.test.tsx +34 -0
- package/examples/demo/test/browser/navigation.browser.test.tsx +34 -0
- package/examples/demo/test/browser/protected-route-navigation.browser.test.tsx +161 -0
- package/examples/demo/test/browser/redirect-url-update.browser.test.tsx +140 -0
- package/examples/demo/test/browser/settings-parameter.browser.test.tsx +164 -0
- package/examples/demo/test/browser/settings-query-freeze.browser.test.ts +141 -0
- package/examples/demo/test/browser/state-driven.browser.test.ts +112 -0
- package/examples/demo/test/browser/tanstack-integration.browser.test.tsx +61 -0
- package/examples/demo/test/browser/uat-xstate-route-regression.browser.test.ts +58 -0
- package/examples/demo/test/browser/xstate-route-events.browser.test.ts +293 -0
- package/examples/demo/test/browser-back-view-rendering.test.ts +104 -0
- package/examples/demo/test/browser-e2e/auth-flow.browser.test.tsx +49 -0
- package/examples/demo/test/invalid-route-redirect.test.ts +40 -0
- package/examples/demo/test/passive-infra.test.ts +35 -0
- package/examples/demo/test/route-parameters.test.ts +539 -0
- package/examples/demo/test/signal-only.test.ts +54 -0
- package/examples/demo/test/strict-separation.test.ts +37 -0
- package/examples/demo/test/test-utils.ts +49 -0
- package/examples/demo/tsconfig.json +21 -0
- package/examples/demo/tsconfig.tsbuildinfo +1 -0
- package/examples/demo/vite.config.ts +13 -0
- package/examples/demo/vitest.browser.config.ts +72 -0
- package/examples/demo/vitest.config.e2e.browser.ts +28 -0
- package/examples/demo/vitest.config.ts +35 -0
- package/package.json +51 -0
- package/src/extract-params.ts +75 -0
- package/src/index.ts +31 -0
- package/src/play-router-provider.tsx +46 -0
- package/src/route-map.ts +158 -0
- package/src/tanstack-router-bridge.ts +135 -0
- package/src/types.ts +26 -0
- package/src/utils.ts +12 -0
- 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 +95 -0
- package/test/route-map.test.ts +107 -0
- package/test/tanstack-router-bridge.test.ts +318 -0
- package/test/urlpattern-integration.test.ts +145 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +35 -0
package/.oxfmtrc.json
ADDED
package/.oxlintrc.json
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @xmachines/play-tanstack-react-router
|
|
2
|
+
|
|
3
|
+
**TanStack React Router adapter for XMachines Play using the RouterBridge pattern.**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@xmachines/play-tanstack-react-router` connects a Play actor to TanStack Router through `TanStackReactRouterBridge`.
|
|
8
|
+
|
|
9
|
+
The bridge extends `RouterBridgeBase` from `@xmachines/play-router`, so adapter behavior stays consistent across frameworks:
|
|
10
|
+
|
|
11
|
+
- Actor route signal (`actor.currentRoute`) drives router navigation.
|
|
12
|
+
- Router history events send `play.route` intents back to the actor.
|
|
13
|
+
- Guarded state transitions remain actor-owned (Actor Authority).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @tanstack/react-router react
|
|
19
|
+
npm install @xmachines/play-tanstack-react-router @xmachines/play-router @xmachines/play-react
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Current Exports
|
|
23
|
+
|
|
24
|
+
- `TanStackReactRouterBridge`
|
|
25
|
+
- `RouteMap`, `createRouteMapFromTree`, `RouteMapping` (type)
|
|
26
|
+
- `extractParams`, `extractQueryParams`
|
|
27
|
+
- `PlayRouterProvider` + `PlayRouterProviderProps`
|
|
28
|
+
- re-exports: `extractMachineRoutes`, `createRouteMap`, `RouterBridge`, `PlayRouteEvent`
|
|
29
|
+
|
|
30
|
+
Peer dependencies:
|
|
31
|
+
|
|
32
|
+
- `@tanstack/react-router` `^1.0.0`
|
|
33
|
+
- `react` `^18 || ^19`
|
|
34
|
+
|
|
35
|
+
## Browser Support
|
|
36
|
+
|
|
37
|
+
This package uses the [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) for route pattern matching.
|
|
38
|
+
|
|
39
|
+
Native support includes current Chrome, Firefox, and Safari 17.4+.
|
|
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
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { createRouter } from "@tanstack/react-router";
|
|
56
|
+
import { definePlayer } from "@xmachines/play-xstate";
|
|
57
|
+
import { extractMachineRoutes } from "@xmachines/play-router";
|
|
58
|
+
import {
|
|
59
|
+
TanStackReactRouterBridge,
|
|
60
|
+
createRouteMapFromTree,
|
|
61
|
+
} from "@xmachines/play-tanstack-react-router";
|
|
62
|
+
|
|
63
|
+
const routeTree = extractMachineRoutes(machine);
|
|
64
|
+
const routeMap = createRouteMapFromTree(routeTree);
|
|
65
|
+
|
|
66
|
+
const router = createRouter({ routeTree: tanstackRouteTree });
|
|
67
|
+
|
|
68
|
+
const actor = definePlayer({ machine, catalog })();
|
|
69
|
+
actor.start();
|
|
70
|
+
|
|
71
|
+
const bridge = new TanStackReactRouterBridge(router, actor, routeMap);
|
|
72
|
+
bridge.connect();
|
|
73
|
+
|
|
74
|
+
// later
|
|
75
|
+
bridge.disconnect();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### React convenience wrapper
|
|
79
|
+
|
|
80
|
+
Use `PlayRouterProvider` when you want bridge lifecycle wiring in a component:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { PlayRenderer } from "@xmachines/play-react";
|
|
84
|
+
|
|
85
|
+
<PlayRouterProvider
|
|
86
|
+
actor={actor}
|
|
87
|
+
router={router}
|
|
88
|
+
routeMap={routeMap}
|
|
89
|
+
renderer={(currentActor, currentRouter) => (
|
|
90
|
+
<PlayRenderer actor={currentActor} components={components} />
|
|
91
|
+
)}
|
|
92
|
+
/>;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## API
|
|
96
|
+
|
|
97
|
+
### `TanStackReactRouterBridge`
|
|
98
|
+
|
|
99
|
+
Primary adapter class.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
class TanStackReactRouterBridge implements RouterBridge {
|
|
103
|
+
constructor(
|
|
104
|
+
router: TanStackRouterLike,
|
|
105
|
+
actor: AbstractActor<AnyActorLogic> & Routable,
|
|
106
|
+
routeMap: RouteMap,
|
|
107
|
+
);
|
|
108
|
+
connect(): void;
|
|
109
|
+
disconnect(): void;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `RouteMap` and `createRouteMapFromTree`
|
|
114
|
+
|
|
115
|
+
Map state IDs to URL paths and resolve URLs back to state IDs:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
class RouteMap {
|
|
119
|
+
constructor(routes: Array<{ stateId: string; path: string }>);
|
|
120
|
+
getStateIdByPath(path: string): string | undefined;
|
|
121
|
+
getPathByStateId(stateId: string): string | undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function createRouteMapFromTree(routeTree: RouteTree): RouteMap;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `PlayRouterProvider`
|
|
128
|
+
|
|
129
|
+
React wrapper around `TanStackReactRouterBridge`.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
interface PlayRouterProviderProps {
|
|
133
|
+
actor: AbstractActor<AnyActorLogic> & Routable & Viewable;
|
|
134
|
+
router: TanStackRouterLike;
|
|
135
|
+
routeMap: RouteMap;
|
|
136
|
+
renderer: (
|
|
137
|
+
actor: AbstractActor<AnyActorLogic> & Routable & Viewable,
|
|
138
|
+
router: TanStackRouterLike,
|
|
139
|
+
) => ReactNode;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Utilities and re-exports
|
|
144
|
+
|
|
145
|
+
- `extractParams`, `extractQueryParams`
|
|
146
|
+
- `extractMachineRoutes`, `createRouteMap` (re-exported from `@xmachines/play-router`)
|
|
147
|
+
- `RouterBridge`, `PlayRouteEvent` types
|
|
148
|
+
|
|
149
|
+
## Examples
|
|
150
|
+
|
|
151
|
+
- Multi-router integration guide: `docs/examples/multi-router-integration.md`
|
|
152
|
+
- Routing patterns guide: `docs/examples/routing-patterns.md`
|
|
153
|
+
|
|
154
|
+
## Architecture
|
|
155
|
+
|
|
156
|
+
Bridge-first flow:
|
|
157
|
+
|
|
158
|
+
1. `RouterBridgeBase.connect()` performs initial actor/router synchronization.
|
|
159
|
+
2. Actor route updates call TanStack navigation (`router.navigate({ to })`).
|
|
160
|
+
3. TanStack history updates are subscribed and translated to `play.route` events.
|
|
161
|
+
4. Actor guards accept or reject transitions; infrastructure reflects resulting state.
|
|
162
|
+
|
|
163
|
+
This keeps routing infrastructure passive while preserving business-logic control.
|
|
164
|
+
|
|
165
|
+
## Historical Note
|
|
166
|
+
|
|
167
|
+
`SignalSyncedHistory` and `createPlayRouter` are legacy migration-era APIs and are not part of the current quick-start path. Use `TanStackReactRouterBridge` + `RouteMap` for new integrations.
|
|
168
|
+
|
|
169
|
+
## Related Packages
|
|
170
|
+
|
|
171
|
+
- [@xmachines/play-router](../play-router)
|
|
172
|
+
- [@xmachines/play-xstate](../play-xstate)
|
|
173
|
+
- [@xmachines/play-react](../play-react)
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter extraction utilities using URLPattern API
|
|
3
|
+
*
|
|
4
|
+
* Provides robust parameter extraction from URL paths and query strings.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Extract route parameters from URL path based on route pattern using URLPattern API
|
|
10
|
+
*
|
|
11
|
+
* @param pathname - Actual URL path (e.g., "/profile/123")
|
|
12
|
+
* @param pattern - Route pattern with params (e.g., "/profile/:userId")
|
|
13
|
+
* @returns Object with extracted parameters
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* extractParams("/profile/123", "/profile/:userId")
|
|
18
|
+
* // Returns: { userId: "123" }
|
|
19
|
+
*
|
|
20
|
+
* extractParams("/api/123", "/api/:id(\\d+)")
|
|
21
|
+
* // Returns: { id: "123" }
|
|
22
|
+
* // Validates numeric constraint via URLPattern
|
|
23
|
+
*
|
|
24
|
+
* extractParams("/docs/intro", "/docs/*")
|
|
25
|
+
* // Returns: { "0": "intro" }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function extractParams(pathname: string, pattern: string): Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Extract query parameters from search string
|
|
31
|
+
*
|
|
32
|
+
* @param search - Query string with or without leading ? (e.g., "?tab=settings" or "tab=settings")
|
|
33
|
+
* @returns Object mapping query parameter names to values
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* extractQueryParams("?tab=settings&theme=dark")
|
|
38
|
+
* // Returns: { tab: "settings", theme: "dark" }
|
|
39
|
+
*
|
|
40
|
+
* extractQueryParams("q=hello%20world")
|
|
41
|
+
* // Returns: { q: "hello world" } (auto-decoded)
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function extractQueryParams(search: string): Record<string, string>;
|
|
45
|
+
//# sourceMappingURL=extract-params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-params.d.ts","sourceRoot":"","sources":["../src/extract-params.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBvF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOzE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter extraction utilities using URLPattern API
|
|
3
|
+
*
|
|
4
|
+
* Provides robust parameter extraction from URL paths and query strings.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Extract route parameters from URL path based on route pattern using URLPattern API
|
|
10
|
+
*
|
|
11
|
+
* @param pathname - Actual URL path (e.g., "/profile/123")
|
|
12
|
+
* @param pattern - Route pattern with params (e.g., "/profile/:userId")
|
|
13
|
+
* @returns Object with extracted parameters
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* extractParams("/profile/123", "/profile/:userId")
|
|
18
|
+
* // Returns: { userId: "123" }
|
|
19
|
+
*
|
|
20
|
+
* extractParams("/api/123", "/api/:id(\\d+)")
|
|
21
|
+
* // Returns: { id: "123" }
|
|
22
|
+
* // Validates numeric constraint via URLPattern
|
|
23
|
+
*
|
|
24
|
+
* extractParams("/docs/intro", "/docs/*")
|
|
25
|
+
* // Returns: { "0": "intro" }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function extractParams(pathname, pattern) {
|
|
29
|
+
// Reuse existing implementation from signal-synced-history.ts
|
|
30
|
+
// URLPattern-based extraction with :param syntax
|
|
31
|
+
const params = {};
|
|
32
|
+
// Parse pattern and pathname to extract named segments
|
|
33
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
34
|
+
const pathParts = pathname.split("/").filter(Boolean);
|
|
35
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
36
|
+
const patternPart = patternParts[i];
|
|
37
|
+
const pathPart = pathParts[i];
|
|
38
|
+
if (patternPart.startsWith(":")) {
|
|
39
|
+
const paramName = patternPart.slice(1).replace("?", "");
|
|
40
|
+
if (pathPart) {
|
|
41
|
+
params[paramName] = decodeURIComponent(pathPart);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return params;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Extract query parameters from search string
|
|
49
|
+
*
|
|
50
|
+
* @param search - Query string with or without leading ? (e.g., "?tab=settings" or "tab=settings")
|
|
51
|
+
* @returns Object mapping query parameter names to values
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* extractQueryParams("?tab=settings&theme=dark")
|
|
56
|
+
* // Returns: { tab: "settings", theme: "dark" }
|
|
57
|
+
*
|
|
58
|
+
* extractQueryParams("q=hello%20world")
|
|
59
|
+
* // Returns: { q: "hello world" } (auto-decoded)
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function extractQueryParams(search) {
|
|
63
|
+
const params = new URLSearchParams(search);
|
|
64
|
+
const result = {};
|
|
65
|
+
params.forEach((value, key) => {
|
|
66
|
+
result[key] = value;
|
|
67
|
+
});
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=extract-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-params.js","sourceRoot":"","sources":["../src/extract-params.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe;IAC9D,8DAA8D;IAC9D,iDAAiD;IACjD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,uDAAuD;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAE9B,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACxD,IAAI,QAAQ,EAAE,CAAC;gBACd,MAAM,CAAC,SAAS,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAClD,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAChD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACrB,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AACf,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xmachines/play-tanstack-react-router
|
|
3
|
+
*
|
|
4
|
+
* TanStack Router adapter for XMachines Play architecture.
|
|
5
|
+
* Synchronizes browser URL with actor state through passive infrastructure.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export { TanStackReactRouterBridge } from "./tanstack-router-bridge.js";
|
|
10
|
+
export { RouteMap, createRouteMapFromTree } from "./route-map.js";
|
|
11
|
+
export { extractParams, extractQueryParams } from "./extract-params.js";
|
|
12
|
+
export type { RouteMapping } from "./route-map.js";
|
|
13
|
+
export type { TanStackRouterLike } from "./tanstack-router-bridge.js";
|
|
14
|
+
export { PlayRouterProvider, type PlayRouterProviderProps, type TanStackRouterInstance, } from "./play-router-provider.js";
|
|
15
|
+
export { extractMachineRoutes, createRouteMap } from "@xmachines/play-router";
|
|
16
|
+
export type { RouteNavigateEvent } from "./types.js";
|
|
17
|
+
export type { RouterBridge, PlayRouteEvent } from "@xmachines/play-router";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGtE,OAAO,EACN,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC3B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG9E,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xmachines/play-tanstack-react-router
|
|
3
|
+
*
|
|
4
|
+
* TanStack Router adapter for XMachines Play architecture.
|
|
5
|
+
* Synchronizes browser URL with actor state through passive infrastructure.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
// New exports (primary API - RouterBridge pattern)
|
|
10
|
+
export { TanStackReactRouterBridge } from "./tanstack-router-bridge.js";
|
|
11
|
+
export { RouteMap, createRouteMapFromTree } from "./route-map.js";
|
|
12
|
+
export { extractParams, extractQueryParams } from "./extract-params.js";
|
|
13
|
+
// TanStack Router integration (React-only)
|
|
14
|
+
export { PlayRouterProvider, } from "./play-router-provider.js";
|
|
15
|
+
// Re-export shared utilities for convenience
|
|
16
|
+
export { extractMachineRoutes, createRouteMap } from "@xmachines/play-router";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,mDAAmD;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAIxE,2CAA2C;AAC3C,OAAO,EACN,kBAAkB,GAGlB,MAAM,2BAA2B,CAAC;AAEnC,6CAA6C;AAC7C,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlayRouterProvider — React convenience wrapper for TanStackReactRouterBridge
|
|
3
|
+
*
|
|
4
|
+
* Creates and connects a TanStackReactRouterBridge in a React component lifecycle.
|
|
5
|
+
* Actor state drives router navigation; router events send play.route to actor.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <PlayRouterProvider
|
|
10
|
+
* actor={actor}
|
|
11
|
+
* router={router}
|
|
12
|
+
* routeMap={routeMap}
|
|
13
|
+
* renderer={(currentActor, currentRouter) => {
|
|
14
|
+
* void currentRouter;
|
|
15
|
+
* return <PlayRenderer actor={currentActor} components={components} />;
|
|
16
|
+
* }}
|
|
17
|
+
* />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import { type ReactNode } from "react";
|
|
21
|
+
import type { AbstractActor, Routable, Viewable } from "@xmachines/play-actor";
|
|
22
|
+
import type { AnyActorLogic } from "xstate";
|
|
23
|
+
import { TanStackReactRouterBridge } from "./tanstack-router-bridge.js";
|
|
24
|
+
import type { RouteMap } from "./route-map.js";
|
|
25
|
+
export type TanStackRouterInstance = ConstructorParameters<typeof TanStackReactRouterBridge>[0];
|
|
26
|
+
export interface PlayRouterProviderProps {
|
|
27
|
+
actor: AbstractActor<AnyActorLogic> & Routable & Viewable;
|
|
28
|
+
router: TanStackRouterInstance;
|
|
29
|
+
routeMap: RouteMap;
|
|
30
|
+
renderer: (actor: AbstractActor<AnyActorLogic> & Routable & Viewable, router: TanStackRouterInstance) => ReactNode;
|
|
31
|
+
}
|
|
32
|
+
export declare function PlayRouterProvider({ actor, router, routeMap, renderer }: PlayRouterProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
//# sourceMappingURL=play-router-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"play-router-provider.d.ts","sourceRoot":"","sources":["../src/play-router-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhG,MAAM,WAAW,uBAAuB;IACvC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1D,MAAM,EAAE,sBAAsB,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,CACT,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,GAAG,QAAQ,EACzD,MAAM,EAAE,sBAAsB,KAC1B,SAAS,CAAC;CACf;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,uBAAuB,2CAQhG"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* PlayRouterProvider — React convenience wrapper for TanStackReactRouterBridge
|
|
4
|
+
*
|
|
5
|
+
* Creates and connects a TanStackReactRouterBridge in a React component lifecycle.
|
|
6
|
+
* Actor state drives router navigation; router events send play.route to actor.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* <PlayRouterProvider
|
|
11
|
+
* actor={actor}
|
|
12
|
+
* router={router}
|
|
13
|
+
* routeMap={routeMap}
|
|
14
|
+
* renderer={(currentActor, currentRouter) => {
|
|
15
|
+
* void currentRouter;
|
|
16
|
+
* return <PlayRenderer actor={currentActor} components={components} />;
|
|
17
|
+
* }}
|
|
18
|
+
* />
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { useEffect } from "react";
|
|
22
|
+
import { TanStackReactRouterBridge } from "./tanstack-router-bridge.js";
|
|
23
|
+
export function PlayRouterProvider({ actor, router, routeMap, renderer }) {
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const bridge = new TanStackReactRouterBridge(router, actor, routeMap);
|
|
26
|
+
bridge.connect();
|
|
27
|
+
return () => bridge.disconnect();
|
|
28
|
+
}, [actor, router, routeMap]);
|
|
29
|
+
return _jsx(_Fragment, { children: renderer(actor, router) });
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=play-router-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"play-router-provider.js","sourceRoot":"","sources":["../src/play-router-provider.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AAGlD,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAexE,MAAM,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAA2B;IAChG,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,MAAM,GAAG,IAAI,yBAAyB,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtE,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE9B,OAAO,4BAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,GAAI,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RouteMap - Bidirectional mapping between state IDs and route paths
|
|
3
|
+
*
|
|
4
|
+
* Provides efficient lookup for:
|
|
5
|
+
* - State ID → Path (actor state changes → router navigation)
|
|
6
|
+
* - Path → State ID (router navigation → actor events)
|
|
7
|
+
*
|
|
8
|
+
* Supports both static paths and parameterized paths with :param syntax.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import type { RouteTree } from "@xmachines/play-router";
|
|
13
|
+
/**
|
|
14
|
+
* Mapping between state machine state ID and router path
|
|
15
|
+
*/
|
|
16
|
+
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
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Bidirectional route mapper with pattern matching support
|
|
24
|
+
*
|
|
25
|
+
* Maps between state IDs (XMachines actor) and paths (router).
|
|
26
|
+
* Handles both exact matches (static paths) and pattern matches (parameterized paths).
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const routes: RouteMapping[] = [
|
|
31
|
+
* { stateId: "home", path: "/" },
|
|
32
|
+
* { stateId: "profile", path: "/profile/:userId" },
|
|
33
|
+
* { stateId: "settings", path: "/settings/:section?" }
|
|
34
|
+
* ];
|
|
35
|
+
*
|
|
36
|
+
* const routeMap = new RouteMap(routes);
|
|
37
|
+
*
|
|
38
|
+
* routeMap.getStateIdByPath("/profile/123"); // "profile"
|
|
39
|
+
* routeMap.getPathByStateId("home"); // "/"
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
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;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create RouteMap from RouteTree
|
|
85
|
+
*
|
|
86
|
+
* Converts XMachines route tree to RouteMap for use with router adapters.
|
|
87
|
+
*
|
|
88
|
+
* @param routeTree - Route tree from extractMachineRoutes()
|
|
89
|
+
* @returns RouteMap instance
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* import { extractMachineRoutes } from '@xmachines/play-router';
|
|
94
|
+
* import { createRouteMapFromTree } from '@xmachines/play-tanstack-react-router';
|
|
95
|
+
*
|
|
96
|
+
* const routeTree = extractMachineRoutes(machine);
|
|
97
|
+
* const routeMap = createRouteMapFromTree(routeTree);
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function createRouteMapFromTree(routeTree: RouteTree): RouteMap;
|
|
101
|
+
//# sourceMappingURL=route-map.d.ts.map
|
|
@@ -0,0 +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;AAEnE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,QAAQ;IACpB,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAA4D;IAE5E;;;;OAIG;gBACS,MAAM,EAAE,YAAY,EAAE;IA0BlC;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAa7C;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAGhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAcrE"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RouteMap - Bidirectional mapping between state IDs and route paths
|
|
3
|
+
*
|
|
4
|
+
* Provides efficient lookup for:
|
|
5
|
+
* - State ID → Path (actor state changes → router navigation)
|
|
6
|
+
* - Path → State ID (router navigation → actor events)
|
|
7
|
+
*
|
|
8
|
+
* Supports both static paths and parameterized paths with :param syntax.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Bidirectional route mapper with pattern matching support
|
|
14
|
+
*
|
|
15
|
+
* Maps between state IDs (XMachines actor) and paths (router).
|
|
16
|
+
* Handles both exact matches (static paths) and pattern matches (parameterized paths).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const routes: RouteMapping[] = [
|
|
21
|
+
* { stateId: "home", path: "/" },
|
|
22
|
+
* { stateId: "profile", path: "/profile/:userId" },
|
|
23
|
+
* { stateId: "settings", path: "/settings/:section?" }
|
|
24
|
+
* ];
|
|
25
|
+
*
|
|
26
|
+
* const routeMap = new RouteMap(routes);
|
|
27
|
+
*
|
|
28
|
+
* routeMap.getStateIdByPath("/profile/123"); // "profile"
|
|
29
|
+
* routeMap.getPathByStateId("home"); // "/"
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
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
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Create RouteMap from RouteTree
|
|
111
|
+
*
|
|
112
|
+
* Converts XMachines route tree to RouteMap for use with router adapters.
|
|
113
|
+
*
|
|
114
|
+
* @param routeTree - Route tree from extractMachineRoutes()
|
|
115
|
+
* @returns RouteMap instance
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* import { extractMachineRoutes } from '@xmachines/play-router';
|
|
120
|
+
* import { createRouteMapFromTree } from '@xmachines/play-tanstack-react-router';
|
|
121
|
+
*
|
|
122
|
+
* const routeTree = extractMachineRoutes(machine);
|
|
123
|
+
* const routeMap = createRouteMapFromTree(routeTree);
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export function createRouteMapFromTree(routeTree) {
|
|
127
|
+
const routes = [];
|
|
128
|
+
function traverse(node) {
|
|
129
|
+
if (node.id && node.path) {
|
|
130
|
+
routes.push({ stateId: node.id, path: node.path });
|
|
131
|
+
}
|
|
132
|
+
if (node.children) {
|
|
133
|
+
node.children.forEach(traverse);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
traverse(routeTree.root);
|
|
137
|
+
return new RouteMap(routes);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=route-map.js.map
|