@blueshed/railroad 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/routes.ts +25 -5
package/package.json
CHANGED
package/routes.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* navigate(path) — set location.hash programmatically
|
|
8
8
|
* matchRoute(pattern, path) — pure pattern matcher, returns params or null
|
|
9
9
|
*
|
|
10
|
-
* Handlers receive (params, params$) and return a Node.
|
|
10
|
+
* Handlers receive (params, params$) and return a Node (sync or async).
|
|
11
11
|
* params — plain object for destructuring: ({ id }) => ...
|
|
12
12
|
* params$ — Signal that updates when params change within the same pattern
|
|
13
13
|
*
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* routes(app, {
|
|
17
17
|
* "/": () => <Home />,
|
|
18
18
|
* "/site/:id": ({ id }, params$) => <SiteDetail id={id} params$={params$} />,
|
|
19
|
+
* "/status": async () => { const s = await api.get(); return <Status data={s} />; },
|
|
19
20
|
* });
|
|
20
21
|
*/
|
|
21
22
|
|
|
@@ -81,7 +82,7 @@ export function navigate(path: string): void {
|
|
|
81
82
|
type RouteHandler = (
|
|
82
83
|
params: Record<string, string>,
|
|
83
84
|
params$: Signal<Record<string, string>>,
|
|
84
|
-
) => Node
|
|
85
|
+
) => Node | Promise<Node>;
|
|
85
86
|
|
|
86
87
|
export function routes(
|
|
87
88
|
target: HTMLElement,
|
|
@@ -91,8 +92,15 @@ export function routes(
|
|
|
91
92
|
let activePattern: string | null = null;
|
|
92
93
|
let activeParams: Signal<Record<string, string>> | null = null;
|
|
93
94
|
let activeDispose: Dispose | null = null;
|
|
95
|
+
let runId = 0;
|
|
96
|
+
let asyncPending = false;
|
|
94
97
|
|
|
95
98
|
function teardown() {
|
|
99
|
+
runId++;
|
|
100
|
+
if (asyncPending) {
|
|
101
|
+
popDisposeScope()();
|
|
102
|
+
asyncPending = false;
|
|
103
|
+
}
|
|
96
104
|
if (activeDispose) activeDispose();
|
|
97
105
|
activeDispose = null;
|
|
98
106
|
activePattern = null;
|
|
@@ -101,11 +109,23 @@ export function routes(
|
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
function run(handler: RouteHandler, params: Record<string, string>) {
|
|
112
|
+
const myRunId = ++runId;
|
|
104
113
|
activeParams = signal(params);
|
|
105
114
|
pushDisposeScope();
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
115
|
+
const result = handler(params, activeParams);
|
|
116
|
+
|
|
117
|
+
if (result instanceof Promise) {
|
|
118
|
+
asyncPending = true;
|
|
119
|
+
result.then((node) => {
|
|
120
|
+
if (myRunId !== runId) return; // navigated away during await
|
|
121
|
+
asyncPending = false;
|
|
122
|
+
activeDispose = popDisposeScope();
|
|
123
|
+
target.appendChild(node);
|
|
124
|
+
});
|
|
125
|
+
} else {
|
|
126
|
+
activeDispose = popDisposeScope();
|
|
127
|
+
target.appendChild(result);
|
|
128
|
+
}
|
|
109
129
|
}
|
|
110
130
|
|
|
111
131
|
const disposeEffect = effect(() => {
|