@lastbrain/app 2.0.24 → 2.0.35

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 (81) hide show
  1. package/dist/analytics/registry.d.ts +7 -0
  2. package/dist/analytics/registry.d.ts.map +1 -0
  3. package/dist/analytics/registry.js +11 -0
  4. package/dist/auth/useAuthSession.d.ts.map +1 -1
  5. package/dist/auth/useAuthSession.js +85 -1
  6. package/dist/cli.js +19 -3
  7. package/dist/components/LanguageSwitcher.d.ts +3 -1
  8. package/dist/components/LanguageSwitcher.d.ts.map +1 -1
  9. package/dist/components/LanguageSwitcher.js +134 -21
  10. package/dist/config/version.d.ts.map +1 -1
  11. package/dist/config/version.js +30 -19
  12. package/dist/i18n/server-lang.d.ts +1 -1
  13. package/dist/i18n/server-lang.d.ts.map +1 -1
  14. package/dist/i18n/types.d.ts +1 -1
  15. package/dist/i18n/types.d.ts.map +1 -1
  16. package/dist/i18n/useLink.d.ts.map +1 -1
  17. package/dist/i18n/useLink.js +15 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +4 -0
  21. package/dist/layouts/AdminLayoutWithSidebar.d.ts +3 -1
  22. package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -1
  23. package/dist/layouts/AdminLayoutWithSidebar.js +2 -2
  24. package/dist/layouts/AppProviders.d.ts +9 -1
  25. package/dist/layouts/AppProviders.d.ts.map +1 -1
  26. package/dist/layouts/AppProviders.js +24 -3
  27. package/dist/layouts/AuthLayout.js +1 -1
  28. package/dist/layouts/PublicLayout.js +1 -1
  29. package/dist/layouts/RootLayout.d.ts.map +1 -1
  30. package/dist/scripts/init-app.d.ts.map +1 -1
  31. package/dist/scripts/init-app.js +343 -138
  32. package/dist/scripts/module-build.d.ts.map +1 -1
  33. package/dist/scripts/module-build.js +784 -59
  34. package/dist/scripts/module-create.d.ts.map +1 -1
  35. package/dist/scripts/module-create.js +227 -10
  36. package/dist/scripts/sitemap-flat-generator.d.ts +39 -0
  37. package/dist/scripts/sitemap-flat-generator.d.ts.map +1 -0
  38. package/dist/scripts/sitemap-flat-generator.js +231 -0
  39. package/dist/scripts/sitemap-manifest-generator.d.ts +59 -0
  40. package/dist/scripts/sitemap-manifest-generator.d.ts.map +1 -0
  41. package/dist/scripts/sitemap-manifest-generator.js +290 -0
  42. package/dist/sitemap/manifest.d.ts +8 -0
  43. package/dist/sitemap/manifest.d.ts.map +1 -0
  44. package/dist/sitemap/manifest.js +6 -0
  45. package/dist/styles.css +2 -2
  46. package/dist/templates/AuthGuidePage.js +2 -0
  47. package/dist/templates/DefaultDoc.d.ts.map +1 -1
  48. package/dist/templates/DefaultDoc.js +9 -5
  49. package/dist/templates/DocPage.d.ts.map +1 -1
  50. package/dist/templates/DocPage.js +40 -0
  51. package/dist/templates/MigrationsGuidePage.js +2 -0
  52. package/dist/templates/ModuleGuidePage.d.ts.map +1 -1
  53. package/dist/templates/ModuleGuidePage.js +4 -1
  54. package/dist/templates/SimpleHomePage.js +2 -0
  55. package/package.json +31 -26
  56. package/src/analytics/registry.ts +14 -0
  57. package/src/auth/useAuthSession.ts +91 -1
  58. package/src/cli.ts +19 -3
  59. package/src/components/LanguageSwitcher.tsx +183 -60
  60. package/src/config/version.ts +30 -19
  61. package/src/i18n/server-lang.ts +2 -1
  62. package/src/i18n/types.ts +2 -1
  63. package/src/i18n/useLink.ts +15 -0
  64. package/src/index.ts +17 -0
  65. package/src/layouts/AdminLayoutWithSidebar.tsx +4 -0
  66. package/src/layouts/AppProviders.tsx +74 -9
  67. package/src/layouts/AuthLayout.tsx +1 -1
  68. package/src/layouts/PublicLayout.tsx +1 -1
  69. package/src/layouts/RootLayout.tsx +0 -1
  70. package/src/scripts/init-app.ts +418 -149
  71. package/src/scripts/module-build.ts +923 -63
  72. package/src/scripts/module-create.ts +260 -10
  73. package/src/scripts/sitemap-flat-generator.ts +313 -0
  74. package/src/scripts/sitemap-manifest-generator.ts +476 -0
  75. package/src/sitemap/manifest.ts +17 -0
  76. package/src/templates/AuthGuidePage.tsx +1 -1
  77. package/src/templates/DefaultDoc.tsx +397 -6
  78. package/src/templates/DocPage.tsx +40 -0
  79. package/src/templates/MigrationsGuidePage.tsx +1 -1
  80. package/src/templates/ModuleGuidePage.tsx +3 -2
  81. package/src/templates/SimpleHomePage.tsx +1 -1
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Global Analytics Registry
3
+ * Permet aux apps d'enregistrer un composant analytics global
4
+ */
5
+ export declare function registerAnalyticsComponent(component: React.ComponentType): void;
6
+ export declare function getAnalyticsComponent(): React.ComponentType | null;
7
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/analytics/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,KAAK,CAAC,aAAa,QAExE;AAED,wBAAgB,qBAAqB,IAAI,KAAK,CAAC,aAAa,GAAG,IAAI,CAElE"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Global Analytics Registry
3
+ * Permet aux apps d'enregistrer un composant analytics global
4
+ */
5
+ let globalAnalyticsComponent = null;
6
+ export function registerAnalyticsComponent(component) {
7
+ globalAnalyticsComponent = component;
8
+ }
9
+ export function getAnalyticsComponent() {
10
+ return globalAnalyticsComponent;
11
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthSession.d.ts","sourceRoot":"","sources":["../../src/auth/useAuthSession.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,wBAAgB,cAAc;;;;EAmD7B"}
1
+ {"version":3,"file":"useAuthSession.d.ts","sourceRoot":"","sources":["../../src/auth/useAuthSession.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAMlD,wBAAgB,cAAc;;;;EAyI7B"}
@@ -1,6 +1,9 @@
1
1
  "use client";
2
2
  import { useEffect, useState } from "react";
3
- import { supabaseBrowserClient } from "@lastbrain/core";
3
+ import { supabaseBrowserClient, useRealtimeListener } from "@lastbrain/core";
4
+ // Note: this hook also listens to `user_profile_updated` realtime broadcasts
5
+ // and centralises cookie + redirect logic so the app reacts to profile language
6
+ // changes in a single place.
4
7
  export function useAuthSession() {
5
8
  const [user, setUser] = useState(null);
6
9
  const [loading, setLoading] = useState(true);
@@ -45,5 +48,86 @@ export function useAuthSession() {
45
48
  });
46
49
  return () => subscription.unsubscribe();
47
50
  }, []);
