@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.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/dist/auth/index.browser.js +1488 -4
  3. package/dist/auth/index.browser.js.map +1 -1
  4. package/dist/auth/index.d.ts +2 -2
  5. package/dist/auth/index.js +1827 -4
  6. package/dist/auth/index.js.map +1 -1
  7. package/dist/core/index.d.ts +54 -937
  8. package/dist/core/index.d.ts.map +1 -1
  9. package/dist/core/index.js +132 -2010
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/form/index.d.ts.map +1 -1
  12. package/dist/form/index.js +6 -1
  13. package/dist/form/index.js.map +1 -1
  14. package/dist/head/index.browser.js +191 -17
  15. package/dist/head/index.browser.js.map +1 -1
  16. package/dist/head/index.d.ts +652 -31
  17. package/dist/head/index.d.ts.map +1 -1
  18. package/dist/head/index.js +209 -18
  19. package/dist/head/index.js.map +1 -1
  20. package/dist/{core → router}/index.browser.js +126 -516
  21. package/dist/router/index.browser.js.map +1 -0
  22. package/dist/router/index.d.ts +1334 -0
  23. package/dist/router/index.d.ts.map +1 -0
  24. package/dist/router/index.js +1939 -0
  25. package/dist/router/index.js.map +1 -0
  26. package/package.json +12 -6
  27. package/src/auth/index.ts +1 -1
  28. package/src/auth/services/ReactAuth.ts +1 -1
  29. package/src/core/components/ClientOnly.tsx +14 -0
  30. package/src/core/components/ErrorBoundary.tsx +3 -2
  31. package/src/core/contexts/AlephaContext.ts +3 -0
  32. package/src/core/contexts/AlephaProvider.tsx +2 -1
  33. package/src/core/index.ts +13 -102
  34. package/src/form/services/FormModel.ts +5 -0
  35. package/src/head/helpers/SeoExpander.ts +141 -0
  36. package/src/head/index.browser.ts +1 -0
  37. package/src/head/index.ts +17 -7
  38. package/src/head/interfaces/Head.ts +69 -27
  39. package/src/head/providers/BrowserHeadProvider.ts +45 -12
  40. package/src/head/providers/HeadProvider.ts +32 -8
  41. package/src/head/providers/ServerHeadProvider.ts +34 -2
  42. package/src/{core → router}/components/ErrorViewer.tsx +2 -0
  43. package/src/router/components/Link.tsx +21 -0
  44. package/src/{core → router}/components/NestedView.tsx +3 -5
  45. package/src/router/components/NotFound.tsx +30 -0
  46. package/src/router/errors/Redirection.ts +28 -0
  47. package/src/{core → router}/hooks/useActive.ts +6 -2
  48. package/src/{core → router}/hooks/useQueryParams.ts +2 -2
  49. package/src/{core → router}/hooks/useRouter.ts +1 -1
  50. package/src/{core → router}/hooks/useRouterState.ts +1 -1
  51. package/src/{core → router}/index.browser.ts +14 -12
  52. package/src/{core/index.shared-router.ts → router/index.shared.ts} +6 -3
  53. package/src/router/index.ts +125 -0
  54. package/src/{core → router}/primitives/$page.ts +1 -1
  55. package/src/{core → router}/providers/ReactBrowserProvider.ts +3 -13
  56. package/src/{core → router}/providers/ReactBrowserRendererProvider.ts +3 -0
  57. package/src/{core → router}/providers/ReactBrowserRouterProvider.ts +3 -0
  58. package/src/{core → router}/providers/ReactPageProvider.ts +5 -3
  59. package/src/{core → router}/providers/ReactServerProvider.ts +9 -28
  60. package/src/{core → router}/services/ReactPageServerService.ts +3 -0
  61. package/src/{core → router}/services/ReactPageService.ts +5 -5
  62. package/src/{core → router}/services/ReactRouter.ts +26 -5
  63. package/dist/core/index.browser.js.map +0 -1
  64. package/dist/core/index.native.js +0 -403
  65. package/dist/core/index.native.js.map +0 -1
  66. package/src/core/components/Link.tsx +0 -18
  67. package/src/core/components/NotFound.tsx +0 -27
  68. package/src/core/errors/Redirection.ts +0 -13
  69. package/src/core/hooks/useSchema.ts +0 -88
  70. package/src/core/index.native.ts +0 -21
  71. package/src/core/index.shared.ts +0 -9
  72. /package/src/{core → router}/contexts/RouterLayerContext.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/head/interfaces/Head.ts","../../src/head/providers/HeadProvider.ts","../../src/head/primitives/$head.ts","../../src/head/hooks/useHead.ts","../../src/head/providers/ServerHeadProvider.ts","../../src/head/index.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/router/errors/Redirection.ts","../../src/router/providers/ReactPageProvider.ts","../../src/router/services/ReactPageService.ts","../../src/router/primitives/$page.ts","../../src/core/index.ts","../../src/router/providers/ReactBrowserProvider.ts","../../src/router/providers/ReactServerProvider.ts","../../src/router/index.ts","../../src/head/interfaces/Head.ts","../../src/head/helpers/SeoExpander.ts","../../src/head/providers/HeadProvider.ts","../../src/head/primitives/$head.ts","../../src/head/hooks/useHead.ts","../../src/head/providers/ServerHeadProvider.ts","../../src/head/index.ts"],"sourcesContent":[],"mappings":"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"}
@@ -3,25 +3,175 @@ import { $hook, $inject, $module, Alepha, KIND, Primitive, createPrimitive } fro
3
3
  import { ServerTimingProvider } from "alepha/server";
4
4
  import { useCallback, useEffect, useMemo } from "react";
5
5
 
6
+ //#region ../../src/head/helpers/SeoExpander.ts
7
+ /**
8
+ * Expands Head configuration into SEO meta tags.
9
+ *
10
+ * Generates:
11
+ * - `<meta name="description">` from head.description
12
+ * - `<meta property="og:*">` OpenGraph tags
13
+ * - `<meta name="twitter:*">` Twitter Card tags
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const helper = new SeoExpander();
18
+ * const { meta, link } = helper.expand({
19
+ * title: "My App",
20
+ * description: "Build amazing apps",
21
+ * image: "https://example.com/og.png",
22
+ * url: "https://example.com/",
23
+ * });
24
+ * ```
25
+ */
26
+ var SeoExpander = class {
27
+ expand(head) {
28
+ const meta = [];
29
+ const link = [];
30
+ if (!(head.description || head.image || head.url || head.siteName || head.locale || head.type || head.og || head.twitter)) return {
31
+ meta,
32
+ link
33
+ };
34
+ if (head.description) meta.push({
35
+ name: "description",
36
+ content: head.description
37
+ });
38
+ if (head.url) link.push({
39
+ rel: "canonical",
40
+ href: head.url
41
+ });
42
+ this.expandOpenGraph(head, meta);
43
+ this.expandTwitter(head, meta);
44
+ return {
45
+ meta,
46
+ link
47
+ };
48
+ }
49
+ expandOpenGraph(head, meta) {
50
+ const ogTitle = head.og?.title ?? head.title;
51
+ const ogDescription = head.og?.description ?? head.description;
52
+ const ogImage = head.og?.image ?? head.image;
53
+ if (head.type || ogTitle) meta.push({
54
+ property: "og:type",
55
+ content: head.type ?? "website"
56
+ });
57
+ if (head.url) meta.push({
58
+ property: "og:url",
59
+ content: head.url
60
+ });
61
+ if (ogTitle) meta.push({
62
+ property: "og:title",
63
+ content: ogTitle
64
+ });
65
+ if (ogDescription) meta.push({
66
+ property: "og:description",
67
+ content: ogDescription
68
+ });
69
+ if (ogImage) {
70
+ meta.push({
71
+ property: "og:image",
72
+ content: ogImage
73
+ });
74
+ if (head.imageWidth) meta.push({
75
+ property: "og:image:width",
76
+ content: String(head.imageWidth)
77
+ });
78
+ if (head.imageHeight) meta.push({
79
+ property: "og:image:height",
80
+ content: String(head.imageHeight)
81
+ });
82
+ if (head.imageAlt) meta.push({
83
+ property: "og:image:alt",
84
+ content: head.imageAlt
85
+ });
86
+ }
87
+ if (head.siteName) meta.push({
88
+ property: "og:site_name",
89
+ content: head.siteName
90
+ });
91
+ if (head.locale) meta.push({
92
+ property: "og:locale",
93
+ content: head.locale
94
+ });
95
+ }
96
+ expandTwitter(head, meta) {
97
+ const twitterTitle = head.twitter?.title ?? head.title;
98
+ const twitterDescription = head.twitter?.description ?? head.description;
99
+ const twitterImage = head.twitter?.image ?? head.image;
100
+ if (head.twitter?.card || twitterTitle || twitterImage) meta.push({
101
+ name: "twitter:card",
102
+ content: head.twitter?.card ?? (twitterImage ? "summary_large_image" : "summary")
103
+ });
104
+ if (head.url) meta.push({
105
+ name: "twitter:url",
106
+ content: head.url
107
+ });
108
+ if (twitterTitle) meta.push({
109
+ name: "twitter:title",
110
+ content: twitterTitle
111
+ });
112
+ if (twitterDescription) meta.push({
113
+ name: "twitter:description",
114
+ content: twitterDescription
115
+ });
116
+ if (twitterImage) {
117
+ meta.push({
118
+ name: "twitter:image",
119
+ content: twitterImage
120
+ });
121
+ if (head.imageAlt) meta.push({
122
+ name: "twitter:image:alt",
123
+ content: head.imageAlt
124
+ });
125
+ }
126
+ if (head.twitter?.site) meta.push({
127
+ name: "twitter:site",
128
+ content: head.twitter.site
129
+ });
130
+ if (head.twitter?.creator) meta.push({
131
+ name: "twitter:creator",
132
+ content: head.twitter.creator
133
+ });
134
+ }
135
+ };
136
+
137
+ //#endregion
6
138
  //#region ../../src/head/providers/HeadProvider.ts
