@creezio/shell-ui 0.22.0

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 (232) hide show
  1. package/README.md +336 -0
  2. package/dist/adapters/nav-shell.d.ts +54 -0
  3. package/dist/adapters/nav-shell.d.ts.map +1 -0
  4. package/dist/adapters/nav-shell.js +112 -0
  5. package/dist/adapters/nav-shell.js.map +1 -0
  6. package/dist/brand.d.ts +64 -0
  7. package/dist/brand.d.ts.map +1 -0
  8. package/dist/brand.js +59 -0
  9. package/dist/brand.js.map +1 -0
  10. package/dist/core-nav.d.ts +17 -0
  11. package/dist/core-nav.d.ts.map +1 -0
  12. package/dist/core-nav.js +40 -0
  13. package/dist/core-nav.js.map +1 -0
  14. package/dist/index.d.ts +29 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +24 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/lib/api-scopes.d.ts +24 -0
  19. package/dist/lib/api-scopes.d.ts.map +1 -0
  20. package/dist/lib/api-scopes.js +78 -0
  21. package/dist/lib/api-scopes.js.map +1 -0
  22. package/dist/lib/catalog-suspense-key.d.ts +3 -0
  23. package/dist/lib/catalog-suspense-key.d.ts.map +1 -0
  24. package/dist/lib/catalog-suspense-key.js +12 -0
  25. package/dist/lib/catalog-suspense-key.js.map +1 -0
  26. package/dist/lib/data-changed.d.ts +51 -0
  27. package/dist/lib/data-changed.d.ts.map +1 -0
  28. package/dist/lib/data-changed.js +227 -0
  29. package/dist/lib/data-changed.js.map +1 -0
  30. package/dist/lib/desktop-home-path.d.ts +14 -0
  31. package/dist/lib/desktop-home-path.d.ts.map +1 -0
  32. package/dist/lib/desktop-home-path.js +29 -0
  33. package/dist/lib/desktop-home-path.js.map +1 -0
  34. package/dist/lib/geo-distance.d.ts +6 -0
  35. package/dist/lib/geo-distance.d.ts.map +1 -0
  36. package/dist/lib/geo-distance.js +27 -0
  37. package/dist/lib/geo-distance.js.map +1 -0
  38. package/dist/lib/img.d.ts +2 -0
  39. package/dist/lib/img.d.ts.map +1 -0
  40. package/dist/lib/img.js +40 -0
  41. package/dist/lib/img.js.map +1 -0
  42. package/dist/lib/keepalive-eviction.d.ts +14 -0
  43. package/dist/lib/keepalive-eviction.d.ts.map +1 -0
  44. package/dist/lib/keepalive-eviction.js +44 -0
  45. package/dist/lib/keepalive-eviction.js.map +1 -0
  46. package/dist/lib/ops-track.d.ts +29 -0
  47. package/dist/lib/ops-track.d.ts.map +1 -0
  48. package/dist/lib/ops-track.js +37 -0
  49. package/dist/lib/ops-track.js.map +1 -0
  50. package/dist/lib/optimize-cover-url.d.ts +10 -0
  51. package/dist/lib/optimize-cover-url.d.ts.map +1 -0
  52. package/dist/lib/optimize-cover-url.js +80 -0
  53. package/dist/lib/optimize-cover-url.js.map +1 -0
  54. package/dist/lib/page-trails.d.ts +9 -0
  55. package/dist/lib/page-trails.d.ts.map +1 -0
  56. package/dist/lib/page-trails.js +20 -0
  57. package/dist/lib/page-trails.js.map +1 -0
  58. package/dist/lib/public-origin.d.ts +32 -0
  59. package/dist/lib/public-origin.d.ts.map +1 -0
  60. package/dist/lib/public-origin.js +125 -0
  61. package/dist/lib/public-origin.js.map +1 -0
  62. package/dist/lib/server-incident.d.ts +12 -0
  63. package/dist/lib/server-incident.d.ts.map +1 -0
  64. package/dist/lib/server-incident.js +72 -0
  65. package/dist/lib/server-incident.js.map +1 -0
  66. package/dist/lib/tab-document-url.d.ts +13 -0
  67. package/dist/lib/tab-document-url.d.ts.map +1 -0
  68. package/dist/lib/tab-document-url.js +60 -0
  69. package/dist/lib/tab-document-url.js.map +1 -0
  70. package/dist/lib/utils.d.ts +20 -0
  71. package/dist/lib/utils.d.ts.map +1 -0
  72. package/dist/lib/utils.js +87 -0
  73. package/dist/lib/utils.js.map +1 -0
  74. package/dist/nav-catalog.d.ts +97 -0
  75. package/dist/nav-catalog.d.ts.map +1 -0
  76. package/dist/nav-catalog.js +282 -0
  77. package/dist/nav-catalog.js.map +1 -0
  78. package/dist/registry.d.ts +11 -0
  79. package/dist/registry.d.ts.map +1 -0
  80. package/dist/registry.js +60 -0
  81. package/dist/registry.js.map +1 -0
  82. package/dist/types.d.ts +22 -0
  83. package/dist/types.d.ts.map +1 -0
  84. package/dist/types.js +2 -0
  85. package/dist/types.js.map +1 -0
  86. package/dist-cjs/adapters/nav-shell.js +115 -0
  87. package/dist-cjs/adapters/nav-shell.js.map +1 -0
  88. package/dist-cjs/brand.js +66 -0
  89. package/dist-cjs/brand.js.map +1 -0
  90. package/dist-cjs/core-nav.js +43 -0
  91. package/dist-cjs/core-nav.js.map +1 -0
  92. package/dist-cjs/index.js +95 -0
  93. package/dist-cjs/index.js.map +1 -0
  94. package/dist-cjs/lib/api-scopes.js +86 -0
  95. package/dist-cjs/lib/api-scopes.js.map +1 -0
  96. package/dist-cjs/lib/catalog-suspense-key.js +15 -0
  97. package/dist-cjs/lib/catalog-suspense-key.js.map +1 -0
  98. package/dist-cjs/lib/data-changed.js +236 -0
  99. package/dist-cjs/lib/data-changed.js.map +1 -0
  100. package/dist-cjs/lib/desktop-home-path.js +34 -0
  101. package/dist-cjs/lib/desktop-home-path.js.map +1 -0
  102. package/dist-cjs/lib/geo-distance.js +30 -0
  103. package/dist-cjs/lib/geo-distance.js.map +1 -0
  104. package/dist-cjs/lib/img.js +43 -0
  105. package/dist-cjs/lib/img.js.map +1 -0
  106. package/dist-cjs/lib/keepalive-eviction.js +49 -0
  107. package/dist-cjs/lib/keepalive-eviction.js.map +1 -0
  108. package/dist-cjs/lib/ops-track.js +41 -0
  109. package/dist-cjs/lib/ops-track.js.map +1 -0
  110. package/dist-cjs/lib/optimize-cover-url.js +83 -0
  111. package/dist-cjs/lib/optimize-cover-url.js.map +1 -0
  112. package/dist-cjs/lib/page-trails.js +25 -0
  113. package/dist-cjs/lib/page-trails.js.map +1 -0
  114. package/dist-cjs/lib/public-origin.js +130 -0
  115. package/dist-cjs/lib/public-origin.js.map +1 -0
  116. package/dist-cjs/lib/server-incident.js +75 -0
  117. package/dist-cjs/lib/server-incident.js.map +1 -0
  118. package/dist-cjs/lib/tab-document-url.js +65 -0
  119. package/dist-cjs/lib/tab-document-url.js.map +1 -0
  120. package/dist-cjs/lib/utils.js +97 -0
  121. package/dist-cjs/lib/utils.js.map +1 -0
  122. package/dist-cjs/nav-catalog.js +293 -0
  123. package/dist-cjs/nav-catalog.js.map +1 -0
  124. package/dist-cjs/package.json +3 -0
  125. package/dist-cjs/registry.js +64 -0
  126. package/dist-cjs/registry.js.map +1 -0
  127. package/dist-cjs/types.js +3 -0
  128. package/dist-cjs/types.js.map +1 -0
  129. package/package.json +163 -0
  130. package/ui/app-error-boundary.tsx +59 -0
  131. package/ui/data-table.tsx +121 -0
  132. package/ui/desktop/auth-window-chrome.tsx +51 -0
  133. package/ui/desktop/desktop-bridge.tsx +87 -0
  134. package/ui/desktop/external-site-slot.tsx +313 -0
  135. package/ui/desktop/external-site-surface.ts +58 -0
  136. package/ui/desktop/site-link.tsx +105 -0
  137. package/ui/desktop/window-chrome-controls.tsx +5 -0
  138. package/ui/desktop-types.ts +30 -0
  139. package/ui/faceted-filters.tsx +119 -0
  140. package/ui/global-search-host.ts +20 -0
  141. package/ui/global-search.tsx +66 -0
  142. package/ui/index.ts +178 -0
  143. package/ui/kit.ts +30 -0
  144. package/ui/layout/app-shell.tsx +58 -0
  145. package/ui/layout/desktop-update-banner.tsx +100 -0
  146. package/ui/layout/entity-header.tsx +44 -0
  147. package/ui/layout/native-os-nav.ts +104 -0
  148. package/ui/layout/nav-catalog-loader.tsx +98 -0
  149. package/ui/layout/nav-icons.ts +67 -0
  150. package/ui/layout/page-chrome.tsx +90 -0
  151. package/ui/layout/page-toolbar-context.tsx +82 -0
  152. package/ui/layout/sandbox-banner.tsx +38 -0
  153. package/ui/layout/section-view-shell.tsx +73 -0
  154. package/ui/layout/sidebar-host.ts +144 -0
  155. package/ui/layout/sidebar.tsx +1150 -0
  156. package/ui/lib/ai-screencast-hub.ts +127 -0
  157. package/ui/lib/ai-workspace-client.ts +46 -0
  158. package/ui/lib/aid.ts +22 -0
  159. package/ui/lib/desktop-host.ts +114 -0
  160. package/ui/lib/fleet-tracker-client.ts +237 -0
  161. package/ui/lib/hermes-ui.ts +114 -0
  162. package/ui/lib/n8n-ui.ts +115 -0
  163. package/ui/lib/use-creezio-resource.tsx +121 -0
  164. package/ui/lib/use-shell-ui-brand.ts +22 -0
  165. package/ui/list-toolbar.tsx +309 -0
  166. package/ui/os-pages/desktop-settings-page.tsx +158 -0
  167. package/ui/os-pages/index.ts +8 -0
  168. package/ui/page-loading/entity-page-loading.tsx +59 -0
  169. package/ui/page-loading/list-page-loading.tsx +61 -0
  170. package/ui/pagination.tsx +56 -0
  171. package/ui/primitives/avatar.tsx +33 -0
  172. package/ui/primitives/badge.tsx +36 -0
  173. package/ui/primitives/breadcrumb.tsx +93 -0
  174. package/ui/primitives/button.tsx +44 -0
  175. package/ui/primitives/card.tsx +44 -0
  176. package/ui/primitives/chart.tsx +317 -0
  177. package/ui/primitives/command.tsx +111 -0
  178. package/ui/primitives/dialog.tsx +100 -0
  179. package/ui/primitives/dropdown-menu.tsx +187 -0
  180. package/ui/primitives/input.tsx +19 -0
  181. package/ui/primitives/label.tsx +17 -0
  182. package/ui/primitives/resizable.tsx +45 -0
  183. package/ui/primitives/scroll-area.tsx +41 -0
  184. package/ui/primitives/select.tsx +73 -0
  185. package/ui/primitives/separator.tsx +26 -0
  186. package/ui/primitives/sheet.tsx +90 -0
  187. package/ui/primitives/skeleton.tsx +7 -0
  188. package/ui/primitives/sonner.tsx +22 -0
  189. package/ui/primitives/tabs.tsx +51 -0
  190. package/ui/primitives/textarea.tsx +22 -0
  191. package/ui/primitives/tooltip.tsx +31 -0
  192. package/ui/pwa/client-error-reporter.tsx +62 -0
  193. package/ui/pwa/register-sw.tsx +50 -0
  194. package/ui/range-filters.tsx +174 -0
  195. package/ui/search/global-search-config.ts +32 -0
  196. package/ui/search/global-search-provider.tsx +528 -0
  197. package/ui/search/search-history.ts +74 -0
  198. package/ui/search-input.tsx +146 -0
  199. package/ui/settings/account-settings.tsx +140 -0
  200. package/ui/settings/agent-profile-settings.tsx +184 -0
  201. package/ui/settings/api-keys-settings.tsx +349 -0
  202. package/ui/settings/desktop-background-settings.tsx +128 -0
  203. package/ui/settings/desktop-connection-settings.tsx +251 -0
  204. package/ui/settings/desktop-embed-env-panel.tsx +257 -0
  205. package/ui/settings/desktop-fleet-telemetry-settings.tsx +269 -0
  206. package/ui/settings/desktop-hermes-settings.tsx +341 -0
  207. package/ui/settings/desktop-llm-keys.tsx +192 -0
  208. package/ui/settings/desktop-n8n-settings.tsx +306 -0
  209. package/ui/settings/desktop-tunnel.tsx +264 -0
  210. package/ui/settings/desktop-update-settings.tsx +175 -0
  211. package/ui/settings/factory-reset-settings.tsx +89 -0
  212. package/ui/settings/host-only-settings.tsx +62 -0
  213. package/ui/settings/locked-config-field.tsx +30 -0
  214. package/ui/settings/ops-diagnostic-settings.tsx +242 -0
  215. package/ui/settings/search-reindex-settings.tsx +158 -0
  216. package/ui/settings/server-mode-cards.tsx +801 -0
  217. package/ui/theme/tailwind-preset.cjs +82 -0
  218. package/ui/theme/theme.css +328 -0
  219. package/ui/workspace/ai-activity-panel-host.tsx +19 -0
  220. package/ui/workspace/ai-workspace-agent-host.tsx +54 -0
  221. package/ui/workspace/ai-workspace-banner.tsx +168 -0
  222. package/ui/workspace/impersonation-banner.tsx +39 -0
  223. package/ui/workspace/keep-alive.tsx +220 -0
  224. package/ui/workspace/tab-workspace-context.tsx +1172 -0
  225. package/ui/workspace/tab-workspace-host.ts +89 -0
  226. package/ui/workspace/types.ts +500 -0
  227. package/ui/workspace/use-location-search.tsx +50 -0
  228. package/ui/workspace/window-chrome-controls.tsx +116 -0
  229. package/ui/workspace/workspace-config.ts +47 -0
  230. package/ui/workspace/workspace-root.tsx +147 -0
  231. package/ui/workspace/workspace-shell.tsx +292 -0
  232. package/ui/workspace/workspace-tab-bar.tsx +572 -0
