@alepha/react 0.7.0 → 0.7.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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/index.browser.cjs +59 -22
  3. package/dist/index.browser.js +42 -6
  4. package/dist/index.cjs +152 -85
  5. package/dist/index.d.ts +317 -206
  6. package/dist/index.js +130 -64
  7. package/dist/{useActive-DjpZBEuB.cjs → useRouterState-C2uo0jXu.cjs} +319 -140
  8. package/dist/{useActive-BX41CqY8.js → useRouterState-D5__ZcUV.js} +321 -143
  9. package/package.json +11 -10
  10. package/src/components/ClientOnly.tsx +35 -0
  11. package/src/components/ErrorBoundary.tsx +1 -1
  12. package/src/components/ErrorViewer.tsx +161 -0
  13. package/src/components/Link.tsx +9 -3
  14. package/src/components/NestedView.tsx +18 -3
  15. package/src/components/NotFound.tsx +30 -0
  16. package/src/descriptors/$page.ts +141 -30
  17. package/src/errors/RedirectionError.ts +4 -1
  18. package/src/hooks/RouterHookApi.ts +42 -24
  19. package/src/hooks/useAlepha.ts +12 -0
  20. package/src/hooks/useClient.ts +8 -6
  21. package/src/hooks/useInject.ts +2 -2
  22. package/src/hooks/useQueryParams.ts +1 -1
  23. package/src/hooks/useRouter.ts +6 -0
  24. package/src/index.browser.ts +4 -2
  25. package/src/index.shared.ts +11 -5
  26. package/src/index.ts +3 -4
  27. package/src/providers/BrowserRouterProvider.ts +4 -3
  28. package/src/providers/PageDescriptorProvider.ts +91 -20
  29. package/src/providers/ReactBrowserProvider.ts +6 -59
  30. package/src/providers/ReactBrowserRenderer.ts +72 -0
  31. package/src/providers/ReactServerProvider.ts +200 -81
  32. package/dist/index.browser.cjs.map +0 -1
  33. package/dist/index.browser.js.map +0 -1
  34. package/dist/index.cjs.map +0 -1
  35. package/dist/index.js.map +0 -1
  36. package/dist/useActive-BX41CqY8.js.map +0 -1
  37. package/dist/useActive-DjpZBEuB.cjs.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import type { PageDescriptor } from "../descriptors/$page.ts";
2
2
  import type {
3
3
  AnchorProps,
4
+ PageRoute,
4
5
  RouterState,
5
6
  } from "../providers/PageDescriptorProvider.ts";
