@alepha/react 0.14.3 → 0.14.4
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/dist/auth/index.browser.js +29 -14
- package/dist/auth/index.browser.js.map +1 -1
- package/dist/auth/index.js +959 -194
- package/dist/auth/index.js.map +1 -1
- package/dist/head/index.browser.js +59 -19
- package/dist/head/index.browser.js.map +1 -1
- package/dist/head/index.d.ts +99 -560
- package/dist/head/index.d.ts.map +1 -1
- package/dist/head/index.js +91 -87
- package/dist/head/index.js.map +1 -1
- package/dist/router/index.browser.js +30 -15
- package/dist/router/index.browser.js.map +1 -1
- package/dist/router/index.d.ts +616 -192
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +960 -195
- package/dist/router/index.js.map +1 -1
- package/package.json +4 -4
- package/src/core/__tests__/Router.spec.tsx +4 -4
- package/src/head/{__tests__/expandSeo.spec.ts → helpers/SeoExpander.spec.ts} +1 -1
- package/src/head/index.ts +10 -28
- package/src/head/providers/BrowserHeadProvider.browser.spec.ts +1 -76
- package/src/head/providers/BrowserHeadProvider.ts +25 -19
- package/src/head/providers/HeadProvider.ts +76 -10
- package/src/head/providers/ServerHeadProvider.ts +22 -138
- package/src/router/__tests__/page-head-browser.browser.spec.ts +91 -0
- package/src/router/__tests__/page-head.spec.ts +44 -0
- package/src/{head → router}/__tests__/seo-head.spec.ts +2 -2
- package/src/router/atoms/ssrManifestAtom.ts +60 -0
- package/src/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
- package/src/router/errors/Redirection.ts +1 -1
- package/src/router/index.shared.ts +1 -0
- package/src/router/index.ts +16 -2
- package/src/router/primitives/$page.browser.spec.tsx +15 -15
- package/src/router/primitives/$page.spec.tsx +18 -18
- package/src/router/primitives/$page.ts +46 -10
- package/src/router/providers/ReactBrowserProvider.ts +14 -29
- package/src/router/providers/ReactBrowserRouterProvider.ts +5 -0
- package/src/router/providers/ReactPageProvider.ts +11 -4
- package/src/router/providers/ReactServerProvider.ts +331 -316
- package/src/router/providers/ReactServerTemplateProvider.ts +775 -0
- package/src/router/providers/SSRManifestProvider.ts +365 -0
- package/src/router/services/ReactPageServerService.ts +5 -3
- package/src/router/services/ReactRouter.ts +3 -3
- package/src/head/__tests__/page-head.spec.ts +0 -39
- package/src/head/providers/ServerHeadProvider.spec.ts +0 -163
|
@@ -1,36 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
$atom,
|
|
3
|
-
$env,
|
|
4
|
-
$hook,
|
|
5
|
-
$inject,
|
|
6
|
-
$use,
|
|
7
|
-
Alepha,
|
|
8
|
-
type State,
|
|
9
|
-
type Static,
|
|
10
|
-
t,
|
|
11
|
-
} from "alepha";
|
|
1
|
+
import { $atom, $env, $hook, $inject, $use, Alepha, type State, type Static, t, } from "alepha";
|
|
12
2
|
import { DateTimeProvider } from "alepha/datetime";
|
|
13
3
|
import { $logger } from "alepha/logger";
|
|
14
4
|
import { LinkProvider } from "alepha/server/links";
|
|
5
|
+
import { BrowserHeadProvider } from "@alepha/react/head";
|
|
15
6
|
import { ReactBrowserRouterProvider } from "./ReactBrowserRouterProvider.ts";
|
|
16
|
-
import type {
|
|
17
|
-
PreviousLayerData,
|
|
18
|
-
ReactRouterState,
|
|
19
|
-
TransitionOptions,
|
|
20
|
-
} from "./ReactPageProvider.ts";
|
|
7
|
+
import type { PreviousLayerData, ReactRouterState, } from "./ReactPageProvider.ts";
|
|
21
8
|
import type { RouterGoOptions } from "../services/ReactRouter.ts";
|
|
22
9
|
|
|
23
10
|
export type { RouterGoOptions } from "../services/ReactRouter.ts";
|
|
24
11
|
|
|
25
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
26
|
-
|
|
27
|
-
const envSchema = t.object({
|
|
28
|
-
REACT_ROOT_ID: t.text({ default: "root" }),
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
declare module "alepha" {
|
|
32
|
-
interface Env extends Partial<Static<typeof envSchema>> {}
|
|
33
|
-
}
|
|
34
12
|
|
|
35
13
|
/**
|
|
36
14
|
* React browser renderer configuration atom
|
|
@@ -38,7 +16,7 @@ declare module "alepha" {
|
|
|
38
16
|
export const reactBrowserOptions = $atom({
|
|
39
17
|
name: "alepha.react.browser.options",
|
|
40
18
|
schema: t.object({
|
|
41
|
-
scrollRestoration: t.enum(["top", "manual"]),
|
|
19
|
+
scrollRestoration: t.enum(["top", "manual"]), // TODO: must be per page?
|
|
42
20
|
}),
|
|
43
21
|
default: {
|
|
44
22
|
scrollRestoration: "top" as const,
|
|
@@ -58,23 +36,27 @@ declare module "alepha" {
|
|
|
58
36
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
59
37
|
|
|
60
38
|
export class ReactBrowserProvider {
|
|
61
|
-
protected readonly env = $env(envSchema);
|
|
62
39
|
protected readonly log = $logger();
|
|
63
40
|
protected readonly client = $inject(LinkProvider);
|
|
64
41
|
protected readonly alepha = $inject(Alepha);
|
|
65
42
|
protected readonly router = $inject(ReactBrowserRouterProvider);
|
|
66
43
|
protected readonly dateTimeProvider = $inject(DateTimeProvider);
|
|
44
|
+
protected readonly browserHeadProvider = $inject(BrowserHeadProvider);
|
|
67
45
|
|
|
68
46
|
protected readonly options = $use(reactBrowserOptions);
|
|
69
47
|
|
|
48
|
+
public get rootId() {
|
|
49
|
+
return "root";
|
|
50
|
+
}
|
|
51
|
+
|
|
70
52
|
protected getRootElement() {
|
|
71
|
-
const root = this.document.getElementById(this.
|
|
53
|
+
const root = this.document.getElementById(this.rootId);
|
|
72
54
|
if (root) {
|
|
73
55
|
return root;
|
|
74
56
|
}
|
|
75
57
|
|
|
76
58
|
const div = this.document.createElement("div");
|
|
77
|
-
div.id = this.
|
|
59
|
+
div.id = this.rootId;
|
|
78
60
|
|
|
79
61
|
this.document.body.prepend(div);
|
|
80
62
|
|
|
@@ -281,6 +263,9 @@ export class ReactBrowserProvider {
|
|
|
281
263
|
state: this.state,
|
|
282
264
|
});
|
|
283
265
|
|
|
266
|
+
// Fill and render head from route configurations
|
|
267
|
+
this.browserHeadProvider.fillAndRenderHead(this.state);
|
|
268
|
+
|
|
284
269
|
window.addEventListener("popstate", () => {
|
|
285
270
|
// when you update silently queryParams or hash, skip rendering
|
|
286
271
|
// if you want to force a rendering, use #go()
|
|
@@ -2,6 +2,7 @@ import { $hook, $inject, Alepha } from "alepha";
|
|
|
2
2
|
import { $logger } from "alepha/logger";
|
|
3
3
|
import { type Route, RouterProvider } from "alepha/router";
|
|
4
4
|
import { createElement, type ReactNode } from "react";
|
|
5
|
+
import { BrowserHeadProvider } from "@alepha/react/head";
|
|
5
6
|
import NotFoundPage from "../components/NotFound.tsx";
|
|
6
7
|
import {
|
|
7
8
|
isPageRoute,
|
|
@@ -23,6 +24,7 @@ export class ReactBrowserRouterProvider extends RouterProvider<BrowserRoute> {
|
|
|
23
24
|
protected readonly log = $logger();
|
|
24
25
|
protected readonly alepha = $inject(Alepha);
|
|
25
26
|
protected readonly pageApi = $inject(ReactPageProvider);
|
|
27
|
+
protected readonly browserHeadProvider = $inject(BrowserHeadProvider);
|
|
26
28
|
|
|
27
29
|
public add(entry: PageRouteEntry) {
|
|
28
30
|
this.pageApi.add(entry);
|
|
@@ -147,6 +149,9 @@ export class ReactBrowserRouterProvider extends RouterProvider<BrowserRoute> {
|
|
|
147
149
|
await this.alepha.events.emit("react:transition:end", {
|
|
148
150
|
state,
|
|
149
151
|
});
|
|
152
|
+
|
|
153
|
+
// Fill and render head from route configurations
|
|
154
|
+
this.browserHeadProvider.fillAndRenderHead(state);
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
public root(state: ReactRouterState): ReactNode {
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
type PagePrimitive,
|
|
23
23
|
type PagePrimitiveOptions,
|
|
24
24
|
} from "../primitives/$page.ts";
|
|
25
|
+
import type { Head } from "@alepha/react/head";
|
|
25
26
|
|
|
26
27
|
const envSchema = t.object({
|
|
27
28
|
REACT_STRICT_MODE: t.boolean({ default: true }),
|
|
@@ -251,15 +252,15 @@ export class ReactPageProvider {
|
|
|
251
252
|
forceRefresh = true;
|
|
252
253
|
}
|
|
253
254
|
|
|
254
|
-
// no
|
|
255
|
-
if (!route.
|
|
255
|
+
// no loader, render a basic view by default
|
|
256
|
+
if (!route.loader) {
|
|
256
257
|
continue;
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
try {
|
|
260
261
|
const args = Object.create(state);
|
|
261
262
|
Object.assign(args, config, context);
|
|
262
|
-
const props = (await route.
|
|
263
|
+
const props = (await route.loader?.(args)) ?? {};
|
|
263
264
|
|
|
264
265
|
// save props
|
|
265
266
|
it.props = {
|
|
@@ -279,7 +280,7 @@ export class ReactPageProvider {
|
|
|
279
280
|
};
|
|
280
281
|
}
|
|
281
282
|
|
|
282
|
-
this.log.error("Page
|
|
283
|
+
this.log.error("Page loader has failed", e);
|
|
283
284
|
|
|
284
285
|
it.error = e as Error;
|
|
285
286
|
break;
|
|
@@ -696,6 +697,12 @@ export interface ReactRouterState {
|
|
|
696
697
|
*/
|
|
697
698
|
meta: Record<string, any>;
|
|
698
699
|
|
|
700
|
+
/**
|
|
701
|
+
* Head configuration for the current page (title, meta tags, etc.).
|
|
702
|
+
* Populated by HeadProvider during SSR.
|
|
703
|
+
*/
|
|
704
|
+
head: Head;
|
|
705
|
+
|
|
699
706
|
//
|
|
700
707
|
name?: string;
|
|
701
708
|
}
|