package/README.md ADDED
@@ -0,0 +1,336 @@
1
+ # @creezio/shell-ui
2
+
3
+ ## Rôle
4
+
5
+ `@creezio/shell-ui` fournit la navigation native Creezio, les slots de navigation et le chrome CRM partage entre marques : primitives UI, sidebar, workspace a onglets, recherche globale, surfaces desktop/site externe, settings desktop, layouts et petites libs plateforme.
6
+
7
+ Le package a deux couches :
8
+
9
+ | Import | Contenu |
10
+ |---|---|
11
+ | `@creezio/shell-ui` | noyau bas niveau : registry nav, slots, brand tokens, helpers/lib plateforme |
12
+ | `@creezio/shell-ui/ui` | React UI : primitives, AppShell, sidebar, workspace, search, desktop surfaces, settings |
13
+
14
+ Point d'arbitrage important : historiquement, `shell-ui` etait "nav + slots" (H1/I7). Le package contient aujourd'hui aussi du chrome CRM extrait des apps (sidebar, workspace, search, settings, libs client). Selon `docs/archive/AUDIT-SHELL-UI-SCOPE.md`, ce n'est pas seulement un mauvais nom : c'est le SoT court terme pour le chrome shell CRM, tandis que onboarding, cockpit, splash et auth restent dans leurs packages dedies.
15
+
16
+ ## Périmètre (kit vs marque)
17
+
18
+ ### Dans le kit
19
+
20
+ Noyau nav / slots :
21
+
22
+ - `CoreNavItem`, `NavSlotId`, `NavSlot`
23
+ - `CORE_NAV_ITEMS`, `createNavRegistry`, `mergeNav`
24
+ - `createNavShellAdapter`
25
+ - slots `brand-primary`, `brand-secondary`, `plugins`
26
+
27
+ Chrome CRM / UI :
28
+
29
+ - primitives shadcn-like (`Button`, `Input`, `Card`, `Dialog`, `Command`, etc.) ;
30
+ - sidebar CRM (`Sidebar`, `CrmSidebar`) et host `configureSidebar` ;
31
+ - workspace a onglets (`TabWorkspaceProvider`, `WorkspaceShell`, `WorkspaceRoot`, `WorkspaceTabBar`) ;
32
+ - bandeau impersonation natif (`ImpersonationBanner`, rendu par `WorkspaceRoot` dès que `me.impersonating` — « Revenir à mon compte » via `stopImpersonate`) ;
33
+ - recherche globale (`configureGlobalSearch`, `GlobalSearchProvider`) ;
34
+ - surfaces desktop/site externe (`ExternalSiteSlot`, `DesktopBridge`, `SiteLink`) ;
35
+ - settings desktop (`DesktopHermesSettings`, `DesktopN8nSettings`, `ApiKeysSettings`, etc.) ;
36
+ - composants layout (`AppShell`, `PageChrome`, `EntityHeader`, `SectionViewShell`) ;
37
+ - helpers plateforme (`resolvePublicOrigin`, `resolveCookieSecure`, scopes API, URL images, keep-alive, trails, telemetry best-effort).
38
+
39
+ ### Dans la marque
40
+
41
+ - items nav metier avec ids `brand.*` et hrefs produit ;
42
+ - ACL de visibilite (`canShowHref`) ;
43
+ - icones et ordre des liens principaux/admin ;
44
+ - recherche concrete (Meili, fallback DB, labels d'index) ;
45
+ - contexte detail produit / page meta / breadcrumbs metier ;
46
+ - providers metier (`PanierProvider`, RTI, GED, VASP, etc.) ;
47
+ - routes Next (`/site/[id]`, pages settings/admin) ;
48
+ - libelles utilisateur propres a la marque ;
49
+ - choix de `desktopApiGlobal`, prefixe API key, nom produit ;
50
+ - wiring client dans un fichier boot.
51
+
52
+ ### Hors scope a ne pas reabsorber
53
+
54
+ | Domaine | Package SoT |
55
+ |---|---|
56
+ | Login, session UI | `@creezio/auth/ui` |
57
+ | Setup / onboarding | `@creezio/onboarding/ui` |
58
+ | Cockpit serveur | `@creezio/cockpit/ui` |
59
+ | Splash desktop | `@creezio/electron-shell` |
60
+ | Tasks AI panel | `@creezio/tasks/ui`, injecte via `configureAiActivityPanel` |
61
+ | Auth store/session | `@creezio/auth` |
62
+
63
+ Conclusion de l'audit : "NATIF shell" est une classification plateforme, pas une obligation de tout mettre dans un seul package. `shell-ui` garde nav + slots + chrome CRM mince ; onboarding/cockpit/splash/auth restent separes.
64
+
65
+ ## Installation / build
66
+
67
+ ```bash
68
+ npm install
69
+ npm run build -w @creezio/shell-ui
70
+ npm run typecheck -w @creezio/shell-ui
71
+ ```
72
+
73
+ Artefacts :
74
+
75
+ - ESM : `dist/`
76
+ - CJS Electron : `dist-cjs/`
77
+ - UI source : `ui/`
78
+
79
+ Dependances directes : `@creezio/brand-config`, `@creezio/shell`, `clsx`, `tailwind-merge`. Les dependances React/Radix/Next/Recharts/cmdk/lucide/sonner sont peer dependencies optionnelles car elles concernent `./ui`.
80
+
81
+ ## Configuration
82
+
83
+ ### Brand tokens
84
+
85
+ ```ts
86
+ import { configureShellUiBrand } from "@creezio/shell-ui";
87
+
88
+ configureShellUiBrand({
89
+ desktopApiGlobal: "mybrandDesktop",
90
+ publicHostSuffix: "mybrand.example",
91
+ titlebarDragClass: "mybrand-titlebar-drag",
92
+ titlebarNoDragClass: "mybrand-titlebar-no-drag",
93
+ apiKeyPrefix: "mybrand_live_",
94
+ productName: "Ma Marque",
95
+ aidAttr: "data-creezio-aid",
96
+ });
97
+ ```
98
+
99
+ `getShellDesktopApi()` lit `window[desktopApiGlobal]` de maniere souple et retourne `undefined` cote serveur.
100
+
101
+ #### Page login (`login`)
102
+
103
+ Le panneau brand de la page login split-screen (`LoginPage` de
104
+ `@creezio/auth/ui`) se configure via la clé `login` — tout est optionnel,
105
+ le défaut est neutre (gradient encre du thème kit, tuile initiale du nom
106
+ produit, aucun texte marketing) :
107
+
108
+ ```ts
109
+ configureShellUiBrand({
110
+ productName: "Ma Marque",
111
+ // …
112
+ login: {
113
+ tagline: "La tagline produit affichée dans le panneau.",
114
+ highlights: ["Argument un", "Argument deux", "Argument trois"],
115
+ logoUrl: "/logo.svg", // défaut : initiale du produit
116
+ panelBackground: "linear-gradient(165deg, #15112e, #221d4d)",
117
+ panelImageUrl: "/login-visual.jpg", // optionnel, voilé sombre
118
+ panelSide: "right", // ou "left"
119
+ },
120
+ });
121
+ ```
122
+
123
+ En pratique la marque passe cet objet à `CreezioUiBoot` (prop `login`,
124
+ `@creezio/os-ui/boot`) plutôt que d'appeler `configureShellUiBrand`
125
+ elle-même. Les composants qui lisent la brand au render utilisent le hook
126
+ `useShellUiBrand` (`@creezio/shell-ui/ui[/kit]`) : la marque est appliquée
127
+ au render par `CreezioUiBoot` et le hook re-render si elle change.
128
+
129
+ ### Boot client marque typique
130
+
131
+ Un seul fichier de wiring est attendu cote marque, par exemple `crm/src/lib/shell-ui/configure-shell-ui-client.ts`.
132
+
133
+ ```ts
134
+ import {
135
+ configureDefaultNewTabHref,
136
+ configureGlobalSearch,
137
+ configureSidebar,
138
+ configureShellUiBrand,
139
+ } from "@creezio/shell-ui/ui";
140
+
141
+ configureShellUiBrand({
142
+ productName: "Ma Marque",
143
+ desktopApiGlobal: "mybrandDesktop",
144
+ apiKeyPrefix: "mybrand_live_",
145
+ });
146
+
147
+ configureSidebar({
148
+ getNavItems: () => brandNavItems,
149
+ getAdminItems: () => brandAdminItems,
150
+ canShowHref: (href, me) => canAccessHref(href, me),
151
+ resolveForcedActiveHref: (pathname, search) =>
152
+ resolveForcedActiveHref(pathname, search),
153
+ });
154
+
155
+ configureGlobalSearch({
156
+ placeholder: "Rechercher...",
157
+ indexLabels: { products: "Produits", clients: "Clients" },
158
+ search: (query, signal) => searchBrandIndexes(query, signal),
159
+ });
160
+
161
+ configureDefaultNewTabHref("/dashboard");
162
+ ```
163
+
164
+ ### Nav slots bas niveau
165
+
166
+ La marque enregistre seulement ses items ; le kit ne connait pas les ids metier.
167
+
168
+ ```ts
169
+ import { createNavShellAdapter } from "@creezio/shell-ui";
170
+
171
+ const shell = createNavShellAdapter();
172
+ shell.registerBrandNav(
173
+ [{ id: "brand.notes", label: "Notes", href: "/notes", group: "brand" }],
174
+ "brand-primary",
175
+ );
176
+ shell.registerBrandNav(
177
+ [{ id: "brand.plugin-x", label: "Plugin X", href: "/plugins/x", group: "plugin" }],
178
+ "plugins",
179
+ );
180
+
181
+ const model = shell.getRenderModel();
182
+ ```
183
+
184
+ Slots disponibles :
185
+
186
+ | Slot | Usage |
187
+ |---|---|
188
+ | `brand-primary` | navigation metier principale |
189
+ | `brand-secondary` | liens secondaires metier |
190
+ | `plugins` | items issus de plugins Product Hub ou equivalents |
191
+
192
+ Le render model groupe les items par `core`, `brand`, `plugin`.
193
+
194
+ ## API publique (exports + exemples)
195
+
196
+ ### Package root `@creezio/shell-ui`
197
+
198
+ Exports nav :
199
+
200
+ - types `CoreNavItem`, `NavItem`, `NavSlot`, `NavSlotId`
201
+ - `CORE_NAV_ITEMS`, `coreNavItems`
202
+ - `createNavRegistry`, `mergeNav`
203
+ - `createNavShellAdapter`
204
+
205
+ Exports brand :
206
+
207
+ - `configureShellUiBrand`, `getShellUiBrand`, `getShellDesktopApi`, `resetShellUiBrandForTests`, `subscribeShellUiBrand` (+ hook `useShellUiBrand` côté `./ui`)
208
+
209
+ Exports helpers :
210
+
211
+ - scopes API : `API_SCOPE_FULL`, `API_SCOPE_CRM_READ`, `API_SCOPE_CRM_WRITE`, `API_SCOPE_TASKS_RUN`, `normalizeApiScopes`, `parseApiKeyScopes`, `apiKeyAllowsMethod`, `apiKeyAllowsTasks`, `scopesFromPluginPermissions`
212
+ - utils : `cn`, `formatDate`, `formatDateTime`, `formatMoney`, `parsePage`, `formatVariationPct`, `formatDeltaMoney`, `variationTone`
213
+ - origin/cookie : `resolvePublicOrigin`, `resolveCookieSecure`, `isLoopbackHost`
214
+ - ops : `trackServer`, `trackServerDebounced`, `reportServerIncident`
215
+ - UI helpers purs : `haversineKm`, `thumbUrl`, `optimizeCoverUrl`, `buildCatalogSuspenseKey`, `normalizeTabDocumentUrl`, `isSameTabDocument`, `isSameTabOrigin`
216
+ - desktop home/keepalive : `CRM_HOME_PATH`, `SERVER_COCKPIT_PATH`, `resolveDesktopHomePath`, `rankKeepAliveEvictionKeys`
217
+
218
+ ```ts
219
+ import {
220
+ apiKeyAllowsMethod,
221
+ createNavShellAdapter,
222
+ resolveCookieSecure,
223
+ } from "@creezio/shell-ui";
224
+
225
+ const canWrite = apiKeyAllowsMethod("crm:write", "POST");
226
+ const secure = resolveCookieSecure(headers, {
227
+ appPublicUrl: process.env.APP_PUBLIC_URL,
228
+ });
229
+ ```
230
+
231
+ ### UI `@creezio/shell-ui/ui`
232
+
233
+ Exports majeurs :
234
+
235
+ - brand/hosts : `configureShellUiBrand`, `configureTabWorkspaceHost`, `configureGlobalSearchHost`, `configureAiActivityPanel`
236
+ - primitives : `Button`, `Badge`, `Input`, `Card`, `Tabs`, `Dialog`, `Sheet`, `DropdownMenu`, `Command`, `Toaster`, `ChartContainer`, etc.
237
+ - layout : `AppShell`, `PageChrome`, `PageToolbarProvider`, `SectionViewShell`, `EntityHeader`, `Sidebar`, `CrmSidebar`, `configureSidebar`
238
+ - workspace : `TabWorkspaceProvider`, `WorkspaceShell`, `WorkspaceRoot`, `WorkspaceTabBar`, `KeepAliveOutlet`, `ImpersonationBanner`, `createTab`, `createExternalSiteTab`
239
+ - search : `configureGlobalSearch`, `GlobalSearchProvider`, `GlobalSearchTrigger`, `SearchInput`, `search-history`
240
+ - desktop : `ExternalSiteSlot`, `DesktopBridge`, `AuthWindowChrome`, `WindowChromeControls`, `SiteLink`
241
+ - settings : `DesktopHermesSettings`, `DesktopN8nSettings`, `DesktopTunnel`, `ApiKeysSettings`, `AccountSettings`, etc.
242
+
243
+ ```tsx
244
+ import {
245
+ GlobalSearchProvider,
246
+ Sidebar,
247
+ TabWorkspaceProvider,
248
+ WorkspaceRoot,
249
+ } from "@creezio/shell-ui/ui";
250
+
251
+ export function AppChrome({ children }) {
252
+ return (
253
+ <TabWorkspaceProvider>
254
+ <GlobalSearchProvider>
255
+ <WorkspaceRoot sidebar={<Sidebar />}>{children}</WorkspaceRoot>
256
+ </GlobalSearchProvider>
257
+ </TabWorkspaceProvider>
258
+ );
259
+ }
260
+ ```
261
+
262
+ ### Sites externes : noms neutres vs alias legacy
263
+
264
+ La terminologie kit est neutre :
265
+
266
+ | SoT kit | Alias deprecie TF |
267
+ |---|---|
268
+ | `OpenExternalSiteOpts`, `openExternalSite`, `siteId` | `OpenSupplierSiteOpts`, `openSupplierSite`, `fournisseurId` |
269
+ | `ExternalSiteSlot`, `ExternalSiteTabMeta`, `createExternalSiteTab` | `SupplierSiteSlot`, `SupplierTabMeta`, `createSupplierTab` |
270
+ | `siteIdFromHref`, `isExternalSiteHref` | `fournisseurIdFromHref`, `isSupplierHref` |
271
+
272
+ Ne pas ajouter de nouveau libelle utilisateur "fournisseur" dans le kit. Les alias restent supportes pour compat, mais les nouveaux appels doivent utiliser les noms `ExternalSite`. Regle de fond : [ADR-no-brand-domain-in-native-packages](../../docs/adr/ADR-no-brand-domain-in-native-packages.md) (gate `test-phase-p29`).
273
+
274
+ ## Flux / fonctionnement
275
+
276
+ ### Nav slots
277
+
278
+ 1. `CORE_NAV_ITEMS` fournit les items Creezio de base.
279
+ 2. La marque appelle `registerBrandNav(items, slot)`.
280
+ 3. `mergeNav` combine core + marque.
281
+ 4. `getRenderModel()` classe les items en groupes `core`, `brand`, `plugin`.
282
+ 5. L'UI React ou un rendu HTML minimal consomme le render model.
283
+
284
+ ### Chrome CRM
285
+
286
+ 1. La marque configure `ShellUiBrand`, `SidebarHost`, `GlobalSearchConfig` et defaults workspace.
287
+ 2. `Sidebar` lit `getSidebarHost()` et applique ACL/active href.
288
+ 3. `TabWorkspaceProvider` gere onglets, historique, keep-alive, liens externes et verrouillages.
289
+ 4. `WorkspaceShell` / `WorkspaceRoot` composent sidebar, tab bar, footbar, banners et children metier.
290
+ 5. `GlobalSearchProvider` appelle la fonction `search` injectee par la marque et ouvre les resultats via workspace.
291
+ 6. `ExternalSiteSlot` coordonne les etats de chargement webview/site externe avec le desktop.
292
+
293
+ ### Settings et libs client
294
+
295
+ Les settings desktop sont dans `shell-ui/ui/settings` pour eviter les jumeaux TF/CV/Fidu a court terme. Si ce domaine grossit, une extraction future vers `@creezio/desktop-settings` est envisagee, mais elle n'est pas le SoT actuel.
296
+
297
+ ## Intégration marques
298
+
299
+ Checklist :
300
+
301
+ 1. Appeler `configureShellUiBrand`.
302
+ 2. Configurer `configureSidebar` avec nav items, admin items, ACL, render plugins/tools si besoin.
303
+ 3. Configurer `configureGlobalSearch`.
304
+ 4. Configurer workspace : `configureDefaultNewTabHref`, `configureSidebarCollapsedKey`, `configureProductDetailCtx` si necessaire.
305
+ 5. Remplacer les composants locaux par les imports `@creezio/shell-ui/ui`.
306
+ 6. Garder un `WorkspaceRoot` local uniquement s'il compose des providers/banners metier minces.
307
+ 7. Migrer les surfaces "supplier" vers "external site" pour les nouveaux usages.
308
+ 8. Ne pas remettre onboarding/cockpit/auth/splash dans ce package.
309
+
310
+ Doublons historiques côté marque (à ne pas recréer — remplacés par le kit) :
311
+
312
+ - `src/components/layout/sidebar.tsx`
313
+ - `src/components/workspace/tab-workspace-context.tsx`
314
+ - `src/components/workspace/workspace-shell.tsx`
315
+ - `src/components/global-search-provider.tsx`
316
+ - `src/components/desktop/supplier-site-slot.tsx`
317
+
318
+ ## Dépendances @creezio/*
319
+
320
+ | Dependance | Rôle |
321
+ |---|---|
322
+ | `@creezio/brand-config` | contexte marque et convergence config |
323
+ | `@creezio/shell` | types desktop, IPC/bridge et shell runtime |
324
+
325
+ Peer optional / interactions :
326
+
327
+ - `@creezio/auth` : `SessionProvider`, `LoginForm`; shell-ui ne possede pas l'auth.
328
+ - `@creezio/assistant` : surfaces AI optionnelles.
329
+ - `@creezio/tasks` : panel AI tasks injecte via `configureAiActivityPanel`.
330
+ - `@creezio/onboarding`, `@creezio/cockpit`, `@creezio/electron-shell` : packages dedies, hors shell-ui.
331
+
332
+ ## Voir aussi → AGENTS.md + docs/FILES.md
333
+
334
+ - [`AGENTS.md`](./AGENTS.md) : consignes de modification pour agents.
335
+ - [`docs/FILES.md`](./docs/FILES.md) : inventaire fichier par fichier.
336
+ - [`../../docs/archive/AUDIT-SHELL-UI-SCOPE.md`](../../docs/archive/AUDIT-SHELL-UI-SCOPE.md) : arbitrage nav slots vs chrome CRM et frontieres avec onboarding/cockpit/splash/auth.
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Adapter nav shell (Phase I7) — contrat de rendu UI-agnostique.
3
+ *
4
+ * Marque = `registerBrandNav` uniquement ; pas de hardcode panier/dispatch
5
+ * dans le kit. React/Next consomme `getRenderModel()` / `subscribe`.
6
+ */
7
+ import { type NavRegistry } from "../registry.js";
8
+ import type { CoreNavItem, NavSlotId } from "../types.js";
9
+ export type NavRenderItem = CoreNavItem & {
10
+ source: "core" | "brand" | "plugin";
11
+ active?: boolean;
12
+ };
13
+ export type NavRenderGroup = {
14
+ id: "core" | "brand" | "plugin";
15
+ label: string;
16
+ items: NavRenderItem[];
17
+ };
18
+ export type NavRenderModel = {
19
+ items: NavRenderItem[];
20
+ groups: NavRenderGroup[];
21
+ activeHref: string | null;
22
+ generatedAt: string;
23
+ };
24
+ export type NavShellAdapter = {
25
+ /** Registre sous-jacent (tests / advanced). */
26
+ readonly registry: NavRegistry;
27
+ /** Seule API marque recommandée. */
28
+ registerBrandNav(items: CoreNavItem[], slot?: NavSlotId): void;
29
+ clearBrandNav(slot?: NavSlotId): void;
30
+ setActiveHref(href: string | null): void;
31
+ getMergedNav(): CoreNavItem[];
32
+ getRenderModel(): NavRenderModel;
33
+ subscribe(listener: () => void): () => void;
34
+ /** HTML minimal (preuve demobrand / SSR sans React). */
35
+ renderNavHtml(opts?: {
36
+ className?: string;
37
+ }): string;
38
+ };
39
+ export type CreateNavShellAdapterOptions = {
40
+ coreItems?: readonly CoreNavItem[];
41
+ registry?: NavRegistry;
42
+ activeHref?: string | null;
43
+ };
44
+ /**
45
+ * Crée l'adapter shell. Usage marque :
46
+ *
47
+ * ```ts
48
+ * const shell = createNavShellAdapter();
49
+ * shell.registerBrandNav([{ id: "brand.home", label: "Métier", href: "/brand" }]);
50
+ * const model = shell.getRenderModel(); // → UI React / HTML
51
+ * ```
52
+ */
53
+ export declare function createNavShellAdapter(opts?: CreateNavShellAdapterOptions): NavShellAdapter;
54
+ //# sourceMappingURL=nav-shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav-shell.d.ts","sourceRoot":"","sources":["../../src/adapters/nav-shell.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAA+B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACxC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,oCAAoC;IACpC,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC/D,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACzC,YAAY,IAAI,WAAW,EAAE,CAAC;IAC9B,cAAc,IAAI,cAAc,CAAC;IACjC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,wDAAwD;IACxD,aAAa,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CACtD,CAAC;AAcF,MAAM,MAAM,4BAA4B,GAAG;IACzC,SAAS,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,4BAA4B,GAClC,eAAe,CAwFjB"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Adapter nav shell (Phase I7) — contrat de rendu UI-agnostique.
3
+ *
4
+ * Marque = `registerBrandNav` uniquement ; pas de hardcode panier/dispatch
5
+ * dans le kit. React/Next consomme `getRenderModel()` / `subscribe`.
6
+ */
7
+ import { CORE_NAV_ITEMS } from "../core-nav.js";
8
+ import { createNavRegistry, mergeNav } from "../registry.js";
9
+ const GROUP_LABELS = {
10
+ core: "Creezio",
11
+ brand: "Métier",
12
+ plugin: "Plugins",
13
+ };
14
+ function sourceOf(item) {
15
+ if (item.group === "plugin")
16
+ return "plugin";
17
+ if (item.group === "brand" || item.id.startsWith("brand."))
18
+ return "brand";
19
+ return "core";
20
+ }
21
+ /**
22
+ * Crée l'adapter shell. Usage marque :
23
+ *
24
+ * ```ts
25
+ * const shell = createNavShellAdapter();
26
+ * shell.registerBrandNav([{ id: "brand.home", label: "Métier", href: "/brand" }]);
27
+ * const model = shell.getRenderModel(); // → UI React / HTML
28
+ * ```
29
+ */
30
+ export function createNavShellAdapter(opts) {
31
+ const core = opts?.coreItems || CORE_NAV_ITEMS;
32
+ const registry = opts?.registry || createNavRegistry();
33
+ let activeHref = opts?.activeHref ?? null;
34
+ const listeners = new Set();
35
+ function notify() {
36
+ for (const l of listeners)
37
+ l();
38
+ }
39
+ const adapter = {
40
+ registry,
41
+ registerBrandNav(items, slot) {
42
+ registry.registerBrandNav(items, slot);
43
+ notify();
44
+ },
45
+ clearBrandNav(slot) {
46
+ registry.clearBrandNav(slot);
47
+ notify();
48
+ },
49
+ setActiveHref(href) {
50
+ activeHref = href;
51
+ notify();
52
+ },
53
+ getMergedNav() {
54
+ const brand = [
55
+ ...registry.getBrandNav("brand-primary"),
56
+ ...registry.getBrandNav("brand-secondary"),
57
+ ...registry.getBrandNav("plugins"),
58
+ ];
59
+ return mergeNav(core, brand);
60
+ },
61
+ getRenderModel() {
62
+ const items = adapter.getMergedNav().map((i) => ({
63
+ ...i,
64
+ source: sourceOf(i),
65
+ active: Boolean(activeHref && i.href === activeHref),
66
+ }));
67
+ const groups = ["core", "brand", "plugin"].map((id) => ({
68
+ id,
69
+ label: GROUP_LABELS[id],
70
+ items: items.filter((i) => i.source === id),
71
+ }));
72
+ return {
73
+ items,
74
+ groups,
75
+ activeHref,
76
+ generatedAt: new Date().toISOString(),
77
+ };
78
+ },
79
+ subscribe(listener) {
80
+ listeners.add(listener);
81
+ return () => listeners.delete(listener);
82
+ },
83
+ renderNavHtml(htmlOpts) {
84
+ const model = adapter.getRenderModel();
85
+ const cls = htmlOpts?.className || "creezio-nav";
86
+ const parts = [`<nav class="${cls}" data-creezio-shell-ui="i7">`];
87
+ for (const g of model.groups) {
88
+ if (!g.items.length)
89
+ continue;
90
+ parts.push(`<div class="${cls}__group" data-group="${g.id}">`);
91
+ parts.push(`<div class="${cls}__group-label">${escapeHtml(g.label)}</div>`);
92
+ parts.push(`<ul>`);
93
+ for (const item of g.items) {
94
+ const active = item.active ? ' aria-current="page"' : "";
95
+ parts.push(`<li data-source="${item.source}"><a href="${escapeHtml(item.href)}"${active}>${escapeHtml(item.label)}</a></li>`);
96
+ }
97
+ parts.push(`</ul></div>`);
98
+ }
99
+ parts.push(`</nav>`);
100
+ return parts.join("");
101
+ },
102
+ };
103
+ return adapter;
104
+ }
105
+ function escapeHtml(s) {
106
+ return s
107
+ .replace(/&/g, "&amp;")
108
+ .replace(/</g, "&lt;")
109
+ .replace(/>/g, "&gt;")
110
+ .replace(/"/g, "&quot;");
111
+ }
112
+ //# sourceMappingURL=nav-shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav-shell.js","sourceRoot":"","sources":["../../src/adapters/nav-shell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * O9 — tokens marque pour shell-ui (desktop API, hosts, titlebar).
3
+ */
4
+ /**
5
+ * Panneau brand de la page login split-screen (@creezio/auth LoginPage).
6
+ * Tout est optionnel : une marque sans config obtient le défaut neutre
7
+ * (gradient encre du thème kit, tuile initiale, sans tagline ni highlights).
8
+ */
9
+ export type ShellUiLoginBrand = {
10
+ /** Tagline sous le nom produit dans le panneau (défaut : aucune). */
11
+ tagline?: string;
12
+ /** Points marketing en liste à puces (défaut : aucun — 3 ou 4 recommandés). */
13
+ highlights?: string[];
14
+ /** URL d'un logo image (défaut : tuile avec l'initiale du produit). */
15
+ logoUrl?: string;
16
+ /**
17
+ * Fond du panneau — valeur CSS `background` complète (couleur ou gradient).
18
+ * Défaut : gradient encre neutre du thème kit.
19
+ */
20
+ panelBackground?: string;
21
+ /** Image de fond du panneau (sous un voile sombre, par-dessus le fond). */
22
+ panelImageUrl?: string;
23
+ /** Côté du panneau sur desktop (défaut "right"). */
24
+ panelSide?: "left" | "right";
25
+ /**
26
+ * Lien d'action secondaire sous le formulaire de connexion (ex.
27
+ * inscription POS de la marque : { label: "Créer un compte", href:
28
+ * "/inscription" }). Absent = aucun lien affiché — jamais de défaut kit.
29
+ */
30
+ secondaryLink?: {
31
+ label: string;
32
+ href: string;
33
+ };
34
+ };
35
+ export type ShellUiBrand = {
36
+ /** Ex. creezioDesktop / certivanDesktop / fiduDesktop */
37
+ desktopApiGlobal: string;
38
+ /** Suffixe hôte public (ex. app.example.com / tenant.creez.io) */
39
+ publicHostSuffix: string;
40
+ /** Classe CSS titlebar no-drag */
41
+ titlebarDragClass: string;
42
+ titlebarNoDragClass: string;
43
+ /** Préfixe clés API live (ex. product_live_) */
44
+ apiKeyPrefix: string;
45
+ /** Nom produit UI — injecté par la marque */
46
+ productName: string;
47
+ /** Attribut data-* analytics clics (défaut data-creezio-aid). */
48
+ aidAttr?: string;
49
+ /** Config page login split-screen (défauts neutres si absente). */
50
+ login?: ShellUiLoginBrand;
51
+ };
52
+ export declare function configureShellUiBrand(next: Partial<ShellUiBrand>): void;
53
+ export declare function getShellUiBrand(): ShellUiBrand;
54
+ /**
55
+ * Abonnement aux changements de brand — la marque est appliquée par
56
+ * CreezioUiBoot en useEffect (après le 1er render) : les composants qui
57
+ * lisent la brand au render (page login…) doivent passer par le hook
58
+ * useShellUiBrand (@creezio/shell-ui/ui/kit) pour re-render.
59
+ */
60
+ export declare function subscribeShellUiBrand(listener: () => void): () => void;
61
+ export declare function resetShellUiBrandForTests(): void;
62
+ /** Accès typé soft à window[desktopApiGlobal]. */
63
+ export declare function getShellDesktopApi(): any;
64
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B;;;;OAIG;IACH,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,CAAC;IACzB,kCAAkC;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAoBF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAcvE;AAED,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAKtE;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,IAAI,GAAG,CAIxC"}
package/dist/brand.js ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * O9 — tokens marque pour shell-ui (desktop API, hosts, titlebar).
3
+ */
4
+ const DEFAULT = {
5
+ desktopApiGlobal: "creezioDesktop",
6
+ publicHostSuffix: "creez.io",
7
+ titlebarDragClass: "creezio-titlebar-drag",
8
+ titlebarNoDragClass: "creezio-titlebar-no-drag",
9
+ apiKeyPrefix: "creezio_live_",
10
+ productName: "Creezio",
11
+ aidAttr: "data-creezio-aid",
12
+ };
13
+ let brand = { ...DEFAULT };
14
+ const listeners = new Set();
15
+ function notifyBrandChanged() {
16
+ for (const listener of listeners)
17
+ listener();
18
+ }
19
+ export function configureShellUiBrand(next) {
20
+ const merged = { ...brand, ...next };
21
+ // No-op si aucune clé ne change — CreezioUiBoot appelle au render (marque
22
+ // correcte dès le 1er paint, zéro flash du défaut) : la détection évite
23
+ // les boucles de re-render des abonnés useSyncExternalStore. `login` est
24
+ // comparé en profondeur (objet littéral → nouvelle identité à chaque render).
25
+ const changed = Object.keys(merged).some((k) => k === "login"
26
+ ? JSON.stringify(merged.login ?? null) !== JSON.stringify(brand.login ?? null)
27
+ : merged[k] !== brand[k]);
28
+ if (!changed)
29
+ return;
30
+ brand = merged;
31
+ notifyBrandChanged();
32
+ }
33
+ export function getShellUiBrand() {
34
+ return brand;
35
+ }
36
+ /**
37
+ * Abonnement aux changements de brand — la marque est appliquée par
38
+ * CreezioUiBoot en useEffect (après le 1er render) : les composants qui
39
+ * lisent la brand au render (page login…) doivent passer par le hook
40
+ * useShellUiBrand (@creezio/shell-ui/ui/kit) pour re-render.
41
+ */
42
+ export function subscribeShellUiBrand(listener) {
43
+ listeners.add(listener);
44
+ return () => {
45
+ listeners.delete(listener);
46
+ };
47
+ }
48
+ export function resetShellUiBrandForTests() {
49
+ brand = { ...DEFAULT };
50
+ notifyBrandChanged();
51
+ }
52
+ /** Accès typé soft à window[desktopApiGlobal]. */
53
+ export function getShellDesktopApi() {
54
+ if (typeof window === "undefined")
55
+ return undefined;
56
+ const key = getShellUiBrand().desktopApiGlobal;
57
+ return window[key];
58
+ }
59
+ //# sourceMappingURL=brand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.js","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiDH,MAAM,OAAO,GAAiB;IAC5B,gBAAgB,EAAE,gBAAgB;IAClC,gBAAgB,EAAE,UAAU;IAC5B,iBAAiB,EAAE,uBAAuB;IAC1C,mBAAmB,EAAE,0BAA0B;IAC/C,YAAY,EAAE,eAAe;IAC7B,WAAW,EAAE,SAAS;IACtB,OAAO,EAAE,kBAAkB;CAC5B,CAAC;AAEF,IAAI,KAAK,GAAiB,EAAE,GAAG,OAAO,EAAE,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;AAExC,SAAS,kBAAkB;IACzB,KAAK,MAAM,QAAQ,IAAI,SAAS;QAAE,QAAQ,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAA2B;IAC/D,MAAM,MAAM,GAAiB,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IACnD,0EAA0E;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,8EAA8E;IAC9E,MAAM,OAAO,GAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAA4B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACzE,CAAC,KAAK,OAAO;QACX,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC;QAC9E,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAC3B,CAAC;IACF,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,KAAK,GAAG,MAAM,CAAC;IACf,kBAAkB,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAoB;IACxD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,KAAK,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;IACvB,kBAAkB,EAAE,CAAC;AACvB,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACpD,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC,gBAAgB,CAAC;IAC/C,OAAQ,MAAc,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { CoreNavItem } from "./types.js";
2
+ /**
3
+ * Entrées nav natives Creezio — aucune entrée métier marque
4
+ * (panier, dispatch, GED, RTI…).
5
+ *
6
+ * Liste historique (home / assistant / setup / login / about…) consommée
7
+ * par `createNavShellAdapter` — **pas** la sidebar CRM. La sidebar OS
8
+ * primaire (taches, mails, granola, grokbot…) vit dans le catalogue
9
+ * `defaultOsCatalogEntries()` / `registerOsNavEntry`
10
+ * (`nav-catalog.ts`, plan `docs/plans/PLAN-NAV-CATALOG.md`). Ne pas
11
+ * recopier granola/grokbot ici pour « aligner » : Phase D dérivera
12
+ * `CORE_NAV_ITEMS` du catalogue, ou documentera l'écart à vie.
13
+ */
14
+ export declare const CORE_NAV_ITEMS: readonly CoreNavItem[];
15
+ /** Alias factory / demobrand. */
16
+ export declare const coreNavItems: CoreNavItem[];
17
+ //# sourceMappingURL=core-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-nav.d.ts","sourceRoot":"","sources":["../src/core-nav.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,WAAW,EAsBvC,CAAC;AAEX,iCAAiC;AACjC,eAAO,MAAM,YAAY,EAAE,WAAW,EAEnC,CAAC"}