@tyndall/react 0.0.1 → 0.0.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/README.md +4 -0
- package/dist/adapter.d.ts +10 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +254 -34
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +31 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +8 -1
- package/dist/route-data.d.ts +5 -0
- package/dist/route-data.d.ts.map +1 -0
- package/dist/route-data.js +4 -0
- package/dist/router.d.ts +19 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +287 -39
- package/dist/types.d.ts +15 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -7,6 +7,10 @@ React adapter package that implements UIAdapter contracts, routing integration,
|
|
|
7
7
|
- Provide React-based rendering adapter, factory, and registry
|
|
8
8
|
- Provide client router and navigation components
|
|
9
9
|
- Integrate route payload transitions and head updates
|
|
10
|
+
- Provide `_app` wrapper support and pass `{ Component, pageProps, routeData, routeId }` to App components
|
|
11
|
+
- Expose `RouteDataProvider` and `useRouteData` for consuming route data maps
|
|
12
|
+
- Provide `useBlockRouting` and navigation blocker hooks for client transitions and `beforeunload`
|
|
13
|
+
- Support `router.softReload()` and scroll restoration during client-side transitions
|
|
10
14
|
- Coordinate hydration lifecycle markers and mounted-state guards for payload-driven navigation
|
|
11
15
|
- Guard dev runtime generation changes with controlled dispose/re-initialize flow to avoid mixed React hook dispatcher states during HMR
|
|
12
16
|
- Compose nested layout trees when route metadata supplies `layoutFiles`
|
package/dist/adapter.d.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { HmrIntegration, RouteGraph, UIAdapter, UIAdapterEntryContext, UIAdapterRenderContext, UIAdapterRenderResult } from "@tyndall/core";
|
|
2
3
|
export interface ReactAdapterOptions {
|
|
3
4
|
name?: string;
|
|
4
5
|
createClientEntry?: (ctx: UIAdapterEntryContext) => string;
|
|
5
6
|
createServerEntry?: (ctx: UIAdapterEntryContext) => string;
|
|
6
7
|
renderToHtml?: (ctx: UIAdapterRenderContext) => Promise<UIAdapterRenderResult> | UIAdapterRenderResult;
|
|
7
|
-
render?: (ctx: UIAdapterRenderContext) => Promise<
|
|
8
|
+
render?: (ctx: UIAdapterRenderContext) => Promise<React.ReactElement | null> | React.ReactElement | null;
|
|
8
9
|
getHead?: UIAdapter["getHead"];
|
|
9
10
|
hmrIntegration?: HmrIntegration;
|
|
10
11
|
routeGraph?: RouteGraph;
|
|
11
12
|
nestedLayouts?: boolean;
|
|
12
13
|
rootDir?: string;
|
|
13
14
|
routeRoot?: string;
|
|
15
|
+
appModule?: string;
|
|
16
|
+
appComponent?: React.ComponentType<AppComponentProps>;
|
|
17
|
+
}
|
|
18
|
+
export interface AppComponentProps {
|
|
19
|
+
Component: React.ComponentType<Record<string, unknown>>;
|
|
20
|
+
pageProps: Record<string, unknown>;
|
|
21
|
+
routeData: Record<string, unknown>;
|
|
22
|
+
routeId: string;
|
|
14
23
|
}
|
|
15
24
|
export declare const createReactAdapter: (options?: ReactAdapterOptions) => UIAdapter;
|
|
16
25
|
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,SAAS,EACT,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAKvB,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC3D,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC3D,YAAY,CAAC,EAAE,CACb,GAAG,EAAE,sBAAsB,KACxB,OAAO,CAAC,qBAAqB,CAAC,GAAG,qBAAqB,CAAC;IAC5D,MAAM,CAAC,EAAE,CACP,GAAG,EAAE,sBAAsB,KACxB,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IACpE,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;CACvD;AAMD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB;AAiiCD,eAAO,MAAM,kBAAkB,GAAI,UAAS,mBAAwB,KAAG,SAQrE,CAAC"}
|
package/dist/adapter.js
CHANGED
|
@@ -3,8 +3,13 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { join, relative, sep } from "node:path";
|
|
4
4
|
import { mergeHeadDescriptors, serializeProps } from "@tyndall/core";
|
|
5
5
|
import { collectHeadFromTree } from "./head.js";
|
|
6
|
+
import { RouteDataProvider } from "./route-data.js";
|
|
6
7
|
const REACT_ELEMENT = Symbol.for("react.element");
|
|
7
8
|
const REACT_TRANSITIONAL_ELEMENT = Symbol.for("react.transitional.element");
|
|
9
|
+
const REACT_FRAGMENT = Symbol.for("react.fragment");
|
|
10
|
+
const REACT_PROVIDER = Symbol.for("react.provider");
|
|
11
|
+
const REACT_MEMO = Symbol.for("react.memo");
|
|
12
|
+
const REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
8
13
|
const HEAD_ELEMENT = Symbol.for("hyper.head");
|
|
9
14
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
15
|
const isElementLike = (value) => isRecord(value) &&
|
|
@@ -54,6 +59,30 @@ const renderElementToString = (node) => {
|
|
|
54
59
|
if (isHeadMarker(node)) {
|
|
55
60
|
return "";
|
|
56
61
|
}
|
|
62
|
+
if (node.type === REACT_FRAGMENT) {
|
|
63
|
+
return renderElementToString(node.props.children);
|
|
64
|
+
}
|
|
65
|
+
if (isRecord(node.type) && node.type.$$typeof === REACT_PROVIDER) {
|
|
66
|
+
return renderElementToString(node.props.children);
|
|
67
|
+
}
|
|
68
|
+
if (isRecord(node.type) && node.type.$$typeof === REACT_MEMO) {
|
|
69
|
+
const innerType = node.type.type;
|
|
70
|
+
if (typeof innerType === "function") {
|
|
71
|
+
return renderElementToString(innerType(node.props));
|
|
72
|
+
}
|
|
73
|
+
if (typeof innerType === "string") {
|
|
74
|
+
return renderElementToString({ ...node, type: innerType });
|
|
75
|
+
}
|
|
76
|
+
return "";
|
|
77
|
+
}
|
|
78
|
+
if (isRecord(node.type) && node.type.$$typeof === REACT_FORWARD_REF) {
|
|
79
|
+
const render = node.type
|
|
80
|
+
.render;
|
|
81
|
+
if (typeof render === "function") {
|
|
82
|
+
return renderElementToString(render(node.props, null));
|
|
83
|
+
}
|
|
84
|
+
return "";
|
|
85
|
+
}
|
|
57
86
|
if (typeof node.type === "function") {
|
|
58
87
|
return renderElementToString(node.type(node.props));
|
|
59
88
|
}
|
|
@@ -75,12 +104,7 @@ const resolveReactDomServer = async () => {
|
|
|
75
104
|
const renderWithFallback = async (element) => {
|
|
76
105
|
const reactDomServer = await resolveReactDomServer();
|
|
77
106
|
if (reactDomServer?.renderToString) {
|
|
78
|
-
|
|
79
|
-
return reactDomServer.renderToString(element);
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
// Fall back when custom markers (e.g., <Head>) are not React-renderable.
|
|
83
|
-
}
|
|
107
|
+
return reactDomServer.renderToString(element);
|
|
84
108
|
}
|
|
85
109
|
// Fallback renderer keeps local tests/dev flows working without react-dom.
|
|
86
110
|
return renderElementToString(element);
|
|
@@ -91,6 +115,11 @@ const resolvePageImport = (ctx) => {
|
|
|
91
115
|
const specifier = typeof pageModule === "string" ? pageModule : "./page";
|
|
92
116
|
return JSON.stringify(specifier);
|
|
93
117
|
};
|
|
118
|
+
const resolveAppImport = (ctx) => {
|
|
119
|
+
const options = ctx.uiOptions ?? ctx.adapterOptions;
|
|
120
|
+
const appModule = options?.appModule;
|
|
121
|
+
return typeof appModule === "string" && appModule.length > 0 ? appModule : null;
|
|
122
|
+
};
|
|
94
123
|
const resolveHydrationMode = (ctx) => {
|
|
95
124
|
const options = ctx.uiOptions ?? ctx.adapterOptions;
|
|
96
125
|
return options?.hydration === "islands" ? "islands" : "full";
|
|
@@ -103,6 +132,13 @@ const resolveClientRenderMode = (ctx) => {
|
|
|
103
132
|
const options = ctx.uiOptions ?? ctx.adapterOptions;
|
|
104
133
|
return options?.clientRenderMode === "module" ? "module" : "payload";
|
|
105
134
|
};
|
|
135
|
+
const resolveScrollRestoration = (ctx) => {
|
|
136
|
+
const options = ctx.uiOptions ?? ctx.adapterOptions;
|
|
137
|
+
if (options && "scrollRestoration" in options) {
|
|
138
|
+
return options.scrollRestoration !== false;
|
|
139
|
+
}
|
|
140
|
+
return true;
|
|
141
|
+
};
|
|
106
142
|
const resolveClientRouteModules = (ctx) => {
|
|
107
143
|
const options = ctx.uiOptions ?? ctx.adapterOptions;
|
|
108
144
|
const raw = options?.clientRouteModules;
|
|
@@ -137,8 +173,8 @@ const resolveLayoutFilesForRoute = (routeGraph, routeId) => {
|
|
|
137
173
|
const route = findRouteRecord(routeGraph, routeId);
|
|
138
174
|
return route?.layoutFiles ?? [];
|
|
139
175
|
};
|
|
140
|
-
const resolveLayoutModulePath = (layoutFile, rootDir, routeRoot) => {
|
|
141
|
-
if (!rootDir || !routeRoot) {
|
|
176
|
+
const resolveLayoutModulePath = (layoutFile, rootDir, routeRoot, preferRouteRoot) => {
|
|
177
|
+
if (!preferRouteRoot || !rootDir || !routeRoot) {
|
|
142
178
|
return layoutFile;
|
|
143
179
|
}
|
|
144
180
|
const relativePath = relative(rootDir, layoutFile);
|
|
@@ -168,8 +204,18 @@ const resolveLayoutSpecifiersForRoute = (ctx, routeId) => {
|
|
|
168
204
|
if (layoutFiles.length === 0) {
|
|
169
205
|
return [];
|
|
170
206
|
}
|
|
207
|
+
const preferRouteRoot = typeof ctx.routeId === "string" && ctx.routeId === routeId;
|
|
171
208
|
return layoutFiles.map((layoutFile) => {
|
|
172
|
-
const modulePath = resolveLayoutModulePath(layoutFile, ctx.rootDir, ctx.routeRoot);
|
|
209
|
+
const modulePath = resolveLayoutModulePath(layoutFile, ctx.rootDir, ctx.routeRoot, preferRouteRoot);
|
|
210
|
+
return toImportSpecifier(ctx.entryDir ?? "", modulePath);
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
const resolveLayoutSpecifiersForEntry = (ctx, layoutFiles) => {
|
|
214
|
+
if (!ctx.entryDir || !layoutFiles || layoutFiles.length === 0) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
return layoutFiles.map((layoutFile) => {
|
|
218
|
+
const modulePath = resolveLayoutModulePath(layoutFile, ctx.rootDir, ctx.routeRoot, true);
|
|
173
219
|
return toImportSpecifier(ctx.entryDir ?? "", modulePath);
|
|
174
220
|
});
|
|
175
221
|
};
|
|
@@ -195,6 +241,7 @@ const buildClientRouteLayoutLoaderSource = (layoutModules) => {
|
|
|
195
241
|
};
|
|
196
242
|
};
|
|
197
243
|
const layoutComponentCache = new Map();
|
|
244
|
+
const appComponentCache = new Map();
|
|
198
245
|
const extractLayoutComponent = (loaded) => {
|
|
199
246
|
if (loaded && typeof loaded === "object" && "default" in loaded) {
|
|
200
247
|
const candidate = loaded.default;
|
|
@@ -207,8 +254,28 @@ const extractLayoutComponent = (loaded) => {
|
|
|
207
254
|
}
|
|
208
255
|
return null;
|
|
209
256
|
};
|
|
257
|
+
const extractAppComponent = (loaded) => {
|
|
258
|
+
if (loaded && typeof loaded === "object") {
|
|
259
|
+
if ("default" in loaded) {
|
|
260
|
+
const candidate = loaded.default;
|
|
261
|
+
if (typeof candidate === "function") {
|
|
262
|
+
return candidate;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if ("App" in loaded) {
|
|
266
|
+
const candidate = loaded.App;
|
|
267
|
+
if (typeof candidate === "function") {
|
|
268
|
+
return candidate;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (typeof loaded === "function") {
|
|
273
|
+
return loaded;
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
};
|
|
210
277
|
const loadLayoutComponent = async (layoutFile, options) => {
|
|
211
|
-
const modulePath = resolveLayoutModulePath(layoutFile, options.rootDir, options.routeRoot);
|
|
278
|
+
const modulePath = resolveLayoutModulePath(layoutFile, options.rootDir, options.routeRoot, true);
|
|
212
279
|
const cacheKey = `${options.routeRoot ?? ""}::${modulePath}`;
|
|
213
280
|
if (layoutComponentCache.has(cacheKey)) {
|
|
214
281
|
return layoutComponentCache.get(cacheKey);
|
|
@@ -233,6 +300,40 @@ const loadLayoutComponent = async (layoutFile, options) => {
|
|
|
233
300
|
}
|
|
234
301
|
}
|
|
235
302
|
};
|
|
303
|
+
const loadAppComponent = async (modulePath) => {
|
|
304
|
+
if (appComponentCache.has(modulePath)) {
|
|
305
|
+
return appComponentCache.get(modulePath);
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const moduleUrl = toFileUrl(modulePath);
|
|
309
|
+
const loaded = await import(moduleUrl);
|
|
310
|
+
const component = extractAppComponent(loaded);
|
|
311
|
+
appComponentCache.set(modulePath, component);
|
|
312
|
+
return component;
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
try {
|
|
316
|
+
const require = createRequire(import.meta.url);
|
|
317
|
+
const loaded = require(modulePath);
|
|
318
|
+
const component = extractAppComponent(loaded);
|
|
319
|
+
appComponentCache.set(modulePath, component);
|
|
320
|
+
return component;
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
const resolveAppComponentForRender = async (options) => {
|
|
328
|
+
if (typeof options.appComponent === "function") {
|
|
329
|
+
return options.appComponent;
|
|
330
|
+
}
|
|
331
|
+
if (!options.appModule) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
const loaded = await loadAppComponent(options.appModule);
|
|
335
|
+
return typeof loaded === "function" ? loaded : null;
|
|
336
|
+
};
|
|
236
337
|
const resolveLayoutComponentsForRender = async (routeId, options) => {
|
|
237
338
|
if (!resolveNestedLayoutsEnabled(options)) {
|
|
238
339
|
return [];
|
|
@@ -271,9 +372,11 @@ const buildClientRouteModuleLoaderSource = (modules) => {
|
|
|
271
372
|
};
|
|
272
373
|
const defaultClientEntry = (ctx) => {
|
|
273
374
|
const pageImport = resolvePageImport(ctx);
|
|
375
|
+
const appImport = resolveAppImport(ctx);
|
|
274
376
|
const hydrationMode = JSON.stringify(resolveHydrationMode(ctx));
|
|
275
377
|
const navigationMode = JSON.stringify(resolveNavigationMode(ctx));
|
|
276
378
|
const clientRenderMode = JSON.stringify(resolveClientRenderMode(ctx));
|
|
379
|
+
const scrollRestoration = JSON.stringify(resolveScrollRestoration(ctx));
|
|
277
380
|
const routeGraph = JSON.stringify(ctx.routeGraph ?? { routes: [] });
|
|
278
381
|
const entryRouteId = JSON.stringify(typeof ctx.routeId === "string" ? ctx.routeId : "");
|
|
279
382
|
const routeModules = resolveClientRouteModules(ctx);
|
|
@@ -288,25 +391,49 @@ const defaultClientEntry = (ctx) => {
|
|
|
288
391
|
: {};
|
|
289
392
|
const routeLayoutLoaders = buildClientRouteLayoutLoaderSource(routeLayoutModules);
|
|
290
393
|
const entryLayoutSpecifiers = nestedLayoutsEnabled && typeof ctx.routeId === "string"
|
|
291
|
-
?
|
|
394
|
+
? ctx.entryLayoutFiles && ctx.entryLayoutFiles.length > 0
|
|
395
|
+
? resolveLayoutSpecifiersForEntry(ctx, ctx.entryLayoutFiles)
|
|
396
|
+
: resolveLayoutSpecifiersForRoute(ctx, ctx.routeId)
|
|
292
397
|
: [];
|
|
293
398
|
const entryLayoutImports = entryLayoutSpecifiers.map((specifier, index) => `import EntryLayout${index} from ${JSON.stringify(specifier)};`);
|
|
294
399
|
const entryLayoutRefs = entryLayoutSpecifiers.map((_specifier, index) => `EntryLayout${index}`);
|
|
295
400
|
const entryLayoutArray = entryLayoutRefs.length > 0 ? `[${entryLayoutRefs.join(", ")}]` : "[]";
|
|
401
|
+
const appImportSource = appImport ? `import * as AppModule from ${JSON.stringify(appImport)};` : "";
|
|
402
|
+
const appResolverSource = appImport
|
|
403
|
+
? [
|
|
404
|
+
"const resolveAppComponent = (module) => {",
|
|
405
|
+
" if (!module || typeof module !== \"object\") {",
|
|
406
|
+
" return null;",
|
|
407
|
+
" }",
|
|
408
|
+
" if (typeof module.default === \"function\") {",
|
|
409
|
+
" return module.default;",
|
|
410
|
+
" }",
|
|
411
|
+
" if (typeof module.App === \"function\") {",
|
|
412
|
+
" return module.App;",
|
|
413
|
+
" }",
|
|
414
|
+
" return null;",
|
|
415
|
+
"};",
|
|
416
|
+
"const AppComponent = resolveAppComponent(AppModule);",
|
|
417
|
+
]
|
|
418
|
+
: ["const AppComponent = null;"];
|
|
296
419
|
return [
|
|
297
420
|
"import React from \"react\";",
|
|
298
421
|
"import { createRoot, hydrateRoot } from \"react-dom/client\";",
|
|
299
422
|
"import {",
|
|
300
423
|
" RouterProvider,",
|
|
424
|
+
" RouteDataProvider,",
|
|
301
425
|
" createClientRouteModuleResolver,",
|
|
302
426
|
" createRouter,",
|
|
303
427
|
" installRouterIslands,",
|
|
304
428
|
"} from \"@tyndall/react\";",
|
|
305
429
|
`import Page from ${pageImport};`,
|
|
430
|
+
...(appImportSource ? [appImportSource] : []),
|
|
306
431
|
...entryLayoutImports,
|
|
307
432
|
...routeModuleLoaders.declarations,
|
|
308
433
|
...routeLayoutLoaders.declarations,
|
|
434
|
+
...appResolverSource,
|
|
309
435
|
"const ROUTE_PAYLOAD_EVENT = \"hyper:route-payload-applied\";",
|
|
436
|
+
"const ROUTE_DATA_EVENT = \"hyper:route-data-applied\";",
|
|
310
437
|
"const HYDRATED_EVENT = \"hyper:hydrated\";",
|
|
311
438
|
"const container = document.getElementById(\"app\");",
|
|
312
439
|
"const readPropsPayload = () => {",
|
|
@@ -320,7 +447,20 @@ const defaultClientEntry = (ctx) => {
|
|
|
320
447
|
" return {};",
|
|
321
448
|
" }",
|
|
322
449
|
"};",
|
|
450
|
+
"const readRouteDataPayload = () => {",
|
|
451
|
+
" const dataEl = document.getElementById(\"__HYPER_ROUTE_DATA__\");",
|
|
452
|
+
" if (!dataEl?.textContent) {",
|
|
453
|
+
" return {};",
|
|
454
|
+
" }",
|
|
455
|
+
" try {",
|
|
456
|
+
" return JSON.parse(dataEl.textContent);",
|
|
457
|
+
" } catch {",
|
|
458
|
+
" return {};",
|
|
459
|
+
" }",
|
|
460
|
+
"};",
|
|
323
461
|
"let props = readPropsPayload();",
|
|
462
|
+
"let routeData = readRouteDataPayload();",
|
|
463
|
+
"window.__HYPER_ROUTE_DATA__ = routeData;",
|
|
324
464
|
`const entryRouteId = ${entryRouteId};`,
|
|
325
465
|
"const runtimeModuleUrl = (() => {",
|
|
326
466
|
" try {",
|
|
@@ -346,6 +486,7 @@ const defaultClientEntry = (ctx) => {
|
|
|
346
486
|
`const routeGraph = ${routeGraph};`,
|
|
347
487
|
`const navigationMode = ${navigationMode};`,
|
|
348
488
|
`const clientRenderMode = ${clientRenderMode};`,
|
|
489
|
+
`const scrollRestoration = ${scrollRestoration};`,
|
|
349
490
|
`let routeModuleLoaders = ${routeModuleLoaders.objectLiteral};`,
|
|
350
491
|
"window.__HYPER_CLIENT_ROUTE_MODULES__ = routeModuleLoaders;",
|
|
351
492
|
`let routeLayoutLoaders = ${routeLayoutLoaders.objectLiteral};`,
|
|
@@ -360,6 +501,7 @@ const defaultClientEntry = (ctx) => {
|
|
|
360
501
|
" routeGraph,",
|
|
361
502
|
" navigationMode,",
|
|
362
503
|
" clientRenderMode,",
|
|
504
|
+
" scrollRestoration,",
|
|
363
505
|
" resolveClientRouteModule: routeModuleResolver,",
|
|
364
506
|
" });",
|
|
365
507
|
"if (!runtimeAlreadyInitialized) {",
|
|
@@ -387,6 +529,7 @@ const defaultClientEntry = (ctx) => {
|
|
|
387
529
|
"}",
|
|
388
530
|
"let activeLayouts = routeEntryLayouts[entryRouteId] ?? [];",
|
|
389
531
|
"let activeProps = props;",
|
|
532
|
+
"let activeRouteData = routeData;",
|
|
390
533
|
"let root = null;",
|
|
391
534
|
"const runtimeDisposers = [];",
|
|
392
535
|
"const registerRuntimeDisposer = (dispose) => {",
|
|
@@ -427,9 +570,22 @@ const defaultClientEntry = (ctx) => {
|
|
|
427
570
|
" if (!container || hydration === \"islands\") {",
|
|
428
571
|
" return;",
|
|
429
572
|
" }",
|
|
573
|
+
" const routeId = typeof window.__HYPER_ROUTE_ID__ === \"string\"",
|
|
574
|
+
" ? window.__HYPER_ROUTE_ID__",
|
|
575
|
+
" : container.getAttribute(\"data-hyper-route\") || entryRouteId;",
|
|
576
|
+
" const RoutedPage = (pageProps) => applyLayouts(activePage, pageProps, activeLayouts);",
|
|
577
|
+
" const appTree = AppComponent",
|
|
578
|
+
" ? React.createElement(AppComponent, {",
|
|
579
|
+
" Component: RoutedPage,",
|
|
580
|
+
" pageProps: activeProps,",
|
|
581
|
+
" routeData: activeRouteData,",
|
|
582
|
+
" routeId,",
|
|
583
|
+
" })",
|
|
584
|
+
" : React.createElement(RoutedPage, activeProps);",
|
|
430
585
|
" const element = React.createElement(",
|
|
431
|
-
"
|
|
432
|
-
" {
|
|
586
|
+
" RouteDataProvider,",
|
|
587
|
+
" { value: activeRouteData },",
|
|
588
|
+
" React.createElement(RouterProvider, { router, children: appTree })",
|
|
433
589
|
" );",
|
|
434
590
|
" if (root && typeof root.render === \"function\") {",
|
|
435
591
|
" window.__HYPER_CLIENT_APP_MOUNTED__ = true;",
|
|
@@ -509,6 +665,7 @@ const defaultClientEntry = (ctx) => {
|
|
|
509
665
|
" activePage = nextPage;",
|
|
510
666
|
" activeLayouts = nextLayouts;",
|
|
511
667
|
" activeProps = readPropsPayload();",
|
|
668
|
+
" activeRouteData = readRouteDataPayload();",
|
|
512
669
|
" renderActivePage(false);",
|
|
513
670
|
"};",
|
|
514
671
|
"const applyRuntimeUpdate = (next) => {",
|
|
@@ -628,6 +785,10 @@ const defaultClientEntry = (ctx) => {
|
|
|
628
785
|
" : window.__HYPER_ROUTE_ID__;",
|
|
629
786
|
" void rerenderRoute(routeId);",
|
|
630
787
|
" };",
|
|
788
|
+
" const onRouteDataApplied = () => {",
|
|
789
|
+
" activeRouteData = readRouteDataPayload();",
|
|
790
|
+
" renderActivePage(false);",
|
|
791
|
+
" };",
|
|
631
792
|
" const onPopState = () => {",
|
|
632
793
|
" deferRouteSync(syncRouteFromDom);",
|
|
633
794
|
" };",
|
|
@@ -643,6 +804,7 @@ const defaultClientEntry = (ctx) => {
|
|
|
643
804
|
" patchHistoryForRouteSync();",
|
|
644
805
|
" renderActivePage(true);",
|
|
645
806
|
" addRuntimeListener(window, ROUTE_PAYLOAD_EVENT, onRoutePayloadApplied);",
|
|
807
|
+
" addRuntimeListener(window, ROUTE_DATA_EVENT, onRouteDataApplied);",
|
|
646
808
|
" addRuntimeListener(window, \"popstate\", onPopState);",
|
|
647
809
|
"} else if (runtimeAlreadyInitialized) {",
|
|
648
810
|
" const rerenderRuntime = window.__HYPER_CLIENT_RUNTIME_RERENDER__;",
|
|
@@ -657,6 +819,7 @@ const defaultClientEntry = (ctx) => {
|
|
|
657
819
|
};
|
|
658
820
|
const defaultServerEntry = (ctx) => {
|
|
659
821
|
const pageImport = resolvePageImport(ctx);
|
|
822
|
+
const appImport = resolveAppImport(ctx);
|
|
660
823
|
const hydrationMode = JSON.stringify(resolveHydrationMode(ctx));
|
|
661
824
|
const adapterOptions = (ctx.uiOptions ?? ctx.adapterOptions);
|
|
662
825
|
const nestedLayoutsEnabled = resolveNestedLayoutsEnabled(adapterOptions);
|
|
@@ -666,48 +829,94 @@ const defaultServerEntry = (ctx) => {
|
|
|
666
829
|
const layoutImports = layoutSpecifiers.map((specifier, index) => `import Layout${index} from ${JSON.stringify(specifier)};`);
|
|
667
830
|
const layoutRefs = layoutSpecifiers.map((_specifier, index) => `Layout${index}`);
|
|
668
831
|
const layoutArray = layoutRefs.length > 0 ? `[${layoutRefs.join(", ")}]` : "[]";
|
|
832
|
+
const appImportSource = appImport ? `import * as AppModule from ${JSON.stringify(appImport)};` : "";
|
|
833
|
+
const appResolverSource = appImport
|
|
834
|
+
? [
|
|
835
|
+
"const resolveAppComponent = (module) => {",
|
|
836
|
+
" if (!module || typeof module !== \"object\") {",
|
|
837
|
+
" return null;",
|
|
838
|
+
" }",
|
|
839
|
+
" if (typeof module.default === \"function\") {",
|
|
840
|
+
" return module.default;",
|
|
841
|
+
" }",
|
|
842
|
+
" if (typeof module.App === \"function\") {",
|
|
843
|
+
" return module.App;",
|
|
844
|
+
" }",
|
|
845
|
+
" return null;",
|
|
846
|
+
"};",
|
|
847
|
+
"const AppComponent = resolveAppComponent(AppModule);",
|
|
848
|
+
]
|
|
849
|
+
: ["const AppComponent = null;"];
|
|
669
850
|
return [
|
|
670
851
|
"import React from \"react\";",
|
|
671
852
|
"import { renderToString, renderToPipeableStream } from \"react-dom/server\";",
|
|
672
853
|
"import { PassThrough } from \"stream\";",
|
|
673
|
-
"import { collectHeadFromTree } from \"@tyndall/react\";",
|
|
854
|
+
"import { collectHeadFromTree, RouteDataProvider } from \"@tyndall/react\";",
|
|
674
855
|
`import Page from ${pageImport};`,
|
|
856
|
+
...(appImportSource ? [appImportSource] : []),
|
|
675
857
|
...layoutImports,
|
|
858
|
+
...appResolverSource,
|
|
676
859
|
`export const hydration = ${hydrationMode};`,
|
|
677
860
|
"export const renderToHtml = async (ctx) => {",
|
|
678
|
-
" let element = React.createElement(Page, ctx.props);",
|
|
679
861
|
` const layouts = ${layoutArray};`,
|
|
680
|
-
"
|
|
681
|
-
"
|
|
682
|
-
"
|
|
683
|
-
"
|
|
684
|
-
"
|
|
862
|
+
" const createRoutedTree = (pageProps) => {",
|
|
863
|
+
" let element = React.createElement(Page, pageProps);",
|
|
864
|
+
" if (Array.isArray(layouts) && layouts.length > 0) {",
|
|
865
|
+
" for (let i = layouts.length - 1; i >= 0; i -= 1) {",
|
|
866
|
+
" const Layout = layouts[i];",
|
|
867
|
+
" if (typeof Layout === \"function\") {",
|
|
868
|
+
" element = React.createElement(Layout, { ...pageProps, children: element });",
|
|
869
|
+
" }",
|
|
685
870
|
" }",
|
|
686
871
|
" }",
|
|
687
|
-
"
|
|
688
|
-
"
|
|
689
|
-
" const
|
|
872
|
+
" return element;",
|
|
873
|
+
" };",
|
|
874
|
+
" const routedElement = createRoutedTree(ctx.props);",
|
|
875
|
+
" const appTree = AppComponent",
|
|
876
|
+
" ? React.createElement(AppComponent, {",
|
|
877
|
+
" Component: createRoutedTree,",
|
|
878
|
+
" pageProps: ctx.props,",
|
|
879
|
+
" routeData: ctx.routeData ?? {},",
|
|
880
|
+
" routeId: ctx.routeId,",
|
|
881
|
+
" })",
|
|
882
|
+
" : routedElement;",
|
|
883
|
+
" const tree = React.createElement(RouteDataProvider, { value: ctx.routeData ?? {} }, appTree);",
|
|
884
|
+
" const html = renderToString(tree);",
|
|
885
|
+
" const head = collectHeadFromTree(tree);",
|
|
690
886
|
" return { html, head };",
|
|
691
887
|
"};",
|
|
692
888
|
"export const renderToStream = async (ctx) => {",
|
|
693
889
|
" if (typeof renderToPipeableStream !== \"function\") {",
|
|
694
890
|
" return null;",
|
|
695
891
|
" }",
|
|
696
|
-
" let element = React.createElement(Page, ctx.props);",
|
|
697
892
|
` const layouts = ${layoutArray};`,
|
|
698
|
-
"
|
|
699
|
-
"
|
|
700
|
-
"
|
|
701
|
-
"
|
|
702
|
-
"
|
|
893
|
+
" const createRoutedTree = (pageProps) => {",
|
|
894
|
+
" let element = React.createElement(Page, pageProps);",
|
|
895
|
+
" if (Array.isArray(layouts) && layouts.length > 0) {",
|
|
896
|
+
" for (let i = layouts.length - 1; i >= 0; i -= 1) {",
|
|
897
|
+
" const Layout = layouts[i];",
|
|
898
|
+
" if (typeof Layout === \"function\") {",
|
|
899
|
+
" element = React.createElement(Layout, { ...pageProps, children: element });",
|
|
900
|
+
" }",
|
|
703
901
|
" }",
|
|
704
902
|
" }",
|
|
705
|
-
"
|
|
706
|
-
"
|
|
903
|
+
" return element;",
|
|
904
|
+
" };",
|
|
905
|
+
" const routedElement = createRoutedTree(ctx.props);",
|
|
906
|
+
" const appTree = AppComponent",
|
|
907
|
+
" ? React.createElement(AppComponent, {",
|
|
908
|
+
" Component: createRoutedTree,",
|
|
909
|
+
" pageProps: ctx.props,",
|
|
910
|
+
" routeData: ctx.routeData ?? {},",
|
|
911
|
+
" routeId: ctx.routeId,",
|
|
912
|
+
" })",
|
|
913
|
+
" : routedElement;",
|
|
914
|
+
" const tree = React.createElement(RouteDataProvider, { value: ctx.routeData ?? {} }, appTree);",
|
|
915
|
+
" const head = collectHeadFromTree(tree);",
|
|
707
916
|
" return await new Promise((resolve, reject) => {",
|
|
708
917
|
" let didError = false;",
|
|
709
918
|
" const stream = new PassThrough();",
|
|
710
|
-
" const { pipe, abort } = renderToPipeableStream(
|
|
919
|
+
" const { pipe, abort } = renderToPipeableStream(tree, {",
|
|
711
920
|
" onShellReady() {",
|
|
712
921
|
" pipe(stream);",
|
|
713
922
|
" resolve({ stream, head, abort });",
|
|
@@ -733,8 +942,19 @@ const defaultRenderToHtml = async (ctx, options) => {
|
|
|
733
942
|
const element = await options.render(ctx);
|
|
734
943
|
const layouts = await resolveLayoutComponentsForRender(ctx.routeId, options);
|
|
735
944
|
const composed = layouts.length > 0 ? applyLayoutsToElement(element, ctx.props, layouts) : element;
|
|
736
|
-
const
|
|
737
|
-
const
|
|
945
|
+
const appComponent = await resolveAppComponentForRender(options);
|
|
946
|
+
const RoutedPage = () => composed;
|
|
947
|
+
const appTree = appComponent
|
|
948
|
+
? React.createElement(appComponent, {
|
|
949
|
+
Component: RoutedPage,
|
|
950
|
+
pageProps: ctx.props,
|
|
951
|
+
routeData: ctx.routeData ?? {},
|
|
952
|
+
routeId: ctx.routeId,
|
|
953
|
+
})
|
|
954
|
+
: composed;
|
|
955
|
+
const tree = React.createElement(RouteDataProvider, { value: ctx.routeData ?? {} }, appTree);
|
|
956
|
+
const html = await renderWithFallback(tree);
|
|
957
|
+
const collected = collectHeadFromTree(tree);
|
|
738
958
|
const provided = options.getHead?.(ctx);
|
|
739
959
|
const head = mergeHeadDescriptors(provided ?? {}, collected);
|
|
740
960
|
return { html, head };
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,EAAE,UAAU,MAAM,KAAG,IA8BpE,CAAC"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import { getRouter } from "./router.js";
|
|
3
|
+
export const useBlockRouting = (enabled, message) => {
|
|
4
|
+
const messageRef = useRef(message);
|
|
5
|
+
messageRef.current = message;
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (!enabled) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const router = getRouter();
|
|
11
|
+
const blocker = () => messageRef.current ?? "";
|
|
12
|
+
const unblock = router.block(blocker);
|
|
13
|
+
const handleBeforeUnload = (event) => {
|
|
14
|
+
const text = messageRef.current ?? "";
|
|
15
|
+
if (!text) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
event.returnValue = text;
|
|
20
|
+
};
|
|
21
|
+
if (typeof window !== "undefined") {
|
|
22
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
23
|
+
}
|
|
24
|
+
return () => {
|
|
25
|
+
unblock();
|
|
26
|
+
if (typeof window !== "undefined") {
|
|
27
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}, [enabled]);
|
|
31
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export { createReactAdapter } from "./adapter.js";
|
|
2
|
-
export type { ReactAdapterOptions } from "./adapter.js";
|
|
2
|
+
export type { AppComponentProps, ReactAdapterOptions } from "./adapter.js";
|
|
3
3
|
export { createReactUiAdapterFactory, createReactAdapterRegistry } from "./registry.js";
|
|
4
4
|
export { Link, Head, RouterProvider } from "./components.js";
|
|
5
5
|
export type { LinkProps, HeadProps, RouterProviderProps, ElementLike } from "./components.js";
|
|
6
|
+
export { RouteDataProvider, useRouteData } from "./route-data.js";
|
|
7
|
+
export type { RouteDataMap } from "./route-data.js";
|
|
6
8
|
export { createRouter, getRouter, useRouter } from "./router.js";
|
|
7
|
-
export
|
|
9
|
+
export { useBlockRouting } from "./hooks.js";
|
|
10
|
+
export type { ClientRenderMode, ClientRouteModule, ClientRouteModuleContext, ClientRouteModuleLoader, ClientRouteModuleLoaderMap, ClientRouteModuleResolver, ClientRouteModuleResolverContext, ClientRouteRenderResult, DynamicManifestEnvelope, DynamicManifestRenderer, DynamicManifestResolver, HydrationMode, NavigationMode, NavigationBlockContext, NavigationBlocker, RenderPolicy, RoutePayload, RouteRedirectPayload, RoutePayloadApplier, RoutePayloadResolver, Router, RouterOptions, RouterQuery, } from "./router.js";
|
|
8
11
|
export { createClientRouteModuleResolver } from "./router.js";
|
|
9
12
|
export { installRouterIslands } from "./islands.js";
|
|
10
13
|
export { collectHeadFromTree } from "./head.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAExF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,gCAAgC,EAChC,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,MAAM,EACN,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,uBAAuB,CAAC;AAE/B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { createReactAdapter } from "./adapter.js";
|
|
2
2
|
export { createReactUiAdapterFactory, createReactAdapterRegistry } from "./registry.js";
|
|
3
3
|
export { Link, Head, RouterProvider } from "./components.js";
|
|
4
|
+
export { RouteDataProvider, useRouteData } from "./route-data.js";
|
|
4
5
|
export { createRouter, getRouter, useRouter } from "./router.js";
|
|
6
|
+
export { useBlockRouting } from "./hooks.js";
|
|
5
7
|
export { createClientRouteModuleResolver } from "./router.js";
|
|
6
8
|
export { installRouterIslands } from "./islands.js";
|
|
7
9
|
export { collectHeadFromTree } from "./head.js";
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA8B,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAiBrG,eAAO,MAAM,2BAA2B,QAAO,gBAwB9C,CAAC;AAEF,eAAO,MAAM,0BAA0B,QAAO,iBAE5C,CAAC"}
|
package/dist/registry.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
1
2
|
import { createReactAdapter } from "./adapter.js";
|
|
2
3
|
const isFunction = (value) => typeof value === "function";
|
|
3
4
|
export const createReactUiAdapterFactory = () => (options) => {
|
|
@@ -9,8 +10,14 @@ export const createReactUiAdapterFactory = () => (options) => {
|
|
|
9
10
|
? normalized.routeHead
|
|
10
11
|
: undefined;
|
|
11
12
|
return createReactAdapter({
|
|
12
|
-
render: routeRender ? ({ props }) => routeRender
|
|
13
|
+
render: routeRender ? ({ props }) => createElement(routeRender, props) : undefined,
|
|
13
14
|
getHead: routeHead ? ({ props }) => routeHead(props) : undefined,
|
|
15
|
+
routeGraph: normalized.routeGraph,
|
|
16
|
+
rootDir: normalized.rootDir,
|
|
17
|
+
routeRoot: normalized.routeRoot,
|
|
18
|
+
nestedLayouts: normalized.nestedLayouts,
|
|
19
|
+
appModule: typeof normalized.appModule === "string" ? normalized.appModule : undefined,
|
|
20
|
+
appComponent: typeof normalized.appComponent === "function" ? normalized.appComponent : undefined,
|
|
14
21
|
});
|
|
15
22
|
};
|
|
16
23
|
export const createReactAdapterRegistry = () => ({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-data.d.ts","sourceRoot":"","sources":["../src/route-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAInD,eAAO,MAAM,iBAAiB,8BAA4B,CAAC;AAE3D,eAAO,MAAM,YAAY,QAAO,YAAkD,CAAC"}
|
package/dist/router.d.ts
CHANGED
|
@@ -20,9 +20,16 @@ export interface RoutePayload {
|
|
|
20
20
|
routeId: string;
|
|
21
21
|
appHtml: string;
|
|
22
22
|
propsPayload: string;
|
|
23
|
+
routeDataPayload?: string;
|
|
23
24
|
head?: HeadDescriptor;
|
|
24
25
|
hydration?: HydrationMode;
|
|
25
26
|
}
|
|
27
|
+
export interface RouteRedirectPayload {
|
|
28
|
+
kind: "hyper-route-redirect";
|
|
29
|
+
destination: string;
|
|
30
|
+
status?: number;
|
|
31
|
+
replace?: boolean;
|
|
32
|
+
}
|
|
26
33
|
export interface ClientRouteModuleContext {
|
|
27
34
|
href: string;
|
|
28
35
|
pathname: string;
|
|
@@ -34,6 +41,8 @@ export interface ClientRouteRenderResult {
|
|
|
34
41
|
routeId?: string;
|
|
35
42
|
appHtml: string;
|
|
36
43
|
propsPayload?: string;
|
|
44
|
+
routeDataPayload?: string;
|
|
45
|
+
routeData?: Record<string, unknown>;
|
|
37
46
|
head?: HeadDescriptor;
|
|
38
47
|
hydration?: HydrationMode;
|
|
39
48
|
}
|
|
@@ -50,7 +59,7 @@ export interface ClientRouteModuleResolverContext {
|
|
|
50
59
|
export type ClientRouteModuleResolver = (ctx: ClientRouteModuleResolverContext) => Promise<ClientRouteModule | null>;
|
|
51
60
|
export type ClientRouteModuleLoader = () => Promise<unknown>;
|
|
52
61
|
export type ClientRouteModuleLoaderMap = Record<string, ClientRouteModuleLoader>;
|
|
53
|
-
export type RoutePayloadResolver = (href: string) => Promise<RoutePayload | null>;
|
|
62
|
+
export type RoutePayloadResolver = (href: string) => Promise<RoutePayload | RouteRedirectPayload | null>;
|
|
54
63
|
export type RoutePayloadApplier = (payload: RoutePayload) => void | Promise<void>;
|
|
55
64
|
export interface RouterOptions {
|
|
56
65
|
routeGraph?: RouteGraph;
|
|
@@ -65,15 +74,24 @@ export interface RouterOptions {
|
|
|
65
74
|
buildMode?: "ssg" | "ssr";
|
|
66
75
|
onWarning?: (message: string) => void;
|
|
67
76
|
fallbackPolicy?: ResolverFallbackPolicy;
|
|
77
|
+
scrollRestoration?: boolean;
|
|
68
78
|
}
|
|
69
79
|
export interface Router {
|
|
70
80
|
pathname: string;
|
|
71
81
|
query: RouterQuery;
|
|
72
82
|
push: (href: string) => Promise<void>;
|
|
73
83
|
replace: (href: string) => Promise<void>;
|
|
84
|
+
softReload: () => Promise<void>;
|
|
74
85
|
prefetch: (href: string) => Promise<void>;
|
|
75
86
|
subscribe: (listener: (router: Router) => void) => () => void;
|
|
87
|
+
block: (blocker: NavigationBlocker) => () => void;
|
|
88
|
+
}
|
|
89
|
+
export interface NavigationBlockContext {
|
|
90
|
+
href: string;
|
|
91
|
+
replace: boolean;
|
|
92
|
+
type: "push" | "replace" | "popstate" | "softReload" | "redirect";
|
|
76
93
|
}
|
|
94
|
+
export type NavigationBlocker = (ctx: NavigationBlockContext) => boolean | string | void;
|
|
77
95
|
export declare const createClientRouteModuleResolver: (loaders: ClientRouteModuleLoaderMap) => ClientRouteModuleResolver;
|
|
78
96
|
export declare const createRouter: (initialHref?: string | RouterOptions, options?: RouterOptions) => Router;
|
|
79
97
|
export declare const getRouter: () => Router;
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/dist/router.js
CHANGED
|
@@ -1,10 +1,41 @@
|
|
|
1
|
-
import { evaluateRenderPolicy, shouldForceDynamicFallback, } from "@tyndall/core";
|
|
1
|
+
import { evaluateRenderPolicy, shouldForceDynamicFallback, ROUTE_DATA_SCRIPT_ID, } from "@tyndall/core";
|
|
2
2
|
import { applyHead } from "./head-manager.js";
|
|
3
3
|
import { createReactRouterRouteMatcher } from "./react-router-bridge.js";
|
|
4
4
|
const NAVIGATION_HEADER = "x-hyper-navigation";
|
|
5
5
|
const NAVIGATION_MODE = "csr";
|
|
6
6
|
const ROUTE_PAYLOAD_EVENT = "hyper:route-payload-applied";
|
|
7
|
+
const ROUTE_DATA_EVENT = "hyper:route-data-applied";
|
|
8
|
+
const ROUTE_REDIRECT_KIND = "hyper-route-redirect";
|
|
7
9
|
const inflightPrefetchRequests = new Map();
|
|
10
|
+
const navigationBlockers = new Set();
|
|
11
|
+
const resolveBlockDecision = (result) => {
|
|
12
|
+
if (typeof result === "string") {
|
|
13
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.confirm === "function") {
|
|
14
|
+
return globalThis.confirm(result);
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (result === false) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
};
|
|
23
|
+
const runNavigationBlockers = (ctx) => {
|
|
24
|
+
if (navigationBlockers.size === 0) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
for (const blocker of navigationBlockers) {
|
|
28
|
+
const decision = resolveBlockDecision(blocker(ctx));
|
|
29
|
+
if (!decision) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
};
|
|
35
|
+
if (typeof globalThis !== "undefined") {
|
|
36
|
+
globalThis
|
|
37
|
+
.__HYPER_NAVIGATION_GUARD__ = runNavigationBlockers;
|
|
38
|
+
}
|
|
8
39
|
const hasBrowserHistory = () => typeof globalThis !== "undefined" &&
|
|
9
40
|
"history" in globalThis &&
|
|
10
41
|
Boolean(globalThis.history);
|
|
@@ -65,6 +96,17 @@ const parseHref = (href, baseUrl) => {
|
|
|
65
96
|
return { pathname: url.pathname, query };
|
|
66
97
|
};
|
|
67
98
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
99
|
+
const parseJsonPayload = (value) => {
|
|
100
|
+
if (!value) {
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
return JSON.parse(value);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return {};
|
|
108
|
+
}
|
|
109
|
+
};
|
|
68
110
|
const isClientRouteRenderResult = (value) => {
|
|
69
111
|
if (!isRecord(value) || typeof value.appHtml !== "string") {
|
|
70
112
|
return false;
|
|
@@ -75,6 +117,12 @@ const isClientRouteRenderResult = (value) => {
|
|
|
75
117
|
if (value.propsPayload !== undefined && typeof value.propsPayload !== "string") {
|
|
76
118
|
return false;
|
|
77
119
|
}
|
|
120
|
+
if (value.routeDataPayload !== undefined && typeof value.routeDataPayload !== "string") {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (value.routeData !== undefined && !isRecord(value.routeData)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
78
126
|
if (value.hydration !== undefined &&
|
|
79
127
|
value.hydration !== "full" &&
|
|
80
128
|
value.hydration !== "islands") {
|
|
@@ -93,6 +141,9 @@ const isRoutePayload = (value) => {
|
|
|
93
141
|
typeof payload.propsPayload !== "string") {
|
|
94
142
|
return false;
|
|
95
143
|
}
|
|
144
|
+
if (payload.routeDataPayload !== undefined && typeof payload.routeDataPayload !== "string") {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
96
147
|
if (payload.hydration !== undefined &&
|
|
97
148
|
payload.hydration !== "full" &&
|
|
98
149
|
payload.hydration !== "islands") {
|
|
@@ -100,6 +151,19 @@ const isRoutePayload = (value) => {
|
|
|
100
151
|
}
|
|
101
152
|
return true;
|
|
102
153
|
};
|
|
154
|
+
const isRouteRedirectPayload = (value) => {
|
|
155
|
+
if (!value || typeof value !== "object") {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const payload = value;
|
|
159
|
+
if (payload.kind !== ROUTE_REDIRECT_KIND) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (typeof payload.destination !== "string") {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
};
|
|
103
167
|
const resolveRoutePayloadFromServer = async (href, baseUrl) => {
|
|
104
168
|
if (typeof fetch === "undefined") {
|
|
105
169
|
return null;
|
|
@@ -121,7 +185,13 @@ const resolveRoutePayloadFromServer = async (href, baseUrl) => {
|
|
|
121
185
|
return null;
|
|
122
186
|
}
|
|
123
187
|
const json = (await response.json());
|
|
124
|
-
|
|
188
|
+
if (isRoutePayload(json)) {
|
|
189
|
+
return json;
|
|
190
|
+
}
|
|
191
|
+
if (isRouteRedirectPayload(json)) {
|
|
192
|
+
return json;
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
125
195
|
}
|
|
126
196
|
catch {
|
|
127
197
|
return null;
|
|
@@ -154,6 +224,14 @@ const applyRoutePayloadToDom = (payload) => {
|
|
|
154
224
|
if (propsScript) {
|
|
155
225
|
propsScript.textContent = payload.propsPayload;
|
|
156
226
|
}
|
|
227
|
+
const routeDataPayload = typeof payload.routeDataPayload === "string" ? payload.routeDataPayload : "{}";
|
|
228
|
+
const routeDataScript = document.getElementById(ROUTE_DATA_SCRIPT_ID);
|
|
229
|
+
if (routeDataScript) {
|
|
230
|
+
routeDataScript.textContent = routeDataPayload;
|
|
231
|
+
}
|
|
232
|
+
const routeData = parseJsonPayload(routeDataPayload);
|
|
233
|
+
globalThis.__HYPER_ROUTE_DATA__ =
|
|
234
|
+
routeData;
|
|
157
235
|
if (payload.head) {
|
|
158
236
|
applyHead(payload.head);
|
|
159
237
|
}
|
|
@@ -163,19 +241,37 @@ const applyRoutePayloadToDom = (payload) => {
|
|
|
163
241
|
globalThis.dispatchEvent?.(new CustomEvent(ROUTE_PAYLOAD_EVENT, {
|
|
164
242
|
detail: { routeId: payload.routeId },
|
|
165
243
|
}));
|
|
244
|
+
globalThis.dispatchEvent?.(new CustomEvent(ROUTE_DATA_EVENT, {
|
|
245
|
+
detail: { routeId: payload.routeId, routeData },
|
|
246
|
+
}));
|
|
166
247
|
}
|
|
167
248
|
catch {
|
|
168
249
|
// Keep client navigation flow resilient if event dispatch is unavailable.
|
|
169
250
|
}
|
|
170
251
|
};
|
|
171
|
-
const toRoutePayload = (rendered) =>
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
252
|
+
const toRoutePayload = (rendered) => {
|
|
253
|
+
let routeDataPayload = "{}";
|
|
254
|
+
if (typeof rendered.routeDataPayload === "string") {
|
|
255
|
+
routeDataPayload = rendered.routeDataPayload;
|
|
256
|
+
}
|
|
257
|
+
else if (rendered.routeData && typeof rendered.routeData === "object") {
|
|
258
|
+
try {
|
|
259
|
+
routeDataPayload = JSON.stringify(rendered.routeData);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
routeDataPayload = "{}";
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
kind: "hyper-route-payload",
|
|
267
|
+
routeId: rendered.routeId,
|
|
268
|
+
appHtml: rendered.appHtml,
|
|
269
|
+
propsPayload: rendered.propsPayload ?? "{}",
|
|
270
|
+
routeDataPayload,
|
|
271
|
+
head: rendered.head,
|
|
272
|
+
hydration: rendered.hydration,
|
|
273
|
+
};
|
|
274
|
+
};
|
|
179
275
|
const isMetaDefinition = (value) => {
|
|
180
276
|
if (!value || typeof value !== "object") {
|
|
181
277
|
return false;
|
|
@@ -232,20 +328,118 @@ export const createRouter = (initialHref, options) => {
|
|
|
232
328
|
const baseUrl = getBaseUrl();
|
|
233
329
|
const navigationMode = routerOptions.navigationMode ?? "client";
|
|
234
330
|
const clientRenderMode = routerOptions.clientRenderMode ?? "payload";
|
|
331
|
+
const scrollRestoration = routerOptions.scrollRestoration !== false;
|
|
235
332
|
const fallbackToUrl = routerOptions.fallbackToUrl ?? true;
|
|
236
333
|
const hasCustomRoutePayloadResolver = typeof routerOptions.resolveRoutePayload === "function";
|
|
237
334
|
const resolveRoutePayload = routerOptions.resolveRoutePayload ??
|
|
238
335
|
((href) => resolveRoutePayloadFromServer(href, baseUrl));
|
|
239
336
|
const applyRoutePayload = routerOptions.applyRoutePayload ?? applyRoutePayloadToDom;
|
|
337
|
+
const existingScrollPositions = typeof globalThis !== "undefined"
|
|
338
|
+
? globalThis.__HYPER_SCROLL_POSITIONS__
|
|
339
|
+
: undefined;
|
|
340
|
+
const scrollPositions = existingScrollPositions && typeof existingScrollPositions === "object"
|
|
341
|
+
? existingScrollPositions
|
|
342
|
+
: {};
|
|
343
|
+
if (typeof globalThis !== "undefined") {
|
|
344
|
+
globalThis.__HYPER_SCROLL_POSITIONS__ = scrollPositions;
|
|
345
|
+
}
|
|
346
|
+
if (scrollRestoration && hasBrowserHistory()) {
|
|
347
|
+
try {
|
|
348
|
+
const history = globalThis.history;
|
|
349
|
+
if (history && "scrollRestoration" in history) {
|
|
350
|
+
history.scrollRestoration = "manual";
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
// Ignore browsers that block scrollRestoration assignment.
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const toScrollKey = (href) => {
|
|
358
|
+
try {
|
|
359
|
+
const url = new URL(href, baseUrl);
|
|
360
|
+
return `${url.pathname}${url.search}`;
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
return href;
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const saveScrollPosition = (href) => {
|
|
367
|
+
if (!scrollRestoration) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const key = toScrollKey(href);
|
|
371
|
+
if (!key) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (typeof globalThis !== "undefined") {
|
|
375
|
+
const win = globalThis;
|
|
376
|
+
scrollPositions[key] = {
|
|
377
|
+
x: typeof win.scrollX === "number" ? win.scrollX : win.pageXOffset ?? 0,
|
|
378
|
+
y: typeof win.scrollY === "number" ? win.scrollY : win.pageYOffset ?? 0,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
const scrollToHash = (href) => {
|
|
383
|
+
if (typeof document === "undefined") {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
try {
|
|
387
|
+
const url = new URL(href, baseUrl);
|
|
388
|
+
if (!url.hash) {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
const id = url.hash.slice(1);
|
|
392
|
+
if (!id) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
const node = document.getElementById(id);
|
|
396
|
+
if (node && typeof node.scrollIntoView === "function") {
|
|
397
|
+
node.scrollIntoView();
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
405
|
+
};
|
|
406
|
+
const restoreScrollPosition = (href, fromHistory) => {
|
|
407
|
+
if (!scrollRestoration || typeof globalThis === "undefined") {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (scrollToHash(href)) {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
const key = toScrollKey(href);
|
|
414
|
+
if (fromHistory && key && scrollPositions[key]) {
|
|
415
|
+
const position = scrollPositions[key];
|
|
416
|
+
const x = typeof position.x === "number" ? position.x : 0;
|
|
417
|
+
const y = typeof position.y === "number" ? position.y : 0;
|
|
418
|
+
globalThis.scrollTo?.(x, y);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
globalThis.scrollTo?.(0, 0);
|
|
422
|
+
};
|
|
240
423
|
const listeners = new Set();
|
|
241
424
|
const router = {
|
|
242
425
|
pathname: "/",
|
|
243
426
|
query: {},
|
|
244
427
|
push: async (href) => {
|
|
245
|
-
await resolveAndNavigate(href, false);
|
|
428
|
+
await resolveAndNavigate(href, false, { type: "push" });
|
|
246
429
|
},
|
|
247
430
|
replace: async (href) => {
|
|
248
|
-
await resolveAndNavigate(href, true);
|
|
431
|
+
await resolveAndNavigate(href, true, { type: "replace" });
|
|
432
|
+
},
|
|
433
|
+
softReload: async () => {
|
|
434
|
+
const href = typeof globalThis !== "undefined" && "location" in globalThis
|
|
435
|
+
? globalThis.location.href
|
|
436
|
+
: currentHref || "/";
|
|
437
|
+
await resolveAndNavigate(href, true, {
|
|
438
|
+
skipHistory: true,
|
|
439
|
+
skipScrollSave: true,
|
|
440
|
+
skipScrollRestore: true,
|
|
441
|
+
type: "softReload",
|
|
442
|
+
});
|
|
249
443
|
},
|
|
250
444
|
prefetch: async (href) => {
|
|
251
445
|
await requestPrefetch(href);
|
|
@@ -271,26 +465,34 @@ export const createRouter = (initialHref, options) => {
|
|
|
271
465
|
listeners.delete(listener);
|
|
272
466
|
};
|
|
273
467
|
},
|
|
468
|
+
block: (blocker) => {
|
|
469
|
+
navigationBlockers.add(blocker);
|
|
470
|
+
return () => {
|
|
471
|
+
navigationBlockers.delete(blocker);
|
|
472
|
+
};
|
|
473
|
+
},
|
|
274
474
|
};
|
|
475
|
+
let currentHref = "";
|
|
275
476
|
const updateState = (href) => {
|
|
276
477
|
const next = parseHref(href, baseUrl);
|
|
277
478
|
router.pathname = next.pathname;
|
|
278
479
|
router.query = next.query;
|
|
480
|
+
currentHref = href;
|
|
279
481
|
for (const listener of listeners) {
|
|
280
482
|
listener(router);
|
|
281
483
|
}
|
|
282
484
|
};
|
|
283
485
|
const matchRouteGraph = (pathname) => routeMatcher?.match(pathname) ?? null;
|
|
284
|
-
const navigate = async (href, replace) => {
|
|
486
|
+
const navigate = async (href, replace, options = {}) => {
|
|
285
487
|
// Important: only touch browser history when it exists (SSR-safe).
|
|
286
|
-
if (hasBrowserHistory()) {
|
|
488
|
+
if (!options.skipHistory && hasBrowserHistory()) {
|
|
287
489
|
const history = globalThis.history;
|
|
288
490
|
const method = replace ? "replaceState" : "pushState";
|
|
289
491
|
history[method](null, "", href);
|
|
290
492
|
}
|
|
291
493
|
updateState(href);
|
|
292
494
|
};
|
|
293
|
-
const navigateWithUrl = async (href, replace) => {
|
|
495
|
+
const navigateWithUrl = async (href, replace, _options = {}) => {
|
|
294
496
|
const location = globalThis.location;
|
|
295
497
|
if (location) {
|
|
296
498
|
if (replace && typeof location.replace === "function") {
|
|
@@ -304,20 +506,34 @@ export const createRouter = (initialHref, options) => {
|
|
|
304
506
|
location.href = href;
|
|
305
507
|
return;
|
|
306
508
|
}
|
|
307
|
-
await navigate(href, replace);
|
|
509
|
+
await navigate(href, replace, _options);
|
|
308
510
|
};
|
|
309
|
-
const navigateWithPayload = async (href, replace) => {
|
|
511
|
+
const navigateWithPayload = async (href, replace, options = {}) => {
|
|
310
512
|
const payload = await resolveRoutePayload(href);
|
|
311
|
-
if (payload) {
|
|
513
|
+
if (payload && payload.kind === ROUTE_REDIRECT_KIND) {
|
|
514
|
+
const destination = payload.destination;
|
|
515
|
+
if (destination) {
|
|
516
|
+
await resolveAndNavigate(destination, Boolean(payload.replace), {
|
|
517
|
+
...options,
|
|
518
|
+
type: "redirect",
|
|
519
|
+
skipScrollSave: true,
|
|
520
|
+
});
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (payload && payload.kind === "hyper-route-payload") {
|
|
312
525
|
await applyRoutePayload(payload);
|
|
313
|
-
await navigate(href, replace);
|
|
526
|
+
await navigate(href, replace, options);
|
|
527
|
+
if (!options.skipScrollRestore) {
|
|
528
|
+
restoreScrollPosition(href, Boolean(options.fromHistory));
|
|
529
|
+
}
|
|
314
530
|
return true;
|
|
315
531
|
}
|
|
316
532
|
if (fallbackToUrl) {
|
|
317
|
-
await navigateWithUrl(href, replace);
|
|
533
|
+
await navigateWithUrl(href, replace, options);
|
|
318
534
|
return false;
|
|
319
535
|
}
|
|
320
|
-
await navigate(href, replace);
|
|
536
|
+
await navigate(href, replace, options);
|
|
321
537
|
return false;
|
|
322
538
|
};
|
|
323
539
|
const resolveClientRouteRender = async (href) => {
|
|
@@ -359,36 +575,39 @@ export const createRouter = (initialHref, options) => {
|
|
|
359
575
|
return null;
|
|
360
576
|
}
|
|
361
577
|
};
|
|
362
|
-
const navigateWithClientModule = async (href, replace) => {
|
|
578
|
+
const navigateWithClientModule = async (href, replace, options = {}) => {
|
|
363
579
|
const rendered = await resolveClientRouteRender(href);
|
|
364
580
|
if (!rendered) {
|
|
365
581
|
return false;
|
|
366
582
|
}
|
|
367
583
|
await applyRoutePayload(toRoutePayload(rendered));
|
|
368
|
-
await navigate(href, replace);
|
|
584
|
+
await navigate(href, replace, options);
|
|
585
|
+
if (!options.skipScrollRestore) {
|
|
586
|
+
restoreScrollPosition(href, Boolean(options.fromHistory));
|
|
587
|
+
}
|
|
369
588
|
return true;
|
|
370
589
|
};
|
|
371
|
-
const navigateWithClientRender = async (href, replace) => {
|
|
590
|
+
const navigateWithClientRender = async (href, replace, options = {}) => {
|
|
372
591
|
if (clientRenderMode === "module") {
|
|
373
|
-
const moduleApplied = await navigateWithClientModule(href, replace);
|
|
592
|
+
const moduleApplied = await navigateWithClientModule(href, replace, options);
|
|
374
593
|
if (moduleApplied) {
|
|
375
594
|
return;
|
|
376
595
|
}
|
|
377
596
|
}
|
|
378
|
-
await navigateWithPayload(href, replace);
|
|
597
|
+
await navigateWithPayload(href, replace, options);
|
|
379
598
|
};
|
|
380
|
-
const navigateByMode = async (href, replace) => {
|
|
599
|
+
const navigateByMode = async (href, replace, options = {}) => {
|
|
381
600
|
if (navigationMode === "url") {
|
|
382
|
-
await navigateWithUrl(href, replace);
|
|
601
|
+
await navigateWithUrl(href, replace, options);
|
|
383
602
|
return;
|
|
384
603
|
}
|
|
385
|
-
await navigateWithClientRender(href, replace);
|
|
604
|
+
await navigateWithClientRender(href, replace, options);
|
|
386
605
|
};
|
|
387
|
-
const resolveDynamicFallback = async (href, replace) => {
|
|
606
|
+
const resolveDynamicFallback = async (href, replace, options = {}) => {
|
|
388
607
|
const next = parseHref(href, baseUrl);
|
|
389
608
|
const forceDynamic = shouldForceDynamicFallback(next.pathname, routerOptions.fallbackPolicy);
|
|
390
609
|
if (routeMatcher && !forceDynamic && matchRouteGraph(next.pathname)) {
|
|
391
|
-
await navigateByMode(href, replace);
|
|
610
|
+
await navigateByMode(href, replace, options);
|
|
392
611
|
return;
|
|
393
612
|
}
|
|
394
613
|
if (routerOptions.resolveDynamicManifest) {
|
|
@@ -396,7 +615,7 @@ export const createRouter = (initialHref, options) => {
|
|
|
396
615
|
if (envelope) {
|
|
397
616
|
const policy = envelope.policy?.render ?? "auto";
|
|
398
617
|
if (policy === "redirect" && envelope.policy?.redirect) {
|
|
399
|
-
await navigateByMode(envelope.policy.redirect, replace);
|
|
618
|
+
await navigateByMode(envelope.policy.redirect, replace, options);
|
|
400
619
|
return;
|
|
401
620
|
}
|
|
402
621
|
let policyRender;
|
|
@@ -424,22 +643,30 @@ export const createRouter = (initialHref, options) => {
|
|
|
424
643
|
}
|
|
425
644
|
}
|
|
426
645
|
if (decision.mode === "ssr") {
|
|
427
|
-
await navigateWithUrl(href, replace);
|
|
646
|
+
await navigateWithUrl(href, replace, options);
|
|
428
647
|
return;
|
|
429
648
|
}
|
|
430
649
|
const meta = envelope.meta ??
|
|
431
650
|
(isMetaDefinition(envelope.definition) ? envelope.definition.root : undefined);
|
|
432
651
|
if (decision.mode === "csr" && meta !== undefined) {
|
|
433
652
|
await routerOptions.renderDynamic?.(meta, envelope);
|
|
434
|
-
await navigateByMode(href, replace);
|
|
653
|
+
await navigateByMode(href, replace, options);
|
|
435
654
|
return;
|
|
436
655
|
}
|
|
437
656
|
}
|
|
438
657
|
}
|
|
439
|
-
await navigateByMode(href, replace);
|
|
658
|
+
await navigateByMode(href, replace, options);
|
|
440
659
|
};
|
|
441
|
-
const resolveAndNavigate = async (href, replace) => {
|
|
442
|
-
|
|
660
|
+
const resolveAndNavigate = async (href, replace, options = {}) => {
|
|
661
|
+
const navType = options.type ?? (replace ? "replace" : "push");
|
|
662
|
+
const allow = runNavigationBlockers({ href, replace, type: navType });
|
|
663
|
+
if (!allow) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
if (!options.skipScrollSave) {
|
|
667
|
+
saveScrollPosition(currentHref || href);
|
|
668
|
+
}
|
|
669
|
+
await resolveDynamicFallback(href, replace, options);
|
|
443
670
|
};
|
|
444
671
|
const seed = resolved.initialHref ??
|
|
445
672
|
(typeof globalThis !== "undefined" && "location" in globalThis
|
|
@@ -450,9 +677,30 @@ export const createRouter = (initialHref, options) => {
|
|
|
450
677
|
// Keep router state in sync with back/forward navigation.
|
|
451
678
|
globalThis.addEventListener("popstate", () => {
|
|
452
679
|
const location = globalThis.location;
|
|
453
|
-
if (location?.href) {
|
|
454
|
-
|
|
680
|
+
if (!location?.href) {
|
|
681
|
+
return;
|
|
455
682
|
}
|
|
683
|
+
const nextHref = location.href;
|
|
684
|
+
const allow = runNavigationBlockers({ href: nextHref, replace: true, type: "popstate" });
|
|
685
|
+
if (!allow) {
|
|
686
|
+
if (hasBrowserHistory()) {
|
|
687
|
+
const history = globalThis.history;
|
|
688
|
+
try {
|
|
689
|
+
history.pushState(null, "", currentHref);
|
|
690
|
+
updateState(currentHref);
|
|
691
|
+
}
|
|
692
|
+
catch {
|
|
693
|
+
// Ignore history reversal failures.
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
saveScrollPosition(currentHref || nextHref);
|
|
699
|
+
void resolveDynamicFallback(nextHref, true, {
|
|
700
|
+
fromHistory: true,
|
|
701
|
+
skipScrollSave: true,
|
|
702
|
+
type: "popstate",
|
|
703
|
+
});
|
|
456
704
|
});
|
|
457
705
|
}
|
|
458
706
|
return router;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GetServerProps as HyperGetServerProps, GetStaticPaths as HyperGetStaticPaths, GetStaticProps as HyperGetStaticProps, PageContextBase, PageComponent, StaticPropsContext, StaticPropsResult, StaticPathsResult, ServerPropsContext, ServerPropsResult } from "@tyndall/core";
|
|
1
|
+
import type { ErrorDescriptor, GetServerProps as HyperGetServerProps, GetStaticPaths as HyperGetStaticPaths, GetStaticProps as HyperGetStaticProps, GetRouteData as HyperGetRouteData, InitServerHook, PageContextBase, PageComponent, RedirectDescriptor, RouteDataContext as HyperRouteDataContext, RouteDataMap as HyperRouteDataMap, RouteDataResult as HyperRouteDataResult, StaticPropsContext, StaticPropsResult, StaticPathsResult, ServerPropsContext, ServerPropsResult } from "@tyndall/core";
|
|
2
2
|
export type NextPageContext = PageContextBase;
|
|
3
3
|
export type NextPage<Props = Record<string, unknown>> = PageComponent<Props>;
|
|
4
4
|
export type NextStaticPropsContext = StaticPropsContext;
|
|
@@ -14,4 +14,18 @@ export type GetStaticPaths = HyperGetStaticPaths;
|
|
|
14
14
|
export type GetServerSidePropsContext = ServerPropsContext;
|
|
15
15
|
export type GetServerSidePropsResult<Props = Record<string, unknown>> = ServerPropsResult<Props>;
|
|
16
16
|
export type GetServerSideProps<Props = Record<string, unknown>> = HyperGetServerProps<Props>;
|
|
17
|
+
export interface AppProps {
|
|
18
|
+
Component: PageComponent<Record<string, unknown>>;
|
|
19
|
+
pageProps: Record<string, unknown>;
|
|
20
|
+
routeData: HyperRouteDataMap;
|
|
21
|
+
routeId: string;
|
|
22
|
+
}
|
|
23
|
+
export type AppComponent = (props: AppProps) => unknown;
|
|
24
|
+
export type GetRouteData<Data = unknown> = HyperGetRouteData<Data>;
|
|
25
|
+
export type RouteDataResult<Data = unknown> = HyperRouteDataResult<Data>;
|
|
26
|
+
export type RouteDataContext = HyperRouteDataContext;
|
|
27
|
+
export type RouteDataMap = HyperRouteDataMap;
|
|
28
|
+
export type InitServer = InitServerHook;
|
|
29
|
+
export type RedirectResponse = RedirectDescriptor;
|
|
30
|
+
export type ErrorResponse = ErrorDescriptor;
|
|
17
31
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,IAAI,mBAAmB,EACrC,cAAc,IAAI,mBAAmB,EACrC,cAAc,IAAI,mBAAmB,EACrC,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,eAAe,GAAG,eAAe,CAAC;AAC9C,MAAM,MAAM,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;AAC7E,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACxD,MAAM,MAAM,qBAAqB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAC9F,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AACtD,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACxD,MAAM,MAAM,qBAAqB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAE9F,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AACvD,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAC7F,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;AACrD,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;AACzF,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAEjD,MAAM,MAAM,yBAAyB,GAAG,kBAAkB,CAAC;AAC3D,MAAM,MAAM,wBAAwB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AACjG,MAAM,MAAM,kBAAkB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,IAAI,mBAAmB,EACrC,cAAc,IAAI,mBAAmB,EACrC,cAAc,IAAI,mBAAmB,EACrC,YAAY,IAAI,iBAAiB,EACjC,cAAc,EACd,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,gBAAgB,IAAI,qBAAqB,EACzC,YAAY,IAAI,iBAAiB,EACjC,eAAe,IAAI,oBAAoB,EACvC,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,eAAe,GAAG,eAAe,CAAC;AAC9C,MAAM,MAAM,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;AAC7E,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACxD,MAAM,MAAM,qBAAqB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAC9F,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AACtD,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACxD,MAAM,MAAM,qBAAqB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAE9F,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AACvD,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAC7F,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;AACrD,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;AACzF,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAEjD,MAAM,MAAM,yBAAyB,GAAG,kBAAkB,CAAC;AAC3D,MAAM,MAAM,wBAAwB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AACjG,MAAM,MAAM,kBAAkB,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;AAE7F,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;AAExD,MAAM,MAAM,YAAY,CAAC,IAAI,GAAG,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACnE,MAAM,MAAM,eAAe,CAAC,IAAI,GAAG,OAAO,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACzE,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;AACrD,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAC7C,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC;AACxC,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tyndall/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"build": "tsc -p tsconfig.json"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@tyndall/core": "
|
|
25
|
-
"@tyndall/shared": "
|
|
24
|
+
"@tyndall/core": "^0.0.2",
|
|
25
|
+
"@tyndall/shared": "^0.0.2",
|
|
26
26
|
"react-router": "^7.13.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|