@xmachines/docs 1.0.0-beta.25 → 1.0.0-beta.27

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 (268) hide show
  1. package/api/@xmachines/play/classes/PlayError.md +10 -4
  2. package/api/@xmachines/play/type-aliases/PlayEvent.md +2 -2
  3. package/api/@xmachines/play-actor/README.md +4 -0
  4. package/api/@xmachines/play-actor/classes/AbstractActor.md +49 -92
  5. package/api/@xmachines/play-actor/functions/typedSpec.md +57 -0
  6. package/api/@xmachines/play-actor/interfaces/PlaySpec.md +9 -18
  7. package/api/@xmachines/play-actor/interfaces/Routable.md +5 -21
  8. package/api/@xmachines/play-actor/interfaces/ViewMetadata.md +6 -6
  9. package/api/@xmachines/play-actor/interfaces/Viewable.md +5 -6
  10. package/api/@xmachines/play-dom/README.md +24 -8
  11. package/api/@xmachines/play-dom/classes/PlayRenderer.md +4 -4
  12. package/api/@xmachines/play-dom/functions/connectRenderer.md +1 -1
  13. package/api/@xmachines/play-dom/functions/defineRegistry.md +61 -0
  14. package/api/@xmachines/play-dom/functions/renderSpec.md +29 -12
  15. package/api/@xmachines/play-dom/interfaces/ComponentContext.md +62 -0
  16. package/api/@xmachines/play-dom/interfaces/ConnectRendererOptions.md +9 -9
  17. package/api/@xmachines/play-dom/interfaces/DefineRegistryOptions.md +25 -0
  18. package/api/@xmachines/play-dom/interfaces/DefineRegistryResult.md +18 -0
  19. package/api/@xmachines/play-dom/interfaces/DomRenderContext.md +13 -10
  20. package/api/@xmachines/play-dom/interfaces/EventHandle.md +29 -0
  21. package/api/@xmachines/play-dom/interfaces/PlayDomOptions.md +5 -5
  22. package/api/@xmachines/play-dom/type-aliases/ComponentFn.md +53 -0
  23. package/api/@xmachines/play-dom/type-aliases/ComponentRegistry.md +21 -0
  24. package/api/@xmachines/play-dom/type-aliases/DomComponentRenderer.md +16 -3
  25. package/api/@xmachines/play-dom/type-aliases/DomRegistry.md +5 -2
  26. package/api/@xmachines/play-dom-router/README.md +10 -0
  27. package/api/@xmachines/play-dom-router/functions/connectRouter.md +18 -46
  28. package/api/@xmachines/play-dom-router/functions/createBrowserHistory.md +1 -1
  29. package/api/@xmachines/play-dom-router/functions/createRouteMap.md +38 -0
  30. package/api/@xmachines/play-dom-router/functions/createRouter.md +1 -1
  31. package/api/@xmachines/play-dom-router/interfaces/BrowserHistory.md +16 -16
  32. package/api/@xmachines/play-dom-router/interfaces/BrowserWindow.md +16 -16
  33. package/api/@xmachines/play-dom-router/interfaces/ConnectRouterOptions.md +6 -6
  34. package/api/@xmachines/play-dom-router/interfaces/PlayRouteEvent.md +119 -0
  35. package/api/@xmachines/play-dom-router/interfaces/RouteMap.md +114 -0
  36. package/api/@xmachines/play-dom-router/interfaces/RouteMapLike.md +50 -0
  37. package/api/@xmachines/play-dom-router/interfaces/RouteMapping.md +27 -0
  38. package/api/@xmachines/play-dom-router/interfaces/RouterBridge.md +104 -0
  39. package/api/@xmachines/play-dom-router/interfaces/VanillaRouter.md +6 -6
  40. package/api/@xmachines/play-dom-router/type-aliases/RoutableActor.md +9 -0
  41. package/api/@xmachines/play-dom-router-demo/README.md +46 -51
  42. package/api/@xmachines/play-react/README.md +4 -4
  43. package/api/@xmachines/play-react/classes/PlayErrorBoundary.md +31 -5
  44. package/api/@xmachines/play-react/functions/defineRegistry.md +2 -0
  45. package/api/@xmachines/play-react/functions/useActor.md +1 -1
  46. package/api/@xmachines/play-react/functions/useBoundProp.md +2 -0
  47. package/api/@xmachines/play-react/functions/useSignalEffect.md +1 -1
  48. package/api/@xmachines/play-react/functions/useStateBinding.md +2 -0
  49. package/api/@xmachines/play-react/interfaces/ComponentContext.md +2 -0
  50. package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +4 -4
  51. package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +3 -3
  52. package/api/@xmachines/play-react/interfaces/PlayRendererProps.md +7 -7
  53. package/api/@xmachines/play-react/type-aliases/ComponentFn.md +2 -0
  54. package/api/@xmachines/play-react/type-aliases/PlayActor.md +1 -1
  55. package/api/@xmachines/play-react/variables/PlayRenderer.md +1 -1
  56. package/api/@xmachines/play-react-router/README.md +5 -1
  57. package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +102 -25
  58. package/api/@xmachines/play-react-router/classes/RouteMap.md +17 -33
  59. package/api/@xmachines/play-react-router/functions/PlayRouterProvider.md +8 -1
  60. package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +21 -11
  61. package/api/@xmachines/play-react-router/interfaces/PlayRouteEvent.md +8 -8
  62. package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +7 -7
  63. package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +18 -8
  64. package/api/@xmachines/play-react-router/interfaces/RouterBridge.md +3 -3
  65. package/api/@xmachines/play-router/README.md +42 -5
  66. package/api/@xmachines/play-router/classes/BaseRouteMap.md +12 -19
  67. package/api/@xmachines/play-router/classes/RouterBridgeBase.md +100 -25
  68. package/api/@xmachines/play-router/functions/buildPlayRouteEvent.md +1 -1
  69. package/api/@xmachines/play-router/functions/buildRouteTree.md +1 -1
  70. package/api/@xmachines/play-router/functions/createRouteMap.md +1 -1
  71. package/api/@xmachines/play-router/functions/createRouteMapFromMachine.md +38 -0
  72. package/api/@xmachines/play-router/functions/createRouteMapFromTree.md +45 -0
  73. package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +1 -1
  74. package/api/@xmachines/play-router/functions/extractMachineRoutes.md +1 -1
  75. package/api/@xmachines/play-router/functions/extractQuery.md +1 -1
  76. package/api/@xmachines/play-router/functions/extractRouteParams.md +46 -0
  77. package/api/@xmachines/play-router/functions/findRouteById.md +1 -1
  78. package/api/@xmachines/play-router/functions/findRouteByPath.md +1 -1
  79. package/api/@xmachines/play-router/functions/getNavigableRoutes.md +1 -1
  80. package/api/@xmachines/play-router/functions/getRoutableRoutes.md +1 -1
  81. package/api/@xmachines/play-router/functions/getTransitionReachableRoutes.md +1 -1
  82. package/api/@xmachines/play-router/functions/isRouteReachable.md +1 -1
  83. package/api/@xmachines/play-router/functions/machineToGraph.md +1 -1
  84. package/api/@xmachines/play-router/functions/routeExists.md +1 -1
  85. package/api/@xmachines/play-router/functions/sanitizePathname.md +1 -1
  86. package/api/@xmachines/play-router/functions/validateRouteFormat.md +1 -1
  87. package/api/@xmachines/play-router/functions/validateStateExists.md +1 -1
  88. package/api/@xmachines/play-router/interfaces/BuildPlayRouteEventOptions.md +4 -4
  89. package/api/@xmachines/play-router/interfaces/LocationLike.md +27 -0
  90. package/api/@xmachines/play-router/interfaces/MachineEdgeData.md +3 -3
  91. package/api/@xmachines/play-router/interfaces/MachineNodeData.md +5 -5
  92. package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +8 -8
  93. package/api/@xmachines/play-router/interfaces/RouteInfo.md +8 -8
  94. package/api/@xmachines/play-router/interfaces/RouteMap.md +4 -4
  95. package/api/@xmachines/play-router/interfaces/{BaseRouteMapping.md → RouteMapping.md} +5 -5
  96. package/api/@xmachines/play-router/interfaces/RouteMatch.md +5 -5
  97. package/api/@xmachines/play-router/interfaces/RouteNode.md +12 -12
  98. package/api/@xmachines/play-router/interfaces/RouteObject.md +2 -2
  99. package/api/@xmachines/play-router/interfaces/RouteTree.md +5 -5
  100. package/api/@xmachines/play-router/interfaces/RouteWatcherHandle.md +3 -3
  101. package/api/@xmachines/play-router/interfaces/RouterBridge.md +3 -3
  102. package/api/@xmachines/play-router/interfaces/WindowLike.md +65 -0
  103. package/api/@xmachines/play-router/type-aliases/MachineGraph.md +1 -1
  104. package/api/@xmachines/play-router/type-aliases/RouteMetadata.md +1 -1
  105. package/api/@xmachines/play-signals/functions/watchSignal.md +1 -1
  106. package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +2 -2
  107. package/api/@xmachines/play-signals/interfaces/SignalComputed.md +2 -2
  108. package/api/@xmachines/play-signals/interfaces/SignalOptions.md +2 -2
  109. package/api/@xmachines/play-signals/interfaces/SignalState.md +3 -3
  110. package/api/@xmachines/play-signals/interfaces/SignalWatcher.md +4 -4
  111. package/api/@xmachines/play-signals/namespaces/Signal/classes/Computed.md +6 -0
  112. package/api/@xmachines/play-signals/namespaces/Signal/classes/State.md +8 -0
  113. package/api/@xmachines/play-signals/namespaces/Signal/interfaces/Options.md +2 -0
  114. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/classes/Watcher.md +10 -0
  115. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/currentComputed.md +2 -0
  116. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/hasSinks.md +2 -0
  117. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/hasSources.md +2 -0
  118. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/introspectSinks.md +2 -0
  119. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/introspectSources.md +2 -0
  120. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/functions/untrack.md +2 -0
  121. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/variables/unwatched.md +2 -0
  122. package/api/@xmachines/play-signals/namespaces/Signal/namespaces/subtle/variables/watched.md +2 -0
  123. package/api/@xmachines/play-signals/namespaces/Signal/variables/isComputed.md +2 -0
  124. package/api/@xmachines/play-signals/namespaces/Signal/variables/isState.md +2 -0
  125. package/api/@xmachines/play-signals/namespaces/Signal/variables/isWatcher.md +2 -0
  126. package/api/@xmachines/play-signals/type-aliases/WatcherNotify.md +1 -1
  127. package/api/@xmachines/play-solid/README.md +4 -4
  128. package/api/@xmachines/play-solid/functions/defineRegistry.md +2 -0
  129. package/api/@xmachines/play-solid/functions/useActor.md +1 -1
  130. package/api/@xmachines/play-solid/functions/useStateBinding.md +2 -0
  131. package/api/@xmachines/play-solid/interfaces/ComponentContext.md +2 -0
  132. package/api/@xmachines/play-solid/interfaces/PlayRendererProps.md +7 -7
  133. package/api/@xmachines/play-solid/type-aliases/ComponentFn.md +2 -0
  134. package/api/@xmachines/play-solid/type-aliases/PlayActor.md +1 -1
  135. package/api/@xmachines/play-solid/variables/PlayRenderer.md +1 -1
  136. package/api/@xmachines/play-solid-router/README.md +2 -2
  137. package/api/@xmachines/play-solid-router/classes/RouteMap.md +13 -26
  138. package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +121 -46
  139. package/api/@xmachines/play-solid-router/functions/PlayRouterProvider.md +1 -1
  140. package/api/@xmachines/play-solid-router/functions/createRouteMap.md +15 -9
  141. package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +47 -92
  142. package/api/@xmachines/play-solid-router/interfaces/PlayRouteEvent.md +8 -8
  143. package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +5 -5
  144. package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +19 -6
  145. package/api/@xmachines/play-solid-router/interfaces/RouterBridge.md +3 -3
  146. package/api/@xmachines/play-solid-router/type-aliases/RoutableActor.md +1 -1
  147. package/api/@xmachines/play-solid-router/type-aliases/SolidRouterHooks.md +21 -18
  148. package/api/@xmachines/play-solid-router-demo/README.md +25 -28
  149. package/api/@xmachines/play-svelte/README.md +28 -0
  150. package/api/@xmachines/play-svelte/functions/defineRegistry.md +2 -0
  151. package/api/@xmachines/play-svelte/interfaces/BaseComponentProps.md +2 -0
  152. package/api/@xmachines/play-svelte/interfaces/ComponentContext.md +2 -0
  153. package/api/@xmachines/play-svelte/interfaces/PlayRendererProps.md +9 -9
  154. package/api/@xmachines/play-svelte/type-aliases/ComponentFn.md +2 -0
  155. package/api/@xmachines/play-svelte/type-aliases/PlayRenderer.md +2 -0
  156. package/api/@xmachines/play-svelte/variables/PlayRenderer.md +2 -0
  157. package/api/@xmachines/play-svelte-spa-router/README.md +1 -0
  158. package/api/@xmachines/play-svelte-spa-router/classes/RouteMap.md +13 -26
  159. package/api/@xmachines/play-svelte-spa-router/functions/connectRouter.md +14 -1
  160. package/api/@xmachines/play-svelte-spa-router/functions/createRouteMap.md +23 -4
  161. package/api/@xmachines/play-svelte-spa-router/interfaces/ConnectRouterOptions.md +6 -5
  162. package/api/@xmachines/play-svelte-spa-router/interfaces/PlayRouteEvent.md +10 -10
  163. package/api/@xmachines/play-svelte-spa-router/interfaces/RouteMapping.md +20 -5
  164. package/api/@xmachines/play-svelte-spa-router/interfaces/RouterBridge.md +3 -3
  165. package/api/@xmachines/play-svelte-spa-router/interfaces/WindowLike.md +65 -0
  166. package/api/@xmachines/play-svelte-spa-router/type-aliases/RoutableActor.md +1 -1
  167. package/api/@xmachines/play-svelte-spa-router-demo/README.md +119 -12
  168. package/api/@xmachines/play-sveltekit-router/README.md +2 -1
  169. package/api/@xmachines/play-sveltekit-router/classes/RouteMap.md +46 -24
  170. package/api/@xmachines/play-sveltekit-router/functions/connectRouter.md +14 -1
  171. package/api/@xmachines/play-sveltekit-router/functions/createRouteMap.md +23 -4
  172. package/api/@xmachines/play-sveltekit-router/interfaces/ConnectRouterOptions.md +6 -5
  173. package/api/@xmachines/play-sveltekit-router/interfaces/LocationLike.md +27 -0
  174. package/api/@xmachines/play-sveltekit-router/interfaces/PlayRouteEvent.md +10 -10
  175. package/api/@xmachines/play-sveltekit-router/interfaces/RouteMapping.md +20 -5
  176. package/api/@xmachines/play-sveltekit-router/interfaces/RouterBridge.md +3 -3
  177. package/api/@xmachines/play-sveltekit-router/type-aliases/RoutableActor.md +1 -1
  178. package/api/@xmachines/play-sveltekit-router-demo/README.md +120 -12
  179. package/api/@xmachines/play-tanstack-react-router/README.md +5 -3
  180. package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +17 -33
  181. package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +93 -25
  182. package/api/@xmachines/play-tanstack-react-router/functions/PlayRouterProvider.md +1 -1
  183. package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +1 -1
  184. package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +21 -11
  185. package/api/@xmachines/play-tanstack-react-router/functions/extractMachineRoutes.md +1 -1
  186. package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouteEvent.md +8 -8
  187. package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +5 -5
  188. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +18 -8
  189. package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +3 -3
  190. package/api/@xmachines/play-tanstack-react-router/interfaces/RouterBridge.md +3 -3
  191. package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterInstance.md +1 -1
  192. package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterLike.md +13 -19
  193. package/api/@xmachines/play-tanstack-react-router-demo/README.md +23 -29
  194. package/api/@xmachines/play-tanstack-solid-router/README.md +8 -8
  195. package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +13 -26
  196. package/api/@xmachines/play-tanstack-solid-router/classes/SolidRouterBridge.md +101 -36
  197. package/api/@xmachines/play-tanstack-solid-router/functions/PlayRouterProvider.md +1 -1
  198. package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +15 -9
  199. package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouteEvent.md +8 -8
  200. package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +5 -5
  201. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +13 -9
  202. package/api/@xmachines/play-tanstack-solid-router/interfaces/RouterBridge.md +3 -3
  203. package/api/@xmachines/play-tanstack-solid-router/type-aliases/RoutableActor.md +1 -1
  204. package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterInstance.md +1 -1
  205. package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterLike.md +23 -24
  206. package/api/@xmachines/play-tanstack-solid-router-demo/README.md +25 -26
  207. package/api/@xmachines/play-vue/README.md +4 -4
  208. package/api/@xmachines/play-vue/functions/defineRegistry.md +1 -1
  209. package/api/@xmachines/play-vue/functions/useActor.md +1 -1
  210. package/api/@xmachines/play-vue/functions/useStateBinding.md +2 -0
  211. package/api/@xmachines/play-vue/interfaces/ComponentContext.md +2 -0
  212. package/api/@xmachines/play-vue/interfaces/PlayRendererProps.md +5 -5
  213. package/api/@xmachines/play-vue/type-aliases/ComponentEntry.md +1 -1
  214. package/api/@xmachines/play-vue/type-aliases/ComponentFn.md +2 -0
  215. package/api/@xmachines/play-vue/type-aliases/ComponentsMap.md +1 -1
  216. package/api/@xmachines/play-vue/type-aliases/DefineRegistryOptions.md +4 -3
  217. package/api/@xmachines/play-vue/type-aliases/PlayActor.md +1 -1
  218. package/api/@xmachines/play-vue/variables/PlayRenderer.md +1 -1
  219. package/api/@xmachines/play-vue-router/README.md +2 -2
  220. package/api/@xmachines/play-vue-router/classes/RouteMap.md +18 -108
  221. package/api/@xmachines/play-vue-router/classes/VueBaseRouteMap.md +44 -104
  222. package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +127 -62
  223. package/api/@xmachines/play-vue-router/functions/createRouteMap.md +1 -1
  224. package/api/@xmachines/play-vue-router/interfaces/PlayRouteEvent.md +8 -8
  225. package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +19 -7
  226. package/api/@xmachines/play-vue-router/interfaces/RouterBridge.md +3 -3
  227. package/api/@xmachines/play-vue-router/type-aliases/RoutableActor.md +1 -1
  228. package/api/@xmachines/play-vue-router/variables/PlayRouterProvider.md +1 -1
  229. package/api/@xmachines/play-vue-router-demo/README.md +47 -40
  230. package/api/@xmachines/play-xstate/README.md +15 -15
  231. package/api/@xmachines/play-xstate/classes/PlayerActor.md +46 -30
  232. package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +20 -15
  233. package/api/@xmachines/play-xstate/functions/composeGuards.md +1 -1
  234. package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +1 -1
  235. package/api/@xmachines/play-xstate/functions/contextFieldMatches.md +1 -1
  236. package/api/@xmachines/play-xstate/functions/definePlayer.md +1 -1
  237. package/api/@xmachines/play-xstate/functions/deriveRoute.md +1 -1
  238. package/api/@xmachines/play-xstate/functions/eventMatches.md +1 -1
  239. package/api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md +2 -2
  240. package/api/@xmachines/play-xstate/functions/hasContext.md +1 -1
  241. package/api/@xmachines/play-xstate/functions/isAbsoluteRoute.md +1 -1
  242. package/api/@xmachines/play-xstate/functions/negateGuard.md +1 -1
  243. package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +3 -3
  244. package/api/@xmachines/play-xstate/interfaces/PlayerFactoryResumeOptions.md +2 -2
  245. package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +6 -6
  246. package/api/@xmachines/play-xstate/interfaces/RouteContext.md +14 -12
  247. package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +1 -1
  248. package/api/@xmachines/play-xstate/type-aliases/Guard.md +1 -1
  249. package/api/@xmachines/play-xstate/type-aliases/GuardArray.md +1 -1
  250. package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +1 -1
  251. package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +4 -4
  252. package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +4 -4
  253. package/api/@xmachines/shared/functions/defineXmVitestConfig.md +3 -7
  254. package/api/@xmachines/shared/functions/xmAliases.md +1 -1
  255. package/api/README.md +4 -4
  256. package/api/llms.txt +3 -3
  257. package/examples/README.md +50 -32
  258. package/examples/basic-state-machine.md +75 -31
  259. package/examples/form-validation.md +199 -127
  260. package/examples/multi-router-integration.md +312 -230
  261. package/examples/routing-patterns.md +243 -187
  262. package/examples/traffic-light.md +114 -65
  263. package/guides/README.md +29 -15
  264. package/guides/getting-started.md +224 -144
  265. package/guides/installation.md +153 -213
  266. package/package.json +2 -2
  267. package/api/@xmachines/play-tanstack-react-router/functions/extractParams.md +0 -38
  268. package/api/@xmachines/play-tanstack-react-router/functions/extractQueryParams.md +0 -33
