@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.
Files changed (203) hide show
  1. package/.oxfmtrc.json +3 -0
  2. package/.oxlintrc.json +3 -0
  3. package/README.md +177 -0
  4. package/dist/extract-params.d.ts +45 -0
  5. package/dist/extract-params.d.ts.map +1 -0
  6. package/dist/extract-params.js +70 -0
  7. package/dist/extract-params.js.map +1 -0
  8. package/dist/index.d.ts +18 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +17 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/play-router-provider.d.ts +33 -0
  13. package/dist/play-router-provider.d.ts.map +1 -0
  14. package/dist/play-router-provider.js +31 -0
  15. package/dist/play-router-provider.js.map +1 -0
  16. package/dist/route-map.d.ts +101 -0
  17. package/dist/route-map.d.ts.map +1 -0
  18. package/dist/route-map.js +139 -0
  19. package/dist/route-map.js.map +1 -0
  20. package/dist/tanstack-router-bridge.d.ts +115 -0
  21. package/dist/tanstack-router-bridge.d.ts.map +1 -0
  22. package/dist/tanstack-router-bridge.js +112 -0
  23. package/dist/tanstack-router-bridge.js.map +1 -0
  24. package/dist/types.d.ts +26 -0
  25. package/dist/types.d.ts.map +1 -0
  26. package/dist/types.js +7 -0
  27. package/dist/types.js.map +1 -0
  28. package/dist/utils.d.ts +9 -0
  29. package/dist/utils.d.ts.map +1 -0
  30. package/dist/utils.js +10 -0
  31. package/dist/utils.js.map +1 -0
  32. package/examples/demo/README.md +100 -0
  33. package/examples/demo/docs/ARCHITECTURE.md +643 -0
  34. package/examples/demo/docs/INVARIANTS.md +461 -0
  35. package/examples/demo/docs/SWAP-REACT.md +635 -0
  36. package/examples/demo/index.html +16 -0
  37. package/examples/demo/package.json +39 -0
  38. package/examples/demo/src/App.tsx +148 -0
  39. package/examples/demo/src/components/About.tsx +49 -0
  40. package/examples/demo/src/components/Contact.tsx +43 -0
  41. package/examples/demo/src/components/Dashboard.tsx +46 -0
  42. package/examples/demo/src/components/DebugPanel.tsx +68 -0
  43. package/examples/demo/src/components/HeaderNav.tsx +103 -0
  44. package/examples/demo/src/components/Home.tsx +41 -0
  45. package/examples/demo/src/components/Login.tsx +82 -0
  46. package/examples/demo/src/components/Navigation.tsx +262 -0
  47. package/examples/demo/src/components/Profile.tsx +46 -0
  48. package/examples/demo/src/components/Register.tsx +109 -0
  49. package/examples/demo/src/components/Settings.tsx +92 -0
  50. package/examples/demo/src/components/index.ts +16 -0
  51. package/examples/demo/src/main.tsx +20 -0
  52. package/examples/demo/test/actor-authority.test.ts +50 -0
  53. 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
  54. 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
  55. 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
  56. package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--After-authentication-flow-1.png +0 -0
  57. package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Multiple-rapid-navigations-1.png +0 -0
  58. package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Multiple-rapid-navigations-2.png +0 -0
  59. 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
  60. 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
  61. package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Works-correctly-1.png +0 -0
  62. package/examples/demo/test/browser/__screenshots__/back-forward-sync.browser.test.tsx/Back-Forward--Works-correctly-2.png +0 -0
  63. package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to--about-loads-about-page-1.png +0 -0
  64. package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to--contact-loads-contact-page-1.png +0 -0
  65. package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to--home-loads-home-page-1.png +0 -0
  66. package/examples/demo/test/browser/__screenshots__/direct-navigation.browser.test.ts/Direct-navigation-to-protected-route-while-authenticated-loads-dashboard-1.png +0 -0
  67. 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
  68. package/examples/demo/test/browser/__screenshots__/exact-user-scenario.browser.test.tsx/Debug--Print-history-after-each-navigation-1.png +0 -0
  69. package/examples/demo/test/browser/__screenshots__/exact-user-scenario.browser.test.tsx/Debug--Print-history-after-each-navigation-2.png +0 -0
  70. 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
  71. 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
  72. package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Actor-Authority---infrastructure-cannot-override-guards-1.png +0 -0
  73. package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Actor-Authority---infrastructure-cannot-override-guards-2.png +0 -0
  74. package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Guards-reject-invalid-navigation-1.png +0 -0
  75. package/examples/demo/test/browser/__screenshots__/guard-rejection.browser.test.tsx/E2E--Guards-reject-invalid-navigation-2.png +0 -0
  76. package/examples/demo/test/browser/__screenshots__/history-investigation.browser.test.tsx/baseHistory-back---navigation--avoiding-window-history--1.png +0 -0
  77. package/examples/demo/test/browser/__screenshots__/history-investigation.browser.test.tsx/baseHistory-back---navigation--avoiding-window-history--2.png +0 -0
  78. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---authenticated-user-1.png +0 -0
  79. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---authenticated-user-2.png +0 -0
  80. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---unauthenticated-user-1.png +0 -0
  81. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-forward-with-guard-transitions---unauthenticated-user-2.png +0 -0
  82. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-with-guard---authenticated-user-navigates-back-1.png +0 -0
  83. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Back-with-guard---authenticated-user-navigates-back-2.png +0 -0
  84. 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
  85. 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
  86. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back---unique-history-1.png +0 -0
  87. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back---unique-history-2.png +0 -0
  88. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back-1.png +0 -0
  89. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Forward-button-after-back-2.png +0 -0
  90. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Navigate-forward-then-back---unique-history-entries-1.png +0 -0
  91. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Navigate-forward-then-back---unique-history-entries-2.png +0 -0
  92. 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
  93. 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
  94. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---about-to-home-1.png +0 -0
  95. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---about-to-home-2.png +0 -0
  96. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---contact-to-about-1.png +0 -0
  97. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--Single-back-navigation---contact-to-about-2.png +0 -0
  98. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-forward-1.png +0 -0
  99. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-forward-2.png +0 -0
  100. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-navigation-1.png +0 -0
  101. package/examples/demo/test/browser/__screenshots__/history-navigation.browser.test.ts/GAP-12--View-syncs-with-URL-after-back-navigation-2.png +0 -0
  102. package/examples/demo/test/browser/__screenshots__/login-flow.browser.test.tsx/E2E--User-can-log-in-and-see-dashboard-1.png +0 -0
  103. package/examples/demo/test/browser/__screenshots__/login-flow.browser.test.tsx/E2E--User-can-log-in-and-see-dashboard-2.png +0 -0
  104. package/examples/demo/test/browser/__screenshots__/navigation.browser.test.tsx/E2E--Navigation-reflects-actor-state-transitions-1.png +0 -0
  105. package/examples/demo/test/browser/__screenshots__/navigation.browser.test.tsx/E2E--Navigation-reflects-actor-state-transitions-2.png +0 -0
  106. package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/Browser-back-forward-through-multiple-protected-routes-1.png +0 -0
  107. package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/Browser-back-forward-through-multiple-protected-routes-2.png +0 -0
  108. 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
  109. 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
  110. package/examples/demo/test/browser/__screenshots__/protected-route-navigation.browser.test.tsx/RED--Browser-back-forward-through-multiple-protected-routes-1.png +0 -0
  111. 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
  112. 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
  113. 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
  114. 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
  115. 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
  116. 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
  117. 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
  118. 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
  119. 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
  120. 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
  121. package/examples/demo/test/browser/__screenshots__/settings-query-freeze.browser.test.ts/Settings-with-query-parameters-works-correctly-1.png +0 -0
  122. package/examples/demo/test/browser/__screenshots__/settings-query-freeze.browser.test.ts/Settings-with-section-parameter-works-correctly-1.png +0 -0
  123. 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
  124. 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
  125. package/examples/demo/test/browser/__screenshots__/state-driven.browser.test.ts/DEMO-04b--Browser-navigation-with-SignalSyncedHistory-integration-1.png +0 -0
  126. package/examples/demo/test/browser/__screenshots__/state-driven.browser.test.ts/DEMO-04b--Browser-navigation-with-SignalSyncedHistory-integration-2.png +0 -0
  127. package/examples/demo/test/browser/__screenshots__/tanstack-integration.browser.test.tsx/TanStack-Router-Integration-renders-with-RouterProvider-context-1.png +0 -0
  128. package/examples/demo/test/browser/__screenshots__/tanstack-integration.browser.test.tsx/TanStack-Router-Integration-renders-with-RouterProvider-context-2.png +0 -0
  129. package/examples/demo/test/browser/__screenshots__/test-multiple-back.browser.test.tsx/Multiple-back--Navigate-forward-3x-then-back-3x-1.png +0 -0
  130. 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
  131. 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
  132. 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
  133. 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
  134. 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
  135. 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
  136. 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
  137. 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
  138. 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
  139. 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
  140. 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
  141. 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
  142. 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
  143. 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
  144. 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
  145. 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
  146. 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
  147. package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Direct-URL-navigation-sends-play-route-event-1.png +0 -0
  148. package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Direct-URL-navigation-sends-xstate-route-event-1.png +0 -0
  149. package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Forward-button-sends-play-route-event-1.png +0 -0
  150. package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Forward-button-sends-play-route-event-2.png +0 -0
  151. package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Forward-button-sends-xstate-route-event-1.png +0 -0
  152. 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
  153. 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
  154. package/examples/demo/test/browser/__screenshots__/xstate-route-events.browser.test.ts/Protected-route-sends-xstate-route-with-authentication-guard-1.png +0 -0
  155. package/examples/demo/test/browser/back-button-duplicate.browser.test.tsx +148 -0
  156. package/examples/demo/test/browser/back-forward-sync.browser.test.tsx +149 -0
  157. package/examples/demo/test/browser/direct-navigation.browser.test.ts +146 -0
  158. package/examples/demo/test/browser/exact-user-scenario.browser.test.tsx +207 -0
  159. package/examples/demo/test/browser/guard-rejection.browser.test.tsx +52 -0
  160. package/examples/demo/test/browser/history-investigation.browser.test.tsx +82 -0
  161. package/examples/demo/test/browser/history-navigation.browser.test.ts +351 -0
  162. package/examples/demo/test/browser/login-flow.browser.test.tsx +34 -0
  163. package/examples/demo/test/browser/navigation.browser.test.tsx +34 -0
  164. package/examples/demo/test/browser/protected-route-navigation.browser.test.tsx +161 -0
  165. package/examples/demo/test/browser/redirect-url-update.browser.test.tsx +140 -0
  166. package/examples/demo/test/browser/settings-parameter.browser.test.tsx +164 -0
  167. package/examples/demo/test/browser/settings-query-freeze.browser.test.ts +141 -0
  168. package/examples/demo/test/browser/state-driven.browser.test.ts +112 -0
  169. package/examples/demo/test/browser/tanstack-integration.browser.test.tsx +61 -0
  170. package/examples/demo/test/browser/uat-xstate-route-regression.browser.test.ts +58 -0
  171. package/examples/demo/test/browser/xstate-route-events.browser.test.ts +293 -0
  172. package/examples/demo/test/browser-back-view-rendering.test.ts +104 -0
  173. package/examples/demo/test/browser-e2e/auth-flow.browser.test.tsx +49 -0
  174. package/examples/demo/test/invalid-route-redirect.test.ts +40 -0
  175. package/examples/demo/test/passive-infra.test.ts +35 -0
  176. package/examples/demo/test/route-parameters.test.ts +539 -0
  177. package/examples/demo/test/signal-only.test.ts +54 -0
  178. package/examples/demo/test/strict-separation.test.ts +37 -0
  179. package/examples/demo/test/test-utils.ts +49 -0
  180. package/examples/demo/tsconfig.json +21 -0
  181. package/examples/demo/tsconfig.tsbuildinfo +1 -0
  182. package/examples/demo/vite.config.ts +13 -0
  183. package/examples/demo/vitest.browser.config.ts +72 -0
  184. package/examples/demo/vitest.config.e2e.browser.ts +28 -0
  185. package/examples/demo/vitest.config.ts +35 -0
  186. package/package.json +51 -0
  187. package/src/extract-params.ts +75 -0
  188. package/src/index.ts +31 -0
  189. package/src/play-router-provider.tsx +46 -0
  190. package/src/route-map.ts +158 -0
  191. package/src/tanstack-router-bridge.ts +135 -0
  192. package/src/types.ts +26 -0
  193. package/src/utils.ts +12 -0
  194. package/test/browser/__screenshots__/signal-synced-history.browser.test.ts/Browser-back-button-sends-route-navigate-event-to-actor-1.png +0 -0
  195. package/test/browser/__screenshots__/signal-synced-history.browser.test.ts/SignalSyncedHistory-prevents-circular-updates-1.png +0 -0
  196. package/test/browser/__screenshots__/signal-synced-history.browser.test.ts/SignalSyncedHistory-syncs-actor-route-to-browser-URL-1.png +0 -0
  197. package/test/browser/signal-synced-history.browser.test.ts +95 -0
  198. package/test/route-map.test.ts +107 -0
  199. package/test/tanstack-router-bridge.test.ts +318 -0
  200. package/test/urlpattern-integration.test.ts +145 -0
  201. package/tsconfig.json +16 -0
  202. package/tsconfig.tsbuildinfo +1 -0
  203. package/vitest.config.ts +35 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-map.js","sourceRoot":"","sources":["../src/route-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAcH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,QAAQ;IACZ,aAAa,CAAsB;IACnC,aAAa,CAAsB;IACnC,QAAQ,CAA4D;IAE5E;;;;OAIG;IACH,YAAY,MAAsB;QACjC,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QAEnB,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;YACxC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAEtC,+BAA+B;YAC/B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,sCAAsC;gBACtC,MAAM,OAAO,GAAG,IAAI;qBAClB,OAAO,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,sCAAsC;qBAC9E,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,kBAAkB;gBACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAClB,OAAO,EAAE,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,CAAC;oBACnC,OAAO;oBACP,IAAI;iBACJ,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,+BAA+B;gBAC/B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,IAAY;QAC5B,wBAAwB;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;QAElC,oBAAoB;QACpB,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO,OAAO,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,OAAe;QAC/B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IAChD,CAAC;CACD;AAED;;;;;;;;;;;;;;;;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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * TanStackReactRouterBridge - TanStack React Router adapter implementing RouterBridge protocol