6
7
  import type {
@@ -10,6 +11,7 @@ import type {
10
11
 
11
12
  export class RouterHookApi {
12
13
  constructor(
14
+ private readonly pages: PageRoute[],
13
15
  private readonly state: RouterState,
14
16
  private readonly layer: {
15
17
  path: string;
@@ -17,23 +19,14 @@ export class RouterHookApi {
17
19
  private readonly browser?: ReactBrowserProvider,
18
20
  ) {}
19
21
 
20
- /**
21
- *
22
- */
23
22
  public get current(): RouterState {
24
23
  return this.state;
25
24
  }
26
25
 
27
- /**
28
- *
29
- */
30
26
  public get pathname(): string {
31
27
  return this.state.pathname;
32
28
  }
33
29
 
34
- /**
35
- *
36
- */
37
30
  public get query(): Record<string, string> {
38
31
  const query: Record<string, string> = {};
39
32
 
@@ -46,24 +39,14 @@ export class RouterHookApi {
46
39
  return query;
47
40
  }
48
41
 
49
- /**
50
- *
51
- */
52
42
  public async back() {
53
43
  this.browser?.history.back();
54
44
  }
55
45
 
56
- /**
57
- *
58
- */
59
46
  public async forward() {
60
47
  this.browser?.history.forward();
61
48
  }
62
49
 
63
- /**
64
- *
65
- * @param props
66
- */
67
50
  public async invalidate(props?: Record<string, any>) {
68
51
  await this.browser?.invalidate(props);
69
52
  }
@@ -74,11 +57,21 @@ export class RouterHookApi {
74
57
  * @param pathname
75
58
  * @param layer
76
59
  */
77
- public createHref(pathname: HrefLike, layer: { path: string } = this.layer) {
60
+ public createHref(
61
+ pathname: HrefLike,
62
+ layer: { path: string } = this.layer,
63
+ options: { params?: Record<string, any> } = {},
64
+ ) {
78
65
  if (typeof pathname === "object") {
79
66
  pathname = pathname.options.path ?? "";
80
67
  }
81
68
 
69
+ if (options.params) {
70
+ for (const [key, value] of Object.entries(options.params)) {
71
+ pathname = pathname.replace(`:${key}`, String(value));
72
+ }
73
+ }
74
+
82
75
  return pathname.startsWith("/")
83
76
  ? pathname
84
77
  : `${layer.path}/${pathname}`.replace(/\/\/+/g, "/");
@@ -90,18 +83,43 @@ export class RouterHookApi {
90
83
  options?: RouterGoOptions,
91
84
  ): Promise<void>;
92
85
  public async go(path: string, options?: RouterGoOptions): Promise<void> {
93
- await this.browser?.go(this.createHref(path, this.layer), options);
86
+ for (const page of this.pages) {
87
+ if (page.name === path) {
88
+ path = page.path ?? "";
89
+ break;
90
+ }
91
+ }
92
+
93
+ await this.browser?.go(this.createHref(path, this.layer, options), options);
94
94
  }
95
95
 
96
- public anchor(path: string): AnchorProps {
97
- const href = this.createHref(path, this.layer);
96
+ public anchor(
97
+ path: string,
98
+ options?: { params?: Record<string, any> },
99
+ ): AnchorProps;
100
+ public anchor<T extends object>(
101
+ path: keyof VirtualRouter<T>,
102
+ options?: { params?: Record<string, any> },
103
+ ): AnchorProps;
104
+ public anchor(
105
+ path: string,
106
+ options: { params?: Record<string, any> } = {},
107
+ ): AnchorProps {
108
+ for (const page of this.pages) {
109
+ if (page.name === path) {
110
+ path = page.path ?? "";
111
+ break;
112
+ }
113
+ }
114
+
115
+ const href = this.createHref(path, this.layer, options);
98
116
  return {
99
117
  href,
100
118
  onClick: (ev: any) => {
101
119
  ev.stopPropagation();
102
120
  ev.preventDefault();
103
121
 
104
- this.go(path).catch(console.error);
122
+ this.go(path, options).catch(console.error);
105
123
  },
106
124
  };
107
125
  }
@@ -0,0 +1,12 @@
1
+ import type { Alepha } from "@alepha/core";
2
+ import { useContext } from "react";
3
+ import { RouterContext } from "../contexts/RouterContext.ts";
4
+
5
+ export const useAlepha = (): Alepha => {
6
+ const routerContext = useContext(RouterContext);
7
+ if (!routerContext) {
8
+ throw new Error("useAlepha must be used within a RouterProvider");
9
+ }
10
+
11
+ return routerContext.alepha;
12
+ };
@@ -1,10 +1,12 @@
1
- import { HttpClient } from "@alepha/server";
1
+ import {
2
+ type ClientScope,
3
+ HttpClient,
4
+ type HttpVirtualClient,
5
+ } from "@alepha/server";
2
6
  import { useInject } from "./useInject.ts";
3
7
 
4
- export const useClient = (): HttpClient => {
5
- return useInject(HttpClient);
6
- };
7
-
8
- export const useApi = <T extends object>() => {
8
+ export const useClient = <T extends object>(
9
+ _scope?: ClientScope,
10
+ ): HttpVirtualClient<T> => {
9
11
  return useInject(HttpClient).of<T>();
10
12
  };
@@ -1,8 +1,8 @@
1
- import type { Class } from "@alepha/core";
1
+ import type { Service } from "@alepha/core";
2
2
  import { useContext, useMemo } from "react";
3
3
  import { RouterContext } from "../contexts/RouterContext.ts";
4
4
 
5
- export const useInject = <T extends object>(clazz: Class<T>): T => {
5
+ export const useInject = <T extends object>(clazz: Service<T>): T => {
6
6
  const ctx = useContext(RouterContext);
7
7
  if (!ctx) {
8
8
  throw new Error("useRouter must be used within a <RouterProvider>");
@@ -50,7 +50,7 @@ const encode = (alepha: Alepha, schema: TObject, data: any) => {
50
50
  const decode = (alepha: Alepha, schema: TObject, data: any) => {
51
51
  try {
52
52
  return alepha.parse(schema, JSON.parse(atob(decodeURIComponent(data))));
53
- } catch (error) {
53
+ } catch (_error) {
54
54
  return {};
55
55
  }
56
56
  };
@@ -1,6 +1,7 @@
1
1
  import { useContext, useMemo } from "react";
2
2
  import { RouterContext } from "../contexts/RouterContext.ts";
3
3
  import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
4
+ import { PageDescriptorProvider } from "../providers/PageDescriptorProvider.ts";
4
5
  import { ReactBrowserProvider } from "../providers/ReactBrowserProvider.ts";
5
6
  import { RouterHookApi } from "./RouterHookApi.ts";
6
7
 
@@ -11,9 +12,14 @@ export const useRouter = (): RouterHookApi => {
11
12
  throw new Error("useRouter must be used within a RouterProvider");
12
13
  }
13
14
 
15
+ const pages = useMemo(() => {
16
+ return ctx.alepha.get(PageDescriptorProvider).getPages();
17
+ }, []);
18
+
14
19
  return useMemo(
15
20
  () =>
16
21
  new RouterHookApi(
22
+ pages,
17
23
  ctx.state,
18
24
  layer,
19
25
  ctx.alepha.isBrowser()
@@ -1,8 +1,9 @@
1
- import { $inject, Alepha, __bind } from "@alepha/core";
1
+ import { __bind, $inject, Alepha } from "@alepha/core";
2
2
  import { $page } from "./descriptors/$page.ts";
3
3
  import { BrowserRouterProvider } from "./providers/BrowserRouterProvider.ts";
4
4
  import { PageDescriptorProvider } from "./providers/PageDescriptorProvider.ts";
5
5
  import { ReactBrowserProvider } from "./providers/ReactBrowserProvider.ts";
6
+ import { ReactBrowserRenderer } from "./providers/ReactBrowserRenderer.ts";
6
7
 
7
8
  export * from "./index.shared";
8
9
  export * from "./providers/ReactBrowserProvider.ts";
@@ -14,7 +15,8 @@ export class ReactModule {
14
15
  this.alepha //
15
16
  .with(PageDescriptorProvider)
16
17
  .with(ReactBrowserProvider)
17
- .with(BrowserRouterProvider);
18
+ .with(BrowserRouterProvider)
19
+ .with(ReactBrowserRenderer);
18
20
  }
19
21
  }
20
22
 
@@ -1,16 +1,22 @@
1
- export { default as NestedView } from "./components/NestedView.tsx";
2
- export { default as Link } from "./components/Link.tsx";
1
+ export { default as ClientOnly } from "./components/ClientOnly.tsx";
3
2
  export { default as ErrorBoundary } from "./components/ErrorBoundary.tsx";
3
+ export * from "./components/ErrorViewer.tsx";
4
+ export { default as Link } from "./components/Link.tsx";
5
+ export { default as NestedView } from "./components/NestedView.tsx";
4
6
 
5
7
  export * from "./contexts/RouterContext.ts";
6
8
  export * from "./contexts/RouterLayerContext.ts";
9
+
7
10
  export * from "./descriptors/$page.ts";
11
+
12
+ export * from "./errors/RedirectionError.ts";
13
+
8
14
  export * from "./hooks/RouterHookApi.ts";
9
- export * from "./hooks/useInject.ts";
15
+ export * from "./hooks/useActive.ts";
16
+ export * from "./hooks/useAlepha.ts";
10
17
  export * from "./hooks/useClient.ts";
18
+ export * from "./hooks/useInject.ts";
11
19
  export * from "./hooks/useQueryParams.ts";
12
20
  export * from "./hooks/useRouter.ts";
13
21
  export * from "./hooks/useRouterEvents.ts";
14
22
  export * from "./hooks/useRouterState.ts";
15
- export * from "./hooks/useActive.ts";
16
- export * from "./errors/RedirectionError.ts";
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $inject, Alepha, __bind } from "@alepha/core";
1
+ import { __bind, $inject, Alepha } from "@alepha/core";
2
2
  import {
3
3
  ServerLinksProvider,
4
4
  ServerModule,
@@ -13,13 +13,13 @@ import {
13
13
  } from "./providers/PageDescriptorProvider.ts";
14
14
  import type { ReactHydrationState } from "./providers/ReactBrowserProvider.ts";
15
15
  import { ReactServerProvider } from "./providers/ReactServerProvider.ts";
16
- export { default as NestedView } from "./components/NestedView.tsx";
17
16
 
17
+ export { default as NestedView } from "./components/NestedView.tsx";
18
+ export * from "./errors/RedirectionError.ts";
18
19
  export * from "./index.shared.ts";
19
20
  export * from "./providers/PageDescriptorProvider.ts";
20
21
  export * from "./providers/ReactBrowserProvider.ts";
21
22
  export * from "./providers/ReactServerProvider.ts";
22
- export * from "./errors/RedirectionError.ts";
23
23
 
24
24
  declare module "@alepha/core" {
25
25
  interface Hooks {
@@ -32,7 +32,6 @@ declare module "@alepha/core" {
32
32
  request: ServerRequest;
33
33
  pageRequest: PageRequest;
34
34
  };
35
-
36
35
  "react:transition:begin": {
37
36
  state: RouterState;
38
37
  context: PageReactContext;
@@ -1,7 +1,9 @@
1
1
  import { $hook, $inject, $logger, Alepha } from "@alepha/core";
2
2
  import { type Route, RouterProvider } from "@alepha/router";
3
- import type { ReactNode } from "react";
3
+ import { createElement, type ReactNode } from "react";
4
+ import NotFoundPage from "../components/NotFound.tsx";
4
5
  import {
6
+ isPageRoute,
5
7
  PageDescriptorProvider,
6
8
  type PageReactContext,
7
9
  type PageRequest,
@@ -10,7 +12,6 @@ import {
10
12
  type RouterRenderResult,
11
13
  type RouterState,
12
14
  type TransitionOptions,
13
- isPageRoute,
14
15
  } from "./PageDescriptorProvider.ts";
15
16
 
16
17
  export interface BrowserRoute extends Route {
@@ -98,7 +99,7 @@ export class BrowserRouterProvider extends RouterProvider<BrowserRoute> {
98
99
  if (state.layers.length === 0) {
99
100
  state.layers.push({
100
101
  name: "not-found",
101
- element: "Not Found",
102
+ element: createElement(NotFoundPage),
102
103
  index: 0,
103
104
  path: "/",
104
105
  });
@@ -1,7 +1,11 @@
1
- import { $hook, $inject, $logger, Alepha, OPTIONS } from "@alepha/core";
1
+ import type { Static } from "@alepha/core";
2
+ import { $hook, $inject, $logger, Alepha, OPTIONS, t } from "@alepha/core";
2
3
  import type { ApiLinksResponse } from "@alepha/server";
3
- import { type ReactNode, createElement } from "react";
4
+ import { createElement, type ReactNode, StrictMode } from "react";
5
+ import ClientOnly from "../components/ClientOnly.tsx";
6
+ import ErrorViewer from "../components/ErrorViewer.tsx";
4
7
  import NestedView from "../components/NestedView.tsx";
8
+ import NotFoundPage from "../components/NotFound.tsx";
5
9
  import { RouterContext } from "../contexts/RouterContext.ts";
6
10
  import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
7
11
  import {
@@ -11,8 +15,17 @@ import {
11
15
  } from "../descriptors/$page.ts";
12
16
  import { RedirectionError } from "../errors/RedirectionError.ts";
13
17
 
18
+ const envSchema = t.object({
19
+ REACT_STRICT_MODE: t.boolean({ default: true }),
20
+ });
21
+
22
+ declare module "@alepha/core" {
23
+ export interface Env extends Partial<Static<typeof envSchema>> {}
24
+ }
25
+
14
26
  export class PageDescriptorProvider {
15
27
  protected readonly log = $logger();
28
+ protected readonly env = $inject(envSchema);
16
29
  protected readonly alepha = $inject(Alepha);
17
30
  protected readonly pages: PageRoute[] = [];
18
31
 
@@ -30,8 +43,32 @@ export class PageDescriptorProvider {
30
43
  throw new Error(`Page ${name} not found`);
31
44
  }
32
45
 
46
+ public url(
47
+ name: string,
48
+ options: { params?: Record<string, string>; base?: string } = {},
49
+ ): URL {
50
+ const page = this.page(name);
51
+ if (!page) {
52
+ throw new Error(`Page ${name} not found`);
53
+ }
54
+
55
+ let url = page.path ?? "";
56
+ let parent = page.parent;
57
+ while (parent) {
58
+ url = `${parent.path ?? ""}/${url}`;
59
+ parent = parent.parent;
60
+ }
61
+
62
+ url = this.compile(url, options.params ?? {});
63
+
64
+ return new URL(
65
+ url.replace(/\/\/+/g, "/") || "/",
66
+ options.base ?? `http://localhost`,
67
+ );
68
+ }
69
+
33
70
  public root(state: RouterState, context: PageReactContext): ReactNode {
34
- return createElement(
71
+ const root = createElement(
35
72
  RouterContext.Provider,
36
73
  {
37
74
  value: {
@@ -42,6 +79,12 @@ export class PageDescriptorProvider {
42
79
  },
43
80
  createElement(NestedView, {}, state.layers[0]?.element),
44
81
  );
82
+
83
+ if (this.env.REACT_STRICT_MODE) {
84
+ return createElement(StrictMode, {}, root);
85
+ }
86
+
87
+ return root;
45
88
  }
46
89
 
47
90
  public async createLayers(
@@ -52,7 +95,7 @@ export class PageDescriptorProvider {
52
95
  const layers: Layer[] = []; // result layers
53
96
  let context: Record<string, any> = {}; // all props
54
97
  const stack: Array<RouterStackItem> = [{ route }]; // stack of routes
55
- let onError = this.renderError; // error handler
98
+ request.onError = (error) => this.renderError(error); // error handler
56
99
 
57
100
  let parent = route.parent;
58
101
  while (parent) {
@@ -182,12 +225,15 @@ export class PageDescriptorProvider {
182
225
  const path = acc.replace(/\/+/, "/");
183
226
  const localErrorHandler = this.getErrorHandler(it.route);
184
227
  if (localErrorHandler) {
185
- onError = localErrorHandler;
228
+ request.onError = localErrorHandler;
186
229
  }
187
230
 
188
231
  // handler has thrown an error, render an error view
189
232
  if (it.error) {
190
- const element = await onError(it.error);
233
+ let element: ReactNode = await request.onError(it.error);
234
+ if (element === null) {
235
+ element = this.renderError(it.error);
236
+ }
191
237
 
192
238
  layers.push({
193
239
  props,
@@ -195,7 +241,7 @@ export class PageDescriptorProvider {
195
241
  name: it.route.name,
196
242
  part: it.route.path,
197
243
  config: it.config,
198
- element: this.renderView(i + 1, path, element),
244
+ element: this.renderView(i + 1, path, element, it.route),
199
245
  index: i + 1,
200
246
  path,
201
247
  });
@@ -204,7 +250,7 @@ export class PageDescriptorProvider {
204
250
 
205
251
  // normal use case
206
252
 
207
- const layer = await this.createElement(it.route, {
253
+ const element = await this.createElement(it.route, {
208
254
  ...props,
209
255
  ...context,
210
256
  });
@@ -214,7 +260,7 @@ export class PageDescriptorProvider {
214
260
  props,
215
261
  part: it.route.path,
216
262
  config: it.config,
217
- element: this.renderView(i + 1, path, layer),
263
+ element: this.renderView(i + 1, path, element, it.route),
218
264
  index: i + 1,
219
265
  path,
220
266
  });
@@ -293,8 +339,8 @@ export class PageDescriptorProvider {
293
339
  }
294
340
  }
295
341
 
296
- public renderError(e: Error): ReactNode {
297
- return createElement("pre", { style: { overflow: "auto" } }, `${e.stack}`);
342
+ public renderError(error: Error): ReactNode {
343
+ return createElement(ErrorViewer, { error });
298
344
  }
299
345
 
300
346
  public renderEmptyView(): ReactNode {
@@ -332,8 +378,19 @@ export class PageDescriptorProvider {
332
378
  protected renderView(
333
379
  index: number,
334
380
  path: string,
335
- view: ReactNode = this.renderEmptyView(),
381
+ view: ReactNode | undefined,
382
+ page: PageRoute,
336
383
  ): ReactNode {
384
+ view ??= this.renderEmptyView();
385
+
386
+ const element = page.client
387
+ ? createElement(
388
+ ClientOnly,
389
+ typeof page.client === "object" ? page.client : {},
390
+ view,
391
+ )
392
+ : view;
393
+
337
394
  return createElement(
338
395
  RouterLayerContext.Provider,
339
396
  {
@@ -342,24 +399,44 @@ export class PageDescriptorProvider {
342
399
  path,
343
400
  },
344
401
  },
345
- view,
402
+ element,
346
403
  );
347
404
  }
348
405
 
349
406
  protected readonly configure = $hook({
350
407
  name: "configure",
351
408
  handler: () => {
409
+ let hasNotFoundHandler = false;
352
410
  const pages = this.alepha.getDescriptorValues($page);
353
411
  for (const { value, key } of pages) {
354
412
  value[OPTIONS].name ??= key;
413
+ }
355
414
 
415
+ for (const { value } of pages) {
356
416
  // skip children, we only want root pages
357
417
  if (value[OPTIONS].parent) {
358
418
  continue;
359
419
  }
360
420
 
421
+ if (value[OPTIONS].path === "/*") {
422
+ hasNotFoundHandler = true;
423
+ }
424
+
361
425
  this.add(this.map(pages, value));
362
426
  }
427
+
428
+ if (!hasNotFoundHandler && pages.length > 0) {
429
+ // add a default 404 page if not already defined
430
+ this.add({
431
+ path: "/*",
432
+ name: "notFound",
433
+ cache: true,
434
+ component: NotFoundPage,
435
+ afterHandler: ({ reply }) => {
436
+ reply.status = 404;
437
+ },
438
+ });
439
+ }
363
440
  },
364
441
  });
365
442
 
@@ -369,12 +446,6 @@ export class PageDescriptorProvider {
369
446
  ): PageRouteEntry {
370
447
  const children = target[OPTIONS].children ?? [];
371
448
 
372
- for (const it of pages) {
373
- if (it.value[OPTIONS].parent === target) {
374
- children.push(it.value);
375
- }
376
- }
377
-
378
449
  return {
379
450
  ...target[OPTIONS],
380
451
  parent: undefined,
@@ -465,7 +536,7 @@ export interface Layer {
465
536
  path: string;
466
537
  }
467
538
 
468
- export type PreviousLayerData = Omit<Layer, "element">;
539
+ export type PreviousLayerData = Omit<Layer, "element" | "index" | "path">;
469
540
 
470
541
  export interface AnchorProps {
471
542
  href: string;
@@ -1,7 +1,6 @@
1
- import { $hook, $inject, $logger, Alepha, type Static, t } from "@alepha/core";
2
- import { HttpClient, type HttpClientLink } from "@alepha/server";
1
+ import { $hook, $inject, $logger, Alepha } from "@alepha/core";
2
+ import { type ApiLinksResponse, HttpClient } from "@alepha/server";
3
3
  import type { Root } from "react-dom/client";
4
- import { createRoot, hydrateRoot } from "react-dom/client";
5
4
  import { BrowserHeadProvider } from "./BrowserHeadProvider.ts";
6
5
  import { BrowserRouterProvider } from "./BrowserRouterProvider.ts";
7
6
  import type {
@@ -11,21 +10,12 @@ import type {
11
10
  TransitionOptions,
12
11
  } from "./PageDescriptorProvider.ts";
13
12
 
14
- const envSchema = t.object({
15
- REACT_ROOT_ID: t.string({ default: "root" }),
16
- });
17
-
18
- declare module "@alepha/core" {
19
- interface Env extends Partial<Static<typeof envSchema>> {}
20
- }
21
-
22
13
  export class ReactBrowserProvider {
23
14
  protected readonly log = $logger();
24
15
  protected readonly client = $inject(HttpClient);
25
16
  protected readonly alepha = $inject(Alepha);
26
17
  protected readonly router = $inject(BrowserRouterProvider);
27
18
  protected readonly headProvider = $inject(BrowserHeadProvider);
28
- protected readonly env = $inject(envSchema);
29
19
  protected root!: Root;
30
20
 
31
21
  public transitioning?: {
@@ -75,11 +65,6 @@ export class ReactBrowserProvider {
75
65
  await this.render({ previous });
76
66
  }
77
67
 
78
- /**
79
- *
80
- * @param url
81
- * @param options
82
- */
83
68
  public async go(url: string, options: RouterGoOptions = {}): Promise<void> {
84
69
  const result = await this.render({
85
70
  url,
@@ -101,10 +86,7 @@ export class ReactBrowserProvider {
101
86
  }
102
87
 
103
88
  protected async render(
104
- options: {
105
- url?: string;
106
- previous?: PreviousLayerData[];
107
- } = {},
89
+ options: { url?: string; previous?: PreviousLayerData[] } = {},
108
90
  ): Promise<RouterRenderResult> {
109
91
  const previous = options.previous ?? this.state.layers;
110
92
  const url = options.url ?? this.url;
@@ -130,8 +112,6 @@ export class ReactBrowserProvider {
130
112
 
131
113
  /**
132
114
  * Get embedded layers from the server.
133
- *
134
- * @protected
135
115
  */
136
116
  protected getHydrationState(): ReactHydrationState | undefined {
137
117
  try {
@@ -143,30 +123,8 @@ export class ReactBrowserProvider {
143
123
  }
144
124
  }
145
125
 
146
- /**
147
- *
148
- * @protected
149
- */
150
- protected getRootElement() {
151
- const root = this.document.getElementById(this.env.REACT_ROOT_ID);
152
- if (root) {
153
- return root;
154
- }
155
-
156
- const div = this.document.createElement("div");
157
- div.id = this.env.REACT_ROOT_ID;
158
-
159
- this.document.body.prepend(div);
160
-
161
- return div;
162
- }
163
-
164
126
  // -------------------------------------------------------------------------------------------------------------------
165
127
 
166
- /**
167
- *
168
- * @protected
169
- */
170
128
  public readonly ready = $hook({
171
129
  name: "ready",
172
130
  handler: async () => {
@@ -174,7 +132,7 @@ export class ReactBrowserProvider {
174
132
  const previous = hydration?.layers ?? [];
175
133
 
176
134
  if (hydration?.links) {
177
- for (const link of hydration.links) {
135
+ for (const link of hydration.links.links) {
178
136
  this.client.pushLink(link);
179
137
  }
180
138
  }
@@ -190,17 +148,6 @@ export class ReactBrowserProvider {
190
148
  hydration,
191
149
  });
192
150
 
193
- const element = this.router.root(this.state, context);
194
-
195
- if (previous.length > 0) {
196
- this.root = hydrateRoot(this.getRootElement(), element);
197
- this.log.info("Hydrated root element");
198
- } else {
199
- this.root ??= createRoot(this.getRootElement());
200
- this.root.render(element);
201
- this.log.info("Created root element");
202
- }
203
-
204
151
  window.addEventListener("popstate", () => {
205
152
  this.render();
206
153
  });
@@ -224,6 +171,6 @@ export interface RouterGoOptions {
224
171
  }
225
172
 
226
173
  export interface ReactHydrationState {
227
- layers?: PreviousLayerData[];
228
- links?: HttpClientLink[];
174
+ layers?: Array<PreviousLayerData>;
175
+ links?: ApiLinksResponse;
229
176
  }