51
+ // Realtime listener for user_profile updates (broadcast from RealtimeProvider)
52
+ // This keeps NEXT_LOCALE in sync and performs a single, centralised redirect
53
+ // when the user's language changes remotely.
54
+ useRealtimeListener({
55
+ table: "user_profil",
56
+ // broadcast event produced by RealtimeProvider is `user_profile_updated`
57
+ eventName: "user_profile_updated",
58
+ onUpdate(payload) {
59
+ try {
60
+ // Recherche robuste d'un objet contenant la propriété `language` ou `locale`
61
+ const findLangRecord = (obj) => {
62
+ if (!obj || typeof obj !== "object")
63
+ return null;
64
+ const seen = new WeakSet();
65
+ const queue = [obj];
66
+ while (queue.length) {
67
+ const cur = queue.shift();
68
+ if (!cur || typeof cur !== "object" || seen.has(cur))
69
+ continue;
70
+ seen.add(cur);
71
+ if ("language" in cur || "locale" in cur)
72
+ return cur;
73
+ for (const k of Object.keys(cur)) {
74
+ const v = cur[k];
75
+ if (v && typeof v === "object")
76
+ queue.push(v);
77
+ }
78
+ }
79
+ return null;
80
+ };
81
+ const candidate = findLangRecord(payload) ||
82
+ payload?.new ||
83
+ payload?.record?.new ||
84
+ payload?.payload?.new ||
85
+ payload?.after ||
86
+ payload?.data ||
87
+ null;
88
+ const newLang = candidate?.language || candidate?.locale || null;
89
+ if (!newLang) {
90
+ console.debug("useAuthSession: realtime payload did not contain language", payload);
91
+ return;
92
+ }
93
+ // Read current cookie
94
+ const cookie = document.cookie
95
+ .split("; ")
96
+ .find((c) => c.startsWith("NEXT_LOCALE="));
97
+ const cookieLang = cookie ? cookie.split("=")[1] : null;
98
+ if (cookieLang === newLang)
99
+ return;
100
+ // Set cookie and navigate to the language-prefixed URL
101
+ try {
102
+ const maxAge = 365 * 24 * 60 * 60;
103
+ document.cookie = `NEXT_LOCALE=${newLang}; Path=/; Max-Age=${maxAge}; SameSite=Lax`;
104
+ }
105
+ catch (_e) {
106
+ // ignore
107
+ }
108
+ try {
109
+ sessionStorage.setItem("locale-change-ts", Date.now().toString());
110
+ }
111
+ catch (_e) {
112
+ /* ignore */
113
+ }
114
+ try {
115
+ const pathname = window.location.pathname;
116
+ const pathWithoutLang = pathname.replace(/^\/[a-z]{2}(?=\/|$)/, "") || "/";
117
+ const safePath = pathWithoutLang.startsWith("/api")
118
+ ? "/"
119
+ : pathWithoutLang;
120
+ const search = window.location.search || "";
121
+ window.location.href = `/${newLang}${safePath}${search}`;
122
+ }
123
+ catch (_e) {
124
+ // ignore navigation errors
125
+ }
126
+ }
127
+ catch (e) {
128
+ console.debug("useAuthSession: error handling realtime payload", e);
129
+ }
130
+ },
131
+ });
48
132
  return { user, loading, isSuperAdmin };
