@alepha/react 0.14.0 → 0.14.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 +1 -1
- package/dist/auth/index.browser.js +1488 -4
- package/dist/auth/index.browser.js.map +1 -1
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +1827 -4
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.d.ts +54 -937
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +132 -2010
- package/dist/core/index.js.map +1 -1
- package/dist/form/index.d.ts.map +1 -1
- package/dist/form/index.js +6 -1
- package/dist/form/index.js.map +1 -1
- package/dist/head/index.browser.js +191 -17
- package/dist/head/index.browser.js.map +1 -1
- package/dist/head/index.d.ts +652 -31
- package/dist/head/index.d.ts.map +1 -1
- package/dist/head/index.js +209 -18
- package/dist/head/index.js.map +1 -1
- package/dist/{core → router}/index.browser.js +126 -516
- package/dist/router/index.browser.js.map +1 -0
- package/dist/router/index.d.ts +1334 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +1939 -0
- package/dist/router/index.js.map +1 -0
- package/package.json +12 -6
- package/src/auth/index.ts +1 -1
- package/src/auth/services/ReactAuth.ts +1 -1
- package/src/core/components/ClientOnly.tsx +14 -0
- package/src/core/components/ErrorBoundary.tsx +3 -2
- package/src/core/contexts/AlephaContext.ts +3 -0
- package/src/core/contexts/AlephaProvider.tsx +2 -1
- package/src/core/index.ts +13 -102
- package/src/form/services/FormModel.ts +5 -0
- package/src/head/helpers/SeoExpander.ts +141 -0
- package/src/head/index.browser.ts +1 -0
- package/src/head/index.ts +17 -7
- package/src/head/interfaces/Head.ts +69 -27
- package/src/head/providers/BrowserHeadProvider.ts +45 -12
- package/src/head/providers/HeadProvider.ts +32 -8
- package/src/head/providers/ServerHeadProvider.ts +34 -2
- package/src/{core → router}/components/ErrorViewer.tsx +2 -0
- package/src/router/components/Link.tsx +21 -0
- package/src/{core → router}/components/NestedView.tsx +3 -5
- package/src/router/components/NotFound.tsx +30 -0
- package/src/router/errors/Redirection.ts +28 -0
- package/src/{core → router}/hooks/useActive.ts +6 -2
- package/src/{core → router}/hooks/useQueryParams.ts +2 -2
- package/src/{core → router}/hooks/useRouter.ts +1 -1
- package/src/{core → router}/hooks/useRouterState.ts +1 -1
- package/src/{core → router}/index.browser.ts +14 -12
- package/src/{core/index.shared-router.ts → router/index.shared.ts} +6 -3
- package/src/router/index.ts +125 -0
- package/src/{core → router}/primitives/$page.ts +1 -1
- package/src/{core → router}/providers/ReactBrowserProvider.ts +3 -13
- package/src/{core → router}/providers/ReactBrowserRendererProvider.ts +3 -0
- package/src/{core → router}/providers/ReactBrowserRouterProvider.ts +3 -0
- package/src/{core → router}/providers/ReactPageProvider.ts +5 -3
- package/src/{core → router}/providers/ReactServerProvider.ts +9 -28
- package/src/{core → router}/services/ReactPageServerService.ts +3 -0
- package/src/{core → router}/services/ReactPageService.ts +5 -5
- package/src/{core → router}/services/ReactRouter.ts +26 -5
- package/dist/core/index.browser.js.map +0 -1
- package/dist/core/index.native.js +0 -403
- package/dist/core/index.native.js.map +0 -1
- package/src/core/components/Link.tsx +0 -18
- package/src/core/components/NotFound.tsx +0 -27
- package/src/core/errors/Redirection.ts +0 -13
- package/src/core/hooks/useSchema.ts +0 -88
- package/src/core/index.native.ts +0 -21
- package/src/core/index.shared.ts +0 -9
- /package/src/{core → router}/contexts/RouterLayerContext.ts +0 -0
package/dist/head/index.d.ts
CHANGED
|
@@ -1,36 +1,605 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import * as
|
|
3
|
-
import { KIND, Primitive } from "alepha";
|
|
4
|
-
import { ServerTimingProvider } from "alepha/server";
|
|
1
|
+
import { ClientOnlyProps } from "@alepha/react";
|
|
2
|
+
import * as alepha15 from "alepha";
|
|
3
|
+
import { Alepha, AlephaError, Async, KIND, Primitive, Static, TSchema } from "alepha";
|
|
4
|
+
import { ServerRequest, ServerTimingProvider } from "alepha/server";
|
|
5
|
+
import { FC, ReactNode } from "react";
|
|
6
|
+
import { ServerRouteCache } from "alepha/server/cache";
|
|
7
|
+
import "alepha/logger";
|
|
8
|
+
import "alepha/datetime";
|
|
9
|
+
import "alepha/server/links";
|
|
10
|
+
import "alepha/router";
|
|
11
|
+
import "react/jsx-runtime";
|
|
12
|
+
import "alepha/server/static";
|
|
5
13
|
|
|
14
|
+
//#region ../../src/router/errors/Redirection.d.ts
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Used for Redirection during the page loading.
|
|
18
|
+
*
|
|
19
|
+
* Depends on the context, it can be thrown or just returned.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { Redirection } from "@alepha/react";
|
|
24
|
+
*
|
|
25
|
+
* const MyPage = $page({
|
|
26
|
+
* resolve: async () => {
|
|
27
|
+
* if (needRedirect) {
|
|
28
|
+
* throw new Redirection("/new-path");
|
|
29
|
+
* }
|
|
30
|
+
* },
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare class Redirection extends AlephaError {
|
|
35
|
+
readonly redirect: string;
|
|
36
|
+
constructor(redirect: string);
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region ../../src/router/providers/ReactPageProvider.d.ts
|
|
40
|
+
declare const envSchema$2: alepha15.TObject<{
|
|
41
|
+
REACT_STRICT_MODE: alepha15.TBoolean;
|
|
42
|
+
}>;
|
|
43
|
+
declare module "alepha" {
|
|
44
|
+
interface Env extends Partial<Static<typeof envSchema$2>> {}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Handle page routes for React applications. (Browser and Server)
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
interface PageRouteEntry extends Omit<PagePrimitiveOptions, "children" | "parent"> {
|
|
51
|
+
children?: PageRouteEntry[];
|
|
52
|
+
}
|
|
53
|
+
interface PageRoute extends PageRouteEntry {
|
|
54
|
+
type: "page";
|
|
55
|
+
name: string;
|
|
56
|
+
parent?: PageRoute;
|
|
57
|
+
match: string;
|
|
58
|
+
}
|
|
59
|
+
interface Layer {
|
|
60
|
+
config?: {
|
|
61
|
+
query?: Record<string, any>;
|
|
62
|
+
params?: Record<string, any>;
|
|
63
|
+
context?: Record<string, any>;
|
|
64
|
+
};
|
|
65
|
+
name: string;
|
|
66
|
+
props?: Record<string, any>;
|
|
67
|
+
error?: Error;
|
|
68
|
+
part?: string;
|
|
69
|
+
element: ReactNode;
|
|
70
|
+
index: number;
|
|
71
|
+
path: string;
|
|
72
|
+
route?: PageRoute;
|
|
73
|
+
cache?: boolean;
|
|
74
|
+
}
|
|
75
|
+
type PreviousLayerData = Omit<Layer, "element" | "index" | "path">;
|
|
76
|
+
interface ReactRouterState {
|
|
77
|
+
/**
|
|
78
|
+
* Stack of layers for the current page.
|
|
79
|
+
*/
|
|
80
|
+
layers: Array<Layer>;
|
|
81
|
+
/**
|
|
82
|
+
* URL of the current page.
|
|
83
|
+
*/
|
|
84
|
+
url: URL;
|
|
85
|
+
/**
|
|
86
|
+
* Error handler for the current page.
|
|
87
|
+
*/
|
|
88
|
+
onError: ErrorHandler;
|
|
89
|
+
/**
|
|
90
|
+
* Params extracted from the URL for the current page.
|
|
91
|
+
*/
|
|
92
|
+
params: Record<string, any>;
|
|
93
|
+
/**
|
|
94
|
+
* Query parameters extracted from the URL for the current page.
|
|
95
|
+
*/
|
|
96
|
+
query: Record<string, string>;
|
|
97
|
+
/**
|
|
98
|
+
* Optional meta information associated with the current page.
|
|
99
|
+
*/
|
|
100
|
+
meta: Record<string, any>;
|
|
101
|
+
name?: string;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region ../../src/router/services/ReactPageService.d.ts
|
|
105
|
+
/**
|
|
106
|
+
* $page methods interface.
|
|
107
|
+
*/
|
|
108
|
+
declare abstract class ReactPageService {
|
|
109
|
+
fetch(pathname: string, options?: PagePrimitiveRenderOptions): Promise<{
|
|
110
|
+
html: string;
|
|
111
|
+
response: Response;
|
|
112
|
+
}>;
|
|
113
|
+
render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region ../../src/router/primitives/$page.d.ts
|
|
117
|
+
|
|
118
|
+
interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
|
|
119
|
+
/**
|
|
120
|
+
* Identifier name for the page. Must be unique.
|
|
121
|
+
*
|
|
122
|
+
* @default Primitive key
|
|
123
|
+
*/
|
|
124
|
+
name?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Add a pathname to the page.
|
|
127
|
+
*
|
|
128
|
+
* Pathname can contain parameters, like `/post/:slug`.
|
|
129
|
+
*
|
|
130
|
+
* @default ""
|
|
131
|
+
*/
|
|
132
|
+
path?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Add an input schema to define:
|
|
135
|
+
* - `params`: parameters from the pathname.
|
|
136
|
+
* - `query`: query parameters from the URL.
|
|
137
|
+
*/
|
|
138
|
+
schema?: TConfig;
|
|
139
|
+
/**
|
|
140
|
+
* Load data before rendering the page.
|
|
141
|
+
*
|
|
142
|
+
* This function receives
|
|
143
|
+
* - the request context (params, query, etc.)
|
|
144
|
+
* - the parent props (if page has a parent)
|
|
145
|
+
*
|
|
146
|
+
* > In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.
|
|
147
|
+
*
|
|
148
|
+
* Resolve can be stopped by throwing an error, which will be handled by the `errorHandler` function.
|
|
149
|
+
* It's common to throw a `NotFoundError` to display a 404 page.
|
|
150
|
+
*
|
|
151
|
+
* RedirectError can be thrown to redirect the user to another page.
|
|
152
|
+
*/
|
|
153
|
+
resolve?: (context: PageResolve<TConfig, TPropsParent>) => Async<TProps>;
|
|
154
|
+
/**
|
|
155
|
+
* Default props to pass to the component when rendering the page.
|
|
156
|
+
*
|
|
157
|
+
* Resolved props from the `resolve` function will override these default props.
|
|
158
|
+
*/
|
|
159
|
+
props?: () => Partial<TProps>;
|
|
160
|
+
/**
|
|
161
|
+
* The component to render when the page is loaded.
|
|
162
|
+
*
|
|
163
|
+
* If `lazy` is defined, this will be ignored.
|
|
164
|
+
* Prefer using `lazy` to improve the initial loading time.
|
|
165
|
+
*/
|
|
166
|
+
component?: FC<TProps & TPropsParent>;
|
|
167
|
+
/**
|
|
168
|
+
* Lazy load the component when the page is loaded.
|
|
169
|
+
*
|
|
170
|
+
* It's recommended to use this for components to improve the initial loading time
|
|
171
|
+
* and enable code-splitting.
|
|
172
|
+
*/
|
|
173
|
+
lazy?: () => Promise<{
|
|
174
|
+
default: FC<TProps & TPropsParent>;
|
|
175
|
+
}>;
|
|
176
|
+
/**
|
|
177
|
+
* Attach child pages to create nested routes.
|
|
178
|
+
* This will make the page a parent route.
|
|
179
|
+
*/
|
|
180
|
+
children?: Array<PagePrimitive> | (() => Array<PagePrimitive>);
|
|
181
|
+
/**
|
|
182
|
+
* Define a parent page for nested routing.
|
|
183
|
+
*/
|
|
184
|
+
parent?: PagePrimitive<PageConfigSchema, TPropsParent, any>;
|
|
185
|
+
/**
|
|
186
|
+
* Function to determine if the page can be accessed.
|
|
187
|
+
*
|
|
188
|
+
* If it returns false, the page will not be accessible and a 403 Forbidden error will be returned.
|
|
189
|
+
* This function can be used to implement permission-based access control.
|
|
190
|
+
*/
|
|
191
|
+
can?: () => boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Catch any error from the `resolve` function or during `rendering`.
|
|
194
|
+
*
|
|
195
|
+
* Expected to return one of the following:
|
|
196
|
+
* - a ReactNode to render an error page
|
|
197
|
+
* - a Redirection to redirect the user
|
|
198
|
+
* - undefined to let the error propagate
|
|
199
|
+
*
|
|
200
|
+
* If not defined, the error will be thrown and handled by the server or client error handler.
|
|
201
|
+
* If a leaf $page does not define an error handler, the error can be caught by parent pages.
|
|
202
|
+
*
|
|
203
|
+
* @example Catch a 404 from API and render a custom not found component:
|
|
204
|
+
* ```ts
|
|
205
|
+
* resolve: async ({ params, query }) => {
|
|
206
|
+
* api.fetch("/api/resource", { params, query });
|
|
207
|
+
* },
|
|
208
|
+
* errorHandler: (error, context) => {
|
|
209
|
+
* if (HttpError.is(error, 404)) {
|
|
210
|
+
* return <ResourceNotFound />;
|
|
211
|
+
* }
|
|
212
|
+
* }
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* @example Catch an 401 error and redirect the user to the login page:
|
|
216
|
+
* ```ts
|
|
217
|
+
* resolve: async ({ params, query }) => {
|
|
218
|
+
* // but the user is not authenticated
|
|
219
|
+
* api.fetch("/api/resource", { params, query });
|
|
220
|
+
* },
|
|
221
|
+
* errorHandler: (error, context) => {
|
|
222
|
+
* if (HttpError.is(error, 401)) {
|
|
223
|
+
* // throwing a Redirection is also valid!
|
|
224
|
+
* return new Redirection("/login");
|
|
225
|
+
* }
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
errorHandler?: ErrorHandler;
|
|
230
|
+
/**
|
|
231
|
+
* If true, the page will be considered as a static page, immutable and cacheable.
|
|
232
|
+
* Replace boolean by an object to define static entries. (e.g. list of params/query)
|
|
233
|
+
*
|
|
234
|
+
* Browser-side: it only works with `alepha/vite`, which can pre-render the page at build time.
|
|
235
|
+
*
|
|
236
|
+
* Server-side: It will act as timeless cached page. You can use `cache` to configure the cache behavior.
|
|
237
|
+
*/
|
|
238
|
+
static?: boolean | {
|
|
239
|
+
entries?: Array<Partial<PageRequestConfig<TConfig>>>;
|
|
240
|
+
};
|
|
241
|
+
cache?: ServerRouteCache;
|
|
242
|
+
/**
|
|
243
|
+
* If true, force the page to be rendered only on the client-side (browser).
|
|
244
|
+
* It uses the `<ClientOnly/>` component to render the page.
|
|
245
|
+
*/
|
|
246
|
+
client?: boolean | ClientOnlyProps;
|
|
247
|
+
/**
|
|
248
|
+
* Called before the server response is sent to the client. (server only)
|
|
249
|
+
*/
|
|
250
|
+
onServerResponse?: (request: ServerRequest) => unknown;
|
|
251
|
+
/**
|
|
252
|
+
* Called when user leaves the page. (browser only)
|
|
253
|
+
*/
|
|
254
|
+
onLeave?: () => void;
|
|
255
|
+
/**
|
|
256
|
+
* @experimental
|
|
257
|
+
*
|
|
258
|
+
* Add a css animation when the page is loaded or unloaded.
|
|
259
|
+
* It uses CSS animations, so you need to define the keyframes in your CSS.
|
|
260
|
+
*
|
|
261
|
+
* @example Simple animation name
|
|
262
|
+
* ```ts
|
|
263
|
+
* animation: "fadeIn"
|
|
264
|
+
* ```
|
|
265
|
+
*
|
|
266
|
+
* CSS example:
|
|
267
|
+
* ```css
|
|
268
|
+
* @keyframes fadeIn {
|
|
269
|
+
* from { opacity: 0; }
|
|
270
|
+
* to { opacity: 1; }
|
|
271
|
+
* }
|
|
272
|
+
* ```
|
|
273
|
+
*
|
|
274
|
+
* @example Detailed animation
|
|
275
|
+
* ```ts
|
|
276
|
+
* animation: {
|
|
277
|
+
* enter: { name: "fadeIn", duration: 300 },
|
|
278
|
+
* exit: { name: "fadeOut", duration: 200, timing: "ease-in-out" },
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*
|
|
282
|
+
* @example Only exit animation
|
|
283
|
+
* ```ts
|
|
284
|
+
* animation: {
|
|
285
|
+
* exit: "fadeOut"
|
|
286
|
+
* }
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @example With custom timing function
|
|
290
|
+
* ```ts
|
|
291
|
+
* animation: {
|
|
292
|
+
* enter: { name: "fadeIn", duration: 300, timing: "cubic-bezier(0.4, 0, 0.2, 1)" },
|
|
293
|
+
* exit: { name: "fadeOut", duration: 200, timing: "ease-in-out" },
|
|
294
|
+
* }
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
animation?: PageAnimation;
|
|
298
|
+
}
|
|
299
|
+
type ErrorHandler = (error: Error, state: ReactRouterState) => ReactNode | Redirection | undefined;
|
|
300
|
+
declare class PagePrimitive<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> extends Primitive<PagePrimitiveOptions<TConfig, TProps, TPropsParent>> {
|
|
301
|
+
protected readonly reactPageService: ReactPageService;
|
|
302
|
+
protected onInit(): void;
|
|
303
|
+
get name(): string;
|
|
304
|
+
/**
|
|
305
|
+
* For testing or build purposes.
|
|
306
|
+
*
|
|
307
|
+
* This will render the page (HTML layout included or not) and return the HTML + context.
|
|
308
|
+
* Only valid for server-side rendering, it will throw an error if called on the client-side.
|
|
309
|
+
*/
|
|
310
|
+
render(options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
|
|
311
|
+
fetch(options?: PagePrimitiveRenderOptions): Promise<{
|
|
312
|
+
html: string;
|
|
313
|
+
response: Response;
|
|
314
|
+
}>;
|
|
315
|
+
match(url: string): boolean;
|
|
316
|
+
pathname(config: any): string;
|
|
317
|
+
}
|
|
318
|
+
interface PageConfigSchema {
|
|
319
|
+
query?: TSchema;
|
|
320
|
+
params?: TSchema;
|
|
321
|
+
}
|
|
322
|
+
type TPropsDefault = any;
|
|
323
|
+
type TPropsParentDefault = {};
|
|
324
|
+
interface PagePrimitiveRenderOptions {
|
|
325
|
+
params?: Record<string, string>;
|
|
326
|
+
query?: Record<string, string>;
|
|
327
|
+
/**
|
|
328
|
+
* If true, the HTML layout will be included in the response.
|
|
329
|
+
* If false, only the page content will be returned.
|
|
330
|
+
*
|
|
331
|
+
* @default true
|
|
332
|
+
*/
|
|
333
|
+
html?: boolean;
|
|
334
|
+
hydration?: boolean;
|
|
335
|
+
}
|
|
336
|
+
interface PagePrimitiveRenderResult {
|
|
337
|
+
html: string;
|
|
338
|
+
state: ReactRouterState;
|
|
339
|
+
redirect?: string;
|
|
340
|
+
}
|
|
341
|
+
interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema> {
|
|
342
|
+
params: TConfig["params"] extends TSchema ? Static<TConfig["params"]> : Record<string, string>;
|
|
343
|
+
query: TConfig["query"] extends TSchema ? Static<TConfig["query"]> : Record<string, string>;
|
|
344
|
+
}
|
|
345
|
+
type PageResolve<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & Omit<ReactRouterState, "layers" | "onError">;
|
|
346
|
+
type PageAnimation = PageAnimationObject | ((state: ReactRouterState) => PageAnimationObject | undefined);
|
|
347
|
+
type PageAnimationObject = CssAnimationName | {
|
|
348
|
+
enter?: CssAnimation | CssAnimationName;
|
|
349
|
+
exit?: CssAnimation | CssAnimationName;
|
|
350
|
+
};
|
|
351
|
+
type CssAnimationName = string;
|
|
352
|
+
type CssAnimation = {
|
|
353
|
+
name: string;
|
|
354
|
+
duration?: number;
|
|
355
|
+
timing?: string;
|
|
356
|
+
};
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region ../../src/core/index.d.ts
|
|
359
|
+
declare module "alepha" {
|
|
360
|
+
interface Hooks {
|
|
361
|
+
/**
|
|
362
|
+
* Fires when a user action is starting.
|
|
363
|
+
* Action can be a form submission, a route transition, or a custom action.
|
|
364
|
+
*/
|
|
365
|
+
"react:action:begin": {
|
|
366
|
+
type: string;
|
|
367
|
+
id?: string;
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Fires when a user action has succeeded.
|
|
371
|
+
* Action can be a form submission, a route transition, or a custom action.
|
|
372
|
+
*/
|
|
373
|
+
"react:action:success": {
|
|
374
|
+
type: string;
|
|
375
|
+
id?: string;
|
|
376
|
+
};
|
|
377
|
+
/**
|
|
378
|
+
* Fires when a user action has failed.
|
|
379
|
+
* Action can be a form submission, a route transition, or a custom action.
|
|
380
|
+
*/
|
|
381
|
+
"react:action:error": {
|
|
382
|
+
type: string;
|
|
383
|
+
id?: string;
|
|
384
|
+
error: Error;
|
|
385
|
+
};
|
|
386
|
+
/**
|
|
387
|
+
* Fires when a user action has completed, regardless of success or failure.
|
|
388
|
+
* Action can be a form submission, a route transition, or a custom action.
|
|
389
|
+
*/
|
|
390
|
+
"react:action:end": {
|
|
391
|
+
type: string;
|
|
392
|
+
id?: string;
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Provides full-stack React development with declarative routing, server-side rendering, and client-side hydration.
|
|
398
|
+
*
|
|
399
|
+
* The React module enables building modern React applications using the `$page` primitive on class properties.
|
|
400
|
+
* It delivers seamless server-side rendering, automatic code splitting, and client-side navigation with full
|
|
401
|
+
* type safety and schema validation for route parameters and data.
|
|
402
|
+
*
|
|
403
|
+
* @see {@link $page}
|
|
404
|
+
* @module alepha.react
|
|
405
|
+
*/
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region ../../src/router/providers/ReactBrowserProvider.d.ts
|
|
408
|
+
declare const envSchema$1: alepha15.TObject<{
|
|
409
|
+
REACT_ROOT_ID: alepha15.TString;
|
|
410
|
+
}>;
|
|
411
|
+
declare module "alepha" {
|
|
412
|
+
interface Env extends Partial<Static<typeof envSchema$1>> {}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* React browser renderer configuration atom
|
|
416
|
+
*/
|
|
417
|
+
declare const reactBrowserOptions: alepha15.Atom<alepha15.TObject<{
|
|
418
|
+
scrollRestoration: alepha15.TUnsafe<"top" | "manual">;
|
|
419
|
+
}>, "alepha.react.browser.options">;
|
|
420
|
+
type ReactBrowserRendererOptions = Static<typeof reactBrowserOptions.schema>;
|
|
421
|
+
declare module "alepha" {
|
|
422
|
+
interface State {
|
|
423
|
+
[reactBrowserOptions.key]: ReactBrowserRendererOptions;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
type ReactHydrationState = {
|
|
427
|
+
layers?: Array<PreviousLayerData>;
|
|
428
|
+
} & {
|
|
429
|
+
[key: string]: any;
|
|
430
|
+
};
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region ../../src/router/providers/ReactServerProvider.d.ts
|
|
433
|
+
declare const envSchema: alepha15.TObject<{
|
|
434
|
+
REACT_SSR_ENABLED: alepha15.TOptional<alepha15.TBoolean>;
|
|
435
|
+
REACT_ROOT_ID: alepha15.TString;
|
|
436
|
+
}>;
|
|
437
|
+
declare module "alepha" {
|
|
438
|
+
interface Env extends Partial<Static<typeof envSchema>> {}
|
|
439
|
+
interface State {
|
|
440
|
+
"alepha.react.server.ssr"?: boolean;
|
|
441
|
+
"alepha.react.server.template"?: string;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* React server provider configuration atom
|
|
446
|
+
*/
|
|
447
|
+
declare const reactServerOptions: alepha15.Atom<alepha15.TObject<{
|
|
448
|
+
publicDir: alepha15.TString;
|
|
449
|
+
staticServer: alepha15.TObject<{
|
|
450
|
+
disabled: alepha15.TBoolean;
|
|
451
|
+
path: alepha15.TString;
|
|
452
|
+
}>;
|
|
453
|
+
}>, "alepha.react.server.options">;
|
|
454
|
+
type ReactServerProviderOptions = Static<typeof reactServerOptions.schema>;
|
|
455
|
+
declare module "alepha" {
|
|
456
|
+
interface State {
|
|
457
|
+
[reactServerOptions.key]: ReactServerProviderOptions;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* React server provider responsible for SSR and static file serving.
|
|
462
|
+
*
|
|
463
|
+
* Use `react-dom/server` under the hood.
|
|
464
|
+
*/
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region ../../src/router/index.d.ts
|
|
467
|
+
declare module "alepha" {
|
|
468
|
+
interface State {
|
|
469
|
+
"alepha.react.router.state"?: ReactRouterState;
|
|
470
|
+
}
|
|
471
|
+
interface Hooks {
|
|
472
|
+
/**
|
|
473
|
+
* Fires when the React application is starting to be rendered on the server.
|
|
474
|
+
*/
|
|
475
|
+
"react:server:render:begin": {
|
|
476
|
+
request?: ServerRequest;
|
|
477
|
+
state: ReactRouterState;
|
|
478
|
+
};
|
|
479
|
+
/**
|
|
480
|
+
* Fires when the React application has been rendered on the server.
|
|
481
|
+
*/
|
|
482
|
+
"react:server:render:end": {
|
|
483
|
+
request?: ServerRequest;
|
|
484
|
+
state: ReactRouterState;
|
|
485
|
+
html: string;
|
|
486
|
+
};
|
|
487
|
+
/**
|
|
488
|
+
* Fires when the React application is being rendered on the browser.
|
|
489
|
+
*/
|
|
490
|
+
"react:browser:render": {
|
|
491
|
+
root: HTMLElement;
|
|
492
|
+
element: ReactNode;
|
|
493
|
+
state: ReactRouterState;
|
|
494
|
+
hydration?: ReactHydrationState;
|
|
495
|
+
};
|
|
496
|
+
/**
|
|
497
|
+
* Fires when a route transition is starting.
|
|
498
|
+
*/
|
|
499
|
+
"react:transition:begin": {
|
|
500
|
+
previous: ReactRouterState;
|
|
501
|
+
state: ReactRouterState;
|
|
502
|
+
animation?: PageAnimation;
|
|
503
|
+
};
|
|
504
|
+
/**
|
|
505
|
+
* Fires when a route transition has succeeded.
|
|
506
|
+
*/
|
|
507
|
+
"react:transition:success": {
|
|
508
|
+
state: ReactRouterState;
|
|
509
|
+
};
|
|
510
|
+
/**
|
|
511
|
+
* Fires when a route transition has failed.
|
|
512
|
+
*/
|
|
513
|
+
"react:transition:error": {
|
|
514
|
+
state: ReactRouterState;
|
|
515
|
+
error: Error;
|
|
516
|
+
};
|
|
517
|
+
/**
|
|
518
|
+
* Fires when a route transition has completed, regardless of success or failure.
|
|
519
|
+
*/
|
|
520
|
+
"react:transition:end": {
|
|
521
|
+
state: ReactRouterState;
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Provides declarative routing with the `$page` primitive for building type-safe React routes.
|
|
527
|
+
*
|
|
528
|
+
* This module enables:
|
|
529
|
+
* - URL pattern matching with parameters (e.g., `/users/:id`)
|
|
530
|
+
* - Nested routing with parent-child relationships
|
|
531
|
+
* - Type-safe URL parameter and query string validation
|
|
532
|
+
* - Server-side data fetching with the `resolve` function
|
|
533
|
+
* - Lazy loading and code splitting
|
|
534
|
+
* - Page animations and error handling
|
|
535
|
+
*
|
|
536
|
+
* @see {@link $page}
|
|
537
|
+
* @module alepha.react.router
|
|
538
|
+
*/
|
|
539
|
+
//#endregion
|
|
6
540
|
//#region ../../src/head/interfaces/Head.d.ts
|
|
7
|
-
|
|
541
|
+
/**
|
|
542
|
+
* Complete head configuration combining basic head elements with SEO fields.
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
* ```ts
|
|
546
|
+
* $head({
|
|
547
|
+
* title: "My App",
|
|
548
|
+
* description: "Build amazing apps",
|
|
549
|
+
* image: "https://example.com/og.png",
|
|
550
|
+
* url: "https://example.com/",
|
|
551
|
+
* siteName: "My App",
|
|
552
|
+
* twitter: { card: "summary_large_image" },
|
|
553
|
+
* })
|
|
554
|
+
* ```
|
|
555
|
+
*/
|
|
556
|
+
interface Head extends SimpleHead, Seo {}
|
|
557
|
+
/**
|
|
558
|
+
* SEO configuration for automatic meta tag generation.
|
|
559
|
+
* Fields are used for meta description, OpenGraph, and Twitter Card tags.
|
|
560
|
+
*/
|
|
561
|
+
interface Seo {
|
|
562
|
+
/** Page description - used for meta description, og:description, twitter:description */
|
|
8
563
|
description?: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
og
|
|
564
|
+
/** Primary image URL - used for og:image and twitter:image */
|
|
565
|
+
image?: string;
|
|
566
|
+
/** Canonical URL - used for og:url and link rel="canonical" */
|
|
567
|
+
url?: string;
|
|
568
|
+
/** Site name - used for og:site_name */
|
|
569
|
+
siteName?: string;
|
|
570
|
+
/** Locale - used for og:locale (e.g., "en_US") */
|
|
571
|
+
locale?: string;
|
|
572
|
+
/** Content type - used for og:type (default: "website") */
|
|
573
|
+
type?: "website" | "article" | "product" | "profile" | string;
|
|
574
|
+
/** Image width in pixels - used for og:image:width */
|
|
575
|
+
imageWidth?: number;
|
|
576
|
+
/** Image height in pixels - used for og:image:height */
|
|
577
|
+
imageHeight?: number;
|
|
578
|
+
/** Image alt text - used for og:image:alt and twitter:image:alt */
|
|
579
|
+
imageAlt?: string;
|
|
580
|
+
/** Twitter-specific overrides */
|
|
581
|
+
twitter?: {
|
|
582
|
+
/** Twitter card type */
|
|
583
|
+
card?: "summary" | "summary_large_image" | "app" | "player";
|
|
584
|
+
/** @username of website */
|
|
585
|
+
site?: string;
|
|
586
|
+
/** @username of content creator */
|
|
587
|
+
creator?: string;
|
|
588
|
+
/** Override title for Twitter */
|
|
22
589
|
title?: string;
|
|
590
|
+
/** Override description for Twitter */
|
|
23
591
|
description?: string;
|
|
592
|
+
/** Override image for Twitter */
|
|
24
593
|
image?: string;
|
|
25
|
-
url?: string;
|
|
26
|
-
type?: string;
|
|
27
594
|
};
|
|
28
|
-
|
|
29
|
-
|
|
595
|
+
/** OpenGraph-specific overrides */
|
|
596
|
+
og?: {
|
|
597
|
+
/** Override title for OpenGraph */
|
|
30
598
|
title?: string;
|
|
599
|
+
/** Override description for OpenGraph */
|
|
31
600
|
description?: string;
|
|
601
|
+
/** Override image for OpenGraph */
|
|
32
602
|
image?: string;
|
|
33
|
-
site?: string;
|
|
34
603
|
};
|
|
35
604
|
}
|
|
36
605
|
interface SimpleHead {
|
|
@@ -38,20 +607,63 @@ interface SimpleHead {
|
|
|
38
607
|
titleSeparator?: string;
|
|
39
608
|
htmlAttributes?: Record<string, string>;
|
|
40
609
|
bodyAttributes?: Record<string, string>;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}>;
|
|
610
|
+
/** Meta tags - supports both name and property attributes */
|
|
611
|
+
meta?: Array<HeadMeta>;
|
|
612
|
+
/** Link tags (e.g., stylesheets, preload, canonical) */
|
|
45
613
|
link?: Array<{
|
|
46
614
|
rel: string;
|
|
47
615
|
href: string;
|
|
48
616
|
}>;
|
|
617
|
+
/** Script tags - any valid script attributes (src, type, async, defer, etc.) */
|
|
618
|
+
script?: Array<Record<string, string | boolean>>;
|
|
619
|
+
}
|
|
620
|
+
interface HeadMeta {
|
|
621
|
+
/** Meta name attribute (e.g., "description", "twitter:card") */
|
|
622
|
+
name?: string;
|
|
623
|
+
/** Meta property attribute (e.g., "og:title", "og:image") */
|
|
624
|
+
property?: string;
|
|
625
|
+
/** Meta content value */
|
|
626
|
+
content: string;
|
|
627
|
+
}
|
|
628
|
+
//#endregion
|
|
629
|
+
//#region ../../src/head/helpers/SeoExpander.d.ts
|
|
630
|
+
/**
|
|
631
|
+
* Expands Head configuration into SEO meta tags.
|
|
632
|
+
*
|
|
633
|
+
* Generates:
|
|
634
|
+
* - `<meta name="description">` from head.description
|
|
635
|
+
* - `<meta property="og:*">` OpenGraph tags
|
|
636
|
+
* - `<meta name="twitter:*">` Twitter Card tags
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* ```ts
|
|
640
|
+
* const helper = new SeoExpander();
|
|
641
|
+
* const { meta, link } = helper.expand({
|
|
642
|
+
* title: "My App",
|
|
643
|
+
* description: "Build amazing apps",
|
|
644
|
+
* image: "https://example.com/og.png",
|
|
645
|
+
* url: "https://example.com/",
|
|
646
|
+
* });
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
declare class SeoExpander {
|
|
650
|
+
expand(head: Head): {
|
|
651
|
+
meta: HeadMeta[];
|
|
652
|
+
link: Array<{
|
|
653
|
+
rel: string;
|
|
654
|
+
href: string;
|
|
655
|
+
}>;
|
|
656
|
+
};
|
|
657
|
+
protected expandOpenGraph(head: Head, meta: HeadMeta[]): void;
|
|
658
|
+
protected expandTwitter(head: Head, meta: HeadMeta[]): void;
|
|
49
659
|
}
|
|
50
660
|
//#endregion
|
|
51
661
|
//#region ../../src/head/providers/HeadProvider.d.ts
|
|
52
662
|
declare class HeadProvider {
|
|
663
|
+
protected readonly seoExpander: SeoExpander;
|
|
53
664
|
global?: Array<Head | (() => Head)>;
|
|
54
665
|
fillHead(state: ReactRouterState): void;
|
|
666
|
+
protected mergeHead(state: ReactRouterState, head: Head): void;
|
|
55
667
|
protected fillHeadByPage(page: PageRoute, state: ReactRouterState, props: Record<string, any>): void;
|
|
56
668
|
}
|
|
57
669
|
//#endregion
|
|
@@ -95,18 +707,22 @@ type UseHeadReturn = [Head, (head?: Head | ((previous?: Head) => Head)) => void]
|
|
|
95
707
|
declare class ServerHeadProvider {
|
|
96
708
|
protected readonly headProvider: HeadProvider;
|
|
97
709
|
protected readonly serverTimingProvider: ServerTimingProvider;
|
|
98
|
-
protected readonly onServerRenderEnd:
|
|
710
|
+
protected readonly onServerRenderEnd: alepha15.HookPrimitive<"react:server:render:end">;
|
|
99
711
|
renderHead(template: string, head: SimpleHead): string;
|
|
100
712
|
protected mergeAttributes(existing: string, attrs: Record<string, string>): string;
|
|
101
713
|
protected parseAttributes(attrStr: string): Record<string, string>;
|
|
102
714
|
protected escapeHtml(str: string): string;
|
|
715
|
+
protected renderMetaTag(meta: HeadMeta): string;
|
|
716
|
+
protected renderScriptTag(script: Record<string, string | boolean>): string;
|
|
103
717
|
}
|
|
104
718
|
//#endregion
|
|
105
719
|
//#region ../../src/head/index.d.ts
|
|
106
|
-
declare module "@alepha/react" {
|
|
720
|
+
declare module "@alepha/react/router" {
|
|
107
721
|
interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
|
|
108
722
|
head?: Head | ((props: TProps, previous?: Head) => Head);
|
|
109
723
|
}
|
|
724
|
+
}
|
|
725
|
+
declare module "@alepha/react/router" {
|
|
110
726
|
interface ReactRouterState {
|
|
111
727
|
head: Head;
|
|
112
728
|
}
|
|
@@ -114,10 +730,15 @@ declare module "@alepha/react" {
|
|
|
114
730
|
/**
|
|
115
731
|
* Fill `<head>` server & client side.
|
|
116
732
|
*
|
|
733
|
+
* Generate SEO-friendly meta tags and titles for your React application using AlephaReactHead module.
|
|
734
|
+
*
|
|
735
|
+
* This module provides services and primitives to manage the document head both on the server and client side,
|
|
736
|
+
* ensuring that your application is optimized for search engines and social media sharing.
|
|
737
|
+
*
|
|
117
738
|
* @see {@link ServerHeadProvider}
|
|
118
739
|
* @module alepha.react.head
|
|
119
740
|
*/
|
|
120
|
-
declare const AlephaReactHead:
|
|
741
|
+
declare const AlephaReactHead: alepha15.Service<alepha15.Module>;
|
|
121
742
|
//#endregion
|
|
122
|
-
export { $head, AlephaReactHead, Head, HeadPrimitive, HeadPrimitiveOptions, ServerHeadProvider, SimpleHead, UseHeadOptions, UseHeadReturn, useHead };
|
|
743
|
+
export { $head, AlephaReactHead, Head, HeadMeta, HeadPrimitive, HeadPrimitiveOptions, Seo, SeoExpander, ServerHeadProvider, SimpleHead, UseHeadOptions, UseHeadReturn, useHead };
|
|
123
744
|
//# sourceMappingURL=index.d.ts.map
|