@@ -1,259 +1,315 @@
1
- # Routing Patterns - Play Architecture
1
+ <!-- generated-by: gsd-doc-writer -->
2
2
 
3
- Learn how to implement parameter-aware navigation using routing patterns with `meta.route` URL patterns and `play.route` events.
3
+ # Routing Patterns
4
+
5
+ How the `authMachine` uses `meta.route`, `play.route` events, `formatPlayRouteTransitions`, and `always` guards to implement actor-authoritative URL routing.
4
6
 
5
7
  ## Overview
6
8
 
7
- introduces enhanced routing capabilities that allow state machines to handle dynamic routes with parameters while maintaining Actor Authority (INV-01). The router observes actor state changes and syncs the browser URL, but the actor decides which routes are valid through guards.
9
+ XMachines inverts the usual routing model. The **actor** owns navigation its guards decide which states are valid. The **router** is passive infrastructure that observes `actor.currentRoute` and keeps the browser URL in sync. This is **Actor Authority (INV-01)**.
10
+
11
+ Every routing interaction starts with a `play.route` event sent to the actor. If the machine's guards allow the transition, the state changes and `actor.currentRoute` updates. The router bridge sees the new signal value and pushes a history entry. The URL never changes unless the actor approves.
8
12
 
9
13
  ## Key Concepts
