akanjs 2.3.1-rc.1 → 2.3.1-rc.2
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
CHANGED
package/server/rscClient.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { createElement, type ReactNode, startTransition,
|
|
1
|
+
import { createElement, type ReactNode, startTransition, type Usable, use, useLayoutEffect, useState } from "react";
|
|
2
|
+
import { flushSync } from "react-dom";
|
|
2
3
|
import { hydrateRoot } from "react-dom/client";
|
|
3
4
|
import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
|
|
4
5
|
import {
|
|
@@ -80,6 +81,7 @@ type RscFetchResult =
|
|
|
80
81
|
}
|
|
81
82
|
| { type: "redirected"; status?: number };
|
|
82
83
|
const MAX_RSC_CACHE_ENTRIES = 32;
|
|
84
|
+
const AKAN_RSC_NAVIGATION_COMMITTED_EVENT = "akan:rsc-navigation-committed";
|
|
83
85
|
let documentNavigationFallbackInFlight = false;
|
|
84
86
|
|
|
85
87
|
class RscRedirectNavigationStarted extends Error {
|
|
@@ -150,6 +152,10 @@ function hardNavigateAfterRscFailure(target: string, replace = false, error?: un
|
|
|
150
152
|
else window.location.assign(target);
|
|
151
153
|
}
|
|
152
154
|
|
|
155
|
+
function dispatchRscNavigationCommitted(href: string): void {
|
|
156
|
+
window.dispatchEvent(new CustomEvent(AKAN_RSC_NAVIGATION_COMMITTED_EVENT, { detail: { href } }));
|
|
157
|
+
}
|
|
158
|
+
|
|
153
159
|
function navigateAfterRscRedirect(target: string, replace = true): void {
|
|
154
160
|
const error = new RscRedirectNavigationStarted(target);
|
|
155
161
|
const navigate = globalThis.__AKAN_RSC_NAVIGATE__;
|
|
@@ -168,12 +174,14 @@ function commitRscPatchNavigation({
|
|
|
168
174
|
replace,
|
|
169
175
|
scrollToTop,
|
|
170
176
|
bumpScrollToTop,
|
|
177
|
+
onCommitted,
|
|
171
178
|
}: {
|
|
172
179
|
target: string;
|
|
173
180
|
patch: Extract<RscFetchResult, { type: "patched" }>;
|
|
174
181
|
replace?: boolean;
|
|
175
182
|
scrollToTop?: boolean;
|
|
176
183
|
bumpScrollToTop?: () => void;
|
|
184
|
+
onCommitted?: () => void;
|
|
177
185
|
}): boolean {
|
|
178
186
|
const patchThenable = patch.patchedNode.thenable;
|
|
179
187
|
if (!patchThenable) throw new Error("[rscClient] validated RSC patch is missing a thenable");
|
|
@@ -182,7 +190,7 @@ function commitRscPatchNavigation({
|
|
|
182
190
|
|
|
183
191
|
let outletCommitted = false;
|
|
184
192
|
let headApplied = false;
|
|
185
|
-
|
|
193
|
+
flushSync(() => {
|
|
186
194
|
try {
|
|
187
195
|
headApplied = commitPreparedAkanHeadSnapshotPatch(preparedHeadPatch);
|
|
188
196
|
if (!headApplied) {
|
|
@@ -203,6 +211,7 @@ function commitRscPatchNavigation({
|
|
|
203
211
|
outletCommitted = false;
|
|
204
212
|
}
|
|
205
213
|
});
|
|
214
|
+
if (outletCommitted && headApplied) onCommitted?.();
|
|
206
215
|
return outletCommitted && headApplied;
|
|
207
216
|
}
|
|
208
217
|
|
|
@@ -375,9 +384,12 @@ function Root(): ReactNode {
|
|
|
375
384
|
maxEntries: MAX_RSC_CACHE_ENTRIES,
|
|
376
385
|
startTransition,
|
|
377
386
|
commitThenable: (node) => {
|
|
378
|
-
|
|
379
|
-
|
|
387
|
+
flushSync(() => {
|
|
388
|
+
resetAkanSegmentOutletPatches();
|
|
389
|
+
setThenable(node.thenable);
|
|
390
|
+
});
|
|
380
391
|
},
|
|
392
|
+
onCommitted: () => dispatchRscNavigationCommitted(target),
|
|
381
393
|
navId,
|
|
382
394
|
getCurrentNavId: () => navigationSeq,
|
|
383
395
|
});
|
|
@@ -420,6 +432,7 @@ function Root(): ReactNode {
|
|
|
420
432
|
replace: options.replace,
|
|
421
433
|
scrollToTop,
|
|
422
434
|
bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
|
|
435
|
+
onCommitted: () => dispatchRscNavigationCommitted(target),
|
|
423
436
|
})
|
|
424
437
|
) {
|
|
425
438
|
rememberPatchedRouteState(patchResult.tree, patchResult.patchedNode);
|
|
@@ -444,6 +457,7 @@ function Root(): ReactNode {
|
|
|
444
457
|
replace: options.replace,
|
|
445
458
|
scrollToTop,
|
|
446
459
|
bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
|
|
460
|
+
onCommitted: () => dispatchRscNavigationCommitted(target),
|
|
447
461
|
})
|
|
448
462
|
) {
|
|
449
463
|
rememberPatchedRouteState(fetched.tree, fetched.patchedNode);
|
|
@@ -490,8 +504,10 @@ function Root(): ReactNode {
|
|
|
490
504
|
maxEntries: MAX_RSC_CACHE_ENTRIES,
|
|
491
505
|
startTransition,
|
|
492
506
|
commitThenable: (node) => {
|
|
493
|
-
|
|
494
|
-
|
|
507
|
+
flushSync(() => {
|
|
508
|
+
resetAkanSegmentOutletPatches();
|
|
509
|
+
setThenable(node.thenable);
|
|
510
|
+
});
|
|
495
511
|
},
|
|
496
512
|
updateHistory: () => {
|
|
497
513
|
if (options.replace) window.history.replaceState(null, "", target);
|
|
@@ -499,6 +515,7 @@ function Root(): ReactNode {
|
|
|
499
515
|
},
|
|
500
516
|
scrollToTop,
|
|
501
517
|
bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
|
|
518
|
+
onCommitted: () => dispatchRscNavigationCommitted(target),
|
|
502
519
|
navId,
|
|
503
520
|
getCurrentNavId: () => navigationSeq,
|
|
504
521
|
});
|
|
@@ -329,6 +329,7 @@ interface CommitRscNavigationInput<T> {
|
|
|
329
329
|
updateHistory?: () => void;
|
|
330
330
|
scrollToTop?: boolean;
|
|
331
331
|
bumpScrollToTop?: () => void;
|
|
332
|
+
onCommitted?: () => void;
|
|
332
333
|
}
|
|
333
334
|
|
|
334
335
|
export function commitRscNavigation<T>({
|
|
@@ -341,6 +342,7 @@ export function commitRscNavigation<T>({
|
|
|
341
342
|
updateHistory,
|
|
342
343
|
scrollToTop,
|
|
343
344
|
bumpScrollToTop,
|
|
345
|
+
onCommitted,
|
|
344
346
|
}: CommitRscNavigationInput<T>): void {
|
|
345
347
|
rememberRscCacheEntry(cache, href, thenable, maxEntries);
|
|
346
348
|
startTransition(() => {
|
|
@@ -348,6 +350,7 @@ export function commitRscNavigation<T>({
|
|
|
348
350
|
updateHistory?.();
|
|
349
351
|
if (scrollToTop) bumpScrollToTop?.();
|
|
350
352
|
});
|
|
353
|
+
onCommitted?.();
|
|
351
354
|
}
|
|
352
355
|
|
|
353
356
|
export function commitLatestRscNavigation<T>({
|
|
@@ -87,8 +87,9 @@ interface CommitRscNavigationInput<T> {
|
|
|
87
87
|
updateHistory?: () => void;
|
|
88
88
|
scrollToTop?: boolean;
|
|
89
89
|
bumpScrollToTop?: () => void;
|
|
90
|
+
onCommitted?: () => void;
|
|
90
91
|
}
|
|
91
|
-
export declare function commitRscNavigation<T>({ cache, href, thenable, maxEntries, startTransition, commitThenable, updateHistory, scrollToTop, bumpScrollToTop, }: CommitRscNavigationInput<T>): void;
|
|
92
|
+
export declare function commitRscNavigation<T>({ cache, href, thenable, maxEntries, startTransition, commitThenable, updateHistory, scrollToTop, bumpScrollToTop, onCommitted, }: CommitRscNavigationInput<T>): void;
|
|
92
93
|
export declare function commitLatestRscNavigation<T>({ navId, getCurrentNavId, ...input }: CommitRscNavigationInput<T> & {
|
|
93
94
|
navId: number;
|
|
94
95
|
getCurrentNavId: () => number;
|
package/ui/System/Client.tsx
CHANGED
|
@@ -244,6 +244,8 @@ function buildSearchParams(entries: Iterable<[string, string]>): Record<string,
|
|
|
244
244
|
return params;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
const AKAN_RSC_NAVIGATION_COMMITTED_EVENT = "akan:rsc-navigation-committed";
|
|
248
|
+
|
|
247
249
|
export const ClientInner = () => {
|
|
248
250
|
const uiOperation = st.use.uiOperation();
|
|
249
251
|
return (
|
|
@@ -290,11 +292,9 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
|
|
|
290
292
|
prefix,
|
|
291
293
|
router: {
|
|
292
294
|
push: (href, routeOptions) => {
|
|
293
|
-
syncHref(href);
|
|
294
295
|
navigateRscWithFallback(href, routeOptions, () => window.location.assign(href));
|
|
295
296
|
},
|
|
296
297
|
replace: (href, routeOptions) => {
|
|
297
|
-
syncHref(href);
|
|
298
298
|
navigateRscWithFallback(href, { ...routeOptions, replace: true }, () => window.location.replace(href));
|
|
299
299
|
},
|
|
300
300
|
back: () => {
|
|
@@ -302,7 +302,6 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
|
|
|
302
302
|
},
|
|
303
303
|
refresh: () => {
|
|
304
304
|
clearRscNavigationCache();
|
|
305
|
-
syncHref(window.location.href);
|
|
306
305
|
void navigateRsc(window.location.href, {
|
|
307
306
|
replace: true,
|
|
308
307
|
scrollToTop: false,
|
|
@@ -310,7 +309,13 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
|
|
|
310
309
|
},
|
|
311
310
|
},
|
|
312
311
|
});
|
|
312
|
+
const syncCommittedNavigation = (event: Event) => {
|
|
313
|
+
const detail = (event as CustomEvent<{ href?: string }>).detail;
|
|
314
|
+
syncHref(detail?.href ?? window.location.href);
|
|
315
|
+
};
|
|
316
|
+
window.addEventListener(AKAN_RSC_NAVIGATION_COMMITTED_EVENT, syncCommittedNavigation);
|
|
313
317
|
void Device.load({ lang });
|
|
318
|
+
return () => window.removeEventListener(AKAN_RSC_NAVIGATION_COMMITTED_EVENT, syncCommittedNavigation);
|
|
314
319
|
}, [lang, prefix]);
|
|
315
320
|
|
|
316
321
|
useEffect(() => {
|
|
@@ -322,8 +327,6 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
|
|
|
322
327
|
st.set({ pathname: window.location.pathname, path, searchParams });
|
|
323
328
|
};
|
|
324
329
|
sync();
|
|
325
|
-
window.addEventListener("popstate", sync);
|
|
326
|
-
return () => window.removeEventListener("popstate", sync);
|
|
327
330
|
}, [lang, prefix]);
|
|
328
331
|
return null;
|
|
329
332
|
};
|