@xmachines/play-solid-router 1.1.0 → 2.0.0

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 CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  SolidJS Router adapter for the XMachines Universal Player Architecture. Provides bidirectional synchronisation between a `PlayerActor`'s state machine routes and the browser URL via `@solidjs/router`.
4
4
 
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
- [![Version](https://img.shields.io/badge/version-1.1.0-blue)](https://www.npmjs.com/package/@xmachines/play-solid-router)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-2.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-solid-router)
7
6
 
8
7
  Part of the [xmachines-js monorepo](../../README.md).
9
8
 
@@ -0,0 +1,50 @@
1
+ import { onCleanup } from "solid-js";
2
+ import { memo } from "solid-js/web";
3
+ //#region packages/play-solid-router/src/create-play-router-provider.tsx
4
+ /**
5
+ * createPlayRouterProvider — factory for Solid `PlayRouterProvider` components
6
+ *
7
+ * Captures the provider component shape used by this package's
8
+ * `PlayRouterProvider` — create a bridge synchronously at component evaluation
9
+ * time, `connect()` it, and `disconnect()` in `onCleanup` — so that Solid
10
+ * bridges with the standard `(router, actor, routeMap)` constructor can be
11
+ * wrapped in a provider with a single call. Only the bridge class (and
12
+ * therefore the `router` prop type) differs between providers created by this
13
+ * factory.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ /**
18
+ * Create a Solid `PlayRouterProvider` component bound to a specific bridge class.
19
+ *
20
+ * The returned component connects a `PlayerActor` to the framework router,
21
+ * keeping actor state and browser URL in sync bidirectionally.
22
+ *
23
+ * The bridge is created synchronously at component evaluation time (Solid's
24
+ * execution model) and torn down via `onCleanup` when the component is disposed.
25
+ * Unlike React, prop stability is not a concern — Solid's `props` accessor is
26
+ * already reactive and the bridge is created once per component instance.
27
+ *
28
+ * @param BridgeCtor - Bridge class constructed as `new BridgeCtor(router, actor, routeMap)`.
29
+ * @returns A `PlayRouterProvider` component, generic over the actor type so the
30
+ * `renderer` callback receives the same concrete actor type that was passed in.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * export const PlayRouterProvider = createPlayRouterProvider(MySolidRouterBridge);
35
+ * ```
36
+ */
37
+ function createPlayRouterProvider(BridgeCtor) {
38
+ return function PlayRouterProvider(props) {
39
+ const bridge = new BridgeCtor(props.router, props.actor, props.routeMap);
40
+ bridge.connect();
41
+ onCleanup(() => {
42
+ bridge.disconnect();
43
+ });
44
+ return memo(() => props.renderer(props.actor, props.router));
45
+ };
46
+ }
47
+ //#endregion
48
+ export { createPlayRouterProvider };
49
+
50
+ //# sourceMappingURL=create-play-router-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-play-router-provider.js","names":["onCleanup","JSX","PlayActor","RouteMap","RouterBridge","PlayRouterBridgeConstructor","router","TRouter","actor","routeMap","PlayRouterProviderBaseProps","TActor","renderer","Element","createPlayRouterProvider","BridgeCtor","PlayRouterProvider","props","bridge","connect","disconnect","_$memo"],"sources":["../src/create-play-router-provider.tsx"],"sourcesContent":["/**\n * createPlayRouterProvider — factory for Solid `PlayRouterProvider` components\n *\n * Captures the provider component shape used by this package's\n * `PlayRouterProvider` — create a bridge synchronously at component evaluation\n * time, `connect()` it, and `disconnect()` in `onCleanup` — so that Solid\n * bridges with the standard `(router, actor, routeMap)` constructor can be\n * wrapped in a provider with a single call. Only the bridge class (and\n * therefore the `router` prop type) differs between providers created by this\n * factory.\n *\n * @packageDocumentation\n */\nimport { onCleanup, type JSX } from \"solid-js\";\nimport type { PlayActor, RouteMap, RouterBridge } from \"@xmachines/play-router\";\n\n/**\n * Constructor shape a bridge class must satisfy to be used with\n * `createPlayRouterProvider`: `(router, actor, routeMap) → RouterBridge`.\n *\n * Bridges with a different constructor shape (e.g. `SolidRouterBridge`, which\n * takes the hook results as separate arguments) are adapted with a thin\n * subclass that repackages the `router` prop.\n */\nexport type PlayRouterBridgeConstructor<TRouter> = new (\n\trouter: TRouter,\n\tactor: PlayActor,\n\trouteMap: RouteMap,\n) => RouterBridge;\n\n/**\n * Props shared by every factory-created Solid `PlayRouterProvider`.\n *\n * Adapter packages re-export a concrete alias with `TRouter` bound to their\n * router type (e.g. `SolidRouterHooks` in `@xmachines/play-solid-router`).\n */\nexport interface PlayRouterProviderBaseProps<TRouter, TActor extends PlayActor = PlayActor> {\n\t/** The actor to sync with the router. */\n\tactor: TActor;\n\t/** The router the bridge synchronizes with. */\n\trouter: TRouter;\n\t/** Bidirectional route map for state ID ↔ URL path lookups. */\n\trouteMap: RouteMap;\n\t/** Renderer callback receives the same concrete actor type that was passed in. */\n\trenderer: (actor: TActor, router: TRouter) => JSX.Element;\n}\n\n/**\n * Create a Solid `PlayRouterProvider` component bound to a specific bridge class.\n *\n * The returned component connects a `PlayerActor` to the framework router,\n * keeping actor state and browser URL in sync bidirectionally.\n *\n * The bridge is created synchronously at component evaluation time (Solid's\n * execution model) and torn down via `onCleanup` when the component is disposed.\n * Unlike React, prop stability is not a concern — Solid's `props` accessor is\n * already reactive and the bridge is created once per component instance.\n *\n * @param BridgeCtor - Bridge class constructed as `new BridgeCtor(router, actor, routeMap)`.\n * @returns A `PlayRouterProvider` component, generic over the actor type so the\n * `renderer` callback receives the same concrete actor type that was passed in.\n *\n * @example\n * ```tsx\n * export const PlayRouterProvider = createPlayRouterProvider(MySolidRouterBridge);\n * ```\n */\nexport function createPlayRouterProvider<TRouter>(\n\tBridgeCtor: PlayRouterBridgeConstructor<TRouter>,\n) {\n\treturn function PlayRouterProvider<TActor extends PlayActor>(\n\t\tprops: PlayRouterProviderBaseProps<TRouter, TActor>,\n\t) {\n\t\tconst bridge = new BridgeCtor(props.router, props.actor, props.routeMap);\n\t\tvoid bridge.connect();\n\n\t\tonCleanup(() => {\n\t\t\tvoid bridge.disconnect();\n\t\t});\n\n\t\treturn <>{props.renderer(props.actor, props.router)}</>;\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,SAAgBc,yBACfC,YACC;CACD,OAAO,SAASC,mBACfC,OACC;EACD,MAAMC,SAAS,IAAIH,WAAWE,MAAMX,QAAQW,MAAMT,OAAOS,MAAMR,QAAQ;EACvE,OAAYU,QAAQ;EAEpBnB,gBAAgB;GACf,OAAYoB,WAAW;EACxB,CAAC;EAED,OAAAC,WAAUJ,MAAML,SAASK,MAAMT,OAAOS,MAAMX,MAAM,CAAC;CACpD;AACD"}
package/dist/index.js CHANGED
@@ -1,10 +1,5 @@
1
- /**
2
- * @xmachines/play-solid-router
3
- *
4
- * SolidJS Router adapter for XMachines Universal Player Architecture
5
- */
6
- export { SolidRouterBridge } from "./solid-router-bridge.js";
7
- export { PlayRouterProvider } from "./play-router-provider.js";
8
- export { createPlayRouterProvider } from "./create-play-router-provider.js";
9
- export { RouteMap, createRouteMap, } from "@xmachines/play-router";
10
- //# sourceMappingURL=index.js.map
1
+ import { SolidRouterBridge } from "./solid-router-bridge.js";
2
+ import { createPlayRouterProvider } from "./create-play-router-provider.js";
3
+ import { PlayRouterProvider } from "./play-router-provider.js";
4
+ import { RouteMap, createRouteMap } from "@xmachines/play-router";
5
+ export { PlayRouterProvider, RouteMap, SolidRouterBridge, createPlayRouterProvider, createRouteMap };
@@ -0,0 +1,45 @@
1
+ import { SolidRouterBridge } from "./solid-router-bridge.js";
2
+ import { createPlayRouterProvider } from "./create-play-router-provider.js";
3
+ //#region packages/play-solid-router/src/play-router-provider.tsx
4
+ /**
5
+ * Adapter binding `SolidRouterBridge`'s hook-argument constructor to the
6
+ * `(router, actor, routeMap)` shape expected by `createPlayRouterProvider`.
7
+ */
8
+ var SolidHooksRouterBridge = class extends SolidRouterBridge {
9
+ constructor(router, actor, routeMap) {
10
+ super(router.navigate, router.location, router.params, actor, routeMap);
11
+ }
12
+ };
13
+ /**
14
+ * Connects a `PlayerActor` to Solid Router, keeping actor state and browser URL
15
+ * in sync bidirectionally.
16
+ *
17
+ * The bridge is created synchronously at component evaluation time (Solid's
18
+ * execution model) and torn down via `onCleanup` when the component is disposed.
19
+ * Unlike React, prop stability is not a concern — Solid's `props` accessor is
20
+ * already reactive and the bridge is created once per component instance.
21
+ *
22
+ * The `router` prop must be obtained from Solid Router hooks in the parent component:
23
+ *
24
+ * ```tsx
25
+ * function AppShell() {
26
+ * const navigate = useNavigate();
27
+ * const location = useLocation();
28
+ * const params = useParams();
29
+ *
30
+ * return (
31
+ * <PlayRouterProvider
32
+ * actor={actor}
33
+ * routeMap={routeMap}
34
+ * router={{ navigate, location, params }}
35
+ * renderer={(a) => <PlayRenderer actor={a} registry={registry} />}
36
+ * />
37
+ * );
38
+ * }
39
+ * ```
40
+ */
41
+ var PlayRouterProvider = createPlayRouterProvider(SolidHooksRouterBridge);
42
+ //#endregion
43
+ export { PlayRouterProvider };
44
+
45
+ //# sourceMappingURL=play-router-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"play-router-provider.js","names":["Navigator","Location","Params","PlayActor","RouteMap","SolidRouterBridge","createPlayRouterProvider","PlayRouterProviderBaseProps","RoutableActor","SolidRouterHooks","navigate","location","params","PlayRouterProviderProps","TActor","SolidHooksRouterBridge","constructor","router","actor","routeMap","PlayRouterProvider"],"sources":["../src/play-router-provider.tsx"],"sourcesContent":["/**\n * PlayRouterProvider — Solid convenience wrapper for SolidRouterBridge\n *\n * Created via the shared `createPlayRouterProvider` factory: the bridge is\n * created synchronously at component evaluation time and disconnected via\n * `onCleanup` when the component is disposed.\n */\nimport type { Navigator, Location, Params } from \"@solidjs/router\";\nimport type { PlayActor, RouteMap } from \"@xmachines/play-router\";\nimport { SolidRouterBridge } from \"./solid-router-bridge.js\";\nimport {\n\tcreatePlayRouterProvider,\n\ttype PlayRouterProviderBaseProps,\n} from \"./create-play-router-provider.js\";\n\nexport type { PlayActor };\n\n/** @deprecated Use `PlayActor` from `@xmachines/play-router`. Will be removed in the next major version. */\nexport type RoutableActor = PlayActor;\n\n/**\n * The three Solid Router hook results that `PlayRouterProvider` and `SolidRouterBridge`\n * require. Pass these directly from your component's hook calls:\n *\n * ```tsx\n * const navigate = useNavigate(); // → SolidRouterHooks.navigate\n * const location = useLocation(); // → SolidRouterHooks.location\n * const params = useParams(); // → SolidRouterHooks.params\n * ```\n *\n * - `navigate` — used to push URL changes when the actor's `currentRoute` changes.\n * - `location` — `pathname` and `search` are read at `connect()` time for deep-link sync.\n * Subsequent pathname changes drive router→actor sync via `createEffect`.\n * - `params` — Solid's pre-parsed path parameters for the current route segment. Used\n * directly in `extractParams()` to avoid re-parsing with URLPattern.\n */\nexport type SolidRouterHooks = {\n\tnavigate: Navigator;\n\tlocation: Location;\n\tparams: Params;\n};\n\n/**\n * Props for the Solid Router `PlayRouterProvider`.\n *\n * `router` bundles the three Solid Router hook results that drive bidirectional\n * sync. Obtain these from `useNavigate()`, `useLocation()`, and `useParams()`\n * in the parent component (they must be called inside a router context).\n */\nexport interface PlayRouterProviderProps<\n\tTActor extends PlayActor = PlayActor,\n> extends PlayRouterProviderBaseProps<SolidRouterHooks, TActor> {}\n\n/**\n * Adapter binding `SolidRouterBridge`'s hook-argument constructor to the\n * `(router, actor, routeMap)` shape expected by `createPlayRouterProvider`.\n */\nclass SolidHooksRouterBridge extends SolidRouterBridge {\n\tconstructor(router: SolidRouterHooks, actor: PlayActor, routeMap: RouteMap) {\n\t\tsuper(router.navigate, router.location, router.params, actor, routeMap);\n\t}\n}\n\n/**\n * Connects a `PlayerActor` to Solid Router, keeping actor state and browser URL\n * in sync bidirectionally.\n *\n * The bridge is created synchronously at component evaluation time (Solid's\n * execution model) and torn down via `onCleanup` when the component is disposed.\n * Unlike React, prop stability is not a concern — Solid's `props` accessor is\n * already reactive and the bridge is created once per component instance.\n *\n * The `router` prop must be obtained from Solid Router hooks in the parent component:\n *\n * ```tsx\n * function AppShell() {\n * const navigate = useNavigate();\n * const location = useLocation();\n * const params = useParams();\n *\n * return (\n * <PlayRouterProvider\n * actor={actor}\n * routeMap={routeMap}\n * router={{ navigate, location, params }}\n * renderer={(a) => <PlayRenderer actor={a} registry={registry} />}\n * />\n * );\n * }\n * ```\n */\nexport const PlayRouterProvider = createPlayRouterProvider(SolidHooksRouterBridge);\n"],"mappings":";;;;;;;AAyDA,IAAMe,yBAAN,cAAqCV,kBAAkB;CACtDW,YAAYC,QAA0BC,OAAkBC,UAAoB;EAC3E,MAAMF,OAAOP,UAAUO,OAAON,UAAUM,OAAOL,QAAQM,OAAOC,QAAQ;CACvE;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAaC,qBAAqBd,yBAAyBS,sBAAsB"}
@@ -1,166 +1,167 @@
1
- /**
2
- * SolidJS Router bridge implementing RouterBridge protocol via RouterBridgeBase
3
- *
4
- * Extends RouterBridgeBase to handle all common lifecycle and sync logic.
5
- * Uses Solid's native reactive primitives (createEffect) for router→actor direction.
6
- *
7
- * **IMPORTANT:** `connect()` MUST be called inside a Solid reactive owner (component
8
- * or createRoot). The `createEffect()` in `watchRouterChanges()` runs inside
9
- * `createRoot()`, which deliberately isolates it from any parent owner — automatic
10
- * cleanup on component unmount does NOT happen. You MUST call `disconnect()` (or
11
- * `dispose()`) explicitly, typically in `onCleanup()`.
12
- *
13
- * @example
14
- * ```tsx
15
- * import { useNavigate, useLocation, useParams } from '@solidjs/router';
16
- * import { onCleanup } from 'solid-js';
17
- * import { SolidRouterBridge, RouteMap } from '@xmachines/play-solid-router';
18
- *
19
- * function App() {
20
- * const navigate = useNavigate();
21
- * const location = useLocation();
22
- * const params = useParams();
23
- *
24
- * const routeMap = new RouteMap([...]);
25
- * const bridge = new SolidRouterBridge(navigate, location, params, actor, routeMap);
26
- *
27
- * // connect() MUST be called inside a Solid reactive owner
28
- * bridge.connect();
29
- * onCleanup(() => bridge.disconnect());
30
- *
31
- * return <div>...</div>;
32
- * }
33
- * ```
34
- */
35
1
  import { createEffect, createRoot, on } from "solid-js";
36
2
  import { RouterBridgeBase } from "@xmachines/play-router";
3
+ //#region packages/play-solid-router/src/solid-router-bridge.ts
4
+ /**
5
+ * SolidJS Router bridge implementing RouterBridge protocol via RouterBridgeBase
6
+ *
7
+ * Extends RouterBridgeBase to handle all common lifecycle and sync logic.
8
+ * Uses Solid's native reactive primitives (createEffect) for router→actor direction.
9
+ *
10
+ * **IMPORTANT:** `connect()` MUST be called inside a Solid reactive owner (component
11
+ * or createRoot). The `createEffect()` in `watchRouterChanges()` runs inside
12
+ * `createRoot()`, which deliberately isolates it from any parent owner — automatic
13
+ * cleanup on component unmount does NOT happen. You MUST call `disconnect()` (or
14
+ * `dispose()`) explicitly, typically in `onCleanup()`.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * import { useNavigate, useLocation, useParams } from '@solidjs/router';
19
+ * import { onCleanup } from 'solid-js';
20
+ * import { SolidRouterBridge, RouteMap } from '@xmachines/play-solid-router';
21
+ *
22
+ * function App() {
23
+ * const navigate = useNavigate();
24
+ * const location = useLocation();
25
+ * const params = useParams();
26
+ *
27
+ * const routeMap = new RouteMap([...]);
28
+ * const bridge = new SolidRouterBridge(navigate, location, params, actor, routeMap);
29
+ *
30
+ * // connect() MUST be called inside a Solid reactive owner
31
+ * bridge.connect();
32
+ * onCleanup(() => bridge.disconnect());
33
+ *
34
+ * return <div>...</div>;
35
+ * }
36
+ * ```
37
+ */
37
38
  /**
38
- * SolidJS Router integration bridge extending RouterBridgeBase
39
- *
40
- * Implements RouterBridge protocol for SolidJS Router using Solid's reactive
41
- * primitives. The actor→router direction uses TC39 Signal watcher (from base class).
42
- * The router→actor direction uses Solid's createEffect for native reactivity.
43
- *
44
- * Path parameters are extracted from Solid's `useParams()` reactive proxy rather than
45
- * re-parsing the URL with URLPattern. This means parameterized routes work without the
46
- * URLPattern polyfill — Solid's router has already extracted the values.
47
- */
48
- export class SolidRouterBridge extends RouterBridgeBase {
49
- solidNavigate;
50
- location;
51
- disposeRouterWatcher = null;
52
- /**
53
- * Live reactive params object from Solid's `useParams()`.
54
- * Read inside the createEffect callback so it always reflects the current route.
55
- */
56
- solidParams;
57
- /**
58
- * Create a SolidJS Router bridge
59
- *
60
- * **CRITICAL:** `connect()` must be called inside a Solid component where hooks are available.
61
- *
62
- * @param solidNavigate - Result of useNavigate() hook
63
- * @param location - Result of useLocation() hook
64
- * @param params - Result of useParams() hook — used directly for path parameter extraction,
65
- * avoiding the URLPattern polyfill requirement for parameterized routes
66
- * @param actor - XMachines actor instance
67
- * @param routeMap - Bidirectional state ID ↔ path mapping
68
- */
69
- constructor(solidNavigate, location, params, actor, routeMap) {
70
- super(actor, {
71
- getStateIdByPath: (path) => routeMap.getStateIdByPath(path),
72
- getPathByStateId: (id) => routeMap.getPathByStateId(id),
73
- });
74
- this.solidNavigate = solidNavigate;
75
- this.location = location;
76
- this.solidParams = params;
77
- }
78
- /**
79
- * Extract path parameters using Solid's pre-parsed `useParams()` values.
80
- *
81
- * Solid's router has already extracted all named parameters for the matched route
82
- * segment. Reading `this.solidParams` inside the createEffect callback that drives
83
- * `syncActorFromRouter` is safe — the reactive proxy always reflects the current
84
- * route at the time the effect runs.
85
- *
86
- * Falls back to URLPattern-based extraction (base class) only when Solid provided
87
- * no params for this route (i.e. the route has no `:param` segments).
88
- *
89
- * @param pathname - The actual URL path (unused — params already extracted by Solid)
90
- * @param stateId - The matched state ID (unused — params already extracted by Solid)
91
- * @returns Normalized path parameters with undefined/empty values filtered out
92
- */
93
- extractParams(pathname, stateId) {
94
- const entries = Object.entries(this.solidParams).filter((entry) => entry[1] !== undefined && entry[1] !== null && entry[1] !== "");
95
- if (entries.length > 0) {
96
- return Object.fromEntries(entries);
97
- }
98
- // No params from Solid — fall back to URLPattern for routes with no segments
99
- return super.extractParams(pathname, stateId);
100
- }
101
- /**
102
- * Navigate SolidJS Router to the given path.
103
- */
104
- navigateRouter(path) {
105
- this.solidNavigate(path);
106
- }
107
- /**
108
- * Get the current router pathname for initial URL -> actor sync on connect.
109
- */
110
- getInitialRouterPath() {
111
- return this.location.pathname ?? null;
112
- }
113
- /**
114
- * Return the initial URL search string for query-param forwarding on `connect()`.
115
- *
116
- * Reads `this.location.search` from Solid's `useLocation()` reactive object —
117
- * the same source used by `getInitialRouterPath()`. An empty string (no query
118
- * params) returns `undefined` so `syncActorFromRouter` produces `query: {}`.
119
- */
120
- getInitialRouterSearch() {
121
- return this.location.search || undefined;
122
- }
123
- /**
124
- * Subscribe to SolidJS Router location changes using createEffect.
125
- *
126
- * MUST be called inside a Solid reactive owner (component or createRoot).
127
- *
128
- * The effect runs inside `createRoot()` to give it a stable owner independent
129
- * of the calling component's lifecycle this prevents the effect from being
130
- * disposed if the component re-renders while the bridge should stay active.
131
- * The trade-off is that component unmount does NOT automatically clean up the
132
- * effect; `disconnect()` (or `dispose()`) MUST be called explicitly to avoid a leak.
133
- */
134
- watchRouterChanges() {
135
- this.disposeRouterWatcher = createRoot((dispose) => {
136
- createEffect(on(() => this.location.pathname, (pathname) => {
137
- const search = this.location.search ?? "";
138
- this.syncActorFromRouter(pathname, search);
139
- }));
140
- return dispose;
141
- });
142
- }
143
- /**
144
- * Stop watching SolidJS Router changes.
145
- *
146
- * Calls the `dispose` function returned by `createRoot()` in `watchRouterChanges()`,
147
- * tearing down the reactive effect and freeing the isolated owner. This is the only
148
- * cleanup path — component unmount does NOT trigger this automatically.
149
- */
150
- unwatchRouterChanges() {
151
- this.disposeRouterWatcher?.();
152
- this.disposeRouterWatcher = null;
153
- }
154
- /**
155
- * Dispose the bridge (alias for disconnect).
156
- *
157
- * @example
158
- * ```tsx
159
- * onCleanup(() => bridge.dispose());
160
- * ```
161
- */
162
- dispose() {
163
- this.disconnect();
164
- }
165
- }
39
+ * SolidJS Router integration bridge extending RouterBridgeBase
40
+ *
41
+ * Implements RouterBridge protocol for SolidJS Router using Solid's reactive
42
+ * primitives. The actor→router direction uses TC39 Signal watcher (from base class).
43
+ * The router→actor direction uses Solid's createEffect for native reactivity.
44
+ *
45
+ * Path parameters are extracted from Solid's `useParams()` reactive proxy rather than
46
+ * re-parsing the URL with URLPattern. This means parameterized routes work without the
47
+ * URLPattern polyfill — Solid's router has already extracted the values.
48
+ */
49
+ var SolidRouterBridge = class extends RouterBridgeBase {
50
+ solidNavigate;
51
+ location;
52
+ disposeRouterWatcher = null;
53
+ /**
54
+ * Live reactive params object from Solid's `useParams()`.
55
+ * Read inside the createEffect callback so it always reflects the current route.
56
+ */
57
+ solidParams;
58
+ /**
59
+ * Create a SolidJS Router bridge
60
+ *
61
+ * **CRITICAL:** `connect()` must be called inside a Solid component where hooks are available.
62
+ *
63
+ * @param solidNavigate - Result of useNavigate() hook
64
+ * @param location - Result of useLocation() hook
65
+ * @param params - Result of useParams() hook — used directly for path parameter extraction,
66
+ * avoiding the URLPattern polyfill requirement for parameterized routes
67
+ * @param actor - XMachines actor instance
68
+ * @param routeMap - Bidirectional state ID ↔ path mapping
69
+ */
70
+ constructor(solidNavigate, location, params, actor, routeMap) {
71
+ super(actor, {
72
+ getStateIdByPath: (path) => routeMap.getStateIdByPath(path),
73
+ getPathByStateId: (id) => routeMap.getPathByStateId(id)
74
+ });
75
+ this.solidNavigate = solidNavigate;
76
+ this.location = location;
77
+ this.solidParams = params;
78
+ }
79
+ /**
80
+ * Extract path parameters using Solid's pre-parsed `useParams()` values.
81
+ *
82
+ * Solid's router has already extracted all named parameters for the matched route
83
+ * segment. Reading `this.solidParams` inside the createEffect callback that drives
84
+ * `syncActorFromRouter` is safe — the reactive proxy always reflects the current
85
+ * route at the time the effect runs.
86
+ *
87
+ * Falls back to URLPattern-based extraction (base class) only when Solid provided
88
+ * no params for this route (i.e. the route has no `:param` segments).
89
+ *
90
+ * @param pathname - The actual URL path (unused — params already extracted by Solid)
91
+ * @param stateId - The matched state ID (unused — params already extracted by Solid)
92
+ * @returns Normalized path parameters with undefined/empty values filtered out
93
+ */
94
+ extractParams(pathname, stateId) {
95
+ const entries = Object.entries(this.solidParams).filter((entry) => entry[1] !== void 0 && entry[1] !== null && entry[1] !== "");
96
+ if (entries.length > 0) return Object.fromEntries(entries);
97
+ return super.extractParams(pathname, stateId);
98
+ }
99
+ /**
100
+ * Navigate SolidJS Router to the given path.
101
+ */
102
+ navigateRouter(path) {
103
+ this.solidNavigate(path);
104
+ }
105
+ /**
106
+ * Get the current router pathname for initial URL -> actor sync on connect.
107
+ */
108
+ getInitialRouterPath() {
109
+ return this.location.pathname ?? null;
110
+ }
111
+ /**
112
+ * Return the initial URL search string for query-param forwarding on `connect()`.
113
+ *
114
+ * Reads `this.location.search` from Solid's `useLocation()` reactive object —
115
+ * the same source used by `getInitialRouterPath()`. An empty string (no query
116
+ * params) returns `undefined` so `syncActorFromRouter` produces `query: {}`.
117
+ */
118
+ getInitialRouterSearch() {
119
+ return this.location.search || void 0;
120
+ }
121
+ /**
122
+ * Subscribe to SolidJS Router location changes using createEffect.
123
+ *
124
+ * MUST be called inside a Solid reactive owner (component or createRoot).
125
+ *
126
+ * The effect runs inside `createRoot()` to give it a stable owner independent
127
+ * of the calling component's lifecycle this prevents the effect from being
128
+ * disposed if the component re-renders while the bridge should stay active.
129
+ * The trade-off is that component unmount does NOT automatically clean up the
130
+ * effect; `disconnect()` (or `dispose()`) MUST be called explicitly to avoid a leak.
131
+ */
132
+ watchRouterChanges() {
133
+ this.disposeRouterWatcher = createRoot((dispose) => {
134
+ createEffect(on(() => this.location.pathname, (pathname) => {
135
+ const search = this.location.search ?? "";
136
+ this.syncActorFromRouter(pathname, search);
137
+ }));
138
+ return dispose;
139
+ });
140
+ }
141
+ /**
142
+ * Stop watching SolidJS Router changes.
143
+ *
144
+ * Calls the `dispose` function returned by `createRoot()` in `watchRouterChanges()`,
145
+ * tearing down the reactive effect and freeing the isolated owner. This is the only
146
+ * cleanup path — component unmount does NOT trigger this automatically.
147
+ */
148
+ unwatchRouterChanges() {
149
+ this.disposeRouterWatcher?.();
150
+ this.disposeRouterWatcher = null;
151
+ }
152
+ /**
153
+ * Dispose the bridge (alias for disconnect).
154
+ *
155
+ * @example
156
+ * ```tsx
157
+ * onCleanup(() => bridge.dispose());
158
+ * ```
159
+ */
160
+ dispose() {
161
+ this.disconnect();
162
+ }
163
+ };
164
+ //#endregion
165
+ export { SolidRouterBridge };
166
+
166
167
  //# sourceMappingURL=solid-router-bridge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"solid-router-bridge.js","sourceRoot":"","sources":["../src/solid-router-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAK1D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IAsBpC;IACA;IAtBV,oBAAoB,GAAwB,IAAI,CAAC;IAEzD;;;OAGG;IACc,WAAW,CAAS;IAErC;;;;;;;;;;;OAWG;IACH,YACkB,aAAwB,EACxB,QAAsB,EACvC,MAAc,EACd,KAAoB,EACpB,QAAkB;QAElB,KAAK,CAAC,KAAK,EAAE;YACZ,gBAAgB,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACnE,gBAAgB,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAC;QATc,kBAAa,GAAb,aAAa,CAAW;QACxB,aAAQ,GAAR,QAAQ,CAAc;QASvC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACgB,aAAa,CAAC,QAAgB,EAAE,OAAe;QACjE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CACtD,CAAC,KAAK,EAA6B,EAAE,CACpC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAC/D,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;QACD,6EAA6E;QAC7E,OAAO,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACO,cAAc,CAAC,IAAY;QACpC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACgB,oBAAoB;QACtC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC;IACvC,CAAC;IAED;;;;;;OAMG;IACgB,sBAAsB;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,SAAS,CAAC;IAC1C,CAAC;IAED;;;;;;;;;;OAUG;IACO,kBAAkB;QAC3B,IAAI,CAAC,oBAAoB,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,EAAE;YAClD,YAAY,CACX,EAAE,CACD,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAC5B,CAAC,QAAgB,EAAE,EAAE;gBACpB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;gBAC1C,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC5C,CAAC,CACD,CACD,CAAC;YACF,OAAO,OAAO,CAAC;QAChB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACO,oBAAoB;QAC7B,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAClC,CAAC;IAED;;;;;;;OAOG;IACH,OAAO;QACN,IAAI,CAAC,UAAU,EAAE,CAAC;IACnB,CAAC;CACD"}
1
+ {"version":3,"file":"solid-router-bridge.js","names":[],"sources":["../src/solid-router-bridge.ts"],"sourcesContent":["/**\n * SolidJS Router bridge implementing RouterBridge protocol via RouterBridgeBase\n *\n * Extends RouterBridgeBase to handle all common lifecycle and sync logic.\n * Uses Solid's native reactive primitives (createEffect) for router→actor direction.\n *\n * **IMPORTANT:** `connect()` MUST be called inside a Solid reactive owner (component\n * or createRoot). The `createEffect()` in `watchRouterChanges()` runs inside\n * `createRoot()`, which deliberately isolates it from any parent owner — automatic\n * cleanup on component unmount does NOT happen. You MUST call `disconnect()` (or\n * `dispose()`) explicitly, typically in `onCleanup()`.\n *\n * @example\n * ```tsx\n * import { useNavigate, useLocation, useParams } from '@solidjs/router';\n * import { onCleanup } from 'solid-js';\n * import { SolidRouterBridge, RouteMap } from '@xmachines/play-solid-router';\n *\n * function App() {\n * const navigate = useNavigate();\n * const location = useLocation();\n * const params = useParams();\n *\n * const routeMap = new RouteMap([...]);\n * const bridge = new SolidRouterBridge(navigate, location, params, actor, routeMap);\n *\n * // connect() MUST be called inside a Solid reactive owner\n * bridge.connect();\n * onCleanup(() => bridge.disconnect());\n *\n * return <div>...</div>;\n * }\n * ```\n */\n\nimport { createEffect, createRoot, on } from \"solid-js\";\nimport type { Navigator, Params } from \"@solidjs/router\";\nimport { RouterBridgeBase } from \"@xmachines/play-router\";\nimport type { LocationLike } from \"@xmachines/play-router\";\nimport type { RoutableActor } from \"@xmachines/play-router\";\nimport type { RouteMap } from \"@xmachines/play-router\";\n\n/**\n * SolidJS Router integration bridge extending RouterBridgeBase\n *\n * Implements RouterBridge protocol for SolidJS Router using Solid's reactive\n * primitives. The actor→router direction uses TC39 Signal watcher (from base class).\n * The router→actor direction uses Solid's createEffect for native reactivity.\n *\n * Path parameters are extracted from Solid's `useParams()` reactive proxy rather than\n * re-parsing the URL with URLPattern. This means parameterized routes work without the\n * URLPattern polyfill — Solid's router has already extracted the values.\n */\nexport class SolidRouterBridge extends RouterBridgeBase {\n\tprivate disposeRouterWatcher: (() => void) | null = null;\n\n\t/**\n\t * Live reactive params object from Solid's `useParams()`.\n\t * Read inside the createEffect callback so it always reflects the current route.\n\t */\n\tprivate readonly solidParams: Params;\n\n\t/**\n\t * Create a SolidJS Router bridge\n\t *\n\t * **CRITICAL:** `connect()` must be called inside a Solid component where hooks are available.\n\t *\n\t * @param solidNavigate - Result of useNavigate() hook\n\t * @param location - Result of useLocation() hook\n\t * @param params - Result of useParams() hook — used directly for path parameter extraction,\n\t * avoiding the URLPattern polyfill requirement for parameterized routes\n\t * @param actor - XMachines actor instance\n\t * @param routeMap - Bidirectional state ID ↔ path mapping\n\t */\n\tconstructor(\n\t\tprivate readonly solidNavigate: Navigator,\n\t\tprivate readonly location: LocationLike,\n\t\tparams: Params,\n\t\tactor: RoutableActor,\n\t\trouteMap: RouteMap,\n\t) {\n\t\tsuper(actor, {\n\t\t\tgetStateIdByPath: (path: string) => routeMap.getStateIdByPath(path),\n\t\t\tgetPathByStateId: (id: string) => routeMap.getPathByStateId(id),\n\t\t});\n\t\tthis.solidParams = params;\n\t}\n\n\t/**\n\t * Extract path parameters using Solid's pre-parsed `useParams()` values.\n\t *\n\t * Solid's router has already extracted all named parameters for the matched route\n\t * segment. Reading `this.solidParams` inside the createEffect callback that drives\n\t * `syncActorFromRouter` is safe — the reactive proxy always reflects the current\n\t * route at the time the effect runs.\n\t *\n\t * Falls back to URLPattern-based extraction (base class) only when Solid provided\n\t * no params for this route (i.e. the route has no `:param` segments).\n\t *\n\t * @param pathname - The actual URL path (unused — params already extracted by Solid)\n\t * @param stateId - The matched state ID (unused — params already extracted by Solid)\n\t * @returns Normalized path parameters with undefined/empty values filtered out\n\t */\n\tprotected override extractParams(pathname: string, stateId: string): Record<string, string> {\n\t\tconst entries = Object.entries(this.solidParams).filter(\n\t\t\t(entry): entry is [string, string] =>\n\t\t\t\tentry[1] !== undefined && entry[1] !== null && entry[1] !== \"\",\n\t\t);\n\t\tif (entries.length > 0) {\n\t\t\treturn Object.fromEntries(entries);\n\t\t}\n\t\t// No params from Solid — fall back to URLPattern for routes with no segments\n\t\treturn super.extractParams(pathname, stateId);\n\t}\n\n\t/**\n\t * Navigate SolidJS Router to the given path.\n\t */\n\tprotected navigateRouter(path: string): void {\n\t\tthis.solidNavigate(path);\n\t}\n\n\t/**\n\t * Get the current router pathname for initial URL -> actor sync on connect.\n\t */\n\tprotected override getInitialRouterPath(): string | null {\n\t\treturn this.location.pathname ?? null;\n\t}\n\n\t/**\n\t * Return the initial URL search string for query-param forwarding on `connect()`.\n\t *\n\t * Reads `this.location.search` from Solid's `useLocation()` reactive object —\n\t * the same source used by `getInitialRouterPath()`. An empty string (no query\n\t * params) returns `undefined` so `syncActorFromRouter` produces `query: {}`.\n\t */\n\tprotected override getInitialRouterSearch(): string | undefined {\n\t\treturn this.location.search || undefined;\n\t}\n\n\t/**\n\t * Subscribe to SolidJS Router location changes using createEffect.\n\t *\n\t * MUST be called inside a Solid reactive owner (component or createRoot).\n\t *\n\t * The effect runs inside `createRoot()` to give it a stable owner independent\n\t * of the calling component's lifecycle — this prevents the effect from being\n\t * disposed if the component re-renders while the bridge should stay active.\n\t * The trade-off is that component unmount does NOT automatically clean up the\n\t * effect; `disconnect()` (or `dispose()`) MUST be called explicitly to avoid a leak.\n\t */\n\tprotected watchRouterChanges(): void {\n\t\tthis.disposeRouterWatcher = createRoot((dispose) => {\n\t\t\tcreateEffect(\n\t\t\t\ton(\n\t\t\t\t\t() => this.location.pathname,\n\t\t\t\t\t(pathname: string) => {\n\t\t\t\t\t\tconst search = this.location.search ?? \"\";\n\t\t\t\t\t\tthis.syncActorFromRouter(pathname, search);\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn dispose;\n\t\t});\n\t}\n\n\t/**\n\t * Stop watching SolidJS Router changes.\n\t *\n\t * Calls the `dispose` function returned by `createRoot()` in `watchRouterChanges()`,\n\t * tearing down the reactive effect and freeing the isolated owner. This is the only\n\t * cleanup path — component unmount does NOT trigger this automatically.\n\t */\n\tprotected unwatchRouterChanges(): void {\n\t\tthis.disposeRouterWatcher?.();\n\t\tthis.disposeRouterWatcher = null;\n\t}\n\n\t/**\n\t * Dispose the bridge (alias for disconnect).\n\t *\n\t * @example\n\t * ```tsx\n\t * onCleanup(() => bridge.dispose());\n\t * ```\n\t */\n\tdispose(): void {\n\t\tthis.disconnect();\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,IAAa,oBAAb,cAAuC,iBAAiB;CAsBrC;CACA;CAtBlB,uBAAoD;;;;;CAMpD;;;;;;;;;;;;;CAcA,YACC,eACA,UACA,QACA,OACA,UACC;EACD,MAAM,OAAO;GACZ,mBAAmB,SAAiB,SAAS,iBAAiB,IAAI;GAClE,mBAAmB,OAAe,SAAS,iBAAiB,EAAE;EAC/D,CAAC;EATgB,KAAA,gBAAA;EACA,KAAA,WAAA;EASjB,KAAK,cAAc;CACpB;;;;;;;;;;;;;;;;CAiBA,cAAiC,UAAkB,SAAyC;EAC3F,MAAM,UAAU,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,QAC/C,UACA,MAAM,OAAO,KAAA,KAAa,MAAM,OAAO,QAAQ,MAAM,OAAO,EAC9D;EACA,IAAI,QAAQ,SAAS,GACpB,OAAO,OAAO,YAAY,OAAO;EAGlC,OAAO,MAAM,cAAc,UAAU,OAAO;CAC7C;;;;CAKA,eAAyB,MAAoB;EAC5C,KAAK,cAAc,IAAI;CACxB;;;;CAKA,uBAAyD;EACxD,OAAO,KAAK,SAAS,YAAY;CAClC;;;;;;;;CASA,yBAAgE;EAC/D,OAAO,KAAK,SAAS,UAAU,KAAA;CAChC;;;;;;;;;;;;CAaA,qBAAqC;EACpC,KAAK,uBAAuB,YAAY,YAAY;GACnD,aACC,SACO,KAAK,SAAS,WACnB,aAAqB;IACrB,MAAM,SAAS,KAAK,SAAS,UAAU;IACvC,KAAK,oBAAoB,UAAU,MAAM;GAC1C,CACD,CACD;GACA,OAAO;EACR,CAAC;CACF;;;;;;;;CASA,uBAAuC;EACtC,KAAK,uBAAuB;EAC5B,KAAK,uBAAuB;CAC7B;;;;;;;;;CAUA,UAAgB;EACf,KAAK,WAAW;CACjB;AACD"}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@xmachines/play-solid-router",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "SolidJS Router adapter for XMachines Universal Player Architecture",
5
5
  "license": "MIT",
6
6
  "author": "XMachines Contributors",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+ssh://git@gitlab.com/xmachin-es/xmachines-js.git",
9
+ "url": "git+https://gitlab.com/xmachin-es/xmachines-js.git",
10
10
  "directory": "packages/play-solid-router"
11
11
  },
12
12
  "files": [
@@ -22,13 +22,14 @@
22
22
  ".": {
23
23
  "types": "./dist/index.d.ts",
24
24
  "default": "./dist/index.js"
25
- }
25
+ },
26
+ "./package.json": "./package.json"
26
27
  },
27
28
  "publishConfig": {
28
29
  "access": "public"
29
30
  },
30
31
  "scripts": {
31
- "build": "tsc --build",
32
+ "build": "vite build && tsc --build",
32
33
  "lint": "oxlint .",
33
34
  "format": "oxfmt .",
34
35
  "test": "vitest",
@@ -36,22 +37,23 @@
36
37
  "clean": "rm -rf dist *.tsbuildinfo coverage node_modules/.svelte2tsx-* node_modules/.vite*"
37
38
  },
38
39
  "dependencies": {
39
- "@xmachines/play": "1.1.0",
40
- "@xmachines/play-actor": "1.1.0",
41
- "@xmachines/play-router": "1.1.0",
42
- "@xmachines/play-signals": "1.1.0"
40
+ "@xmachines/play": "2.0.0",
41
+ "@xmachines/play-actor": "2.0.0",
42
+ "@xmachines/play-router": "2.0.0",
43
+ "@xmachines/play-signals": "2.0.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@solidjs/router": "^0.16.1",
46
47
  "@solidjs/testing-library": "^0.8.10",
47
48
  "@testing-library/jest-dom": "^6.9.1",
48
49
  "@types/node": "^26.2.0",
49
- "@vitest/browser-playwright": "^4.1.10",
50
- "@xmachines/play-xstate": "1.1.0",
50
+ "@vitest/browser-playwright": "^4.1.11",
51
+ "@xmachines/play-xstate": "2.0.0",
51
52
  "jsdom": "^29.1.0",
52
53
  "oxfmt": "^0.64.0",
53
54
  "oxlint": "^1.79.0",
54
55
  "solid-js": "^1.9.12",
56
+ "vite": "^8.0.10",
55
57
  "vite-plugin-solid": "^2.11.11",
56
58
  "vitest": "^4.1.11",
57
59
  "xstate": "^5.31.0"
@@ -1,45 +0,0 @@
1
- /**
2
- * createPlayRouterProvider — factory for Solid `PlayRouterProvider` components
3
- *
4
- * Captures the provider component shape used by this package's
5
- * `PlayRouterProvider` — create a bridge synchronously at component evaluation
6
- * time, `connect()` it, and `disconnect()` in `onCleanup` — so that Solid
7
- * bridges with the standard `(router, actor, routeMap)` constructor can be
8
- * wrapped in a provider with a single call. Only the bridge class (and
9
- * therefore the `router` prop type) differs between providers created by this
10
- * factory.
11
- *
12
- * @packageDocumentation
13
- */
14
- import { onCleanup } from "solid-js";
15
- /**
16
- * Create a Solid `PlayRouterProvider` component bound to a specific bridge class.
17
- *
18
- * The returned component connects a `PlayerActor` to the framework router,
19
- * keeping actor state and browser URL in sync bidirectionally.
20
- *
21
- * The bridge is created synchronously at component evaluation time (Solid's
22
- * execution model) and torn down via `onCleanup` when the component is disposed.
23
- * Unlike React, prop stability is not a concern — Solid's `props` accessor is
24
- * already reactive and the bridge is created once per component instance.
25
- *
26
- * @param BridgeCtor - Bridge class constructed as `new BridgeCtor(router, actor, routeMap)`.
27
- * @returns A `PlayRouterProvider` component, generic over the actor type so the
28
- * `renderer` callback receives the same concrete actor type that was passed in.
29
- *
30
- * @example
31
- * ```tsx
32
- * export const PlayRouterProvider = createPlayRouterProvider(MySolidRouterBridge);
33
- * ```
34
- */
35
- export function createPlayRouterProvider(BridgeCtor) {
36
- return function PlayRouterProvider(props) {
37
- const bridge = new BridgeCtor(props.router, props.actor, props.routeMap);
38
- void bridge.connect();
39
- onCleanup(() => {
40
- void bridge.disconnect();
41
- });
42
- return <>{props.renderer(props.actor, props.router)}</>;
43
- };
44
- }
45
- //# sourceMappingURL=create-play-router-provider.jsx.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-play-router-provider.jsx","sourceRoot":"","sources":["../src/create-play-router-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,SAAS,EAAY,MAAM,UAAU,CAAC;AAkC/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,wBAAwB,CACvC,UAAgD;IAEhD,OAAO,SAAS,kBAAkB,CACjC,KAAmD;QAEnD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACzE,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;QAEtB,SAAS,CAAC,GAAG,EAAE;YACd,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC;IACzD,CAAC,CAAC;AACH,CAAC"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAO/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAK5E,OAAO,EACN,QAAQ,EACR,cAAc,GAGd,MAAM,wBAAwB,CAAC"}
@@ -1,41 +0,0 @@
1
- import { SolidRouterBridge } from "./solid-router-bridge.js";
2
- import { createPlayRouterProvider, } from "./create-play-router-provider.js";
3
- /**
4
- * Adapter binding `SolidRouterBridge`'s hook-argument constructor to the
5
- * `(router, actor, routeMap)` shape expected by `createPlayRouterProvider`.
6
- */
7
- class SolidHooksRouterBridge extends SolidRouterBridge {
8
- constructor(router, actor, routeMap) {
9
- super(router.navigate, router.location, router.params, actor, routeMap);
10
- }
11
- }
12
- /**
13
- * Connects a `PlayerActor` to Solid Router, keeping actor state and browser URL
14
- * in sync bidirectionally.
15
- *
16
- * The bridge is created synchronously at component evaluation time (Solid's
17
- * execution model) and torn down via `onCleanup` when the component is disposed.
18
- * Unlike React, prop stability is not a concern — Solid's `props` accessor is
19
- * already reactive and the bridge is created once per component instance.
20
- *
21
- * The `router` prop must be obtained from Solid Router hooks in the parent component:
22
- *
23
- * ```tsx
24
- * function AppShell() {
25
- * const navigate = useNavigate();
26
- * const location = useLocation();
27
- * const params = useParams();
28
- *
29
- * return (
30
- * <PlayRouterProvider
31
- * actor={actor}
32
- * routeMap={routeMap}
33
- * router={{ navigate, location, params }}
34
- * renderer={(a) => <PlayRenderer actor={a} registry={registry} />}
35
- * />
36
- * );
37
- * }
38
- * ```
39
- */
40
- export const PlayRouterProvider = createPlayRouterProvider(SolidHooksRouterBridge);
41
- //# sourceMappingURL=play-router-provider.jsx.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"play-router-provider.jsx","sourceRoot":"","sources":["../src/play-router-provider.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACN,wBAAwB,GAExB,MAAM,kCAAkC,CAAC;AAwC1C;;;GAGG;AACH,MAAM,sBAAuB,SAAQ,iBAAiB;IACrD,YAAY,MAAwB,EAAE,KAAgB,EAAE,QAAkB;QACzE,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzE,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,sBAAsB,CAAC,CAAC"}
package/dist/types.js DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * Type definitions for @xmachines/play-solid-router
3
- */
4
- export {};
5
- //# sourceMappingURL=types.js.map
package/dist/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}