10
14
 
11
- ### Route Marker
15
+ ### `meta.route` — Marking States as Routable
12
16
 
13
- States with `meta.route` property are routable - they can receive `play.route` events and be navigated to by URL. States without `meta.route` are internal machine states that don't correspond to URLs.
17
+ Add a `meta.route` URL template to any state to make it routable:
14
18
 
15
19
  ```typescript
16
20
  states: {
21
+ home: {
22
+ id: "home", // required: used as the play.route target ("#home")
23
+ meta: {
24
+ route: "/", // absolute URL path
25
+ },
26
+ },
17
27
  dashboard: {
28
+ id: "dashboard",
29
+ meta: {
30
+ route: "/dashboard", // absolute URL path
31
+ },
32
+ states: {
33
+ overview: {
34
+ id: "dashboard-overview",
35
+ meta: {
36
+ route: "overview", // RELATIVE — resolves to /dashboard/overview
37
+ },
38
+ },
39
+ },
40
+ },
41
+ profile: {
42
+ id: "profile",
43
+ meta: {
44
+ route: "/profile/:username", // required parameter
45
+ },
46
+ },
47
+ settings: {
48
+ id: "settings",
18
49
  meta: {
19
- route: '/dashboard', // Marks state as routable
20
- view: { component: 'Dashboard' }
21
- }
22
- }
50
+ route: "/settings/:section?", // optional parameter
51
+ },
52
+ },
23
53
  }
24
54
  ```