49
133
  }
package/dist/cli.js CHANGED
@@ -20,9 +20,25 @@ program
20
20
  .option("--no-interactive", "Mode non-interactif (skip la sélection des modules)")
21
21
  .action(async (directory, options) => {
22
22
  try {
23
- const targetDir = directory
24
- ? path.resolve(process.cwd(), directory)
25
- : process.cwd();
23
+ let targetDir;
24
+ if (directory) {
25
+ // Si on est dans un monorepo (détecté par pnpm-workspace.yaml à la racine)
26
+ const fs = await import("fs-extra");
27
+ const cwd = process.cwd();
28
+ const workspaceFile = path.join(cwd, "pnpm-workspace.yaml");
29
+ const isMonorepo = await fs.pathExists(workspaceFile);
30
+ if (isMonorepo) {
31
+ // Dans un monorepo, créer dans apps/
32
+ targetDir = path.resolve(cwd, "apps", directory);
33
+ }
34
+ else {
35
+ // Hors monorepo, créer où demandé
36
+ targetDir = path.resolve(cwd, directory);
37
+ }
38
+ }
39
+ else {
40
+ targetDir = process.cwd();
41
+ }
26
42
  await initApp({
27
43
  force: options.force || false,
28
44
  targetDir,
@@ -1,7 +1,9 @@
1
1
  interface LanguageSwitcherProps {
2
2
  variant?: "default" | "minimal";
3
3
  className?: string;
4
+ availableLanguages?: string[];
5
+ localeMap?: Record<string, string>;
4
6
  }
5
- export declare function LanguageSwitcher({ variant, className, }: LanguageSwitcherProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function LanguageSwitcher({ variant, className, availableLanguages, localeMap, }: LanguageSwitcherProps): import("react/jsx-runtime").JSX.Element;
6
8
  export {};
7
9
  //# sourceMappingURL=LanguageSwitcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LanguageSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/LanguageSwitcher.tsx"],"names":[],"mappings":"AAaA,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAmB,EACnB,SAAc,GACf,EAAE,qBAAqB,2CAsIvB"}
1
+ {"version":3,"file":"LanguageSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/LanguageSwitcher.tsx"],"names":[],"mappings":"AAgBA,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAmB,EACnB,SAAc,EACd,kBAAiC,EACjC,SAAwC,GACzC,EAAE,qBAAqB,2CA0PvB"}
@@ -1,35 +1,128 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useState } from "react";
4
+ import { useRouter } from "next/navigation";
4
5
  import { useLanguage } from "../i18n/LanguageProvider";
6
+ import { eventBus } from "@lastbrain/core";
7
+ import { useAuth } from "@lastbrain/core";
5
8
  import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Spinner, } from "@lastbrain/ui";
6
- export function LanguageSwitcher({ variant = "default", className = "", }) {
7
- const { lang, setLang } = useLanguage();
8
- const [flagUrls, setFlagUrls] = useState({
9
- fr: "",
10
- en: "",
11
- });
9
+ export function LanguageSwitcher({ variant = "default", className = "", availableLanguages = ["fr", "en"], localeMap = { fr: "fr_FR", en: "en_US" }, }) {
10
+ const { lang, setLang: setLangFromContext } = useLanguage();
11
+ const router = useRouter();
12
+ const [flagUrls, setFlagUrls] = useState({});
12
13
  const [loading, setLoading] = useState(false);
13
14
  const [isHydrated, setIsHydrated] = useState(false);
14
15
  // Marquer l'hydration comme terminée
15
16
  useEffect(() => {
16
17
  setIsHydrated(true);
17
18
  }, []);
19
+ // Fonction pour changer la langue avec redirection correcte
20
+ const { user } = useAuth();
21
+ const handleLanguageChange = async (newLang) => {
22
+ const currentPath = window.location.pathname;
23
+ // Extraire les segments du chemin
24
+ const segments = currentPath.split("/").filter(Boolean);
25
+ // Nettoyer TOUS les codes langue (2 lettres) du début du path
26
+ // Ça corrige les paths corrompus comme /en/es/recipes
27
+ while (segments.length > 0 && /^[a-z]{2}$/.test(segments[0])) {
28
+ segments.shift(); // Enlever le premier segment s'il est une langue
29
+ }
30
+ // Reconstruire le path avec la nouvelle langue
31
+ const pathWithoutLang = segments.length > 0 ? "/" + segments.join("/") : "";
32
+ const newPath = `/${newLang}${pathWithoutLang}`;
33
+ // Si l'utilisateur est connecté, mettre à jour sa préférence en BDD
34
+ if (user) {
35
+ try {
36
+ const resp = await fetch("/api/auth/profile", {
37
+ method: "PATCH",
38
+ headers: { "Content-Type": "application/json" },
39
+ credentials: "include",
40
+ body: JSON.stringify({ language: newLang }),
41
+ });
42
+ // attendre la confirmation du serveur que la locale a bien été mise à jour
43
+ // afin d'éviter un reload avant que le cookie soit appliqué côté serveur.
44
+ try {
45
+ const json = await resp.json();
46
+ if (json && json.data) {
47
+ // émettre localement l'événement realtime pour propager immédiatement
48
+ try {
49
+ eventBus.emit("user_profile_updated", { new: json.data });
50
+ }
51
+ catch (e) {
52
+ /* ignore */
53
+ }
54
+ }
55
+ else {
56
+ // si serveur n'a pas renvoyé de données attendues, on continue
57
+ }
58
+ }
59
+ catch (e) {
60
+ // ignore json parse errors
61
+ }
62
+ }
63
+ catch (e) {
64
+ console.debug("language switch: failed to update profile language", e);
65
+ }
66
+ }
67
+ // Mettre à jour le contexte local immédiatement (UX local)
68
+ try {
69
+ setLangFromContext(newLang);
70
+ }
71
+ catch (_e) {
72
+ // ignore
73
+ }
74
+ // Si l'utilisateur n'est pas authentifié, écrire immédiatement
75
+ // le cookie NEXT_LOCALE et forcer un refresh pour que Next.js
76
+ // prenne en compte la nouvelle locale côté serveur.
77
+ if (!user) {
78
+ try {
79
+ // 1 an
80
+ document.cookie = `NEXT_LOCALE=${newLang}; Path=/; Max-Age=${31536000}; SameSite=Lax`;
81
+ }
82
+ catch (e) {
83
+ // ignore
84
+ }
85
+ try {
86
+ // Navigate to the same path prefixed with the new locale,
87
+ // preserving search and hash.
88
+ const target = `${newPath}${window.location.search || ""}${window.location.hash || ""}`;
89
+ router.push(target);
90
+ }
91
+ catch (e) {
92
+ // fallback: navigate to the same path but with the new locale
93
+ try {
94
+ window.location.assign(`${newPath}${window.location.search || ""}${window.location.hash || ""}`);
95
+ }
96
+ catch (_err) {
97
+ /* ignore */
98
+ }
99
+ }
100
+ return;
101
+ }
102
+ // Pour utilisateurs authentifiés, la redirection et l'écriture
103
+ // du cookie NEXT_LOCALE sont gérées par le listener realtime centralisé.
104
+ };
18
105
  useEffect(() => {
19
106
  let canceled = false;
20
107
  const objectUrls = [];
21
108
  async function loadFlags() {
22
109
  setLoading(true);
23
110
  try {
24
- const entries = await Promise.all(["fr", "en"].map(async (code) => {
25
- const apiCode = code === "fr" ? "fr" : "gb";
26
- const response = await fetch(`https://flagcdn.com/${apiCode}.svg`);
27
- if (!response.ok)
28
- throw new Error(`Flag fetch failed: ${code}`);
29
- const blob = await response.blob();
30
- const url = URL.createObjectURL(blob);
31
- objectUrls.push(url);
32
- return [code, url];
111
+ const entries = await Promise.all(availableLanguages.map(async (code) => {
112
+ const apiCode = code === "fr" ? "fr" : code === "en" ? "gb" : code;
113
+ try {
114
+ const response = await fetch(`https://flagcdn.com/${apiCode}.svg`);
115
+ if (!response.ok)
116
+ throw new Error(`Flag fetch failed: ${code}`);
117
+ const blob = await response.blob();
118
+ const url = URL.createObjectURL(blob);
119
+ objectUrls.push(url);
120
+ return [code, url];
121
+ }
122
+ catch {
123
+ // Fallback to direct URL if fetch fails
124
+ return [code, `https://flagcdn.com/${apiCode}.svg`];
125
+ }
33
126
  }));
34
127
  if (!canceled) {
35
128
  setFlagUrls(Object.fromEntries(entries));
@@ -37,10 +130,13 @@ export function LanguageSwitcher({ variant = "default", className = "", }) {
37
130
  }
38
131
  catch (_err) {
39
132
  if (!canceled) {
40
- setFlagUrls({
41
- fr: "https://flagcdn.com/fr.svg",
42
- en: "https://flagcdn.com/gb.svg",
133
+ // Fallback: create a map with direct URLs
134
+ const fallbackUrls = {};
135
+ availableLanguages.forEach((code) => {
136
+ const apiCode = code === "fr" ? "fr" : code === "en" ? "gb" : code;
137
+ fallbackUrls[code] = `https://flagcdn.com/${apiCode}.svg`;
43
138
  });
139
+ setFlagUrls(fallbackUrls);
44
140
  }
45
141
  }
46
142
  finally {
@@ -53,10 +149,27 @@ export function LanguageSwitcher({ variant = "default", className = "", }) {
53
149
  canceled = true;
54
150
  objectUrls.forEach((url) => URL.revokeObjectURL(url));
55
151
  };
56
- }, []);
152
+ }, [availableLanguages]);
57
153
  const renderFlag = (code) => (_jsx("span", { className: "inline-flex items-center gap-2", children: flagUrls[code] ? (_jsx("img", { src: flagUrls[code], alt: code === "fr" ? "Drapeau français" : "Flag English", className: "h-4 w-6 rounded-sm border border-slate-200 object-cover" })) : isHydrated ? (_jsx("span", { className: "inline-flex h-4 w-6 items-center justify-center rounded-sm bg-slate-200 text-[10px] font-semibold text-slate-600", children: code.toUpperCase() })) : null }));
154
+ // SSR placeholder - ne pas rendre le Dropdown avant l'hydration
155
+ // pour éviter les mismatches d'ID React Aria
156
+ if (!isHydrated) {
157
+ return (_jsx("span", { className: "inline-flex h-4 w-6 items-center justify-center rounded-sm bg-slate-200 text-[10px] font-semibold text-slate-600", children: lang.toUpperCase() }));
158
+ }
58
159
  if (variant === "minimal") {
59
- return (_jsxs(Dropdown, { size: "sm", className: "px-0 m-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: renderFlag(lang) }), _jsxs(DropdownMenu, { children: [_jsxs(DropdownItem, { onPress: () => setLang("en"), startContent: renderFlag("en"), className: lang === "en" ? "bg-primary/10" : "", children: ["English ", isHydrated && lang === "en" && "✓"] }, "en"), _jsxs(DropdownItem, { onPress: () => setLang("fr"), startContent: renderFlag("fr"), className: lang === "fr" ? "bg-primary/10" : "", children: ["Fran\u00E7ais ", isHydrated && lang === "fr" && "✓"] }, "fr")] })] }));
160
+ return (_jsx("div", { className: "", children: _jsxs(Dropdown, { size: "sm", className: "px-0 m-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: renderFlag(lang) }), _jsx(DropdownMenu, { children: availableLanguages.map((code) => (_jsxs(DropdownItem, { onPress: () => handleLanguageChange(code), startContent: renderFlag(code), className: lang === code ? "bg-primary/10" : "", children: [code === "fr"
161
+ ? "Français"
162
+ : code === "en"
163
+ ? "English"
164
+ : code === "es"
165
+ ? "Spanish"
166
+ : code, isHydrated && lang === code && " ✓"] }, code))) })] }) }));
60
167
  }
61
- return (_jsxs(Dropdown, { size: "sm", className: "px-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: _jsx(Button, { variant: "light", size: "sm", className: "px-0 m-0", startContent: renderFlag(lang), endContent: loading ? _jsx(Spinner, { size: "sm" }) : null }) }), _jsxs(DropdownMenu, { children: [_jsxs(DropdownItem, { onPress: () => setLang("en"), className: lang === "en" ? "bg-primary/10" : "", children: [renderFlag("en"), " English ", isHydrated && lang === "en" && "✓"] }, "en"), _jsxs(DropdownItem, { onPress: () => setLang("fr"), className: lang === "fr" ? "bg-primary/10" : "", children: [renderFlag("fr"), " Fran\u00E7ais ", isHydrated && lang === "fr" && "✓"] }, "fr")] })] }));
168
+ return (_jsxs(Dropdown, { size: "sm", className: "px-0 ", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: _jsx(Button, { variant: "light", size: "sm", className: "px-0 m-0", "aria-label": `Switch language (current: ${lang})`, startContent: renderFlag(lang), endContent: loading ? _jsx(Spinner, { size: "sm" }) : null }) }), _jsx(DropdownMenu, { children: availableLanguages.map((code) => (_jsxs(DropdownItem, { onPress: () => handleLanguageChange(code), className: lang === code ? "bg-primary/10" : "", children: [renderFlag(code), " ", code === "fr"
169
+ ? "Français"
170
+ : code === "en"
171
+ ? "English"
172
+ : code === "es"
173
+ ? "Spanish"
174
+ : code, isHydrated && lang === code && " ✓"] }, code))) })] }));
62
175
  }
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/config/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAoBnD,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/config/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA+BnD,CAAC"}
@@ -4,23 +4,34 @@
4
4
  * Mise à jour automatique lors de pnpm version:patch/minor/major
5
5
  */
6
6
  export const PACKAGE_VERSIONS = {
7
- "@lastbrain-labs/module-billing-pro": "^2.0.18",
8
- "@lastbrain-labs/module-cj-analyzer-pro": "^0.1.10",
9
- "@lastbrain-labs/module-core-cart-pro": "^2.0.18",
10
- "@lastbrain-labs/module-core-commerce-pro": "^2.0.18",
11
- "@lastbrain-labs/module-core-order-pro": "^2.0.18",
12
- "@lastbrain-labs/module-core-payment-pro": "^2.0.18",
13
- "@lastbrain-labs/module-core-product-pro": "^2.0.18",
14
- "@lastbrain-labs/module-recipes-pro": "^2.0.18",
15
- "@lastbrain-labs/module-shop-pro": "^0.1.10",
16
- "@lastbrain/app": "^2.0.21",
17
- "@lastbrain/core": "^2.0.19",
18
- "@lastbrain/module-ai": "^2.0.18",
19
- "@lastbrain/module-auth": "^2.0.19",
20
- "@lastbrain/module-legal": "^2.0.18",
21
- "@lastbrain/module-project-board": "^2.0.18",
22
- "@lastbrain/module-tasks": "^2.0.18",
23
- "@lastbrain/ui": "^2.0.19",
24
- "apps/recipe": "^2.0.11",
25
- lastbrain: "^2.0.11",
7
+ "@lastbrain-labs/metrics-ui": "^1.0.2",
8
+ "@lastbrain-labs/module-billing-pro": "^2.0.29",
9
+ "@lastbrain-labs/module-cj-analyzer-pro": "^0.1.21",
10
+ "@lastbrain-labs/module-contact-pro": "^0.1.2",
11
+ "@lastbrain-labs/module-core-cart-pro": "^2.0.29",
12
+ "@lastbrain-labs/module-core-commerce-pro": "^2.0.29",
13
+ "@lastbrain-labs/module-core-order-pro": "^2.0.29",
14
+ "@lastbrain-labs/module-core-payment-pro": "^2.0.29",
15
+ "@lastbrain-labs/module-core-product-pro": "^2.0.29",
16
+ "@lastbrain-labs/module-metrics-pro": "^0.1.2",
17
+ "@lastbrain-labs/module-recipes-pro": "^2.0.31",
18
+ "@lastbrain-labs/module-shop-pro": "^0.1.21",
19
+ "@lastbrain/ai-ui-core": "^1.0.2",
20
+ "@lastbrain/ai-ui-react": "^1.0.2",
21
+ "@lastbrain/ai-ui-theme-heroui": "^1.0.2",
22
+ "@lastbrain/app": "^2.0.34",
23
+ "@lastbrain/core": "^2.0.30",
24
+ "@lastbrain/module-ai": "^2.0.29",
25
+ "@lastbrain/module-audit-pro": "^0.1.2",
26
+ "@lastbrain/module-auth": "^2.0.30",
27
+ "@lastbrain/module-blog": "^0.1.2",
28
+ "@lastbrain/module-legal": "^2.0.29",
29
+ "@lastbrain/module-project-board": "^2.0.29",
30
+ "@lastbrain/module-tasks": "^2.0.29",
31
+ "@lastbrain/module-tools": "^0.1.2",
32
+ "@lastbrain/ui": "^2.0.30",
33
+ "audit": "^2.0.14",
34
+ "prompt": "^0.1.1",
35
+ "recipe": "^2.0.14",
36
+ "tools": "^2.0.14",
26
37
  };
@@ -1,4 +1,4 @@
1
- export type Language = "fr" | "en";
1
+ export type Language = string;
2
2
  /**
3
3
  * Récupère la langue depuis les cookies côté serveur
4
4
  */
@@ -1 +1 @@
1
- {"version":3,"file":"server-lang.d.ts","sourceRoot":"","sources":["../../src/i18n/server-lang.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAI3D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA8BjC"}
1
+ {"version":3,"file":"server-lang.d.ts","sourceRoot":"","sources":["../../src/i18n/server-lang.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAI3D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA8BjC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Types pour le système i18n
3
3
  */
4
- export type Language = "fr" | "en";
4
+ export type Language = string;
5
5
  export type TranslationKey = string;
6
6
  export interface Translations {
7
7
  [key: string]: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,QAAQ,CAAC;IACxB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,QAAQ,CAAC;IACxB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useLink.d.ts","sourceRoot":"","sources":["../../src/i18n/useLink.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAgB7D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,OAAO,KAGb,MAAM,MAAM,KAAG,MAAM,CAG9B"}
1
+ {"version":3,"file":"useLink.d.ts","sourceRoot":"","sources":["../../src/i18n/useLink.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAYxC;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAqB7D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,OAAO,KAGb,MAAM,MAAM,KAAG,MAAM,CAG9B"}
@@ -1,5 +1,14 @@
1
1
  "use client";
2
2
  import { useLanguage } from "./LanguageProvider";
3
+ /**
4
+ * Détecte si un chemin commence par un code de langue ISO 639-1 (2 lettres)
5
+ * Ex: /fr/auth/billing -> true, /auth/billing -> false
6
+ */
7
+ function startsWithLocale(href) {
8
+ // Pattern: /XX/ ou /XX où XX est un code langue de 2 lettres minuscules
9
+ const localePattern = /^\/[a-z]{2}(\/|$)/;
10
+ return localePattern.test(href);
11
+ }
3
12
  /**
4
13
  * Helper pour transformer un URL avec le paramètre [lang]
5
14
  * Utile pour les transformations statiques avant le rendu React
@@ -14,12 +23,18 @@ export function langHref(href, lang) {
14
23
  const normalizedHref = String(href);
15
24
  const isAbsolute = normalizedHref.startsWith("http");
16
25
  const hasLangPrefix = normalizedHref.startsWith(`/${lang}/`);
26
+ const hasAnyLangPrefix = startsWithLocale(normalizedHref);
17
27
  if (isAbsolute) {
18
28
  return normalizedHref;
19
29
  }
20
30
  else if (hasLangPrefix) {
31
+ // Déjà préfixé avec la bonne langue
21
32
  return normalizedHref;
22
33
  }
34
+ else if (hasAnyLangPrefix) {
35
+ // Préfixé avec une autre langue - remplacer par la langue courante
36
+ return `/${lang}${normalizedHref.slice(3)}`;
37
+ }
23
38
  else if (normalizedHref === "/") {
24
39
  return `/${lang}`;
25
40
  }
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export { AuthLayoutWithSidebar, type AuthLayoutWithSidebarProps, type MenuIgnore
11
11
  export { AdminLayout } from "./layouts/AdminLayout";
12
12
  export { AdminLayoutWithSidebar } from "./layouts/AdminLayoutWithSidebar";
13
13
  export { getModuleConfigs } from "./modules/module-loader";
14
+ export { registerAnalyticsComponent } from "./analytics/registry";
14
15
  export { LanguageProvider, useLanguage, type Language, } from "./i18n/LanguageProvider";
15
16
  export { useLink, langHref } from "./i18n/useLink";
16
17
  export { useLangRouter } from "./i18n/useLangRouter";
@@ -18,6 +19,7 @@ export { useModuleTranslation } from "@lastbrain/core";
18
19
  export { transformLangHrefs, transformLangHref } from "./i18n/langHrefHelper";
19
20
  export { LanguageSwitcher } from "./components/LanguageSwitcher";
20
21
  export type { TranslationKey, Translations, I18nConfig, LangParams, LangIdParams, ModuleTranslations, } from "./i18n/types";
22
+ export type { ModuleBuildConfig, ModuleApiConfig, ModuleMenuItemConfig, ModulePageConfig, ModuleSection, ModuleRealtimeConfig, ModuleSitemapConfig, } from "@lastbrain/core";
21
23
  export { AppAside } from "@lastbrain/ui";
22
24
  export type { AppAsideMenuItem, AppAsideMenuConfig } from "@lastbrain/ui";
23
25
  export { SimpleHomePage } from "./templates/SimpleHomePage";
@@ -26,4 +28,5 @@ export { SimpleDocPage } from "./templates/SimpleDocPage";
26
28
  export { ModuleGuidePage } from "./templates/ModuleGuidePage";
27
29
  export { AuthGuidePage } from "./templates/AuthGuidePage";
28
30
  export { MigrationsGuidePage } from "./templates/MigrationsGuidePage";
31
+ export { sitemapManifest } from "./sitemap/manifest";
29
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,gBAAgB,IAAI,uBAAuB,GAC5C,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,KAAK,QAAQ,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,gBAAgB,IAAI,uBAAuB,GAC5C,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAGlE,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,KAAK,QAAQ,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAGtE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,8 @@ export { AuthLayoutWithSidebar, } from "./layouts/AuthLayoutWithSidebar";
11
11
  export { AdminLayout } from "./layouts/AdminLayout";
12
12
  export { AdminLayoutWithSidebar } from "./layouts/AdminLayoutWithSidebar";
13
13
  export { getModuleConfigs } from "./modules/module-loader";
14
+ // Analytics
15
+ export { registerAnalyticsComponent } from "./analytics/registry";
14
16
  // i18n
15
17
  export { LanguageProvider, useLanguage, } from "./i18n/LanguageProvider";
16
18
  export { useLink, langHref } from "./i18n/useLink";
@@ -27,3 +29,5 @@ export { SimpleDocPage } from "./templates/SimpleDocPage";
27
29
  export { ModuleGuidePage } from "./templates/ModuleGuidePage";
28
30
  export { AuthGuidePage } from "./templates/AuthGuidePage";
29
31
  export { MigrationsGuidePage } from "./templates/MigrationsGuidePage";
32
+ // Sitemap manifest
33
+ export { sitemapManifest } from "./sitemap/manifest";
@@ -1,10 +1,12 @@
1
1
  import { type MenuConfig, type MenuItem } from "@lastbrain/ui";
2
+ import type { MenuIgnored } from "../types/menu";
2
3
  interface AdminLayoutWithSidebarProps {
3
4
  children: React.ReactNode;
4
5
  menuConfig?: MenuConfig;
5
6
  className?: string;
6
7
  menuCustom?: MenuItem[];
8
+ menuIgnored?: MenuIgnored;
7
9
  }
8
- export declare function AdminLayoutWithSidebar({ children, menuConfig, className, menuCustom, }: AdminLayoutWithSidebarProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function AdminLayoutWithSidebar({ children, menuConfig, className, menuCustom, menuIgnored, }: AdminLayoutWithSidebarProps): import("react/jsx-runtime").JSX.Element;
9
11
  export {};
10
12
  //# sourceMappingURL=AdminLayoutWithSidebar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AAKvB,UAAU,2BAA2B;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,SAAc,EACd,UAAU,GACX,EAAE,2BAA2B,2CAkG7B"}
1
+ {"version":3,"file":"AdminLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AAIvB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,UAAU,2BAA2B;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,SAAc,EACd,UAAU,EACV,WAAW,GACZ,EAAE,2BAA2B,2CAmG7B"}
@@ -5,7 +5,7 @@ import { AppAside, AppAsideSkeleton, } from "@lastbrain/ui";
5
5
  import { useAuthSession } from "../auth/useAuthSession";
6
6
  import { usePathname } from "next/navigation";
7
7
  import { useEffect, useState } from "react";
8
- export function AdminLayoutWithSidebar({ children, menuConfig, className = "", menuCustom, }) {
8
+ export function AdminLayoutWithSidebar({ children, menuConfig, className = "", menuCustom, menuIgnored, }) {
9
9
  const { isSuperAdmin, loading, user } = useAuthSession();
10
10
  const pathname = usePathname();
11
11
  const [isCollapsed, setIsCollapsed] = useState(() => {
@@ -58,5 +58,5 @@ export function AdminLayoutWithSidebar({ children, menuConfig, className = "", m
58
58
  safeMenuConfig.public.length > 0);
59
59
  // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
60
60
  const shouldShowSkeleton = loading || !hasValidMenuConfig;
61
- return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className, ...(menuCustom ? { menuCustom } : {}) })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AdminLayout, { children: children }) })] }));
61
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className, ...(menuIgnored ? { menuIgnored } : {}), ...(menuCustom ? { menuCustom } : {}) })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AdminLayout, { children: children }) })] }));
62
62
  }
@@ -21,10 +21,18 @@ export declare function useAuth(): {
21
21
  loading: boolean;
22
22
  isSuperAdmin: boolean;
23
23
  };
24
- export declare function AppProviders({ children, realtimeConfig, lang, translations, }: {
24
+ export declare function AppProviders({ children, realtimeConfig, lang, translations, availableLanguages, EntitlementsProviderComponent, AnalyticsListenerComponent, }: {
25
25
  children: React.ReactNode;
26
26
  realtimeConfig?: ModuleRealtimeConfig[];
27
27
  lang?: Language;
28
28
  translations?: Record<string, string>;
29
+ /** Liste des langues disponibles depuis locales.generated.ts */
30
+ availableLanguages?: string[];
31
+ /** Provider optionnel pour les entitlements (billing) */
32
+ EntitlementsProviderComponent?: React.ComponentType<{
33
+ children: React.ReactNode;
34
+ }>;
35
+ /** Composant optionnel pour le tracking analytics */
36
+ AnalyticsListenerComponent?: React.ComponentType;
29
37
  }): import("react/jsx-runtime").JSX.Element;
30
38
  //# sourceMappingURL=AppProviders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layouts/AppProviders.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAuCnE,wBAAgB,UAAU,kDAEzB;AAED,wBAAgB,gBAAgB;UAvCxB,iBAAiB;aACd,OAAO;WACT,MAAM,GAAG,IAAI;aACX,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;mBAC1B,MAAM,OAAO,CAAC,IAAI,CAAC;wBACd,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;aACxC,OAAO;eACL,OAAO;oBACF,OAAO;yBACF,OAAO;EA+B7B;AAED,wBAAgB,OAAO;UAjBf,IAAI,GAAG,IAAI;aACR,OAAO;kBACF,OAAO;EAiBtB;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,cAAmB,EACnB,IAAW,EACX,YAAiB,GAClB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC,2CA0CA"}
1
+ {"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layouts/AppProviders.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAqEnE,wBAAgB,UAAU,kDAEzB;AAED,wBAAgB,gBAAgB;UAvCxB,iBAAiB;aACd,OAAO;WACT,MAAM,GAAG,IAAI;aACX,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;mBAC1B,MAAM,OAAO,CAAC,IAAI,CAAC;wBACd,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;aACxC,OAAO;eACL,OAAO;oBACF,OAAO;yBACF,OAAO;EA+B7B;AAED,wBAAgB,OAAO;UAjBf,IAAI,GAAG,IAAI;aACR,OAAO;kBACF,OAAO;EAiBtB;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,cAAmB,EACnB,IAAW,EACX,YAAiB,EACjB,kBAAiC,EACjC,6BAA6B,EAC7B,0BAA0B,GAC3B,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,yDAAyD;IACzD,6BAA6B,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAClD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;KAC3B,CAAC,CAAC;IACH,qDAAqD;IACrD,0BAA0B,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAClD,2CAkEA"}