@orsetra/shared-ui 1.5.13 → 1.5.15

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.
@@ -98,7 +98,7 @@ function LayoutContent({
98
98
  const handleSecondarySidebarOpen = () => setOpen(true)
99
99
 
100
100
  return (
101
- <div className="flex h-screen w-full bg-white overflow-visible">
101
+ <div className="flex h-screen w-full bg-white overflow-hidden">
102
102
  {!isMinimized && !isHidden && (
103
103
  <Sidebar
104
104
  currentMenu={currentMenu}
@@ -144,7 +144,7 @@ function LayoutContent({
144
144
  </div>
145
145
  </header>
146
146
 
147
- <main className="flex-1 overflow-auto">
147
+ <main className="flex-1 min-h-0 overflow-auto">
148
148
  {children}
149
149
  </main>
150
150
  </div>
@@ -1,24 +1,34 @@
1
1
  import { type LucideIcon } from "lucide-react"
2
2
  import {
3
3
  Shield,
4
- Package,
4
+ ShieldCheck,
5
5
  Settings,
6
- Rocket,
7
- LineChart,
8
- Library,
6
+ Activity,
7
+ Layers,
8
+ Cpu,
9
+ Server,
10
+ Webhook,
9
11
  Component,
12
+ LayoutTemplate,
10
13
  FolderGit2,
14
+ GitBranch,
15
+ GitMerge,
16
+ FileJson,
11
17
  Network,
18
+ SlidersHorizontal,
19
+ HardDrive,
20
+ Scale,
21
+ Crosshair,
12
22
  Key,
23
+ Lock,
13
24
  Globe,
14
- Activity,
15
25
  Database,
26
+ Braces,
27
+ AppWindow,
28
+ Fingerprint,
16
29
  Users,
17
- Plug,
18
30
  Box,
19
31
  Monitor,
20
- Server,
21
- Lock,
22
32
  Home,
23
33
  FileText,
24
34
  Code,
@@ -29,7 +39,7 @@ export interface MainMenuItem {
29
39
  id: string
30
40
  label: string
31
41
  icon: LucideIcon
32
- href?: string
42
+ href: string
33
43
  }
34
44
 
35
45
  export interface SubMenuItem {
@@ -87,25 +97,44 @@ export interface MenuApiResponse {
87
97
  }
88
98
 
89
99
  const ICON_MAP: Record<string, LucideIcon> = {
100
+ // Navigation principale
101
+ Layers,
102
+ Cpu,
103
+ Server,
104
+ Activity,
105
+ Webhook,
90
106
  Shield,
91
- Package,
107
+ ShieldCheck,
92
108
  Settings,
93
- Rocket,
94
- LineChart,
95
- Library,
109
+ // Assets
96
110
  Component,
111
+ LayoutTemplate,
97
112
  FolderGit2,
98
- Network,
99
- Key,
113
+ // Projects
114
+ GitBranch,
115
+ FileJson,
116
+ // Runtime
117
+ AppWindow,
118
+ HardDrive,
119
+ SlidersHorizontal,
100
120
  Globe,
101
- Activity,
121
+ // Network
122
+ Scale,
123
+ Network,
124
+ // Infra
125
+ Crosshair,
126
+ // API Manager
127
+ Braces,
128
+ GitMerge,
102
129
  Database,
130
+ // Access
103
131
  Users,
104
- Plug,
132
+ Fingerprint,
133
+ Lock,
134
+ Key,
135
+ // Divers (non utilisés en menu mais gardés pour usage futur)
105
136
  Box,
106
137
  Monitor,
107
- Server,
108
- Lock,
109
138
  Home,
110
139
  FileText,
111
140
  Code,
@@ -300,13 +300,18 @@ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {}, main_base_u
300
300
  <>
301
301
  <div className="border-t border-ui-border mx-1 my-2" />
302
302
  {filteredMainItems.map((item) => {
303
- const href = item.href!.startsWith('http://') || item.href!.startsWith('https://')
304
- ? new URL(item.href!).pathname
305
- : item.href!
303
+ const handleClick = (e: React.MouseEvent) => {
304
+ const href = item.href
305
+ if (href.startsWith('http://') || href.startsWith('https://')) {
306
+ e.preventDefault()
307
+ window.location.href = new URL(href).pathname
308
+ }
309
+ }
306
310
  const linkEl = (
307
311
  <Link
308
312
  key={item.id}
309
- href={href}
313
+ href={ item.href}
314
+ onClick={handleClick}
310
315
  className="flex items-center justify-center p-2 transition-colors border-l-4 border-transparent hover:bg-ui-background"
311
316
  >
312
317
  <item.icon
@@ -52,6 +52,7 @@ export { ScrollArea, ScrollBar } from './scroll-area'
52
52
  export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator } from './select'
53
53
  export { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './sheet'
54
54
  export { SidePanel, SidePanelTrigger, SidePanelClose, SidePanelContent, SidePanelHeader, SidePanelTitle, SidePanelDescription, SidePanelBody, SidePanelFooter } from './side-panel'
55
+ export { PushPanel, type PushPanelProps } from './push-panel'
55
56
  export { Skeleton } from './skeleton'
56
57
  export { Slider } from './slider'
57
58
  export { Toaster } from './toaster'
@@ -0,0 +1,94 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { X } from "lucide-react"
5
+ import { cn } from "../../lib/utils"
6
+
7
+ export interface PushPanelProps {
8
+ open: boolean
9
+ onOpenChange: (open: boolean) => void
10
+ title: React.ReactNode
11
+ description?: React.ReactNode
12
+ headerActions?: React.ReactNode
13
+ children: React.ReactNode
14
+ actions?: React.ReactNode
15
+ width?: string
16
+ className?: string
17
+ }
18
+
19
+ /**
20
+ * Inline push panel that slides in from the right and compresses the main
21
+ * content area, rather than overlaying it as a modal.
22
+ *
23
+ * Usage: place as a flex sibling next to the page content.
24
+ *
25
+ * ```tsx
26
+ * <div className="flex items-start min-h-screen">
27
+ * <div className="flex-1 min-w-0">{page content}</div>
28
+ * <PushPanel open={open} onOpenChange={setOpen} title="Details">
29
+ * {detail content}
30
+ * </PushPanel>
31
+ * </div>
32
+ * ```
33
+ */
34
+ export function PushPanel({
35
+ open,
36
+ onOpenChange,
37
+ title,
38
+ description,
39
+ headerActions,
40
+ children,
41
+ actions,
42
+ width = "w-[480px]",
43
+ className,
44
+ }: PushPanelProps) {
45
+ return (
46
+ <div
47
+ className={cn(
48
+ "hidden lg:flex flex-col flex-shrink-0 sticky top-0 self-start",
49
+ "h-[calc(100vh-3.5rem)] overflow-hidden",
50
+ "transition-[width] duration-300 ease-in-out",
51
+ "border-l border-ibm-gray-20 bg-white",
52
+ open ? width : "w-0",
53
+ className
54
+ )}
55
+ >
56
+ {/* Fixed-width inner wrapper prevents content reflow during animation */}
57
+ <div className={cn("flex flex-col h-full", width)}>
58
+
59
+ {/* Header */}
60
+ <div className="flex items-start justify-between px-5 py-3.5 flex-shrink-0 border-b border-ibm-gray-20">
61
+ <div className="flex-1 min-w-0 pr-3">
62
+ <p className="text-sm font-semibold text-ibm-gray-100 truncate">{title}</p>
63
+ {description && (
64
+ <p className="text-[11px] text-ibm-gray-50 mt-0.5 truncate">{description}</p>
65
+ )}
66
+ </div>
67
+ <div className="flex items-center gap-1.5 flex-shrink-0">
68
+ {headerActions}
69
+ <button
70
+ type="button"
71
+ onClick={() => onOpenChange(false)}
72
+ className="p-1 text-ibm-gray-40 hover:text-ibm-gray-70 hover:bg-ibm-gray-10 transition-colors rounded-sm"
73
+ >
74
+ <X className="h-4 w-4" />
75
+ <span className="sr-only">Close</span>
76
+ </button>
77
+ </div>
78
+ </div>
79
+
80
+ {/* Scrollable body */}
81
+ <div className="flex-1 overflow-y-auto px-5 py-4">
82
+ {children}
83
+ </div>
84
+
85
+ {/* Footer */}
86
+ {actions && (
87
+ <div className="flex items-center gap-2 px-5 py-3 flex-shrink-0 border-t border-ibm-gray-10">
88
+ {actions}
89
+ </div>
90
+ )}
91
+ </div>
92
+ </div>
93
+ )
94
+ }
@@ -59,7 +59,7 @@ const SidePanel = ({
59
59
  <SidePanelOverlay />
60
60
  <DialogPrimitive.Content
61
61
  className={cn(
62
- "fixed z-50 bg-white shadow-lg transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
62
+ "fixed z-50 bg-white shadow-lg !translate-x-0 !translate-y-0 transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
63
63
  side === "right" &&
64
64
  "inset-y-0 right-0 h-full w-full border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",
65
65
  side === "left" &&
@@ -124,7 +124,7 @@ const SidePanelContent = React.forwardRef<
124
124
  <DialogPrimitive.Content
125
125
  ref={ref}
126
126
  className={cn(
127
- "fixed z-50 bg-white shadow-lg transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
127
+ "fixed z-50 bg-white shadow-lg !translate-x-0 !translate-y-0 transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
128
128
  side === "right" &&
129
129
  "inset-y-0 right-0 h-full w-full border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",
130
130
  side === "left" &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orsetra/shared-ui",
3
- "version": "1.5.13",
3
+ "version": "1.5.15",
4
4
  "description": "Shared UI components for Orsetra platform",
5
5
  "main": "./index.ts",
6
6
  "types": "./index.ts",