@xmachines/play-router 1.0.0-beta.22 → 1.0.0-beta.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -5
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -8
- package/dist/index.js.map +1 -1
- package/dist/router-sync.d.ts +5 -6
- package/dist/router-sync.d.ts.map +1 -1
- package/dist/router-sync.js +3 -3
- package/package.json +10 -8
- package/dist/connect-router.d.ts +0 -56
- package/dist/connect-router.d.ts.map +0 -1
- package/dist/connect-router.js +0 -109
- package/dist/connect-router.js.map +0 -1
- package/dist/create-browser-history.d.ts +0 -106
- package/dist/create-browser-history.d.ts.map +0 -1
- package/dist/create-browser-history.js +0 -125
- package/dist/create-browser-history.js.map +0 -1
- package/dist/create-router.d.ts +0 -73
- package/dist/create-router.d.ts.map +0 -1
- package/dist/create-router.js +0 -63
- package/dist/create-router.js.map +0 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ It also exports `RouterBridgeBase`, the shared base class used by framework adap
|
|
|
12
12
|
|
|
13
13
|
`RouterBridgeBase` is the policy point; framework adapters are thin ports that implement only framework-specific navigate/subscribe/unsubscribe behavior.
|
|
14
14
|
|
|
15
|
-
The low-level `connectRouter()`
|
|
15
|
+
The low-level `connectRouter()` from `@xmachines/play-dom-router` uses the same router-to-actor event builder and route-map match helper as `RouterBridgeBase`, so pathname sanitization, state-id normalization, param extraction, and query extraction stay aligned across vanilla and framework adapters.
|
|
16
16
|
|
|
17
17
|
Per [Play RFC](../docs/rfc/play.md), this package implements:
|
|
18
18
|
|
|
@@ -109,9 +109,7 @@ The demo demonstrates:
|
|
|
109
109
|
**Run the demo:**
|
|
110
110
|
|
|
111
111
|
```bash
|
|
112
|
-
|
|
113
|
-
npm install
|
|
114
|
-
npm run dev
|
|
112
|
+
npm run dev -w packages/play-dom-router/examples/demo
|
|
115
113
|
```
|
|
116
114
|
|
|
117
115
|
Open http://localhost:5174/ and explore:
|
|
@@ -180,7 +178,7 @@ Bridge teardown must be explicit and deterministic:
|
|
|
180
178
|
- `disconnect`/`dispose` must unwatch signal subscriptions and unhook router listeners.
|
|
181
179
|
- Do not rely on GC-only cleanup guidance.
|
|
182
180
|
- Infrastructure remains passive: bridges observe and forward intents, actors decide validity.
|
|
183
|
-
- `createBrowserHistory().destroy()` is idempotent and restores shared `window.history` patches only after the last wrapper for that window is removed.
|
|
181
|
+
- `createBrowserHistory().destroy()` (from `@xmachines/play-dom-router`) is idempotent and restores shared `window.history` patches only after the last wrapper for that window is removed.
|
|
184
182
|
- **Note**: `createBrowserHistory()` mutates global `window.history` methods (`pushState` and `replaceState`) and coordinates wrappers with shared ref-count state. To reduce leakage, create one history wrapper per browser window at the application boundary and always pair it with `destroy()` during teardown.
|
|
185
183
|
|
|
186
184
|
## Bridge Sync Ordering
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { RouterBridgeBase } from "./router-bridge-base.js";
|
|
2
2
|
export type { RouteWatcherHandle } from "./router-bridge-base.js";
|
|
3
|
-
export { sanitizePathname } from "./router-sync.js";
|
|
3
|
+
export { sanitizePathname, buildPlayRouteEvent, extractQuery } from "./router-sync.js";
|
|
4
|
+
export type { RouteMatch, BuildPlayRouteEventOptions } from "./router-sync.js";
|
|
4
5
|
export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
|
|
5
6
|
export { buildRouteTree } from "./build-tree.js";
|
|
6
7
|
export { extractMachineRoutes } from "./extract-routes.js";
|
|
@@ -10,8 +11,5 @@ export type { MachineGraph } from "./machine-to-graph.js";
|
|
|
10
11
|
export type { RouteInfo, RouteNode, RouteTree, RouteObject, RouteMetadata, PlayRouteEvent, RouterBridge, MachineNodeData, MachineEdgeData, } from "./types.js";
|
|
11
12
|
export { createRouteMap, type RouteMap } from "./create-route-map.js";
|
|
12
13
|
export { BaseRouteMap, type RouteMapping as BaseRouteMapping } from "./base-route-map.js";
|
|
13
|
-
export { createBrowserHistory, type BrowserHistory, type BrowserWindow, } from "./create-browser-history.js";
|
|
14
|
-
export { createRouter, type VanillaRouter } from "./create-router.js";
|
|
15
|
-
export { connectRouter, type ConnectRouterOptions } from "./connect-router.js";
|
|
16
14
|
export { findRouteById, findRouteByPath } from "./find-route.js";
|
|
17
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACvF,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,YAAY,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,eAAe,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKtE,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,IAAI,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG1F,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// RouterBridgeBase — public API for community adapters
|
|
2
2
|
export { RouterBridgeBase } from "./router-bridge-base.js";
|
|
3
|
-
// Router sync utilities —
|
|
4
|
-
export { sanitizePathname } from "./router-sync.js";
|
|
3
|
+
// Router sync utilities — used by play-dom-router and adapters that bypass syncActorFromRouter()
|
|
4
|
+
export { sanitizePathname, buildPlayRouteEvent, extractQuery } from "./router-sync.js";
|
|
5
5
|
// Route utilities (existing)
|
|
6
6
|
export { validateRouteFormat, validateStateExists, detectDuplicateRoutes, } from "./validate-routes.js";
|
|
7
7
|
export { buildRouteTree } from "./build-tree.js";
|
|
@@ -15,12 +15,6 @@ export { createRouteMap } from "./create-route-map.js";
|
|
|
15
15
|
// Re-exported as `BaseRouteMapping` (not `RouteMapping`) so adapter packages can
|
|
16
16
|
// define their own local `RouteMapping` type without a name collision.
|
|
17
17
|
export { BaseRouteMap } from "./base-route-map.js";
|
|
18
|
-
// Browser history abstraction (aligned with TanStack Router)
|
|
19
|
-
export { createBrowserHistory, } from "./create-browser-history.js";
|
|
20
|
-
// Vanilla router (framework-agnostic)
|
|
21
|
-
export { createRouter } from "./create-router.js";
|
|
22
|
-
// Pure browser integration (low-level API)
|
|
23
|
-
export { connectRouter } from "./connect-router.js";
|
|
24
18
|
// Route lookup helpers — matchesPattern is private within find-route.ts
|
|
25
19
|
export { findRouteById, findRouteByPath } from "./find-route.js";
|
|
26
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,iGAAiG;AACjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,iGAAiG;AACjG,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGvF,6BAA6B;AAC7B,OAAO,EACN,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,qEAAqE;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAevD,iFAAiF;AACjF,OAAO,EAAE,cAAc,EAAiB,MAAM,uBAAuB,CAAC;AAEtE,iDAAiD;AACjD,iFAAiF;AACjF,uEAAuE;AACvE,OAAO,EAAE,YAAY,EAAyC,MAAM,qBAAqB,CAAC;AAE1F,wEAAwE;AACxE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/router-sync.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { PlayRouteEvent } from "./types.js";
|
|
2
|
-
interface RouteMatch {
|
|
2
|
+
export interface RouteMatch {
|
|
3
3
|
to: string | null | undefined;
|
|
4
4
|
params?: Record<string, string>;
|
|
5
5
|
}
|
|
6
|
-
interface BuildPlayRouteEventOptions {
|
|
6
|
+
export interface BuildPlayRouteEventOptions {
|
|
7
7
|
pathname: string;
|
|
8
8
|
search?: string | undefined;
|
|
9
9
|
resolve: (sanitizedPathname: string) => RouteMatch;
|
|
@@ -50,13 +50,12 @@ export declare function extractQuery(search: string): Record<string, string>;
|
|
|
50
50
|
/**
|
|
51
51
|
* Build a normalized `play.route` event from raw router/browser input.
|
|
52
52
|
*
|
|
53
|
-
* Both `connectRouter()` and `RouterBridgeBase`
|
|
54
|
-
* framework adapters share the same pathname
|
|
55
|
-
* query extraction behavior.
|
|
53
|
+
* Both `connectRouter()` (from `@xmachines/play-dom-router`) and `RouterBridgeBase`
|
|
54
|
+
* use this helper so low-level and framework adapters share the same pathname
|
|
55
|
+
* sanitization, route resolution, and query extraction behavior.
|
|
56
56
|
*/
|
|
57
57
|
export declare function buildPlayRouteEvent(options: BuildPlayRouteEventOptions): {
|
|
58
58
|
pathname: string;
|
|
59
59
|
event: PlayRouteEvent;
|
|
60
60
|
} | null;
|
|
61
|
-
export {};
|
|
62
61
|
//# sourceMappingURL=router-sync.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-sync.d.ts","sourceRoot":"","sources":["../src/router-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,
|
|
1
|
+
{"version":3,"file":"router-sync.d.ts","sourceRoot":"","sources":["../src/router-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,UAAU,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAChC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1D,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACxD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,gBAAgB,EAC1B,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1E,UAAU,CAUZ;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUnE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,0BAA0B,GACjC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GAAG,IAAI,CAiBpD"}
|
package/dist/router-sync.js
CHANGED
|
@@ -62,9 +62,9 @@ export function extractQuery(search) {
|
|
|
62
62
|
/**
|
|
63
63
|
* Build a normalized `play.route` event from raw router/browser input.
|
|
64
64
|
*
|
|
65
|
-
* Both `connectRouter()` and `RouterBridgeBase`
|
|
66
|
-
* framework adapters share the same pathname
|
|
67
|
-
* query extraction behavior.
|
|
65
|
+
* Both `connectRouter()` (from `@xmachines/play-dom-router`) and `RouterBridgeBase`
|
|
66
|
+
* use this helper so low-level and framework adapters share the same pathname
|
|
67
|
+
* sanitization, route resolution, and query extraction behavior.
|
|
68
68
|
*/
|
|
69
69
|
export function buildPlayRouteEvent(options) {
|
|
70
70
|
const pathname = sanitizePathname(options.pathname);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmachines/play-router",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.23",
|
|
4
4
|
"description": "Route tree extraction from XState v5 state machines. Part of @xmachines/play Universal Player Architecture.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"routing",
|
|
@@ -34,23 +34,25 @@
|
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsc --build",
|
|
37
|
-
"clean": "rm -rf dist *.tsbuildinfo coverage .vitest-attachments test/browser/__screenshots__ node_modules/.vite
|
|
37
|
+
"clean": "rm -rf dist *.tsbuildinfo coverage .vitest-attachments test/browser/__screenshots__ node_modules/.vite*",
|
|
38
38
|
"lint": "oxlint .",
|
|
39
39
|
"format": "oxfmt .",
|
|
40
40
|
"test": "vitest",
|
|
41
41
|
"prepublishOnly": "npm run build"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@statelyai/graph": "^0.
|
|
45
|
-
"@xmachines/play": "1.0.0-beta.
|
|
46
|
-
"@xmachines/play-actor": "1.0.0-beta.
|
|
47
|
-
"@xmachines/play-signals": "1.0.0-beta.
|
|
44
|
+
"@statelyai/graph": "^0.10.0",
|
|
45
|
+
"@xmachines/play": "1.0.0-beta.23",
|
|
46
|
+
"@xmachines/play-actor": "1.0.0-beta.23",
|
|
47
|
+
"@xmachines/play-signals": "1.0.0-beta.23",
|
|
48
48
|
"quick-lru": "^7.0.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^25.5.0",
|
|
52
|
-
"@xmachines/play-xstate": "1.0.0-beta.
|
|
53
|
-
"@xmachines/shared": "1.0.0-beta.
|
|
52
|
+
"@xmachines/play-xstate": "1.0.0-beta.23",
|
|
53
|
+
"@xmachines/shared": "1.0.0-beta.23",
|
|
54
|
+
"oxfmt": "^0.43.0",
|
|
55
|
+
"oxlint": "^1.57.0",
|
|
54
56
|
"typescript": "^5.9.3 || ^6.0.2",
|
|
55
57
|
"urlpattern-polyfill": "^10.1.0",
|
|
56
58
|
"vitest": "^4.1.2",
|
package/dist/connect-router.d.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type { AbstractActor, Routable } from "@xmachines/play-actor";
|
|
2
|
-
import type { AnyActorLogic } from "xstate";
|
|
3
|
-
import type { VanillaRouter } from "./create-router.js";
|
|
4
|
-
import type { RouteMap } from "./create-route-map.js";
|
|
5
|
-
export interface ConnectRouterOptions {
|
|
6
|
-
actor: AbstractActor<AnyActorLogic> & Routable;
|
|
7
|
-
router: VanillaRouter;
|
|
8
|
-
routeMap: RouteMap;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Connect vanilla router to actor (pure browser integration).
|
|
12
|
-
*
|
|
13
|
-
* This is the LOW-LEVEL API for maximum control. No JSX, no rendering,
|
|
14
|
-
* just actor ↔ router synchronization.
|
|
15
|
-
*
|
|
16
|
-
* Use this when:
|
|
17
|
-
* - You want manual control over rendering
|
|
18
|
-
* - Using non-JSX framework (jQuery, Alpine, HTMX, etc.)
|
|
19
|
-
* - Building custom integration
|
|
20
|
-
*
|
|
21
|
-
* For JSX frameworks, use framework adapters instead:
|
|
22
|
-
* - @xmachines/play-react (React components)
|
|
23
|
-
* - Future: @xmachines/play-preact, @xmachines/play-solid, @xmachines/play-vue
|
|
24
|
-
*
|
|
25
|
-
* Architecture:
|
|
26
|
-
* - Subscribes to history changes → sends play.route to actor
|
|
27
|
-
* - Watches actor.currentRoute signal → updates browser URL
|
|
28
|
-
* - Prevents circular updates (history change triggers actor, actor triggers history)
|
|
29
|
-
* - Returns cleanup function
|
|
30
|
-
*
|
|
31
|
-
* Usage:
|
|
32
|
-
* ```typescript
|
|
33
|
-
* import { createBrowserHistory, createRouter, connectRouter } from '@xmachines/play-router';
|
|
34
|
-
*
|
|
35
|
-
* const history = createBrowserHistory({ window });
|
|
36
|
-
* const router = createRouter({ routeTree, history });
|
|
37
|
-
*
|
|
38
|
-
* // Connect router to actor
|
|
39
|
-
* const disconnect = connectRouter({ actor, router, routeMap });
|
|
40
|
-
*
|
|
41
|
-
* // User handles rendering (vanilla JS)
|
|
42
|
-
* const watcher = new Signal.subtle.Watcher(() => {
|
|
43
|
-
* queueMicrotask(() => {
|
|
44
|
-
* const view = actor.currentView.get();
|
|
45
|
-
* document.getElementById('app').innerHTML = render(view);
|
|
46
|
-
* });
|
|
47
|
-
* });
|
|
48
|
-
* watcher.watch(actor.currentView);
|
|
49
|
-
*
|
|
50
|
-
* // Later: cleanup
|
|
51
|
-
* disconnect();
|
|
52
|
-
* watcher.unwatch(actor.currentView);
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
export declare function connectRouter(options: ConnectRouterOptions): () => void;
|
|
56
|
-
//# sourceMappingURL=connect-router.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connect-router.d.ts","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC;IAC/C,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAqEvE"}
|
package/dist/connect-router.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { watchSignal } from "@xmachines/play-signals";
|
|
2
|
-
import { buildPlayRouteEvent } from "./router-sync.js";
|
|
3
|
-
/**
|
|
4
|
-
* Connect vanilla router to actor (pure browser integration).
|
|
5
|
-
*
|
|
6
|
-
* This is the LOW-LEVEL API for maximum control. No JSX, no rendering,
|
|
7
|
-
* just actor ↔ router synchronization.
|
|
8
|
-
*
|
|
9
|
-
* Use this when:
|
|
10
|
-
* - You want manual control over rendering
|
|
11
|
-
* - Using non-JSX framework (jQuery, Alpine, HTMX, etc.)
|
|
12
|
-
* - Building custom integration
|
|
13
|
-
*
|
|
14
|
-
* For JSX frameworks, use framework adapters instead:
|
|
15
|
-
* - @xmachines/play-react (React components)
|
|
16
|
-
* - Future: @xmachines/play-preact, @xmachines/play-solid, @xmachines/play-vue
|
|
17
|
-
*
|
|
18
|
-
* Architecture:
|
|
19
|
-
* - Subscribes to history changes → sends play.route to actor
|
|
20
|
-
* - Watches actor.currentRoute signal → updates browser URL
|
|
21
|
-
* - Prevents circular updates (history change triggers actor, actor triggers history)
|
|
22
|
-
* - Returns cleanup function
|
|
23
|
-
*
|
|
24
|
-
* Usage:
|
|
25
|
-
* ```typescript
|
|
26
|
-
* import { createBrowserHistory, createRouter, connectRouter } from '@xmachines/play-router';
|
|
27
|
-
*
|
|
28
|
-
* const history = createBrowserHistory({ window });
|
|
29
|
-
* const router = createRouter({ routeTree, history });
|
|
30
|
-
*
|
|
31
|
-
* // Connect router to actor
|
|
32
|
-
* const disconnect = connectRouter({ actor, router, routeMap });
|
|
33
|
-
*
|
|
34
|
-
* // User handles rendering (vanilla JS)
|
|
35
|
-
* const watcher = new Signal.subtle.Watcher(() => {
|
|
36
|
-
* queueMicrotask(() => {
|
|
37
|
-
* const view = actor.currentView.get();
|
|
38
|
-
* document.getElementById('app').innerHTML = render(view);
|
|
39
|
-
* });
|
|
40
|
-
* });
|
|
41
|
-
* watcher.watch(actor.currentView);
|
|
42
|
-
*
|
|
43
|
-
* // Later: cleanup
|
|
44
|
-
* disconnect();
|
|
45
|
-
* watcher.unwatch(actor.currentView);
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export function connectRouter(options) {
|
|
49
|
-
const { actor, router, routeMap } = options;
|
|
50
|
-
const { history } = router;
|
|
51
|
-
// Prevent circular updates — single navigation-processing guard.
|
|
52
|
-
// Matches RouterBridgeBase.isProcessingNavigation pattern.
|
|
53
|
-
// Reduces race-condition surface from 2³=8 flag combinations to 2.
|
|
54
|
-
let isProcessingNavigation = false;
|
|
55
|
-
// Subscribe to history changes (browser navigation)
|
|
56
|
-
const unsubscribeHistory = history.subscribe((location) => {
|
|
57
|
-
if (isProcessingNavigation)
|
|
58
|
-
return;
|
|
59
|
-
const nextRoute = buildPlayRouteEvent({
|
|
60
|
-
pathname: location.pathname,
|
|
61
|
-
search: location.search,
|
|
62
|
-
resolve: (pathname) => routeMap.resolve(pathname),
|
|
63
|
-
});
|
|
64
|
-
if (nextRoute) {
|
|
65
|
-
isProcessingNavigation = true;
|
|
66
|
-
actor.send(nextRoute.event);
|
|
67
|
-
// Check immediately if actor redirected (always-guard)
|
|
68
|
-
// XState processes events synchronously, so snapshot is already updated
|
|
69
|
-
const newActorRoute = actor.currentRoute.get();
|
|
70
|
-
if (newActorRoute && newActorRoute !== nextRoute.pathname) {
|
|
71
|
-
// Actor redirected - update URL
|
|
72
|
-
history.replace(newActorRoute);
|
|
73
|
-
}
|
|
74
|
-
// Clear flag synchronously to prevent race conditions
|
|
75
|
-
isProcessingNavigation = false;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
// Watch actor's currentRoute signal (actor-driven navigation)
|
|
79
|
-
const unwatchRoute = watchSignal(actor.currentRoute, (route) => {
|
|
80
|
-
if (isProcessingNavigation)
|
|
81
|
-
return;
|
|
82
|
-
const currentPath = history.location.pathname;
|
|
83
|
-
if (route && route !== currentPath) {
|
|
84
|
-
isProcessingNavigation = true;
|
|
85
|
-
history.push(route);
|
|
86
|
-
isProcessingNavigation = false;
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
// Sync initial URL to actor
|
|
90
|
-
// ONLY send route event if URL doesn't match actor's initial state
|
|
91
|
-
const initialPath = history.location.pathname;
|
|
92
|
-
const initialActorRoute = actor.currentRoute.get();
|
|
93
|
-
if (initialPath !== initialActorRoute) {
|
|
94
|
-
const nextRoute = buildPlayRouteEvent({
|
|
95
|
-
pathname: initialPath,
|
|
96
|
-
search: history.location.search,
|
|
97
|
-
resolve: (pathname) => routeMap.resolve(pathname),
|
|
98
|
-
});
|
|
99
|
-
if (nextRoute) {
|
|
100
|
-
actor.send(nextRoute.event);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// Return cleanup
|
|
104
|
-
return () => {
|
|
105
|
-
unsubscribeHistory();
|
|
106
|
-
unwatchRoute();
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=connect-router.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connect-router.js","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAKtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAQvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,UAAU,aAAa,CAAC,OAA6B;IAC1D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAE3B,iEAAiE;IACjE,2DAA2D;IAC3D,mEAAmE;IACnE,IAAI,sBAAsB,GAAG,KAAK,CAAC;IAEnC,oDAAoD;IACpD,MAAM,kBAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE;QACzD,IAAI,sBAAsB;YAAE,OAAO;QAEnC,MAAM,SAAS,GAAG,mBAAmB,CAAC;YACrC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjD,CAAC,CAAC;QACH,IAAI,SAAS,EAAE,CAAC;YACf,sBAAsB,GAAG,IAAI,CAAC;YAE9B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAE5B,uDAAuD;YACvD,wEAAwE;YACxE,MAAM,aAAa,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;YAC/C,IAAI,aAAa,IAAI,aAAa,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAC3D,gCAAgC;gBAChC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAChC,CAAC;YAED,sDAAsD;YACtD,sBAAsB,GAAG,KAAK,CAAC;QAChC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,8DAA8D;IAC9D,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9D,IAAI,sBAAsB;YAAE,OAAO;QAEnC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC9C,IAAI,KAAK,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YACpC,sBAAsB,GAAG,IAAI,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,sBAAsB,GAAG,KAAK,CAAC;QAChC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,4BAA4B;IAC5B,mEAAmE;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC9C,MAAM,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;IAEnD,IAAI,WAAW,KAAK,iBAAiB,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,mBAAmB,CAAC;YACrC,QAAQ,EAAE,WAAW;YACrB,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;YAC/B,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjD,CAAC,CAAC;QACH,IAAI,SAAS,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IAED,iBAAiB;IACjB,OAAO,GAAG,EAAE;QACX,kBAAkB,EAAE,CAAC;QACrB,YAAY,EAAE,CAAC;IAChB,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
export interface BrowserHistory {
|
|
2
|
-
/**
|
|
3
|
-
* Get current location state
|
|
4
|
-
*/
|
|
5
|
-
readonly location: {
|
|
6
|
-
pathname: string;
|
|
7
|
-
search: string;
|
|
8
|
-
hash: string;
|
|
9
|
-
state: unknown;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Push new URL to history
|
|
13
|
-
*/
|
|
14
|
-
push(path: string, state?: unknown): void;
|
|
15
|
-
/**
|
|
16
|
-
* Replace current URL in history
|
|
17
|
-
*/
|
|
18
|
-
replace(path: string, state?: unknown): void;
|
|
19
|
-
/**
|
|
20
|
-
* Go back/forward
|
|
21
|
-
*/
|
|
22
|
-
go(delta: number): void;
|
|
23
|
-
back(): void;
|
|
24
|
-
forward(): void;
|
|
25
|
-
/**
|
|
26
|
-
* Subscribe to history changes
|
|
27
|
-
* Returns unsubscribe function
|
|
28
|
-
*/
|
|
29
|
-
subscribe(listener: (location: BrowserHistory["location"]) => void): () => void;
|
|
30
|
-
/**
|
|
31
|
-
* Create href from path
|
|
32
|
-
*/
|
|
33
|
-
createHref(path: string): string;
|
|
34
|
-
/**
|
|
35
|
-
* Cleanup.
|
|
36
|
-
*
|
|
37
|
-
* Safe to call more than once. When multiple wrappers share the same
|
|
38
|
-
* `window.history`, the original methods are restored only after the last
|
|
39
|
-
* wrapper is destroyed.
|
|
40
|
-
*/
|
|
41
|
-
destroy(): void;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Minimal window interface for createBrowserHistory
|
|
45
|
-
*
|
|
46
|
-
* Structural interface covering only the properties actually used.
|
|
47
|
-
* Accepts Window, JSDOM window, or any compatible test double.
|
|
48
|
-
* Avoids coupling to `Window & typeof globalThis` which varies across environments.
|
|
49
|
-
*
|
|
50
|
-
* @public
|
|
51
|
-
*/
|
|
52
|
-
export interface BrowserWindow {
|
|
53
|
-
history: {
|
|
54
|
-
readonly state: unknown;
|
|
55
|
-
pushState(state: unknown, title: string, url?: string | null): void;
|
|
56
|
-
replaceState(state: unknown, title: string, url?: string | null): void;
|
|
57
|
-
go(delta: number): void;
|
|
58
|
-
back(): void;
|
|
59
|
-
forward(): void;
|
|
60
|
-
};
|
|
61
|
-
location: {
|
|
62
|
-
readonly pathname: string;
|
|
63
|
-
readonly search: string;
|
|
64
|
-
readonly hash: string;
|
|
65
|
-
};
|
|
66
|
-
addEventListener(type: "popstate", listener: () => void): void;
|
|
67
|
-
removeEventListener(type: "popstate", listener: () => void): void;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Create browser history that wraps window.history
|
|
71
|
-
*
|
|
72
|
-
* Aligned with TanStack Router's history interface for API parallelism.
|
|
73
|
-
*
|
|
74
|
-
* Architecture:
|
|
75
|
-
* - Patches window.history.pushState/replaceState to detect changes
|
|
76
|
-
* - Listens to popstate for browser back/forward
|
|
77
|
-
* - Provides subscribe() for listeners (like PlayRouterProvider)
|
|
78
|
-
* - Testable (accepts window object)
|
|
79
|
-
*
|
|
80
|
-
* Usage:
|
|
81
|
-
* ```typescript
|
|
82
|
-
* const history = createBrowserHistory({ window });
|
|
83
|
-
*
|
|
84
|
-
* const unsubscribe = history.subscribe((location) => {
|
|
85
|
-
* console.log('URL changed:', location.pathname);
|
|
86
|
-
* });
|
|
87
|
-
*
|
|
88
|
-
* history.push('/new-path');
|
|
89
|
-
*
|
|
90
|
-
* // Later:
|
|
91
|
-
* unsubscribe();
|
|
92
|
-
* history.destroy();
|
|
93
|
-
* ```
|
|
94
|
-
*
|
|
95
|
-
* `destroy()` is idempotent and cooperates with other wrappers created for the
|
|
96
|
-
* same `window` instance.
|
|
97
|
-
*
|
|
98
|
-
* **Warning**: `createBrowserHistory()` mutates global `window.history` methods
|
|
99
|
-
* (`pushState` and `replaceState`) and coordinates wrappers with shared ref-count state.
|
|
100
|
-
* To mitigate leakage, create one history wrapper per browser window at the application
|
|
101
|
-
* boundary and always pair it with `destroy()` during teardown.
|
|
102
|
-
*/
|
|
103
|
-
export declare function createBrowserHistory(options: {
|
|
104
|
-
window: BrowserWindow;
|
|
105
|
-
}): BrowserHistory;
|
|
106
|
-
//# sourceMappingURL=create-browser-history.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create-browser-history.d.ts","sourceRoot":"","sources":["../src/create-browser-history.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,OAAO,CAAC;KACf,CAAC;IAEF;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAE1C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAE7C;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,IAAI,IAAI,CAAC;IAEhB;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAEhF;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAEjC;;;;;;OAMG;IACH,OAAO,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE;QACR,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QACxB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;QACpE,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;QACvE,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,IAAI,IAAI,IAAI,CAAC;QACb,OAAO,IAAI,IAAI,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE;QACT,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC/D,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAClE;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,cAAc,CA8EvF"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
const historyPatchStates = new WeakMap();
|
|
2
|
-
/**
|
|
3
|
-
* Create browser history that wraps window.history
|
|
4
|
-
*
|
|
5
|
-
* Aligned with TanStack Router's history interface for API parallelism.
|
|
6
|
-
*
|
|
7
|
-
* Architecture:
|
|
8
|
-
* - Patches window.history.pushState/replaceState to detect changes
|
|
9
|
-
* - Listens to popstate for browser back/forward
|
|
10
|
-
* - Provides subscribe() for listeners (like PlayRouterProvider)
|
|
11
|
-
* - Testable (accepts window object)
|
|
12
|
-
*
|
|
13
|
-
* Usage:
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const history = createBrowserHistory({ window });
|
|
16
|
-
*
|
|
17
|
-
* const unsubscribe = history.subscribe((location) => {
|
|
18
|
-
* console.log('URL changed:', location.pathname);
|
|
19
|
-
* });
|
|
20
|
-
*
|
|
21
|
-
* history.push('/new-path');
|
|
22
|
-
*
|
|
23
|
-
* // Later:
|
|
24
|
-
* unsubscribe();
|
|
25
|
-
* history.destroy();
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* `destroy()` is idempotent and cooperates with other wrappers created for the
|
|
29
|
-
* same `window` instance.
|
|
30
|
-
*
|
|
31
|
-
* **Warning**: `createBrowserHistory()` mutates global `window.history` methods
|
|
32
|
-
* (`pushState` and `replaceState`) and coordinates wrappers with shared ref-count state.
|
|
33
|
-
* To mitigate leakage, create one history wrapper per browser window at the application
|
|
34
|
-
* boundary and always pair it with `destroy()` during teardown.
|
|
35
|
-
*/
|
|
36
|
-
export function createBrowserHistory(options) {
|
|
37
|
-
const win = options.window;
|
|
38
|
-
const listeners = new Set();
|
|
39
|
-
const patchState = getOrCreatePatchState(win);
|
|
40
|
-
let destroyed = false;
|
|
41
|
-
function getLocation() {
|
|
42
|
-
return {
|
|
43
|
-
pathname: win.location.pathname,
|
|
44
|
-
search: win.location.search,
|
|
45
|
-
hash: win.location.hash,
|
|
46
|
-
state: win.history.state,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function notify() {
|
|
50
|
-
const location = getLocation();
|
|
51
|
-
listeners.forEach((listener) => listener(location));
|
|
52
|
-
}
|
|
53
|
-
patchState.wrappers.add(notify);
|
|
54
|
-
// Listen to popstate
|
|
55
|
-
const popstateHandler = () => notify();
|
|
56
|
-
win.addEventListener("popstate", popstateHandler);
|
|
57
|
-
return {
|
|
58
|
-
get location() {
|
|
59
|
-
return getLocation();
|
|
60
|
-
},
|
|
61
|
-
push(path, state) {
|
|
62
|
-
win.history.pushState(state, "", path);
|
|
63
|
-
},
|
|
64
|
-
replace(path, state) {
|
|
65
|
-
win.history.replaceState(state, "", path);
|
|
66
|
-
},
|
|
67
|
-
go(delta) {
|
|
68
|
-
win.history.go(delta);
|
|
69
|
-
},
|
|
70
|
-
back() {
|
|
71
|
-
win.history.back();
|
|
72
|
-
},
|
|
73
|
-
forward() {
|
|
74
|
-
win.history.forward();
|
|
75
|
-
},
|
|
76
|
-
subscribe(listener) {
|
|
77
|
-
listeners.add(listener);
|
|
78
|
-
return () => listeners.delete(listener);
|
|
79
|
-
},
|
|
80
|
-
createHref(path) {
|
|
81
|
-
return path;
|
|
82
|
-
},
|
|
83
|
-
destroy() {
|
|
84
|
-
if (destroyed) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
destroyed = true;
|
|
88
|
-
patchState.wrappers.delete(notify);
|
|
89
|
-
patchState.refCount -= 1;
|
|
90
|
-
win.removeEventListener("popstate", popstateHandler);
|
|
91
|
-
listeners.clear();
|
|
92
|
-
if (patchState.refCount === 0) {
|
|
93
|
-
win.history.pushState = patchState.originalPushState;
|
|
94
|
-
win.history.replaceState = patchState.originalReplaceState;
|
|
95
|
-
historyPatchStates.delete(win.history);
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function getOrCreatePatchState(win) {
|
|
101
|
-
const existing = historyPatchStates.get(win.history);
|
|
102
|
-
if (existing) {
|
|
103
|
-
existing.refCount += 1;
|
|
104
|
-
return existing;
|
|
105
|
-
}
|
|
106
|
-
const originalPushState = win.history.pushState;
|
|
107
|
-
const originalReplaceState = win.history.replaceState;
|
|
108
|
-
const patchState = {
|
|
109
|
-
originalPushState,
|
|
110
|
-
originalReplaceState,
|
|
111
|
-
wrappers: new Set(),
|
|
112
|
-
refCount: 1,
|
|
113
|
-
};
|
|
114
|
-
win.history.pushState = function (state, title, url) {
|
|
115
|
-
patchState.originalPushState.call(win.history, state, title, url);
|
|
116
|
-
patchState.wrappers.forEach((notify) => notify());
|
|
117
|
-
};
|
|
118
|
-
win.history.replaceState = function (state, title, url) {
|
|
119
|
-
patchState.originalReplaceState.call(win.history, state, title, url);
|
|
120
|
-
patchState.wrappers.forEach((notify) => notify());
|
|
121
|
-
};
|
|
122
|
-
historyPatchStates.set(win.history, patchState);
|
|
123
|
-
return patchState;
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=create-browser-history.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create-browser-history.js","sourceRoot":"","sources":["../src/create-browser-history.ts"],"names":[],"mappings":"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"}
|
package/dist/create-router.d.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type { RouteTree } from "./types.js";
|
|
2
|
-
import type { BrowserHistory } from "./create-browser-history.js";
|
|
3
|
-
export interface VanillaRouter {
|
|
4
|
-
/**
|
|
5
|
-
* History instance
|
|
6
|
-
*/
|
|
7
|
-
readonly history: BrowserHistory;
|
|
8
|
-
/**
|
|
9
|
-
* Route tree (for structure reference)
|
|
10
|
-
*/
|
|
11
|
-
readonly routeTree: RouteTree;
|
|
12
|
-
/**
|
|
13
|
-
* Cleanup
|
|
14
|
-
*/
|
|
15
|
-
destroy(): void;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Create vanilla router for framework-agnostic routing.
|
|
19
|
-
*
|
|
20
|
-
* Architecture:
|
|
21
|
-
* - Just wraps history and routeTree
|
|
22
|
-
* - Does NOT embed routeMap (providers need it as prop)
|
|
23
|
-
* - Framework-agnostic history management only
|
|
24
|
-
*
|
|
25
|
-
* Why no routeMap:
|
|
26
|
-
* - Router doesn't know about state IDs (that's Play-specific)
|
|
27
|
-
* - RouteMap is the bridge between router and actor
|
|
28
|
-
* - Provider receives routeMap as prop to do path → state ID resolution
|
|
29
|
-
*
|
|
30
|
-
* Usage (parallel to TanStack mode):
|
|
31
|
-
* ```typescript
|
|
32
|
-
* // Both modes: identical setup
|
|
33
|
-
* const routeTree = extractMachineRoutes(machine);
|
|
34
|
-
* const routeMap = createRouteMap(routeTree);
|
|
35
|
-
* const history = createBrowserHistory({ window });
|
|
36
|
-
*
|
|
37
|
-
* // Vanilla router
|
|
38
|
-
* const router = createRouter({ routeTree, history });
|
|
39
|
-
*
|
|
40
|
-
* // Provider needs routeMap as prop (router doesn't have it)
|
|
41
|
-
* <PlayRouterProvider
|
|
42
|
-
* actor={actor}
|
|
43
|
-
* router={router}
|
|
44
|
-
* routeMap={routeMap} // ← Must pass separately
|
|
45
|
-
* renderer={(currentActor, currentRouter) => {
|
|
46
|
-
* void currentRouter;
|
|
47
|
-
* return <Renderer actor={currentActor} components={components} />;
|
|
48
|
-
* }}
|
|
49
|
-
* />
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* Compare to TanStack mode:
|
|
53
|
-
* ```typescript
|
|
54
|
-
* // TanStack router (external library)
|
|
55
|
-
* const router = TanStackCreateRouter({ routeTree, history });
|
|
56
|
-
*
|
|
57
|
-
* // Provider needs routeMap as prop (same as vanilla!)
|
|
58
|
-
* <PlayRouterProvider
|
|
59
|
-
* actor={actor}
|
|
60
|
-
* router={router}
|
|
61
|
-
* routeMap={routeMap} // ← Must pass separately
|
|
62
|
-
* renderer={(currentActor, currentRouter) => {
|
|
63
|
-
* void currentRouter;
|
|
64
|
-
* return <Renderer actor={currentActor} components={components} />;
|
|
65
|
-
* }}
|
|
66
|
-
* />
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export declare function createRouter(options: {
|
|
70
|
-
routeTree: RouteTree;
|
|
71
|
-
history: BrowserHistory;
|
|
72
|
-
}): VanillaRouter;
|
|
73
|
-
//# sourceMappingURL=create-router.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create-router.d.ts","sourceRoot":"","sources":["../src/create-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,cAAc,CAAC;CACxB,GAAG,aAAa,CAWhB"}
|
package/dist/create-router.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create vanilla router for framework-agnostic routing.
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Just wraps history and routeTree
|
|
6
|
-
* - Does NOT embed routeMap (providers need it as prop)
|
|
7
|
-
* - Framework-agnostic history management only
|
|
8
|
-
*
|
|
9
|
-
* Why no routeMap:
|
|
10
|
-
* - Router doesn't know about state IDs (that's Play-specific)
|
|
11
|
-
* - RouteMap is the bridge between router and actor
|
|
12
|
-
* - Provider receives routeMap as prop to do path → state ID resolution
|
|
13
|
-
*
|
|
14
|
-
* Usage (parallel to TanStack mode):
|
|
15
|
-
* ```typescript
|
|
16
|
-
* // Both modes: identical setup
|
|
17
|
-
* const routeTree = extractMachineRoutes(machine);
|
|
18
|
-
* const routeMap = createRouteMap(routeTree);
|
|
19
|
-
* const history = createBrowserHistory({ window });
|
|
20
|
-
*
|
|
21
|
-
* // Vanilla router
|
|
22
|
-
* const router = createRouter({ routeTree, history });
|
|
23
|
-
*
|
|
24
|
-
* // Provider needs routeMap as prop (router doesn't have it)
|
|
25
|
-
* <PlayRouterProvider
|
|
26
|
-
* actor={actor}
|
|
27
|
-
* router={router}
|
|
28
|
-
* routeMap={routeMap} // ← Must pass separately
|
|
29
|
-
* renderer={(currentActor, currentRouter) => {
|
|
30
|
-
* void currentRouter;
|
|
31
|
-
* return <Renderer actor={currentActor} components={components} />;
|
|
32
|
-
* }}
|
|
33
|
-
* />
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* Compare to TanStack mode:
|
|
37
|
-
* ```typescript
|
|
38
|
-
* // TanStack router (external library)
|
|
39
|
-
* const router = TanStackCreateRouter({ routeTree, history });
|
|
40
|
-
*
|
|
41
|
-
* // Provider needs routeMap as prop (same as vanilla!)
|
|
42
|
-
* <PlayRouterProvider
|
|
43
|
-
* actor={actor}
|
|
44
|
-
* router={router}
|
|
45
|
-
* routeMap={routeMap} // ← Must pass separately
|
|
46
|
-
* renderer={(currentActor, currentRouter) => {
|
|
47
|
-
* void currentRouter;
|
|
48
|
-
* return <Renderer actor={currentActor} components={components} />;
|
|
49
|
-
* }}
|
|
50
|
-
* />
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
export function createRouter(options) {
|
|
54
|
-
const { routeTree, history } = options;
|
|
55
|
-
return {
|
|
56
|
-
routeTree,
|
|
57
|
-
history,
|
|
58
|
-
destroy() {
|
|
59
|
-
history.destroy();
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
//# sourceMappingURL=create-router.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create-router.js","sourceRoot":"","sources":["../src/create-router.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,UAAU,YAAY,CAAC,OAG5B;IACA,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAEvC,OAAO;QACN,SAAS;QACT,OAAO;QAEP,OAAO;YACN,OAAO,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;KACD,CAAC;AACH,CAAC"}
|