7
139
  var HeadProvider = class {
140
+ seoExpander = $inject(SeoExpander);
8
141
  global = [];
9
142
  fillHead(state) {
10
143
  state.head = { ...state.head };
11
144
  for (const h of this.global ?? []) {
12
145
  const head = typeof h === "function" ? h() : h;
13
- state.head = {
14
- ...state.head,
15
- ...head,
16
- meta: [...state.head.meta ?? [], ...head.meta ?? []]
17
- };
146
+ this.mergeHead(state, head);
18
147
  }
19
148
  for (const layer of state.layers) if (layer.route?.head && !layer.error) this.fillHeadByPage(layer.route, state, layer.props ?? {});
20
149
  }
150
+ mergeHead(state, head) {
151
+ const { meta, link } = this.seoExpander.expand(head);
152
+ state.head = {
153
+ ...state.head,
154
+ ...head,
155
+ meta: [
156
+ ...state.head.meta ?? [],
157
+ ...meta,
158
+ ...head.meta ?? []
159
+ ],
160
+ link: [
161
+ ...state.head.link ?? [],
162
+ ...link,
163
+ ...head.link ?? []
164
+ ],
165
+ script: [...state.head.script ?? [], ...head.script ?? []]
166
+ };
167
+ }
21
168
  fillHeadByPage(page, state, props) {
22
169
  if (!page.head) return;
23
170
  state.head ??= {};
24
171
  const head = typeof page.head === "function" ? page.head(props, state.head) : page.head;
172
+ const { meta, link } = this.seoExpander.expand(head);
173
+ state.head.meta = [...state.head.meta ?? [], ...meta];
174
+ state.head.link = [...state.head.link ?? [], ...link];
25
175
  if (head.title) {
26
176
  state.head ??= {};
27
177
  if (state.head.titleSeparator) state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;
@@ -37,6 +187,8 @@ var HeadProvider = class {
37
187
  ...head.bodyAttributes
38
188
  };
39
189
  if (head.meta) state.head.meta = [...state.head.meta ?? [], ...head.meta ?? []];
190
+ if (head.link) state.head.link = [...state.head.link ?? [], ...head.link ?? []];
191
+ if (head.script) state.head.script = [...state.head.script ?? [], ...head.script ?? []];
40
192
  }
41
193
  };
42
194
 
@@ -80,8 +232,9 @@ var ServerHeadProvider = class {
80
232
  const title = head.title;
81
233
  if (title) if (template.includes("<title>")) result = result.replace(/<title>(.*?)<\/title>/i, () => `<title>${this.escapeHtml(title)}</title>`);
82
234
  else headContent += `<title>${this.escapeHtml(title)}</title>\n`;
83
- if (head.meta) for (const meta of head.meta) headContent += `<meta name="${this.escapeHtml(meta.name)}" content="${this.escapeHtml(meta.content)}">\n`;
235
+ if (head.meta) for (const meta of head.meta) headContent += this.renderMetaTag(meta);
84
236
  if (head.link) for (const link of head.link) headContent += `<link rel="${this.escapeHtml(link.rel)}" href="${this.escapeHtml(link.href)}">\n`;
237
+ if (head.script) for (const script of head.script) headContent += this.renderScriptTag(script);
85
238
  result = result.replace(/<head([^>]*)>(.*?)<\/head>/is, (_, existingAttrs, existingHead) => `<head${existingAttrs}>${existingHead}${headContent}</head>`);
86
239
  return result.trim();
87
240
  }
@@ -106,6 +259,17 @@ var ServerHeadProvider = class {
106
259
  escapeHtml(str) {
107
260
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
108
261
  }
262
+ renderMetaTag(meta) {
263
+ if (meta.property) return `<meta property="${this.escapeHtml(meta.property)}" content="${this.escapeHtml(meta.content)}">\n`;
264
+ if (meta.name) return `<meta name="${this.escapeHtml(meta.name)}" content="${this.escapeHtml(meta.content)}">\n`;
265
+ return "";
266
+ }
267
+ renderScriptTag(script) {
268
+ return `<script ${Object.entries(script).filter(([, value]) => value !== false).map(([key, value]) => {
269
+ if (value === true) return key;
270
+ return `${key}="${this.escapeHtml(String(value))}"`;
271
+ }).join(" ")}><\/script>\n`;
272
+ }
109
273
  };
110
274
 
111
275
  //#endregion
@@ -154,6 +318,14 @@ var BrowserHeadProvider = class {
154
318
  content
155
319
  });
156
320
  }
321
+ for (const meta of document.head.querySelectorAll("meta[property]")) {
322
+ const property = meta.getAttribute("property");
323
+ const content = meta.getAttribute("content");
324
+ if (property && content) metas.push({
325
+ property,
326
+ content
327
+ });
328
+ }
157
329
  return metas;
158
330
  }
159
331
  };
@@ -164,17 +336,7 @@ var BrowserHeadProvider = class {
164
336
  else document.body.removeAttribute(key);
165
337
  if (head.htmlAttributes) for (const [key, value] of Object.entries(head.htmlAttributes)) if (value) document.documentElement.setAttribute(key, value);
166
338
  else document.documentElement.removeAttribute(key);
167
- if (head.meta) for (const it of head.meta) {
168
- const { name, content } = it;
169
- const meta = document.querySelector(`meta[name="${name}"]`);
170
- if (meta) meta.setAttribute("content", content);
171
- else {
172
- const newMeta = document.createElement("meta");
173
- newMeta.setAttribute("name", name);
174
- newMeta.setAttribute("content", content);
175
- document.head.appendChild(newMeta);
176
- }
177
- }
339
+ if (head.meta) for (const it of head.meta) this.renderMetaTag(document, it);
178
340
  if (head.link) for (const it of head.link) {
179
341
  const { rel, href } = it;
180
342
  let link = document.querySelector(`link[rel="${rel}"][href="${href}"]`);
@@ -186,6 +348,30 @@ var BrowserHeadProvider = class {
186
348
  }
187
349
  }
188
350
  }
351
+ renderMetaTag(document, meta) {
352
+ const { content } = meta;
353
+ if (meta.property) {
354
+ const existing = document.querySelector(`meta[property="${meta.property}"]`);
355
+ if (existing) existing.setAttribute("content", content);
356
+ else {
357
+ const newMeta = document.createElement("meta");
358
+ newMeta.setAttribute("property", meta.property);
359
+ newMeta.setAttribute("content", content);
360
+ document.head.appendChild(newMeta);
361
+ }
362
+ return;
363
+ }
364
+ if (meta.name) {
365
+ const existing = document.querySelector(`meta[name="${meta.name}"]`);
366
+ if (existing) existing.setAttribute("content", content);
367
+ else {
368
+ const newMeta = document.createElement("meta");
369
+ newMeta.setAttribute("name", meta.name);
370
+ newMeta.setAttribute("content", content);
371
+ document.head.appendChild(newMeta);
372
+ }
373
+ }
374
+ }
189
375
  };
190
376
 