3
+ *
4
+ * Provides bidirectional synchronization between XMachines actor state
5
+ * and TanStack React Router. Extends RouterBridgeBase which handles all
6
+ * common lifecycle, sync, and circular-update prevention logic.
7
+ *
8
+ * Only the 3 TanStack-specific methods need to be implemented:
9
+ * - navigateRouter: calls router.navigate({ to: path })
10
+ * - watchRouterChanges: subscribes to router.history for ALL navigation types
11
+ * - unwatchRouterChanges: calls the unsubscribe function
12
+ *
13
+ * Architectural Invariants:
14
+ * - INV-02 (Passive Infrastructure): Router reflects actor state, never decides
15
+ * - Actor validates all navigation via guards before URL changes
16
+ *
17
+ * @packageDocumentation
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { createRouter } from '@tanstack/react-router';
22
+ * import { definePlayer } from '@xmachines/play-xstate';
23
+ * import { TanStackReactRouterBridge, createRouteMapFromTree } from '@xmachines/play-tanstack-react-router';
24
+ *
25
+ * const router = createRouter({ routes });
26
+ * const actor = definePlayer({ machine, catalog })();
27
+ * const routeMap = createRouteMapFromTree(extractMachineRoutes(machine));
28
+ *
29
+ * const bridge = new TanStackReactRouterBridge(router, actor, routeMap);
30
+ * bridge.connect();
31
+ *
32
+ * // Cleanup on unmount
33
+ * return () => bridge.disconnect();
34
+ * ```
35
+ */
36
+ import { RouterBridgeBase } from "@xmachines/play-router";
37
+ import type { AbstractActor, Routable } from "@xmachines/play-actor";
38
+ import type { AnyActorLogic } from "xstate";
39
+ import type { RouteMap } from "./route-map.js";
40
+ export type TanStackRouterLike = {
41
+ navigate(args: {
42
+ to: string;
43
+ }): void;
44
+ state?: {
45
+ location?: {
46
+ pathname?: string;
47
+ };
48
+ };
49
+ history: {
50
+ subscribe(handler: (event: {
51
+ location: {
52
+ pathname: string;
53
+ search?: string;
54
+ };
55
+ }) => void): () => void;
56
+ };
57
+ };
58
+ /**
59
+ * TanStack React Router adapter implementing RouterBridge protocol via RouterBridgeBase
60
+ *
61
+ * @remarks
62
+ * Extends RouterBridgeBase to handle all common lifecycle and sync logic.
63
+ * Only 3 TanStack-specific methods are implemented here.
64
+ *
65
+ * Subscribes to router.history (not router.subscribe("onBeforeLoad")) so that
66
+ * back/forward browser navigation (popstate events) are also captured. The
67
+ * router.subscribe("onBeforeLoad") approach only works when TanStack's
68
+ * Transitioner component is mounted (i.e. inside a full <RouterProvider>).
69
+ * Since this bridge is used without <RouterProvider>, we must subscribe to
70
+ * the underlying history object directly — which is exactly what Transitioner
71
+ * does internally: `router.history.subscribe(router.load)`.
72
+ *
73
+ * Architectural Invariants:
74
+ * - INV-02 (Passive Infrastructure): Router reflects actor state, never decides
75
+ * - Actor validates all navigation via guards before URL changes
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const bridge = new TanStackReactRouterBridge(router, actor, routeMap);
80
+ * bridge.connect();
81
+ * return () => bridge.disconnect();
82
+ * ```
83
+ */
84
+ export declare class TanStackReactRouterBridge extends RouterBridgeBase {
85
+ private readonly router;
86
+ private routerUnsubscribe;
87
+ /**
88
+ * Create TanStack React Router bridge
89
+ *
90
+ * @param router - TanStack React Router instance
91
+ * @param actor - XMachines actor instance
92
+ * @param routeMap - Bidirectional mapping between state IDs and paths
93
+ */
94
+ constructor(router: TanStackRouterLike, actor: AbstractActor<AnyActorLogic> & Routable, routeMap: RouteMap);
95
+ protected navigateRouter(path: string): void;
96
+ /**
97
+ * Read the router's current pathname for initial sync.
98
+ *
99
+ * Called once in connect() to handle cold-load / deep-link scenarios where
100
+ * the URL differs from the actor's initial state.
101
+ */
102
+ protected getInitialRouterPath(): string | null;
103
+ /**
104
+ * Subscribe to ALL navigation events via router.history.
105
+ *
106
+ * router.history.subscribe fires for PUSH, POP, BACK, FORWARD, REPLACE, and GO —
107
+ * covering both link clicks and browser back/forward button presses.
108
+ *
109
+ * The subscriber callback receives { location, action } where location is the
110
+ * new history location with pathname and search already updated.
111
+ */
112
+ protected watchRouterChanges(): void;
113
+ protected unwatchRouterChanges(): void;
114
+ }
115
+ //# sourceMappingURL=tanstack-router-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack-router-bridge.d.ts","sourceRoot":"","sources":["../src/tanstack-router-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,MAAM,kBAAkB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC7C,OAAO,EAAE;QACR,SAAS,CACR,OAAO,EAAE,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE;gBAAE,QAAQ,EAAE,MAAM,CAAC;gBAAC,MAAM,CAAC,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,KAAK,IAAI,GAC3E,MAAM,IAAI,CAAC;KACd,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,yBAA0B,SAAQ,gBAAgB;IAW7D,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVxB,OAAO,CAAC,iBAAiB,CAA6B;IAEtD;;;;;;OAMG;gBAEe,MAAM,EAAE,kBAAkB,EAC3C,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,QAAQ,EAAE,QAAQ;IASnB,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5C;;;;;OAKG;cACgB,oBAAoB,IAAI,MAAM,GAAG,IAAI;IAIxD;;;;;;;;OAQG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAQpC,SAAS,CAAC,oBAAoB,IAAI,IAAI;CAItC"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * TanStackReactRouterBridge - TanStack React Router adapter implementing RouterBridge protocol
3
+ *
4
+ * Provides bidirectional synchronization between XMachines actor state
5
+ * and TanStack React Router. Extends RouterBridgeBase which handles all
6
+ * common lifecycle, sync, and circular-update prevention logic.
7
+ *
8
+ * Only the 3 TanStack-specific methods need to be implemented:
9
+ * - navigateRouter: calls router.navigate({ to: path })
10
+ * - watchRouterChanges: subscribes to router.history for ALL navigation types
11
+ * - unwatchRouterChanges: calls the unsubscribe function
12
+ *
13
+ * Architectural Invariants:
14
+ * - INV-02 (Passive Infrastructure): Router reflects actor state, never decides
15
+ * - Actor validates all navigation via guards before URL changes
16
+ *
17
+ * @packageDocumentation
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { createRouter } from '@tanstack/react-router';
22
+ * import { definePlayer } from '@xmachines/play-xstate';
23
+ * import { TanStackReactRouterBridge, createRouteMapFromTree } from '@xmachines/play-tanstack-react-router';
24
+ *
25
+ * const router = createRouter({ routes });
26
+ * const actor = definePlayer({ machine, catalog })();
27
+ * const routeMap = createRouteMapFromTree(extractMachineRoutes(machine));
28
+ *
29
+ * const bridge = new TanStackReactRouterBridge(router, actor, routeMap);
30
+ * bridge.connect();
31
+ *
32
+ * // Cleanup on unmount
33
+ * return () => bridge.disconnect();
34
+ * ```
35
+ */
36
+ import { RouterBridgeBase } from "@xmachines/play-router";
37
+ /**
38
+ * TanStack React Router adapter implementing RouterBridge protocol via RouterBridgeBase
39
+ *
40
+ * @remarks
41
+ * Extends RouterBridgeBase to handle all common lifecycle and sync logic.
42
+ * Only 3 TanStack-specific methods are implemented here.
43
+ *
44
+ * Subscribes to router.history (not router.subscribe("onBeforeLoad")) so that
45
+ * back/forward browser navigation (popstate events) are also captured. The
46
+ * router.subscribe("onBeforeLoad") approach only works when TanStack's
47
+ * Transitioner component is mounted (i.e. inside a full <RouterProvider>).
48
+ * Since this bridge is used without <RouterProvider>, we must subscribe to
49
+ * the underlying history object directly — which is exactly what Transitioner
50
+ * does internally: `router.history.subscribe(router.load)`.
51
+ *
52
+ * Architectural Invariants:
53
+ * - INV-02 (Passive Infrastructure): Router reflects actor state, never decides
54
+ * - Actor validates all navigation via guards before URL changes
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const bridge = new TanStackReactRouterBridge(router, actor, routeMap);
59
+ * bridge.connect();
60
+ * return () => bridge.disconnect();
61
+ * ```
62
+ */
63
+ export class TanStackReactRouterBridge extends RouterBridgeBase {
64
+ router;
65
+ routerUnsubscribe = null;
66
+ /**
67
+ * Create TanStack React Router bridge
68
+ *
69
+ * @param router - TanStack React Router instance
70
+ * @param actor - XMachines actor instance
71
+ * @param routeMap - Bidirectional mapping between state IDs and paths
72
+ */
73
+ constructor(router, actor, routeMap) {
74
+ // Adapt RouteMap's null returns to undefined for RouterBridgeBase compatibility
75
+ super(actor, {
76
+ getStateIdByPath: (path) => routeMap.getStateIdByPath(path) ?? undefined,
77
+ getPathByStateId: (id) => routeMap.getPathByStateId(id) ?? undefined,
78
+ });
79
+ this.router = router;
80
+ }
81
+ navigateRouter(path) {
82
+ this.router.navigate({ to: path });
83
+ }
84
+ /**
85
+ * Read the router's current pathname for initial sync.
86
+ *
87
+ * Called once in connect() to handle cold-load / deep-link scenarios where
88
+ * the URL differs from the actor's initial state.
89
+ */
90
+ getInitialRouterPath() {
91
+ return this.router.state?.location?.pathname ?? null;
92
+ }
93
+ /**
94
+ * Subscribe to ALL navigation events via router.history.
95
+ *
96
+ * router.history.subscribe fires for PUSH, POP, BACK, FORWARD, REPLACE, and GO —
97
+ * covering both link clicks and browser back/forward button presses.
98
+ *
99
+ * The subscriber callback receives { location, action } where location is the
100
+ * new history location with pathname and search already updated.
101
+ */
102
+ watchRouterChanges() {
103
+ this.routerUnsubscribe = this.router.history.subscribe(({ location }) => {
104
+ this.syncActorFromRouter(location.pathname, location.search ?? "");
105
+ });
106
+ }
107
+ unwatchRouterChanges() {
108
+ this.routerUnsubscribe?.();
109
+ this.routerUnsubscribe = null;
110
+ }
111
+ }
112
+ //# sourceMappingURL=tanstack-router-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack-router-bridge.js","sourceRoot":"","sources":["../src/tanstack-router-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAe1D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,OAAO,yBAA0B,SAAQ,gBAAgB;IAW5C;IAVV,iBAAiB,GAAwB,IAAI,CAAC;IAEtD;;;;;;OAMG;IACH,YACkB,MAA0B,EAC3C,KAA8C,EAC9C,QAAkB;QAElB,gFAAgF;QAChF,KAAK,CAAC,KAAK,EAAE;YACZ,gBAAgB,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,SAAS;YAChF,gBAAgB,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,SAAS;SAC5E,CAAC,CAAC;QARc,WAAM,GAAN,MAAM,CAAoB;IAS5C,CAAC;IAES,cAAc,CAAC,IAAY;QACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACgB,oBAAoB;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,CAAC;IACtD,CAAC;IAED;;;;;;;;OAQG;IACO,kBAAkB;QAC3B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CACrD,CAAC,EAAE,QAAQ,EAAuD,EAAE,EAAE;YACrE,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC,CACD,CAAC;IACH,CAAC;IAES,oBAAoB;QAC7B,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAC/B,CAAC;CACD"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Type definitions for TanStack Router integration with Play Architecture.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ /**
7
+ * Event sent to actor when browser navigates.
8
+ *
9
+ * Browser navigation (user clicks link, back/forward button, direct URL entry)
10
+ * sends this event to the actor. The actor's guards determine if navigation
11
+ * is allowed based on business logic.
12
+ *
13
+ * Invariant: Passive Infrastructure - Router suggests, actor decides validity.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * actor.send({ type: 'route.navigate', path: '/dashboard' });
18
+ * ```
19
+ */
20
+ export interface RouteNavigateEvent {
21
+ /** Event type discriminant (extends XState event pattern) */
22
+ readonly type: "route.navigate";
23
+ /** Target route path (may include parameters, e.g., /posts/123) */
24
+ readonly path: string;
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,kBAAkB;IAClC,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Type definitions for TanStack Router integration with Play Architecture.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Utility barrel exports
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { extractParams, extractQueryParams } from "./extract-params.js";
7
+ export { RouteMap, createRouteMapFromTree } from "./route-map.js";
8
+ export type { RouteMapping } from "./route-map.js";
9
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/utils.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Utility barrel exports
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ // Parameter extraction utilities
7
+ export { extractParams, extractQueryParams } from "./extract-params.js";
8
+ // RouteMap utilities
9
+ export { RouteMap, createRouteMapFromTree } from "./route-map.js";
10
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iCAAiC;AACjC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAExE,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,100 @@
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)