@orsetra/shared-ui 1.0.44 → 1.0.46

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.
@@ -61,10 +61,11 @@ function LayoutContent({ children, sidebarMenus, user, onSignOut, mode = 'expand
61
61
  <div className="flex h-screen w-full bg-white">
62
62
  {/* Desktop sidebar - hidden on mobile (isHidden is true on mobile) */}
63
63
  {!isMinimized && !isHidden && (
64
- <Sidebar
64
+ <Sidebar
65
65
  currentMenu={currentMenu}
66
66
  onMainMenuToggle={handleMainSidebarToggle}
67
67
  sidebarMenus={sidebarMenus}
68
+ main_base_url={main_base_url}
68
69
  />
69
70
  )}
70
71
 
@@ -23,7 +23,10 @@ import {
23
23
  Settings,
24
24
  Package,
25
25
  Rocket,
26
- Menu
26
+ Menu,
27
+ Building2,
28
+ User,
29
+ ChevronUp,
27
30
  } from "lucide-react"
28
31
  import { Logo } from "../../ui/logo"
29
32
  import { menuLabels, type SidebarMenus, type SubMenuItem } from "./data"
@@ -170,22 +173,38 @@ interface SidebarProps {
170
173
  currentMenu?: string
171
174
  onMainMenuToggle?: () => void
172
175
  sidebarMenus?: SidebarMenus
176
+ main_base_url?: string
173
177
  }
174
178
 
175
179
 
176
180
 
177
- function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {} }: SidebarProps = {}) {
181
+ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {}, main_base_url = "" }: SidebarProps = {}) {
178
182
  const pathname = usePathname()
179
183
  const { state } = useSidebar()
184
+ const [settingsOpen, setSettingsOpen] = React.useState(false)
185
+ const settingsRef = React.useRef<HTMLDivElement>(null)
186
+
187
+ // Close dropdown on click outside
188
+ React.useEffect(() => {
189
+ function handleClickOutside(event: MouseEvent) {
190
+ if (settingsRef.current && !settingsRef.current.contains(event.target as Node)) {
191
+ setSettingsOpen(false)
192
+ }
193
+ }
194
+ if (settingsOpen) {
195
+ document.addEventListener("mousedown", handleClickOutside)
196
+ return () => document.removeEventListener("mousedown", handleClickOutside)
197
+ }
198
+ }, [settingsOpen])
180
199
 
181
200
  // Micro apps: utilise 'items' comme clé standard
182
201
  // Main app: utilise currentMenu pour sélectionner le bon groupe
183
- const currentNavigation: SubMenuItem[] = sidebarMenus['items']
184
- || (currentMenu && sidebarMenus[currentMenu])
202
+ const currentNavigation: SubMenuItem[] = sidebarMenus['items']
203
+ || (currentMenu && sidebarMenus[currentMenu])
185
204
  || []
186
205
 
187
206
  return (
188
- <div className="h-screen sticky top-0 flex flex-col bg-white border-r border-ui-border min-w-[var(--sidebar-width-icon)] transition-[width] duration-200"
207
+ <div className="h-screen sticky top-0 flex flex-col bg-white border-r border-ui-border min-w-[var(--sidebar-width-icon)] transition-[width] duration-200"
189
208
  style={{ width: state === "expanded" ? "var(--sidebar-width)" : "var(--sidebar-width-icon)" }}>
190
209
  {/* Logo avec bouton de menu principal */}
191
210
  <div className="h-14 flex items-center justify-between px-4 border-b border-ui-border">
@@ -240,6 +259,48 @@ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {} }: SidebarPr
240
259
  )
241
260
  })}
242
261
  </nav>
262
+
263
+ {/* Footer - Menu Paramètres */}
264
+ <div className="relative border-t border-ui-border px-3 py-3" ref={settingsRef}>
265
+ {/* Dropdown vers le haut */}
266
+ {settingsOpen && (
267
+ <div className="absolute bottom-full left-2 right-2 mb-1 bg-white border border-ui-border rounded-none shadow-lg z-50">
268
+ <div className="py-1">
269
+ <Link
270
+ href={`${main_base_url}/organization`}
271
+ onClick={() => setSettingsOpen(false)}
272
+ className="flex items-center gap-3 px-3 py-2 text-sm text-text-secondary hover:bg-ui-background hover:text-text-primary transition-colors"
273
+ >
274
+ <Building2 className="h-4 w-4" />
275
+ Organization
276
+ </Link>
277
+ <Link
278
+ href={`${main_base_url}/profile`}
279
+ onClick={() => setSettingsOpen(false)}
280
+ className="flex items-center gap-3 px-3 py-2 text-sm text-text-secondary hover:bg-ui-background hover:text-text-primary transition-colors"
281
+ >
282
+ <User className="h-4 w-4" />
283
+ Compte
284
+ </Link>
285
+ </div>
286
+ </div>
287
+ )}
288
+ <button
289
+ onClick={() => setSettingsOpen(!settingsOpen)}
290
+ className={cn(
291
+ "flex items-center justify-between w-full px-3 py-2 text-sm rounded-none gap-x-3 transition-colors",
292
+ settingsOpen
293
+ ? "bg-interactive/10 text-interactive font-medium"
294
+ : "text-text-secondary hover:bg-ui-background hover:text-text-primary"
295
+ )}
296
+ >
297
+ <span className="flex items-center gap-x-3">
298
+ <Settings className="h-4 w-4" />
299
+ {state === "expanded" && "Paramètres"}
300
+ </span>
301
+ {state === "expanded" && <ChevronUp className={cn("h-4 w-4 transition-transform", settingsOpen ? "rotate-0" : "rotate-180")} />}
302
+ </button>
303
+ </div>
243
304
  </div>
244
305
  )
245
306
  }
package/lib/menu-utils.ts CHANGED
@@ -41,7 +41,12 @@ export function getMenuFromPath(pathname: string): string {
41
41
  if (pathname.startsWith("/access-manager")) {
42
42
  return "access-manager"
43
43
  }
44
-
44
+
45
+ // Routes pour Profile et Organization (pages paramètres)
46
+ if (pathname.startsWith("/profile") || pathname.startsWith("/organization")) {
47
+ return "overview"
48
+ }
49
+
45
50
  // Par défaut, Vue d'ensemble
46
51
  return "overview"
47
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orsetra/shared-ui",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "Shared UI components for Orsetra platform",
5
5
  "main": "./index.ts",
6
6
  "types": "./index.ts",
@@ -93,4 +93,4 @@
93
93
  "next": "^16.0.7",
94
94
  "typescript": "^5"
95
95
  }
96
- }
96
+ }