25
55
 
26
- ### Play.route Events with Parameters
27
-
28
- Use `play.route` events to navigate with parameters. Unlike `xstate.route` (which doesn't support parameters), `play.route` allows passing data alongside navigation:
29
-
30
- ```typescript
31
- // Navigate to profile with userId parameter
32
- actor.send({
33
- type: "play.route",
34
- to: "/profile/user123",
35
- params: { userId: "user123" },
36
- });
37
- ```
38
-
39
- ### Parameter Patterns in meta.route
40
-
41
- Define URL patterns with `:param` syntax for required parameters and `:param?` for optional ones:
42
-
43
- ```typescript
44
- meta: {
45
- route: '/profile/:userId', // Required parameter
46
- route: '/settings/:section?', // Optional parameter
47
- }
48
- ```
56
+ **Rules:**
49
57
 
50
- ## Complete Example
58
+ - Absolute paths start with `/`.
59
+ - Relative paths (no leading `/`) are resolved against the parent state's route.
60
+ - Parameter segments use `:param` (required) and `:param?` (optional).
61
+ - Every routable state **must** have an `id` — `formatPlayRouteTransitions` throws `MissingStateIdError` otherwise.
51
62
 
52
- For runnable implementations of these routing patterns, see the [Examples Index](./README.md).
63
+ ### `formatPlayRouteTransitions` Auto-Generating Route Handlers
53
64
 
54
- ### Machine Configuration
65
+ Instead of hand-writing `play.route` event handlers for every routable state, wrap your machine config with `formatPlayRouteTransitions`:
55
66
 
56
67
  ```typescript
57
68
  import { setup } from "xstate";
58
- import { definePlayer } from "@xmachines/play-xstate";
69
+ import { definePlayer, formatPlayRouteTransitions } from "@xmachines/play-xstate";
70
+ import type { PlayRouteEvent } from "@xmachines/play-router";
71
+
72
+ interface AuthContext {
73
+ isAuthenticated: boolean;
74
+ username: string | null;
75
+ params: Record<string, string>; // required for formatPlayRouteTransitions
76
+ query: Record<string, string>; // required for formatPlayRouteTransitions
77
+ }
59
78
 
60
- const authMachine = setup({
79
+ const authSetup = setup({
61
80
  types: {
62
- context: {} as {
63
- isAuthenticated: boolean;
64
- userId: string;
65
- routeParams: Record<string, string>;
66
- },
81
+ context: {} as AuthContext,
67
82
  events: {} as
68
- | { type: "play.route"; to: string; params?: Record<string, string> }
69
- | { type: "auth.login"; userId: string },
70
- },
71
- }).createMachine({
72
- initial: "login",
73
- context: {
74
- isAuthenticated: false,
75
- userId: "",
76
- routeParams: {},
77
- },
78
- states: {
79
- login: {
80
- id: "login",
81
- meta: {
82
- route: "/login",
83
- view: { component: "LoginView" },
84
- },
85
- on: {
86
- "auth.login": {
87
- target: "profile",
88
- actions: ({ context, event }) => {
89
- context.isAuthenticated = true;
90
- context.userId = event.userId;
91
- },
92
- },
93
- },
94
- },
95
-
96
- profile: {
97
- id: "profile",
98
- meta: {
99
- route: "/profile/:userId",
100
- view: {
101
- component: "ProfileView",
102
- userId: (ctx) => ctx.routeParams.userId || ctx.userId,
103
- },
104
- },
105
- always: [
106
- {
107
- target: "login",
108
- guard: ({ context }) => !context.isAuthenticated,
109
- // Redirect to login if not authenticated
110
- },
111
- ],
112
- on: {
113
- "play.route": {
114
- actions: ({ context, event }) => {
115
- if (event.params?.userId) {
116
- context.routeParams = { userId: event.params.userId };
117
- }
118
- },
119
- },
120
- },
121
- },
83
+ | PlayRouteEvent
84
+ | { type: "auth.login"; username: string }
85
+ | { type: "auth.logout" },
86
+ input: {} as Partial<AuthContext> | undefined,
122
87
  },
123
88
  });
124
89
 
125
- const createPlayer = definePlayer({ machine: authMachine });
90
+ const authMachine = authSetup.createMachine(
91
+ formatPlayRouteTransitions({
92
+ id: "auth",
93
+ initial: "home",
94
+ context: ({ input }) => ({
95
+ isAuthenticated: input?.isAuthenticated ?? false,
96
+ username: input?.username ?? null,
97
+ params: input?.params ?? {},
98
+ query: input?.query ?? {},
99
+ }),
100
+ states: {
101
+ home: { id: "home", meta: { route: "/" } },
102
+ about: { id: "about", meta: { route: "/about" } },
103
+ login: { id: "login", meta: { route: "/login" } },
104
+ profile: { id: "profile", meta: { route: "/profile/:username" } },
105
+ },
106
+ }),
107
+ );
126
108
  ```
127
109
 
128
- ### Using the Actor
110
+ `formatPlayRouteTransitions` generates root-level handlers equivalent to:
129
111
 
130
112
  ```typescript
131
- // Create and start actor
132
- const actor = createPlayer();
133
- actor.start();
113
+ on: {
114
+ "play.route": [
115
+ { target: ".home", guard: ({ event }) => event.to === "#home", reenter: true, actions: assign({ params, query }) },
116
+ { target: ".about", guard: ({ event }) => event.to === "#about", reenter: true, actions: assign({ params, query }) },
117
+ { target: ".login", guard: ({ event }) => event.to === "#login", reenter: true, actions: assign({ params, query }) },
118
+ { target: ".profile", guard: ({ event }) => event.to === "#profile", reenter: true, actions: assign({ params, query }) },
119
+ ],
120
+ }
121
+ ```
122
+
123
+ ### `play.route` Events — Navigation
134
124
 
135
- // Login (transitions to profile)
136
- actor.send({ type: "auth.login", userId: "user123" });
125
+ To navigate, send a `play.route` event with `to: "#stateId"`:
126
+
127
+ ```typescript
128
+ // Navigate to home
129
+ actor.send({ type: "play.route", to: "#home" });
137
130
 
138
- // Navigate to different profile with parameters
131
+ // Navigate to profile params are stored in context and used to resolve the URL
139
132
  actor.send({
140
133
  type: "play.route",
141
- to: "/profile/user456",
142
- params: { userId: "user456" },
134
+ to: "#profile",
135
+ params: { username: "alice" },
143
136
  });
144
137
 
145
- // Parameter extracted and available in view
146
- const view = actor.currentView.get();
147
- console.log(view.userId); // 'user456'
138
+ // actor.currentRoute.get() "/profile/alice"
139
+
140
+ // Navigate with query string
141
+ actor.send({
142
+ type: "play.route",
143
+ to: "#settings",
144
+ params: { section: "privacy" },
145
+ query: { tab: "advanced" },
146
+ });
148
147
  ```
149
148
 
150
- ## Pattern Matching for Dynamic Routes
149
+ **`to` always uses `"#stateId"` format** — the state's `id` field prefixed with `#`. Do not pass URL paths here.
151
150
 
152
- Routes with parameters use pattern matching to resolve URL paths:
151
+ ### `always` Guards Protected Routes
153
152
 
154
- - `/profile/:userId` matches `/profile/user123`, `/profile/alice`, etc.
155
- - `/settings/:section?` matches `/settings` (no section) or `/settings/privacy`
153
+ Use XState `always` transitions to protect states. If the guard fires, the machine redirects _before_ the state is fully entered:
156
154
 
157
- The router extracts parameters from the URL and passes them in `play.route` events, which the machine stores in context for view projection.
155
+ ```typescript
156
+ dashboard: {
157
+ id: "dashboard",
158
+ meta: { route: "/dashboard" },
159
+ always: {
160
+ // If not authenticated, redirect to login immediately
161
+ guard: ({ context }) => !context.isAuthenticated,
162
+ target: "login",
163
+ },
164
+ },
165
+ profile: {
166
+ id: "profile",
167
+ meta: { route: "/profile/:username" },
168
+ always: {
169
+ guard: ({ context }) => !context.isAuthenticated,
170
+ target: "login",
171
+ },
172
+ },
173
+ ```
158
174
 
159
- ## Guard Placement Architecture
175
+ **Why `always` and not event guards?** Guards on events check "can I TAKE this transition?". `always` guards check "can I BE in this state?" — the correct invariant for authentication. The actor enforces the guard even on direct URL access (browser back/forward or deep link), because the router sends a `play.route` event which triggers the `always` guard.
160
176
 
161
- **Core Principle:** Guards check if you can BE in a state (state entry), not if you can TAKE an event (event handlers).
177
+ ### Root-Level Event Handlers
162
178
 
163
- ### Pattern 1: Using formatPlayRouteTransitions (RECOMMENDED)
179
+ Domain events placed at the root `on:` level are handled from any state:
164
180
 
165
181
  ```typescript
166
- import { formatPlayRouteTransitions } from "@xmachines/play-xstate";
167
-
168
- const machineConfig = {
169
- initial: "home",
170
- context: { isAuthenticated: false },
171
- states: {
172
- home: { id: "home", meta: { route: "/" } },
173
- profile: {
174
- id: "profile",
175
- meta: { route: "/profile/:userId" },
176
- // Always-guard validates state entry
177
- always: [
178
- {
179
- target: "login",
180
- guard: ({ context }) => !context.isAuthenticated,
181
- },
182
- ],
182
+ const authMachine = authSetup.createMachine(
183
+ formatPlayRouteTransitions({
184
+ // ...
185
+ on: {
186
+ "auth.login": {
187
+ target: ".dashboard",
188
+ guard: ({ context }) => !context.isAuthenticated,
189
+ actions: authSetup.assign({
190
+ isAuthenticated: true,
191
+ username: ({ event }) => (event.type === "auth.login" ? event.username : null),
192
+ }),
193
+ },
194
+ "auth.logout": {
195
+ target: ".home",
196
+ guard: ({ context }) => context.isAuthenticated,
197
+ actions: authSetup.assign({
198
+ isAuthenticated: false,
199
+ username: null,
200
+ }),
201
+ },
183
202
  },
184
- },
185
- };
186
-
187
- // Utility handles routing infrastructure
188
- const machine = createMachine(formatPlayRouteTransitions(machineConfig));
203
+ states: {
204
+ /* ... */
205
+ },
206
+ }),
207
+ );
189
208
  ```
190
209
 
191
- **Why this works:**
210
+ ## Complete Actor Usage
211
+
212
+ ```typescript
213
+ const createPlayer = definePlayer({ machine: authMachine });
214
+ const actor = createPlayer();
215
+ actor.start();
216
+
217
+ // Initial state
218
+ console.log(actor.currentRoute.get()); // "/"
192
219
 
193
- - `formatPlayRouteTransitions` adds routing infrastructure (event.to matching)
194
- - Always-guards handle business logic (authentication, authorization)
195
- - Clear separation: routing layer (infrastructure) vs validation layer (business logic)
220
+ // Navigate to about
221
+ actor.send({ type: "play.route", to: "#about" });
222
+ console.log(actor.currentRoute.get()); // "/about"
196
223
 
197
- ### Pattern 2: Manual Always-Guards (Advanced)
224
+ // Attempt protected route (redirect fires because isAuthenticated=false)
225
+ actor.send({ type: "play.route", to: "#dashboard" });
226
+ console.log(actor.getSnapshot().value); // "login" — guard redirected
227
+
228
+ // Login first
229
+ actor.send({ type: "auth.login", username: "alice" });
230
+ // auth.login root handler transitions to dashboard
231
+ console.log(actor.getSnapshot().value); // "dashboard"
232
+ console.log(actor.getSnapshot().context.username); // "alice"
233
+
234
+ // Navigate to profile with params
235
+ actor.send({ type: "play.route", to: "#profile", params: { username: "alice" } });
236
+ console.log(actor.currentRoute.get()); // "/profile/alice"
237
+
238
+ actor.stop();
239
+ ```
198
240
 
199
- For advanced users who need full control:
241
+ ## Vanilla Router Setup
242
+
243
+ To sync the browser URL with `actor.currentRoute`, use `@xmachines/play-dom-router`:
200
244
 
201
245
  ```typescript
202
- const machine = createMachine({
203
- context: { intendedRoute: null, isAuthenticated: false },
204
- on: {
205
- "play.route": {
206
- actions: assign({
207
- intendedRoute: ({ event }) => event.to,
208
- }),
209
- },
210
- },
211
- always: [
212
- {
213
- target: "profile",
214
- guard: ({ context }) => context.intendedRoute === "#profile" && context.isAuthenticated,
215
- reenter: true,
216
- },
217
- {
218
- target: "login",
219
- guard: ({ context }) =>
220
- context.intendedRoute === "#profile" && !context.isAuthenticated,
221
- },
222
- ],
246
+ import {
247
+ createBrowserHistory,
248
+ createRouter,
249
+ connectRouter,
250
+ createRouteMap,
251
+ } from "@xmachines/play-dom-router";
252
+ import { extractMachineRoutes } from "@xmachines/play-router";
253
+
254
+ const routeTree = extractMachineRoutes(authMachine);
255
+ const routeMap = createRouteMap(authMachine);
256
+
257
+ const history = createBrowserHistory({ window });
258
+ const router = createRouter({ routeTree, history });
259
+
260
+ // connectRouter handles all bidirectional sync:
261
+ // - actor.currentRoute → browser URL
262
+ // - browser URL changes → play.route event to actor
263
+ const disconnect = connectRouter({ actor, router, routeMap });
264
+
265
+ // cleanup on unload
266
+ window.addEventListener("beforeunload", () => {
267
+ disconnect();
268
+ router.destroy();
223
269
  });
224
270
  ```
225
271
 
226
- ### Anti-Pattern: Guards on Events
272
+ ## React Router Setup
227
273
 
228
- **NEVER do this:**
274
+ For React, use `@xmachines/play-react-router` or `@xmachines/play-tanstack-react-router` with the `PlayRouterProvider` and `createRouteMapFromTree`:
229
275
 
230
276
  ```typescript
231
- // WRONG - Guard on event checking event property
232
- on: {
233
- 'play.route': [
234
- {
235
- guard: ({ event }) => event.to === "#dashboard",
236
- target: "dashboard"
237
- }
238
- ]
277
+ import { extractMachineRoutes } from "@xmachines/play-router";
278
+ import { PlayRouterProvider, createRouteMapFromTree } from "@xmachines/play-tanstack-react-router";
279
+
280
+ const routeTree = extractMachineRoutes(authMachine);
281
+ const routeMap = createRouteMapFromTree(routeTree);
282
+
283
+ function App() {
284
+ return (
285
+ <PlayRouterProvider
286
+ actor={actor}
287
+ router={router}
288
+ routeMap={routeMap}
289
+ renderer={(currentActor, currentRouter) => (
290
+ <Shell actor={currentActor} router={currentRouter} registry={registry} />
291
+ )}
292
+ />
293
+ );
239
294
  }
240
295
  ```
241
296
 
242
- **Why this is wrong:** The state doesn't care HOW it was entered (which event triggered it). Guards should validate state invariants: "Can I BE in this state given current context?" not "Can I TAKE this event?"
243
-
244
- **Correct approach:** Use `formatPlayRouteTransitions` for routing infrastructure, use always-guards for state validation.
245
-
246
- ### Actor Authority in Action
297
+ ## Architectural Invariants
247
298
 
248
- This demonstrates **Actor Authority (INV-01)** — the state machine controls navigation through guards, not the router. If a guard returns `false`, the transition is rejected and the URL doesn't change.
299
+ | Invariant | Description |
300
+ | ----------------------------------- | ---------------------------------------------------------------------------------------------- |
301
+ | **Actor Authority (INV-01)** | Guards on the machine validate every navigation. The router cannot change state directly. |
302
+ | **Passive Infrastructure (INV-04)** | The router observes `actor.currentRoute` — it never decides where to go. |
303
+ | **State-Driven Reset (INV-03)** | Browser back/forward sends `play.route` events to the actor. History is driven by actor state. |
304
+ | **Strict Separation (INV-02)** | The machine has zero framework imports. Guards, actions, and context are pure TypeScript. |
249
305
 
250
306
  ## Next Steps
251
307
 
252
- - **[Multi-Router Integration](./multi-router-integration.md)** - Learn about renderer prop pattern
253
- - **[Examples Index](./README.md)** - Complete catalog of runnable demos and example guides
308
+ - **[Multi-Router Integration](./multi-router-integration.md)** All 8 router adapters and the two integration patterns
309
+ - **[Examples Index](./README.md)** Complete catalog of runnable demos
254
310
 
255
311
  ## Learn More
256
312
 
257
- - [XState Routes Documentation](https://stately.ai/docs/routes) - Official Stately routing patterns
258
- - [Play RFC](../rfc/play.md) - Complete architectural specification
259
- - [play-router README](../api/@xmachines/play-router/README.md) - Route extraction and tree building
313
+ - [Play RFC](../rfc/play.md) Complete architectural specification
314
+ - [play-router README](../api/@xmachines/play-router/README.md) Route extraction and tree building
315
+ - [play-dom-router README](../api/@xmachines/play-dom-router/README.md) Vanilla DOM bindings