@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
@@ -0,0 +1,105 @@
1
+ "use client";
2
+
3
+ import { getShellDesktopApi, getShellUiBrand } from "@creezio/shell-ui";
4
+
5
+ /**
6
+ * Lien vers un **site externe** (outil, portail, marketplace… — le métier
7
+ * est décidé par la marque via libellés UI, pas par ce composant).
8
+ *
9
+ * - App desktop (Electron) : ouvre un onglet workspace puis WebContentsView.
10
+ * - Navigateur web : lien target=_blank.
11
+ */
12
+
13
+ import { useCallback, type MouseEvent, type ReactNode } from "react";
14
+ import {
15
+ openExternalSiteFromWorkspace,
16
+ useTabWorkspaceOptional,
17
+ } from "../workspace/tab-workspace-host";
18
+
19
+ const DEFAULT_EXTERNAL_SITE_TITLE = "Site externe";
20
+
21
+ export function SiteLink({
22
+ url,
23
+ siteId = 0,
24
+ /** @deprecated → `siteId` */
25
+ fournisseurId,
26
+ className,
27
+ title,
28
+ children,
29
+ "data-creezio-aid": aid,
30
+ /** @deprecated attribut TF — utiliser data-creezio-aid ou brand.aidAttr */
31
+ "data-tf2-aid": aidLegacy,
32
+ }: {
33
+ url: string;
34
+ /** Id de partition persistante. 0 = onglet générique (hash host). */
35
+ siteId?: number;
36
+ /** @deprecated → `siteId` */
37
+ fournisseurId?: number;
38
+ className?: string;
39
+ title?: string;
40
+ children: ReactNode;
41
+ "data-creezio-aid"?: string;
42
+ "data-tf2-aid"?: string;
43
+ }) {
44
+ const workspace = useTabWorkspaceOptional();
45
+ const resolvedSiteId = siteId || fournisseurId || 0;
46
+ const aidAttr = getShellUiBrand().aidAttr ?? "data-creezio-aid";
47
+ const aidValue = aid ?? aidLegacy;
48
+
49
+ const onClick = useCallback(
50
+ (e: MouseEvent<HTMLAnchorElement>) => {
51
+ const api = getShellDesktopApi();
52
+ if (!api) return;
53
+ e.preventDefault();
54
+
55
+ let tabTitle = (title || "").trim();
56
+ if (!tabTitle) {
57
+ try {
58
+ tabTitle = new URL(url).hostname.replace(/^www\./, "");
59
+ } catch {
60
+ tabTitle = DEFAULT_EXTERNAL_SITE_TITLE;
61
+ }
62
+ }
63
+
64
+ if (workspace?.openExternalSite || workspace?.openSupplierSite) {
65
+ openExternalSiteFromWorkspace(workspace, {
66
+ siteId: resolvedSiteId,
67
+ url,
68
+ title: tabTitle,
69
+ navigateUrl: true,
70
+ });
71
+ return;
72
+ }
73
+
74
+ api
75
+ .openTab(resolvedSiteId, url)
76
+ .then((res: { siteId?: number; fournisseurId?: number }) => {
77
+ const id = res.siteId ?? res.fournisseurId ?? resolvedSiteId;
78
+ window.location.assign(`/site/${id}`);
79
+ })
80
+ .catch(() => {
81
+ window.open(url, "_blank", "noreferrer");
82
+ });
83
+ },
84
+ [url, resolvedSiteId, title, workspace],
85
+ );
86
+
87
+ const extraAid =
88
+ aidValue != null
89
+ ? ({ [aidAttr]: aidValue } as Record<string, string>)
90
+ : undefined;
91
+
92
+ return (
93
+ <a
94
+ href={url}
95
+ target="_blank"
96
+ rel="noreferrer"
97
+ className={className}
98
+ title={title}
99
+ onClick={onClick}
100
+ {...extraAid}
101
+ >
102
+ {children}
103
+ </a>
104
+ );
105
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Re-export — source : `src/components/workspace/window-chrome-controls.tsx`.
3
+ * Conservé aussi sous `desktop/` pour le chemin checklist du port shell.
4
+ */
5
+ export { WindowChromeControls } from "../workspace/window-chrome-controls";
@@ -0,0 +1,30 @@
1
+ /** Types bridge desktop (SoT @creezio/shell) — re-export UI pour cutover O9p. */
2
+ export type {
3
+ DesktopContentRect,
4
+ DesktopTabLoadState,
5
+ DesktopTabInfo,
6
+ } from "@creezio/shell";
7
+
8
+ /** Types update desktop plateforme (O9) — extrait gold TF. */
9
+
10
+ export type DesktopUpdateState =
11
+ | "disabled"
12
+ | "idle"
13
+ | "checking"
14
+ | "available"
15
+ | "not-available"
16
+ | "downloading"
17
+ | "ready"
18
+ | "error";
19
+
20
+ export type DesktopUpdateStatus = {
21
+ state: DesktopUpdateState | string;
22
+ currentVersion: string;
23
+ availableVersion?: string;
24
+ percent?: number;
25
+ bytesPerSecond?: number;
26
+ transferred?: number;
27
+ total?: number;
28
+ error?: string;
29
+ updateAvailable: boolean;
30
+ };
@@ -0,0 +1,119 @@
1
+ "use client";
2
+
3
+ import { useTransition } from "react";
4
+ import { useSearchParams, usePathname, useRouter } from "next/navigation";
5
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./primitives/select";
6
+ import { SearchInput } from "./search-input";
7
+ import { aidProps } from "./lib/aid";
8
+
9
+ export type FacetOption = { value: string; c: number; label?: string };
10
+
11
+ export type FacetDef = {
12
+ key: string;
13
+ label: string;
14
+ options: FacetOption[];
15
+ allLabel?: string;
16
+ /** Valeur affichée si le param URL est absent (ex. period → exercice). */
17
+ defaultValue?: string;
18
+ /** Pas de ligne « Tous » — utile quand les options couvrent déjà le reset (ex. period=all). */
19
+ hideAllOption?: boolean;
20
+ };
21
+
22
+ export function FacetedFilters({
23
+ facets,
24
+ searchKey = "q",
25
+ searchPlaceholder = "Rechercher…",
26
+ showSearchSubmit = false,
27
+ showSearch = true,
28
+ skipRefresh = false,
29
+ }: {
30
+ facets: FacetDef[];
31
+ searchKey?: string;
32
+ searchPlaceholder?: string;
33
+ /** Bouton « Filtrer » (inutile avec le debounce par défaut). */
34
+ showSearchSubmit?: boolean;
35
+ /** Masquer la recherche (ex. synthèse : exercice + période seulement). */
36
+ showSearch?: boolean;
37
+ /** Mode filtre client — pas de `router.refresh()` (voir UI-PATTERNS §4). */
38
+ skipRefresh?: boolean;
39
+ }) {
40
+ const router = useRouter();
41
+ const pathname = usePathname();
42
+ const params = useSearchParams();
43
+ const [, startTransition] = useTransition();
44
+
45
+ function update(
46
+ key: string,
47
+ value: string,
48
+ opts?: { defaultValue?: string; allIsOption?: boolean },
49
+ ) {
50
+ const next = new URLSearchParams(params.toString());
51
+ const isDefault = Boolean(opts?.defaultValue && value === opts.defaultValue);
52
+ const isClearAll = value === "all" && !opts?.allIsOption;
53
+ if (!value || isDefault || isClearAll) next.delete(key);
54
+ else next.set(key, value);
55
+ next.delete("page");
56
+ // Un changement de facette invalide le preset affiché
57
+ next.delete("preset");
58
+ // Période rapide et plage custom sont exclusives
59
+ if (key === "period") {
60
+ next.delete("dateFrom");
61
+ next.delete("dateTo");
62
+ }
63
+ // Changer de famille invalide la catégorie feuille
64
+ if (key === "famille") next.delete("categorie");
65
+ const qs = next.toString();
66
+ const href = qs ? `${pathname}?${qs}` : pathname;
67
+ startTransition(() => {
68
+ router.push(href);
69
+ if (!skipRefresh) router.refresh();
70
+ });
71
+ }
72
+
73
+ return (
74
+ <div className="flex flex-wrap items-end gap-3 rounded-xl border border-slate-200 bg-white p-3 shadow-sm">
75
+ {showSearch ? (
76
+ <SearchInput
77
+ searchKey={searchKey}
78
+ placeholder={searchPlaceholder}
79
+ showSubmit={showSearchSubmit}
80
+ skipRefresh={skipRefresh}
81
+ />
82
+ ) : null}
83
+ {facets.map((f) => {
84
+ const current = params.get(f.key) || f.defaultValue || "all";
85
+ const optionsHaveAll = f.options.some((o) => o.value === "all");
86
+ return (
87
+ <Select
88
+ key={f.key}
89
+ value={current}
90
+ onValueChange={(v) =>
91
+ update(f.key, v, {
92
+ defaultValue: f.defaultValue,
93
+ allIsOption: optionsHaveAll,
94
+ })
95
+ }
96
+ >
97
+ <SelectTrigger
98
+ className="w-52"
99
+ {...aidProps(`filter.${f.key}`)}
100
+ aria-label={`Filtre ${f.label}`}
101
+ >
102
+ <SelectValue placeholder={f.label} />
103
+ </SelectTrigger>
104
+ <SelectContent>
105
+ {!f.hideAllOption && !optionsHaveAll ? (
106
+ <SelectItem value="all">{f.allLabel || `Tous — ${f.label}`}</SelectItem>
107
+ ) : null}
108
+ {f.options.map((o) => (
109
+ <SelectItem key={o.value} value={o.value}>
110
+ {(o.label || o.value)} ({o.c})
111
+ </SelectItem>
112
+ ))}
113
+ </SelectContent>
114
+ </Select>
115
+ );
116
+ })}
117
+ </div>
118
+ );
119
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Host marque pour GlobalSearch (dépend tab-workspace).
3
+ */
4
+
5
+ export type GlobalSearchHost = {
6
+ useGlobalSearch: () => any;
7
+ };
8
+
9
+ let host: GlobalSearchHost | null = null;
10
+
11
+ export function configureGlobalSearchHost(next: GlobalSearchHost): void {
12
+ host = next;
13
+ }
14
+
15
+ export function useGlobalSearch(): any {
16
+ if (!host?.useGlobalSearch) {
17
+ return { open: false, setOpen: () => {}, query: "", setQuery: () => {} };
18
+ }
19
+ return host.useGlobalSearch();
20
+ }
@@ -0,0 +1,66 @@
1
+ "use client";
2
+
3
+ import { Search } from "lucide-react";
4
+ import { useGlobalSearch } from "./global-search-host";
5
+ import { cn } from "@creezio/shell-ui";
6
+
7
+ export function GlobalSearchTrigger({
8
+ className,
9
+ iconOnly = false,
10
+ variant = "sidebar",
11
+ }: {
12
+ className?: string;
13
+ iconOnly?: boolean;
14
+ /** sidebar = fond sombre (nav) ; toolbar = bandeau blanc sous les onglets. */
15
+ variant?: "sidebar" | "toolbar";
16
+ }) {
17
+ const { setOpen } = useGlobalSearch();
18
+ const isToolbar = variant === "toolbar";
19
+
20
+ const baseClass = isToolbar
21
+ ? "border-slate-200/90 bg-slate-50/80 text-slate-500 hover:border-slate-300 hover:bg-white hover:text-slate-700"
22
+ : "border-slate-700/80 bg-slate-800/80 text-slate-400 hover:border-slate-600 hover:bg-slate-800 hover:text-slate-300";
23
+
24
+ if (iconOnly) {
25
+ return (
26
+ <button
27
+ type="button"
28
+ onClick={() => setOpen(true)}
29
+ title="Rechercher (⌘K)"
30
+ aria-label="Rechercher"
31
+ className={cn(
32
+ "flex h-9 w-full items-center justify-center rounded-lg border transition-colors",
33
+ baseClass,
34
+ className,
35
+ )}
36
+ >
37
+ <Search className="h-4 w-4 shrink-0" />
38
+ </button>
39
+ );
40
+ }
41
+
42
+ return (
43
+ <button
44
+ type="button"
45
+ onClick={() => setOpen(true)}
46
+ className={cn(
47
+ "flex w-full items-center gap-2 rounded-lg border px-3 py-1.5 text-left text-sm transition-colors",
48
+ baseClass,
49
+ className,
50
+ )}
51
+ >
52
+ <Search className="h-4 w-4 shrink-0" />
53
+ <span className="flex-1 truncate">Rechercher…</span>
54
+ <kbd
55
+ className={cn(
56
+ "hidden shrink-0 rounded border px-1.5 py-0.5 text-[10px] font-medium sm:inline",
57
+ isToolbar
58
+ ? "border-slate-200 bg-white text-slate-400"
59
+ : "border-slate-600 bg-slate-900/60 text-slate-500",
60
+ )}
61
+ >
62
+ ⌘K
63
+ </kbd>
64
+ </button>
65
+ );
66
+ }
package/ui/index.ts ADDED
@@ -0,0 +1,178 @@
1
+ /**
2
+ * @creezio/shell-ui/ui — primitives + shell CRM UI (O9, gold TF).
3
+ * Consommer via `@creezio/shell-ui/ui`.
4
+ */
5
+
6
+ /* ── Brand / hosts (aussi via package root) ── */
7
+ export {
8
+ configureShellUiBrand,
9
+ getShellUiBrand,
10
+ getShellDesktopApi,
11
+ resetShellUiBrandForTests,
12
+ type ShellUiBrand,
13
+ } from "../dist/brand.js";
14
+ export {
15
+ configureTabWorkspaceHost,
16
+ useTabWorkspace,
17
+ useTabWorkspaceOptional,
18
+ useOpenTab,
19
+ openExternalSiteFromWorkspace,
20
+ normalizeOpenExternalSiteOpts,
21
+ type TabWorkspaceHost,
22
+ type OpenExternalSiteOpts,
23
+ /** @deprecated → OpenExternalSiteOpts */
24
+ type OpenSupplierSiteOpts,
25
+ } from "./workspace/tab-workspace-host";
26
+ export {
27
+ configureGlobalSearchHost,
28
+ useGlobalSearch,
29
+ type GlobalSearchHost,
30
+ } from "./global-search-host";
31
+
32
+ /* ── Primitives ── */
33
+ export * from "./primitives/button";
34
+ export * from "./primitives/badge";
35
+ export * from "./primitives/input";
36
+ export * from "./primitives/card";
37
+ export * from "./primitives/tabs";
38
+ export * from "./primitives/label";
39
+ export * from "./primitives/separator";
40
+ export * from "./primitives/skeleton";
41
+ export * from "./primitives/dialog";
42
+ export * from "./primitives/sheet";
43
+ export * from "./primitives/select";
44
+ export * from "./primitives/dropdown-menu";
45
+ export * from "./primitives/scroll-area";
46
+ export * from "./primitives/avatar";
47
+ export * from "./primitives/breadcrumb";
48
+ export * from "./primitives/command";
49
+ export * from "./primitives/sonner";
50
+ export * from "./primitives/chart";
51
+
52
+ /* ── Lib client ── */
53
+ export * from "./lib/aid";
54
+ export { useShellUiBrand } from "./lib/use-shell-ui-brand";
55
+ export type { ShellUiLoginBrand } from "../dist/brand.js";
56
+ export * from "./lib/desktop-host";
57
+ export * from "./lib/n8n-ui";
58
+ export * from "./lib/hermes-ui";
59
+ export * from "./lib/fleet-tracker-client";
60
+ export * from "./lib/ai-workspace-client";
61
+ export * from "./lib/ai-screencast-hub";
62
+ export {
63
+ useCreezioResource,
64
+ useCreezioResources,
65
+ type UseCreezioResourceOptions,
66
+ } from "./lib/use-creezio-resource";
67
+
68
+ /* ── Layout / chrome ── */
69
+ export * from "./layout/page-chrome";
70
+ export * from "./layout/page-toolbar-context";
71
+ export * from "./layout/section-view-shell";
72
+ export * from "./layout/entity-header";
73
+ export * from "./layout/sandbox-banner";
74
+ export * from "./layout/app-shell";
75
+ export * from "./layout/desktop-update-banner";
76
+ export * from "./layout/sidebar";
77
+ export * from "./layout/sidebar-host";
78
+ export * from "./layout/native-os-nav";
79
+ export { resolveNavIcon } from "./layout/nav-icons";
80
+ export {
81
+ NAV_ICON_ALLOWLIST,
82
+ defaultOsCatalogEntries,
83
+ isKnownNavIcon,
84
+ listOsNavEntries,
85
+ parseNavCatalogSessionItems,
86
+ registerDefaultOsNavEntries,
87
+ registerOsNavEntry,
88
+ resetOsNavRegistryForTests,
89
+ resolveNavCatalog,
90
+ type NavCatalogEntry,
91
+ type NavCatalogError,
92
+ type NavCatalogFeatures,
93
+ type NavCatalogGroup,
94
+ type NavCatalogSessionItem,
95
+ type NavCatalogSource,
96
+ type NavIconName,
97
+ type NavOverride,
98
+ type ResolveNavCatalogInput,
99
+ type ResolveNavCatalogResult,
100
+ } from "../dist/nav-catalog.js";
101
+ export {
102
+ NAV_CATALOG_ENDPOINT,
103
+ NavCatalogLoader,
104
+ applyNavCatalogItemsToSidebar,
105
+ mapNavCatalogSessionToSidebar,
106
+ } from "./layout/nav-catalog-loader";
107
+
108
+ /* ── Workspace ── */
109
+ export * from "./workspace/types";
110
+ export * from "./workspace/workspace-config";
111
+ export {
112
+ TabWorkspaceProvider,
113
+ getWorkspaceTabNavigate,
114
+ useTabWorkspace as useTabWorkspaceImpl,
115
+ useTabWorkspaceOptional as useTabWorkspaceOptionalImpl,
116
+ useOpenTab as useOpenTabImpl,
117
+ type NavigateOptions,
118
+ type OpenExternalSiteOpts as TabWorkspaceOpenExternalSiteOpts,
119
+ /** @deprecated → TabWorkspaceOpenExternalSiteOpts */
120
+ type OpenSupplierSiteOpts as TabWorkspaceOpenSupplierSiteOpts,
121
+ } from "./workspace/tab-workspace-context";
122
+ export * from "./workspace/workspace-shell";
123
+ export * from "./workspace/workspace-root";
124
+ export * from "./workspace/workspace-tab-bar";
125
+ export * from "./workspace/keep-alive";
126
+ export * from "./workspace/ai-workspace-banner";
127
+ export * from "./workspace/impersonation-banner";
128
+ export { configureAiActivityPanel, AiActivityPanelHost } from "./workspace/ai-activity-panel-host";
129
+ export * from "./workspace/window-chrome-controls";
130
+ export * from "./workspace/ai-workspace-agent-host";
131
+ export * from "./workspace/use-location-search";
132
+
133
+ /* ── Pages OS composées (wrappers marque = re-export) ── */
134
+ export { DesktopSettingsPage } from "./os-pages/desktop-settings-page";
135
+
136
+ /* ── Settings desktop ── */
137
+ export * from "./settings/desktop-hermes-settings";
138
+ export * from "./settings/desktop-n8n-settings";
139
+ export * from "./settings/desktop-fleet-telemetry-settings";
140
+ export * from "./settings/desktop-tunnel";
141
+ export * from "./settings/desktop-embed-env-panel";
142
+ export * from "./settings/desktop-connection-settings";
143
+ export * from "./settings/desktop-llm-keys";
144
+ export * from "./settings/desktop-update-settings";
145
+ export * from "./settings/desktop-background-settings";
146
+ export * from "./settings/ops-diagnostic-settings";
147
+ export * from "./settings/api-keys-settings";
148
+ export * from "./settings/agent-profile-settings";
149
+ export * from "./settings/account-settings";
150
+ export * from "./settings/search-reindex-settings";
151
+ export * from "./settings/factory-reset-settings";
152
+ export * from "./settings/locked-config-field";
153
+ export * from "./settings/host-only-settings";
154
+
155
+ /* ── Desktop / PWA / misc ── */
156
+ export * from "./desktop/site-link";
157
+ export * from "./desktop/external-site-slot";
158
+ export * from "./desktop/external-site-surface";
159
+ export * from "./desktop/desktop-bridge";
160
+ export * from "./desktop/auth-window-chrome";
161
+ export * from "./desktop/window-chrome-controls";
162
+ export * from "./pwa/client-error-reporter";
163
+ export * from "./pwa/register-sw";
164
+ export * from "./page-loading/list-page-loading";
165
+ export * from "./page-loading/entity-page-loading";
166
+ export * from "./desktop-types";
167
+
168
+ export * from "./list-toolbar";
169
+ export * from "./data-table";
170
+ export * from "./range-filters";
171
+ export * from "./faceted-filters";
172
+ export * from "./search-input";
173
+ export * from "./global-search";
174
+ export { GlobalSearchProvider, useGlobalSearch as useGlobalSearchImpl } from "./search/global-search-provider";
175
+ export * from "./search/global-search-config";
176
+ export * from "./search/search-history";
177
+ export * from "./pagination";
178
+ export * from "./app-error-boundary";
package/ui/kit.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Entrée légère client-safe — primitives + helpers desktop (pas de workspace/assistant).
3
+ * À préférer dans les packages kit UI (@creezio/mails, tasks, cockpit, auth…).
4
+ */
5
+ export * from "./primitives/button";
6
+ export * from "./primitives/badge";
7
+ export * from "./primitives/input";
8
+ export * from "./primitives/card";
9
+ export * from "./primitives/tabs";
10
+ export * from "./primitives/label";
11
+ export * from "./primitives/separator";
12
+ export * from "./primitives/skeleton";
13
+ export * from "./primitives/dialog";
14
+ export * from "./primitives/sheet";
15
+ export * from "./primitives/select";
16
+ export * from "./primitives/dropdown-menu";
17
+ export * from "./primitives/scroll-area";
18
+ export * from "./primitives/avatar";
19
+ export * from "./primitives/breadcrumb";
20
+ export * from "./primitives/command";
21
+ export * from "./primitives/sonner";
22
+ export * from "./primitives/chart";
23
+ export * from "./primitives/resizable";
24
+ export * from "./primitives/tooltip";
25
+ export * from "./primitives/textarea";
26
+
27
+ export { isRemoteDesktopClient } from "./lib/desktop-host";
28
+ export { useShellUiBrand } from "./lib/use-shell-ui-brand";
29
+ export type { ShellUiBrand, ShellUiLoginBrand } from "../dist/brand.js";
30
+ export { openAiWorkspaceView, aiWorkspaceAvailable } from "./lib/ai-workspace-client";
@@ -0,0 +1,58 @@
1
+ "use client";
2
+
3
+ import { useEffect, type ReactNode } from "react";
4
+ import { usePaneActive, usePaneHref } from "../workspace/keep-alive";
5
+ import { useTabWorkspaceOptional } from "../workspace/tab-workspace-host";
6
+ import type { PageKind, TrailCrumb } from "../workspace/types";
7
+ import { useRegisterPageToolbar } from "./page-toolbar-context";
8
+
9
+ /**
10
+ * Cadre de page CRM — API unique.
11
+ *
12
+ * `title` → label d'onglet (toujours).
13
+ * `kind="section"` → bandeau toolbar sous les onglets (recherche + actions).
14
+ * `kind="entity"` → fil d'Ariane dans le bandeau ; titre via EntityHeader.
15
+ */
16
+ export function AppShell({
17
+ children,
18
+ title,
19
+ subtitle,
20
+ kind = "section",
21
+ trail,
22
+ fullscreen,
23
+ actions,
24
+ }: {
25
+ children: React.ReactNode;
26
+ title: string;
27
+ subtitle?: string;
28
+ kind?: PageKind;
29
+ /** Fil d'Ariane sticky — requis si kind=entity. */
30
+ trail?: TrailCrumb[];
31
+ /** Canvas plein écran — masque le bandeau sous les onglets. */
32
+ fullscreen?: boolean;
33
+ /** Boutons / toggles affichés à droite du bandeau sticky. */
34
+ actions?: ReactNode;
35
+ }) {
36
+ const workspace = useTabWorkspaceOptional();
37
+ const paneHref = usePaneHref();
38
+ const paneActive = usePaneActive();
39
+ const ready = workspace?.ready ?? false;
40
+ const setTabMeta = workspace?.setTabMeta;
41
+ const targetHref = paneHref ?? workspace?.currentHref ?? null;
42
+ const trailKey = JSON.stringify(trail ?? null);
43
+
44
+ useRegisterPageToolbar(paneActive ? targetHref : null, actions);
45
+
46
+ useEffect(() => {
47
+ if (!ready || !setTabMeta || !targetHref) return;
48
+ setTabMeta(targetHref, {
49
+ title,
50
+ subtitle,
51
+ kind,
52
+ trail: trailKey ? (JSON.parse(trailKey) as TrailCrumb[]) : undefined,
53
+ fullscreen,
54
+ });
55
+ }, [ready, setTabMeta, targetHref, title, subtitle, kind, trailKey, fullscreen]);
56
+
57
+ return <div className="contents">{children}</div>;
58
+ }