191
377
  //#endregion
@@ -228,6 +414,11 @@ const useHead = (options) => {
228
414
  /**
229
415
  * Fill `<head>` server & client side.
230
416
  *
417
+ * Generate SEO-friendly meta tags and titles for your React application using AlephaReactHead module.
418
+ *
419
+ * This module provides services and primitives to manage the document head both on the server and client side,
420
+ * ensuring that your application is optimized for search engines and social media sharing.
421
+ *
231
422
  * @see {@link ServerHeadProvider}
232
423
  * @module alepha.react.head
233
424
  */
@@ -242,5 +433,5 @@ const AlephaReactHead = $module({
242
433
  });
243
434
 
244
435
  //#endregion
245
- export { $head, AlephaReactHead, HeadPrimitive, ServerHeadProvider, useHead };
436
+ export { $head, AlephaReactHead, HeadPrimitive, SeoExpander, ServerHeadProvider, useHead };
246
437
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["attrs: Record<string, string>","match: RegExpExecArray | null","attrs: Record<string, string>","metas: { name: string; content: string }[]"],"sources":["../../src/head/providers/HeadProvider.ts","../../src/head/primitives/$head.ts","../../src/head/providers/ServerHeadProvider.ts","../../src/head/providers/BrowserHeadProvider.ts","../../src/head/hooks/useHead.ts","../../src/head/index.ts"],"sourcesContent":["import type { PageRoute, ReactRouterState } from \"@alepha/react\";\nimport type { Head } from \"../interfaces/Head.ts\";\n\nexport class HeadProvider {\n public global?: Array<Head | (() => Head)> = [];\n\n public fillHead(state: ReactRouterState) {\n state.head = {\n ...state.head,\n };\n\n for (const h of this.global ?? []) {\n const head =\n typeof h === \"function\" ? h() : h;\n state.head = {\n ...state.head,\n ...head,\n meta: [...(state.head.meta ?? []), ...(head.meta ?? [])],\n };\n }\n\n for (const layer of state.layers) {\n if (layer.route?.head && !layer.error) {\n this.fillHeadByPage(layer.route, state, layer.props ?? {});\n }\n }\n }\n\n protected fillHeadByPage(\n page: PageRoute,\n state: ReactRouterState,\n props: Record<string, any>,\n ): void {\n if (!page.head) {\n return;\n }\n\n state.head ??= {};\n\n const head =\n typeof page.head === \"function\"\n ? page.head(props, state.head)\n : page.head;\n\n if (head.title) {\n state.head ??= {};\n\n if (state.head.titleSeparator) {\n state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;\n } else {\n state.head.title = head.title;\n }\n\n state.head.titleSeparator = head.titleSeparator;\n }\n\n if (head.htmlAttributes) {\n state.head.htmlAttributes = {\n ...state.head.htmlAttributes,\n ...head.htmlAttributes,\n };\n }\n\n if (head.bodyAttributes) {\n state.head.bodyAttributes = {\n ...state.head.bodyAttributes,\n ...head.bodyAttributes,\n };\n }\n\n if (head.meta) {\n state.head.meta = [...(state.head.meta ?? []), ...(head.meta ?? [])];\n }\n }\n}\n","import { $inject, createPrimitive, Primitive, KIND } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"../providers/HeadProvider.ts\";\n\n/**\n * Set global `<head>` options for the application.\n */\nexport const $head = (options: HeadPrimitiveOptions) => {\n return createPrimitive(HeadPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type HeadPrimitiveOptions = Head | (() => Head);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {\n protected readonly provider = $inject(HeadProvider);\n protected onInit() {\n this.provider.global = [\n ...(this.provider.global ?? []),\n this.options,\n ];\n }\n}\n\n$head[KIND] = HeadPrimitive;\n","import { $hook, $inject } from \"alepha\";\nimport { ServerTimingProvider } from \"alepha/server\";\nimport type { SimpleHead } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\nexport class ServerHeadProvider {\n protected readonly headProvider = $inject(HeadProvider);\n protected readonly serverTimingProvider = $inject(ServerTimingProvider);\n\n protected readonly onServerRenderEnd = $hook({\n on: \"react:server:render:end\",\n handler: async (ev) => {\n this.serverTimingProvider.beginTiming(\"renderHead\");\n this.headProvider.fillHead(ev.state);\n if (ev.state.head) {\n ev.html = this.renderHead(ev.html, ev.state.head);\n }\n this.serverTimingProvider.endTiming(\"renderHead\");\n },\n });\n\n public renderHead(template: string, head: SimpleHead): string {\n let result = template;\n\n // Inject htmlAttributes\n const htmlAttributes = head.htmlAttributes;\n if (htmlAttributes) {\n result = result.replace(\n /<html([^>]*)>/i,\n (_, existingAttrs) =>\n `<html${this.mergeAttributes(existingAttrs, htmlAttributes)}>`,\n );\n }\n\n // Inject bodyAttributes\n const bodyAttributes = head.bodyAttributes;\n if (bodyAttributes) {\n result = result.replace(\n /<body([^>]*)>/i,\n (_, existingAttrs) =>\n `<body${this.mergeAttributes(existingAttrs, bodyAttributes)}>`,\n );\n }\n\n // Build head content\n let headContent = \"\";\n const title = head.title;\n if (title) {\n if (template.includes(\"<title>\")) {\n result = result.replace(\n /<title>(.*?)<\\/title>/i,\n () => `<title>${this.escapeHtml(title)}</title>`,\n );\n } else {\n headContent += `<title>${this.escapeHtml(title)}</title>\\n`;\n }\n }\n\n if (head.meta) {\n for (const meta of head.meta) {\n headContent += `<meta name=\"${this.escapeHtml(meta.name)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n }\n\n if (head.link) {\n for (const link of head.link) {\n headContent += `<link rel=\"${this.escapeHtml(link.rel)}\" href=\"${this.escapeHtml(link.href)}\">\\n`;\n }\n }\n\n // Inject into <head>...</head>\n result = result.replace(\n /<head([^>]*)>(.*?)<\\/head>/is,\n (_, existingAttrs, existingHead) =>\n `<head${existingAttrs}>${existingHead}${headContent}</head>`,\n );\n\n return result.trim();\n }\n\n protected mergeAttributes(\n existing: string,\n attrs: Record<string, string>,\n ): string {\n const existingAttrs = this.parseAttributes(existing);\n const merged = { ...existingAttrs, ...attrs };\n return Object.entries(merged)\n .map(([k, v]) => ` ${k}=\"${this.escapeHtml(v)}\"`)\n .join(\"\");\n }\n\n protected parseAttributes(attrStr: string): Record<string, string> {\n attrStr = attrStr.replaceAll(\"'\", '\"');\n\n const attrs: Record<string, string> = {};\n const attrRegex = /([^\\s=]+)(?:=\"([^\"]*)\")?/g;\n let match: RegExpExecArray | null = attrRegex.exec(attrStr);\n\n while (match) {\n attrs[match[1]] = match[2] ?? \"\";\n match = attrRegex.exec(attrStr);\n }\n\n return attrs;\n }\n\n protected escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n }\n}\n","import { $hook, $inject } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\nexport class BrowserHeadProvider {\n protected readonly headProvider = $inject(HeadProvider);\n\n protected get document(): Document {\n return window.document;\n }\n\n protected readonly onBrowserRender = $hook({\n on: \"react:browser:render\",\n handler: async ({ state }) => {\n this.headProvider.fillHead(state);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n },\n });\n\n protected readonly onTransitionEnd = $hook({\n on: \"react:transition:end\",\n handler: async ({ state }) => {\n this.headProvider.fillHead(state);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n },\n });\n\n public getHead(document: Document): Head {\n return {\n get title() {\n return document.title;\n },\n get htmlAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.documentElement.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get bodyAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.body.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get meta() {\n const metas: { name: string; content: string }[] = [];\n for (const meta of document.head.querySelectorAll(\"meta[name]\")) {\n const name = meta.getAttribute(\"name\");\n const content = meta.getAttribute(\"content\");\n if (name && content) {\n metas.push({ name, content });\n }\n }\n return metas;\n },\n };\n }\n\n public renderHead(document: Document, head: Head): void {\n if (head.title) {\n document.title = head.title;\n }\n\n if (head.bodyAttributes) {\n for (const [key, value] of Object.entries(head.bodyAttributes)) {\n if (value) {\n document.body.setAttribute(key, value);\n } else {\n document.body.removeAttribute(key);\n }\n }\n }\n\n if (head.htmlAttributes) {\n for (const [key, value] of Object.entries(head.htmlAttributes)) {\n if (value) {\n document.documentElement.setAttribute(key, value);\n } else {\n document.documentElement.removeAttribute(key);\n }\n }\n }\n\n if (head.meta) {\n for (const it of head.meta) {\n const { name, content } = it;\n const meta = document.querySelector(`meta[name=\"${name}\"]`);\n if (meta) {\n meta.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"name\", name);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n }\n }\n\n if (head.link) {\n for (const it of head.link) {\n const { rel, href } = it;\n let link = document.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`);\n if (!link) {\n link = document.createElement(\"link\");\n link.setAttribute(\"rel\", rel);\n link.setAttribute(\"href\", href);\n document.head.appendChild(link);\n }\n }\n }\n }\n}\n","import { useInject } from \"@alepha/react\";\nimport { Alepha } from \"alepha\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { BrowserHeadProvider } from \"../providers/BrowserHeadProvider.ts\";\n\n/**\n * ```tsx\n * const App = () => {\n * const [head, setHead] = useHead({\n * // will set the document title on the first render\n * title: \"My App\",\n * });\n *\n * return (\n * // This will update the document title when the button is clicked\n * <button onClick={() => setHead({ title: \"Change Title\" })}>\n * Change Title {head.title}\n * </button>\n * );\n * }\n * ```\n */\nexport const useHead = (options?: UseHeadOptions): UseHeadReturn => {\n const alepha = useInject(Alepha);\n\n const current = useMemo(() => {\n if (!alepha.isBrowser()) {\n return {};\n }\n\n return alepha.inject(BrowserHeadProvider).getHead(window.document);\n }, []);\n\n const setHead = useCallback((head?: Head | ((previous?: Head) => Head)) => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n alepha\n .inject(BrowserHeadProvider)\n .renderHead(\n window.document,\n typeof head === \"function\" ? head(current) : head || {},\n );\n }, []);\n\n useEffect(() => {\n if (options) {\n setHead(options);\n }\n }, []);\n\n return [current, setHead];\n};\n\nexport type UseHeadOptions = Head | ((previous?: Head) => Head);\n\nexport type UseHeadReturn = [\n Head,\n (head?: Head | ((previous?: Head) => Head)) => void,\n];\n","import {\n AlephaReact,\n type PageConfigSchema,\n type TPropsDefault,\n type TPropsParentDefault,\n} from \"@alepha/react\";\nimport { $module } from \"alepha\";\nimport { $head } from \"./primitives/$head.ts\";\nimport type { Head } from \"./interfaces/Head.ts\";\nimport { ServerHeadProvider } from \"./providers/ServerHeadProvider.ts\";\nimport { HeadProvider } from \"./providers/HeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$head.ts\";\nexport * from \"./hooks/useHead.ts\";\nexport * from \"./interfaces/Head.ts\";\nexport * from \"./providers/ServerHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"@alepha/react\" {\n interface PagePrimitiveOptions<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n > {\n head?: Head | ((props: TProps, previous?: Head) => Head);\n }\n\n interface ReactRouterState {\n head: Head;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Fill `<head>` server & client side.\n *\n * @see {@link ServerHeadProvider}\n * @module alepha.react.head\n */\nexport const AlephaReactHead = $module({\n name: \"alepha.react.head\",\n primitives: [$head],\n services: [AlephaReact, ServerHeadProvider, HeadProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/head/helpers/SeoExpander.ts","../../src/head/providers/HeadProvider.ts","../../src/head/primitives/$head.ts","../../src/head/providers/ServerHeadProvider.ts","../../src/head/providers/BrowserHeadProvider.ts","../../src/head/hooks/useHead.ts","../../src/head/index.ts"],"sourcesContent":["import type { Head, HeadMeta } from \"../interfaces/Head.ts\";\n\n/**\n * Expands Head configuration into SEO meta tags.\n *\n * Generates:\n * - `<meta name=\"description\">` from head.description\n * - `<meta property=\"og:*\">` OpenGraph tags\n * - `<meta name=\"twitter:*\">` Twitter Card tags\n *\n * @example\n * ```ts\n * const helper = new SeoExpander();\n * const { meta, link } = helper.expand({\n * title: \"My App\",\n * description: \"Build amazing apps\",\n * image: \"https://example.com/og.png\",\n * url: \"https://example.com/\",\n * });\n * ```\n */\nexport class SeoExpander {\n public expand(head: Head): {\n meta: HeadMeta[];\n link: Array<{ rel: string; href: string }>;\n } {\n const meta: HeadMeta[] = [];\n const link: Array<{ rel: string; href: string }> = [];\n\n // Only expand SEO if there's meaningful content beyond just title\n const hasSeoContent =\n head.description ||\n head.image ||\n head.url ||\n head.siteName ||\n head.locale ||\n head.type ||\n head.og ||\n head.twitter;\n\n if (!hasSeoContent) {\n return { meta, link };\n }\n\n // Base description\n if (head.description) {\n meta.push({ name: \"description\", content: head.description });\n }\n\n // Canonical URL\n if (head.url) {\n link.push({ rel: \"canonical\", href: head.url });\n }\n\n // OpenGraph tags\n this.expandOpenGraph(head, meta);\n\n // Twitter Card tags\n this.expandTwitter(head, meta);\n\n return { meta, link };\n }\n\n protected expandOpenGraph(head: Head, meta: HeadMeta[]): void {\n const ogTitle = head.og?.title ?? head.title;\n const ogDescription = head.og?.description ?? head.description;\n const ogImage = head.og?.image ?? head.image;\n\n if (head.type || ogTitle) {\n meta.push({ property: \"og:type\", content: head.type ?? \"website\" });\n }\n if (head.url) {\n meta.push({ property: \"og:url\", content: head.url });\n }\n if (ogTitle) {\n meta.push({ property: \"og:title\", content: ogTitle });\n }\n if (ogDescription) {\n meta.push({ property: \"og:description\", content: ogDescription });\n }\n if (ogImage) {\n meta.push({ property: \"og:image\", content: ogImage });\n if (head.imageWidth) {\n meta.push({\n property: \"og:image:width\",\n content: String(head.imageWidth),\n });\n }\n if (head.imageHeight) {\n meta.push({\n property: \"og:image:height\",\n content: String(head.imageHeight),\n });\n }\n if (head.imageAlt) {\n meta.push({ property: \"og:image:alt\", content: head.imageAlt });\n }\n }\n if (head.siteName) {\n meta.push({ property: \"og:site_name\", content: head.siteName });\n }\n if (head.locale) {\n meta.push({ property: \"og:locale\", content: head.locale });\n }\n }\n\n protected expandTwitter(head: Head, meta: HeadMeta[]): void {\n const twitterTitle = head.twitter?.title ?? head.title;\n const twitterDescription = head.twitter?.description ?? head.description;\n const twitterImage = head.twitter?.image ?? head.image;\n\n if (head.twitter?.card || twitterTitle || twitterImage) {\n meta.push({\n name: \"twitter:card\",\n content:\n head.twitter?.card ?? (twitterImage ? \"summary_large_image\" : \"summary\"),\n });\n }\n if (head.url) {\n meta.push({ name: \"twitter:url\", content: head.url });\n }\n if (twitterTitle) {\n meta.push({ name: \"twitter:title\", content: twitterTitle });\n }\n if (twitterDescription) {\n meta.push({ name: \"twitter:description\", content: twitterDescription });\n }\n if (twitterImage) {\n meta.push({ name: \"twitter:image\", content: twitterImage });\n if (head.imageAlt) {\n meta.push({ name: \"twitter:image:alt\", content: head.imageAlt });\n }\n }\n if (head.twitter?.site) {\n meta.push({ name: \"twitter:site\", content: head.twitter.site });\n }\n if (head.twitter?.creator) {\n meta.push({ name: \"twitter:creator\", content: head.twitter.creator });\n }\n }\n}\n","import type { PageRoute, ReactRouterState } from \"@alepha/react/router\";\nimport { $inject } from \"alepha\";\nimport { SeoExpander } from \"../helpers/SeoExpander.ts\";\nimport type { Head } from \"../interfaces/Head.ts\";\n\nexport class HeadProvider {\n protected readonly seoExpander = $inject(SeoExpander);\n\n public global?: Array<Head | (() => Head)> = [];\n\n public fillHead(state: ReactRouterState) {\n state.head = {\n ...state.head,\n };\n\n for (const h of this.global ?? []) {\n const head = typeof h === \"function\" ? h() : h;\n this.mergeHead(state, head);\n }\n\n for (const layer of state.layers) {\n if (layer.route?.head && !layer.error) {\n this.fillHeadByPage(layer.route, state, layer.props ?? {});\n }\n }\n }\n\n protected mergeHead(state: ReactRouterState, head: Head): void {\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head = {\n ...state.head,\n ...head,\n meta: [...(state.head.meta ?? []), ...meta, ...(head.meta ?? [])],\n link: [...(state.head.link ?? []), ...link, ...(head.link ?? [])],\n script: [...(state.head.script ?? []), ...(head.script ?? [])],\n };\n }\n\n protected fillHeadByPage(\n page: PageRoute,\n state: ReactRouterState,\n props: Record<string, any>,\n ): void {\n if (!page.head) {\n return;\n }\n\n state.head ??= {};\n\n const head =\n typeof page.head === \"function\"\n ? page.head(props, state.head)\n : page.head;\n\n // Expand SEO fields into meta tags\n const { meta, link } = this.seoExpander.expand(head);\n state.head.meta = [...(state.head.meta ?? []), ...meta];\n state.head.link = [...(state.head.link ?? []), ...link];\n\n if (head.title) {\n state.head ??= {};\n\n if (state.head.titleSeparator) {\n state.head.title = `${head.title}${state.head.titleSeparator}${state.head.title}`;\n } else {\n state.head.title = head.title;\n }\n\n state.head.titleSeparator = head.titleSeparator;\n }\n\n if (head.htmlAttributes) {\n state.head.htmlAttributes = {\n ...state.head.htmlAttributes,\n ...head.htmlAttributes,\n };\n }\n\n if (head.bodyAttributes) {\n state.head.bodyAttributes = {\n ...state.head.bodyAttributes,\n ...head.bodyAttributes,\n };\n }\n\n if (head.meta) {\n state.head.meta = [...(state.head.meta ?? []), ...(head.meta ?? [])];\n }\n\n if (head.link) {\n state.head.link = [...(state.head.link ?? []), ...(head.link ?? [])];\n }\n\n if (head.script) {\n state.head.script = [...(state.head.script ?? []), ...(head.script ?? [])];\n }\n }\n}\n","import { $inject, createPrimitive, Primitive, KIND } from \"alepha\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"../providers/HeadProvider.ts\";\n\n/**\n * Set global `<head>` options for the application.\n */\nexport const $head = (options: HeadPrimitiveOptions) => {\n return createPrimitive(HeadPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type HeadPrimitiveOptions = Head | (() => Head);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {\n protected readonly provider = $inject(HeadProvider);\n protected onInit() {\n this.provider.global = [\n ...(this.provider.global ?? []),\n this.options,\n ];\n }\n}\n\n$head[KIND] = HeadPrimitive;\n","import { $hook, $inject } from \"alepha\";\nimport { ServerTimingProvider } from \"alepha/server\";\nimport type { HeadMeta, SimpleHead } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\nexport class ServerHeadProvider {\n protected readonly headProvider = $inject(HeadProvider);\n protected readonly serverTimingProvider = $inject(ServerTimingProvider);\n\n protected readonly onServerRenderEnd = $hook({\n on: \"react:server:render:end\",\n handler: async (ev) => {\n this.serverTimingProvider.beginTiming(\"renderHead\");\n this.headProvider.fillHead(ev.state);\n if (ev.state.head) {\n ev.html = this.renderHead(ev.html, ev.state.head);\n }\n this.serverTimingProvider.endTiming(\"renderHead\");\n },\n });\n\n public renderHead(template: string, head: SimpleHead): string {\n let result = template;\n\n // Inject htmlAttributes\n const htmlAttributes = head.htmlAttributes;\n if (htmlAttributes) {\n result = result.replace(\n /<html([^>]*)>/i,\n (_, existingAttrs) =>\n `<html${this.mergeAttributes(existingAttrs, htmlAttributes)}>`,\n );\n }\n\n // Inject bodyAttributes\n const bodyAttributes = head.bodyAttributes;\n if (bodyAttributes) {\n result = result.replace(\n /<body([^>]*)>/i,\n (_, existingAttrs) =>\n `<body${this.mergeAttributes(existingAttrs, bodyAttributes)}>`,\n );\n }\n\n // Build head content\n let headContent = \"\";\n const title = head.title;\n if (title) {\n if (template.includes(\"<title>\")) {\n result = result.replace(\n /<title>(.*?)<\\/title>/i,\n () => `<title>${this.escapeHtml(title)}</title>`,\n );\n } else {\n headContent += `<title>${this.escapeHtml(title)}</title>\\n`;\n }\n }\n\n if (head.meta) {\n for (const meta of head.meta) {\n headContent += this.renderMetaTag(meta);\n }\n }\n\n if (head.link) {\n for (const link of head.link) {\n headContent += `<link rel=\"${this.escapeHtml(link.rel)}\" href=\"${this.escapeHtml(link.href)}\">\\n`;\n }\n }\n\n if (head.script) {\n for (const script of head.script) {\n headContent += this.renderScriptTag(script);\n }\n }\n\n // Inject into <head>...</head>\n result = result.replace(\n /<head([^>]*)>(.*?)<\\/head>/is,\n (_, existingAttrs, existingHead) =>\n `<head${existingAttrs}>${existingHead}${headContent}</head>`,\n );\n\n return result.trim();\n }\n\n protected mergeAttributes(\n existing: string,\n attrs: Record<string, string>,\n ): string {\n const existingAttrs = this.parseAttributes(existing);\n const merged = { ...existingAttrs, ...attrs };\n return Object.entries(merged)\n .map(([k, v]) => ` ${k}=\"${this.escapeHtml(v)}\"`)\n .join(\"\");\n }\n\n protected parseAttributes(attrStr: string): Record<string, string> {\n attrStr = attrStr.replaceAll(\"'\", '\"');\n\n const attrs: Record<string, string> = {};\n const attrRegex = /([^\\s=]+)(?:=\"([^\"]*)\")?/g;\n let match: RegExpExecArray | null = attrRegex.exec(attrStr);\n\n while (match) {\n attrs[match[1]] = match[2] ?? \"\";\n match = attrRegex.exec(attrStr);\n }\n\n return attrs;\n }\n\n protected escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n }\n\n protected renderMetaTag(meta: HeadMeta): string {\n // OpenGraph tags use property attribute\n if (meta.property) {\n return `<meta property=\"${this.escapeHtml(meta.property)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n // Standard meta tags use name attribute\n if (meta.name) {\n return `<meta name=\"${this.escapeHtml(meta.name)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n return \"\";\n }\n\n protected renderScriptTag(script: Record<string, string | boolean>): string {\n const attrs = Object.entries(script)\n .filter(([, value]) => value !== false)\n .map(([key, value]) => {\n // Boolean attributes - render without value if true\n if (value === true) {\n return key;\n }\n return `${key}=\"${this.escapeHtml(String(value))}\"`;\n })\n .join(\" \");\n return `<script ${attrs}></script>\\n`;\n }\n}\n","import { $hook, $inject } from \"alepha\";\nimport type { Head, HeadMeta } from \"../interfaces/Head.ts\";\nimport { HeadProvider } from \"./HeadProvider.ts\";\n\nexport class BrowserHeadProvider {\n protected readonly headProvider = $inject(HeadProvider);\n\n protected get document(): Document {\n return window.document;\n }\n\n protected readonly onBrowserRender = $hook({\n on: \"react:browser:render\",\n handler: async ({ state }) => {\n this.headProvider.fillHead(state);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n },\n });\n\n protected readonly onTransitionEnd = $hook({\n on: \"react:transition:end\",\n handler: async ({ state }) => {\n this.headProvider.fillHead(state);\n if (state.head) {\n this.renderHead(this.document, state.head);\n }\n },\n });\n\n public getHead(document: Document): Head {\n return {\n get title() {\n return document.title;\n },\n get htmlAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.documentElement.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get bodyAttributes() {\n const attrs: Record<string, string> = {};\n for (const attr of document.body.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n },\n get meta() {\n const metas: HeadMeta[] = [];\n // Get meta tags with name attribute\n for (const meta of document.head.querySelectorAll(\"meta[name]\")) {\n const name = meta.getAttribute(\"name\");\n const content = meta.getAttribute(\"content\");\n if (name && content) {\n metas.push({ name, content });\n }\n }\n // Get meta tags with property attribute (OpenGraph)\n for (const meta of document.head.querySelectorAll(\"meta[property]\")) {\n const property = meta.getAttribute(\"property\");\n const content = meta.getAttribute(\"content\");\n if (property && content) {\n metas.push({ property, content });\n }\n }\n return metas;\n },\n };\n }\n\n public renderHead(document: Document, head: Head): void {\n if (head.title) {\n document.title = head.title;\n }\n\n if (head.bodyAttributes) {\n for (const [key, value] of Object.entries(head.bodyAttributes)) {\n if (value) {\n document.body.setAttribute(key, value);\n } else {\n document.body.removeAttribute(key);\n }\n }\n }\n\n if (head.htmlAttributes) {\n for (const [key, value] of Object.entries(head.htmlAttributes)) {\n if (value) {\n document.documentElement.setAttribute(key, value);\n } else {\n document.documentElement.removeAttribute(key);\n }\n }\n }\n\n if (head.meta) {\n for (const it of head.meta) {\n this.renderMetaTag(document, it);\n }\n }\n\n if (head.link) {\n for (const it of head.link) {\n const { rel, href } = it;\n let link = document.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`);\n if (!link) {\n link = document.createElement(\"link\");\n link.setAttribute(\"rel\", rel);\n link.setAttribute(\"href\", href);\n document.head.appendChild(link);\n }\n }\n }\n }\n\n protected renderMetaTag(document: Document, meta: HeadMeta): void {\n const { content } = meta;\n\n // Handle OpenGraph tags (property attribute)\n if (meta.property) {\n const existing = document.querySelector(\n `meta[property=\"${meta.property}\"]`,\n );\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"property\", meta.property);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n return;\n }\n\n // Handle standard meta tags (name attribute)\n if (meta.name) {\n const existing = document.querySelector(`meta[name=\"${meta.name}\"]`);\n if (existing) {\n existing.setAttribute(\"content\", content);\n } else {\n const newMeta = document.createElement(\"meta\");\n newMeta.setAttribute(\"name\", meta.name);\n newMeta.setAttribute(\"content\", content);\n document.head.appendChild(newMeta);\n }\n }\n }\n}\n","import { useInject } from \"@alepha/react\";\nimport { Alepha } from \"alepha\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport type { Head } from \"../interfaces/Head.ts\";\nimport { BrowserHeadProvider } from \"../providers/BrowserHeadProvider.ts\";\n\n/**\n * ```tsx\n * const App = () => {\n * const [head, setHead] = useHead({\n * // will set the document title on the first render\n * title: \"My App\",\n * });\n *\n * return (\n * // This will update the document title when the button is clicked\n * <button onClick={() => setHead({ title: \"Change Title\" })}>\n * Change Title {head.title}\n * </button>\n * );\n * }\n * ```\n */\nexport const useHead = (options?: UseHeadOptions): UseHeadReturn => {\n const alepha = useInject(Alepha);\n\n const current = useMemo(() => {\n if (!alepha.isBrowser()) {\n return {};\n }\n\n return alepha.inject(BrowserHeadProvider).getHead(window.document);\n }, []);\n\n const setHead = useCallback((head?: Head | ((previous?: Head) => Head)) => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n alepha\n .inject(BrowserHeadProvider)\n .renderHead(\n window.document,\n typeof head === \"function\" ? head(current) : head || {},\n );\n }, []);\n\n useEffect(() => {\n if (options) {\n setHead(options);\n }\n }, []);\n\n return [current, setHead];\n};\n\nexport type UseHeadOptions = Head | ((previous?: Head) => Head);\n\nexport type UseHeadReturn = [\n Head,\n (head?: Head | ((previous?: Head) => Head)) => void,\n];\n","import { AlephaReact } from \"@alepha/react\";\nimport type {\n PageConfigSchema,\n TPropsDefault,\n TPropsParentDefault,\n} from \"@alepha/react/router\";\nimport { $module } from \"alepha\";\nimport { $head } from \"./primitives/$head.ts\";\nimport type { Head } from \"./interfaces/Head.ts\";\nimport { ServerHeadProvider } from \"./providers/ServerHeadProvider.ts\";\nimport { HeadProvider } from \"./providers/HeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$head.ts\";\nexport * from \"./hooks/useHead.ts\";\nexport * from \"./interfaces/Head.ts\";\nexport * from \"./helpers/SeoExpander.ts\";\nexport * from \"./providers/ServerHeadProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n// Augment PagePrimitiveOptions in router module\ndeclare module \"@alepha/react/router\" {\n interface PagePrimitiveOptions<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n > {\n head?: Head | ((props: TProps, previous?: Head) => Head);\n }\n}\n\n// Augment ReactRouterState in router module\ndeclare module \"@alepha/react/router\" {\n interface ReactRouterState {\n head: Head;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Fill `<head>` server & client side.\n *\n * Generate SEO-friendly meta tags and titles for your React application using AlephaReactHead module.\n *\n * This module provides services and primitives to manage the document head both on the server and client side,\n * ensuring that your application is optimized for search engines and social media sharing.\n *\n * @see {@link ServerHeadProvider}\n * @module alepha.react.head\n */\nexport const AlephaReactHead = $module({\n name: \"alepha.react.head\",\n primitives: [$head],\n services: [AlephaReact, ServerHeadProvider, HeadProvider],\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAa,cAAb,MAAyB;CACvB,AAAO,OAAO,MAGZ;EACA,MAAM,OAAmB,EAAE;EAC3B,MAAM,OAA6C,EAAE;AAarD,MAAI,EATF,KAAK,eACL,KAAK,SACL,KAAK,OACL,KAAK,YACL,KAAK,UACL,KAAK,QACL,KAAK,MACL,KAAK,SAGL,QAAO;GAAE;GAAM;GAAM;AAIvB,MAAI,KAAK,YACP,MAAK,KAAK;GAAE,MAAM;GAAe,SAAS,KAAK;GAAa,CAAC;AAI/D,MAAI,KAAK,IACP,MAAK,KAAK;GAAE,KAAK;GAAa,MAAM,KAAK;GAAK,CAAC;AAIjD,OAAK,gBAAgB,MAAM,KAAK;AAGhC,OAAK,cAAc,MAAM,KAAK;AAE9B,SAAO;GAAE;GAAM;GAAM;;CAGvB,AAAU,gBAAgB,MAAY,MAAwB;EAC5D,MAAM,UAAU,KAAK,IAAI,SAAS,KAAK;EACvC,MAAM,gBAAgB,KAAK,IAAI,eAAe,KAAK;EACnD,MAAM,UAAU,KAAK,IAAI,SAAS,KAAK;AAEvC,MAAI,KAAK,QAAQ,QACf,MAAK,KAAK;GAAE,UAAU;GAAW,SAAS,KAAK,QAAQ;GAAW,CAAC;AAErE,MAAI,KAAK,IACP,MAAK,KAAK;GAAE,UAAU;GAAU,SAAS,KAAK;GAAK,CAAC;AAEtD,MAAI,QACF,MAAK,KAAK;GAAE,UAAU;GAAY,SAAS;GAAS,CAAC;AAEvD,MAAI,cACF,MAAK,KAAK;GAAE,UAAU;GAAkB,SAAS;GAAe,CAAC;AAEnE,MAAI,SAAS;AACX,QAAK,KAAK;IAAE,UAAU;IAAY,SAAS;IAAS,CAAC;AACrD,OAAI,KAAK,WACP,MAAK,KAAK;IACR,UAAU;IACV,SAAS,OAAO,KAAK,WAAW;IACjC,CAAC;AAEJ,OAAI,KAAK,YACP,MAAK,KAAK;IACR,UAAU;IACV,SAAS,OAAO,KAAK,YAAY;IAClC,CAAC;AAEJ,OAAI,KAAK,SACP,MAAK,KAAK;IAAE,UAAU;IAAgB,SAAS,KAAK;IAAU,CAAC;;AAGnE,MAAI,KAAK,SACP,MAAK,KAAK;GAAE,UAAU;GAAgB,SAAS,KAAK;GAAU,CAAC;AAEjE,MAAI,KAAK,OACP,MAAK,KAAK;GAAE,UAAU;GAAa,SAAS,KAAK;GAAQ,CAAC;;CAI9D,AAAU,cAAc,MAAY,MAAwB;EAC1D,MAAM,eAAe,KAAK,SAAS,SAAS,KAAK;EACjD,MAAM,qBAAqB,KAAK,SAAS,eAAe,KAAK;EAC7D,MAAM,eAAe,KAAK,SAAS,SAAS,KAAK;AAEjD,MAAI,KAAK,SAAS,QAAQ,gBAAgB,aACxC,MAAK,KAAK;GACR,MAAM;GACN,SACE,KAAK,SAAS,SAAS,eAAe,wBAAwB;GACjE,CAAC;AAEJ,MAAI,KAAK,IACP,MAAK,KAAK;GAAE,MAAM;GAAe,SAAS,KAAK;GAAK,CAAC;AAEvD,MAAI,aACF,MAAK,KAAK;GAAE,MAAM;GAAiB,SAAS;GAAc,CAAC;AAE7D,MAAI,mBACF,MAAK,KAAK;GAAE,MAAM;GAAuB,SAAS;GAAoB,CAAC;AAEzE,MAAI,cAAc;AAChB,QAAK,KAAK;IAAE,MAAM;IAAiB,SAAS;IAAc,CAAC;AAC3D,OAAI,KAAK,SACP,MAAK,KAAK;IAAE,MAAM;IAAqB,SAAS,KAAK;IAAU,CAAC;;AAGpE,MAAI,KAAK,SAAS,KAChB,MAAK,KAAK;GAAE,MAAM;GAAgB,SAAS,KAAK,QAAQ;GAAM,CAAC;AAEjE,MAAI,KAAK,SAAS,QAChB,MAAK,KAAK;GAAE,MAAM;GAAmB,SAAS,KAAK,QAAQ;GAAS,CAAC;;;;;;ACpI3E,IAAa,eAAb,MAA0B;CACxB,AAAmB,cAAc,QAAQ,YAAY;CAErD,AAAO,SAAsC,EAAE;CAE/C,AAAO,SAAS,OAAyB;AACvC,QAAM,OAAO,EACX,GAAG,MAAM,MACV;AAED,OAAK,MAAM,KAAK,KAAK,UAAU,EAAE,EAAE;GACjC,MAAM,OAAO,OAAO,MAAM,aAAa,GAAG,GAAG;AAC7C,QAAK,UAAU,OAAO,KAAK;;AAG7B,OAAK,MAAM,SAAS,MAAM,OACxB,KAAI,MAAM,OAAO,QAAQ,CAAC,MAAM,MAC9B,MAAK,eAAe,MAAM,OAAO,OAAO,MAAM,SAAS,EAAE,CAAC;;CAKhE,AAAU,UAAU,OAAyB,MAAkB;EAE7D,MAAM,EAAE,MAAM,SAAS,KAAK,YAAY,OAAO,KAAK;AACpD,QAAM,OAAO;GACX,GAAG,MAAM;GACT,GAAG;GACH,MAAM;IAAC,GAAI,MAAM,KAAK,QAAQ,EAAE;IAAG,GAAG;IAAM,GAAI,KAAK,QAAQ,EAAE;IAAE;GACjE,MAAM;IAAC,GAAI,MAAM,KAAK,QAAQ,EAAE;IAAG,GAAG;IAAM,GAAI,KAAK,QAAQ,EAAE;IAAE;GACjE,QAAQ,CAAC,GAAI,MAAM,KAAK,UAAU,EAAE,EAAG,GAAI,KAAK,UAAU,EAAE,CAAE;GAC/D;;CAGH,AAAU,eACR,MACA,OACA,OACM;AACN,MAAI,CAAC,KAAK,KACR;AAGF,QAAM,SAAS,EAAE;EAEjB,MAAM,OACJ,OAAO,KAAK,SAAS,aACjB,KAAK,KAAK,OAAO,MAAM,KAAK,GAC5B,KAAK;EAGX,MAAM,EAAE,MAAM,SAAS,KAAK,YAAY,OAAO,KAAK;AACpD,QAAM,KAAK,OAAO,CAAC,GAAI,MAAM,KAAK,QAAQ,EAAE,EAAG,GAAG,KAAK;AACvD,QAAM,KAAK,OAAO,CAAC,GAAI,MAAM,KAAK,QAAQ,EAAE,EAAG,GAAG,KAAK;AAEvD,MAAI,KAAK,OAAO;AACd,SAAM,SAAS,EAAE;AAEjB,OAAI,MAAM,KAAK,eACb,OAAM,KAAK,QAAQ,GAAG,KAAK,QAAQ,MAAM,KAAK,iBAAiB,MAAM,KAAK;OAE1E,OAAM,KAAK,QAAQ,KAAK;AAG1B,SAAM,KAAK,iBAAiB,KAAK;;AAGnC,MAAI,KAAK,eACP,OAAM,KAAK,iBAAiB;GAC1B,GAAG,MAAM,KAAK;GACd,GAAG,KAAK;GACT;AAGH,MAAI,KAAK,eACP,OAAM,KAAK,iBAAiB;GAC1B,GAAG,MAAM,KAAK;GACd,GAAG,KAAK;GACT;AAGH,MAAI,KAAK,KACP,OAAM,KAAK,OAAO,CAAC,GAAI,MAAM,KAAK,QAAQ,EAAE,EAAG,GAAI,KAAK,QAAQ,EAAE,CAAE;AAGtE,MAAI,KAAK,KACP,OAAM,KAAK,OAAO,CAAC,GAAI,MAAM,KAAK,QAAQ,EAAE,EAAG,GAAI,KAAK,QAAQ,EAAE,CAAE;AAGtE,MAAI,KAAK,OACP,OAAM,KAAK,SAAS,CAAC,GAAI,MAAM,KAAK,UAAU,EAAE,EAAG,GAAI,KAAK,UAAU,EAAE,CAAE;;;;;;;;;ACxFhF,MAAa,SAAS,YAAkC;AACtD,QAAO,gBAAgB,eAAe,QAAQ;;AAShD,IAAa,gBAAb,cAAmC,UAAgC;CACjE,AAAmB,WAAW,QAAQ,aAAa;CACnD,AAAU,SAAS;AACjB,OAAK,SAAS,SAAS,CACrB,GAAI,KAAK,SAAS,UAAU,EAAE,EAC9B,KAAK,QACN;;;AAIL,MAAM,QAAQ;;;;ACtBd,IAAa,qBAAb,MAAgC;CAC9B,AAAmB,eAAe,QAAQ,aAAa;CACvD,AAAmB,uBAAuB,QAAQ,qBAAqB;CAEvE,AAAmB,oBAAoB,MAAM;EAC3C,IAAI;EACJ,SAAS,OAAO,OAAO;AACrB,QAAK,qBAAqB,YAAY,aAAa;AACnD,QAAK,aAAa,SAAS,GAAG,MAAM;AACpC,OAAI,GAAG,MAAM,KACX,IAAG,OAAO,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,KAAK;AAEnD,QAAK,qBAAqB,UAAU,aAAa;;EAEpD,CAAC;CAEF,AAAO,WAAW,UAAkB,MAA0B;EAC5D,IAAI,SAAS;EAGb,MAAM,iBAAiB,KAAK;AAC5B,MAAI,eACF,UAAS,OAAO,QACd,mBACC,GAAG,kBACF,QAAQ,KAAK,gBAAgB,eAAe,eAAe,CAAC,GAC/D;EAIH,MAAM,iBAAiB,KAAK;AAC5B,MAAI,eACF,UAAS,OAAO,QACd,mBACC,GAAG,kBACF,QAAQ,KAAK,gBAAgB,eAAe,eAAe,CAAC,GAC/D;EAIH,IAAI,cAAc;EAClB,MAAM,QAAQ,KAAK;AACnB,MAAI,MACF,KAAI,SAAS,SAAS,UAAU,CAC9B,UAAS,OAAO,QACd,gCACM,UAAU,KAAK,WAAW,MAAM,CAAC,UACxC;MAED,gBAAe,UAAU,KAAK,WAAW,MAAM,CAAC;AAIpD,MAAI,KAAK,KACP,MAAK,MAAM,QAAQ,KAAK,KACtB,gBAAe,KAAK,cAAc,KAAK;AAI3C,MAAI,KAAK,KACP,MAAK,MAAM,QAAQ,KAAK,KACtB,gBAAe,cAAc,KAAK,WAAW,KAAK,IAAI,CAAC,UAAU,KAAK,WAAW,KAAK,KAAK,CAAC;AAIhG,MAAI,KAAK,OACP,MAAK,MAAM,UAAU,KAAK,OACxB,gBAAe,KAAK,gBAAgB,OAAO;AAK/C,WAAS,OAAO,QACd,iCACC,GAAG,eAAe,iBACjB,QAAQ,cAAc,GAAG,eAAe,YAAY,SACvD;AAED,SAAO,OAAO,MAAM;;CAGtB,AAAU,gBACR,UACA,OACQ;EAER,MAAM,SAAS;GAAE,GADK,KAAK,gBAAgB,SAAS;GACjB,GAAG;GAAO;AAC7C,SAAO,OAAO,QAAQ,OAAO,CAC1B,KAAK,CAAC,GAAG,OAAO,IAAI,EAAE,IAAI,KAAK,WAAW,EAAE,CAAC,GAAG,CAChD,KAAK,GAAG;;CAGb,AAAU,gBAAgB,SAAyC;AACjE,YAAU,QAAQ,WAAW,KAAK,KAAI;EAEtC,MAAM,QAAgC,EAAE;EACxC,MAAM,YAAY;EAClB,IAAI,QAAgC,UAAU,KAAK,QAAQ;AAE3D,SAAO,OAAO;AACZ,SAAM,MAAM,MAAM,MAAM,MAAM;AAC9B,WAAQ,UAAU,KAAK,QAAQ;;AAGjC,SAAO;;CAGT,AAAU,WAAW,KAAqB;AACxC,SAAO,IACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS,CACvB,QAAQ,MAAM,SAAS;;CAG5B,AAAU,cAAc,MAAwB;AAE9C,MAAI,KAAK,SACP,QAAO,mBAAmB,KAAK,WAAW,KAAK,SAAS,CAAC,aAAa,KAAK,WAAW,KAAK,QAAQ,CAAC;AAGtG,MAAI,KAAK,KACP,QAAO,eAAe,KAAK,WAAW,KAAK,KAAK,CAAC,aAAa,KAAK,WAAW,KAAK,QAAQ,CAAC;AAE9F,SAAO;;CAGT,AAAU,gBAAgB,QAAkD;AAW1E,SAAO,WAVO,OAAO,QAAQ,OAAO,CACjC,QAAQ,GAAG,WAAW,UAAU,MAAM,CACtC,KAAK,CAAC,KAAK,WAAW;AAErB,OAAI,UAAU,KACZ,QAAO;AAET,UAAO,GAAG,IAAI,IAAI,KAAK,WAAW,OAAO,MAAM,CAAC,CAAC;IACjD,CACD,KAAK,IAAI,CACY;;;;;;AC5I5B,IAAa,sBAAb,MAAiC;CAC/B,AAAmB,eAAe,QAAQ,aAAa;CAEvD,IAAc,WAAqB;AACjC,SAAO,OAAO;;CAGhB,AAAmB,kBAAkB,MAAM;EACzC,IAAI;EACJ,SAAS,OAAO,EAAE,YAAY;AAC5B,QAAK,aAAa,SAAS,MAAM;AACjC,OAAI,MAAM,KACR,MAAK,WAAW,KAAK,UAAU,MAAM,KAAK;;EAG/C,CAAC;CAEF,AAAmB,kBAAkB,MAAM;EACzC,IAAI;EACJ,SAAS,OAAO,EAAE,YAAY;AAC5B,QAAK,aAAa,SAAS,MAAM;AACjC,OAAI,MAAM,KACR,MAAK,WAAW,KAAK,UAAU,MAAM,KAAK;;EAG/C,CAAC;CAEF,AAAO,QAAQ,UAA0B;AACvC,SAAO;GACL,IAAI,QAAQ;AACV,WAAO,SAAS;;GAElB,IAAI,iBAAiB;IACnB,MAAM,QAAgC,EAAE;AACxC,SAAK,MAAM,QAAQ,SAAS,gBAAgB,WAC1C,OAAM,KAAK,QAAQ,KAAK;AAE1B,WAAO;;GAET,IAAI,iBAAiB;IACnB,MAAM,QAAgC,EAAE;AACxC,SAAK,MAAM,QAAQ,SAAS,KAAK,WAC/B,OAAM,KAAK,QAAQ,KAAK;AAE1B,WAAO;;GAET,IAAI,OAAO;IACT,MAAM,QAAoB,EAAE;AAE5B,SAAK,MAAM,QAAQ,SAAS,KAAK,iBAAiB,aAAa,EAAE;KAC/D,MAAM,OAAO,KAAK,aAAa,OAAO;KACtC,MAAM,UAAU,KAAK,aAAa,UAAU;AAC5C,SAAI,QAAQ,QACV,OAAM,KAAK;MAAE;MAAM;MAAS,CAAC;;AAIjC,SAAK,MAAM,QAAQ,SAAS,KAAK,iBAAiB,iBAAiB,EAAE;KACnE,MAAM,WAAW,KAAK,aAAa,WAAW;KAC9C,MAAM,UAAU,KAAK,aAAa,UAAU;AAC5C,SAAI,YAAY,QACd,OAAM,KAAK;MAAE;MAAU;MAAS,CAAC;;AAGrC,WAAO;;GAEV;;CAGH,AAAO,WAAW,UAAoB,MAAkB;AACtD,MAAI,KAAK,MACP,UAAS,QAAQ,KAAK;AAGxB,MAAI,KAAK,eACP,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,eAAe,CAC5D,KAAI,MACF,UAAS,KAAK,aAAa,KAAK,MAAM;MAEtC,UAAS,KAAK,gBAAgB,IAAI;AAKxC,MAAI,KAAK,eACP,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,eAAe,CAC5D,KAAI,MACF,UAAS,gBAAgB,aAAa,KAAK,MAAM;MAEjD,UAAS,gBAAgB,gBAAgB,IAAI;AAKnD,MAAI,KAAK,KACP,MAAK,MAAM,MAAM,KAAK,KACpB,MAAK,cAAc,UAAU,GAAG;AAIpC,MAAI,KAAK,KACP,MAAK,MAAM,MAAM,KAAK,MAAM;GAC1B,MAAM,EAAE,KAAK,SAAS;GACtB,IAAI,OAAO,SAAS,cAAc,aAAa,IAAI,WAAW,KAAK,IAAI;AACvE,OAAI,CAAC,MAAM;AACT,WAAO,SAAS,cAAc,OAAO;AACrC,SAAK,aAAa,OAAO,IAAI;AAC7B,SAAK,aAAa,QAAQ,KAAK;AAC/B,aAAS,KAAK,YAAY,KAAK;;;;CAMvC,AAAU,cAAc,UAAoB,MAAsB;EAChE,MAAM,EAAE,YAAY;AAGpB,MAAI,KAAK,UAAU;GACjB,MAAM,WAAW,SAAS,cACxB,kBAAkB,KAAK,SAAS,IACjC;AACD,OAAI,SACF,UAAS,aAAa,WAAW,QAAQ;QACpC;IACL,MAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,YAAQ,aAAa,YAAY,KAAK,SAAS;AAC/C,YAAQ,aAAa,WAAW,QAAQ;AACxC,aAAS,KAAK,YAAY,QAAQ;;AAEpC;;AAIF,MAAI,KAAK,MAAM;GACb,MAAM,WAAW,SAAS,cAAc,cAAc,KAAK,KAAK,IAAI;AACpE,OAAI,SACF,UAAS,aAAa,WAAW,QAAQ;QACpC;IACL,MAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,YAAQ,aAAa,QAAQ,KAAK,KAAK;AACvC,YAAQ,aAAa,WAAW,QAAQ;AACxC,aAAS,KAAK,YAAY,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;AC3H1C,MAAa,WAAW,YAA4C;CAClE,MAAM,SAAS,UAAU,OAAO;CAEhC,MAAM,UAAU,cAAc;AAC5B,MAAI,CAAC,OAAO,WAAW,CACrB,QAAO,EAAE;AAGX,SAAO,OAAO,OAAO,oBAAoB,CAAC,QAAQ,OAAO,SAAS;IACjE,EAAE,CAAC;CAEN,MAAM,UAAU,aAAa,SAA8C;AACzE,MAAI,CAAC,OAAO,WAAW,CACrB;AAGF,SACG,OAAO,oBAAoB,CAC3B,WACC,OAAO,UACP,OAAO,SAAS,aAAa,KAAK,QAAQ,GAAG,QAAQ,EAAE,CACxD;IACF,EAAE,CAAC;AAEN,iBAAgB;AACd,MAAI,QACF,SAAQ,QAAQ;IAEjB,EAAE,CAAC;AAEN,QAAO,CAAC,SAAS,QAAQ;;;;;;;;;;;;;;;;ACA3B,MAAa,kBAAkB,QAAQ;CACrC,MAAM;CACN,YAAY,CAAC,MAAM;CACnB,UAAU;EAAC;EAAa;EAAoB;EAAa;CAC1D,CAAC"}