@motor-hero/ui-kit 0.48.0 → 0.49.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motor-hero/ui-kit",
3
- "version": "0.48.0",
3
+ "version": "0.49.0",
4
4
  "description": "Componentes React reutilizáveis para o ecossistema MotorHero — shadcn/ui + Tailwind CSS v4",
5
5
  "author": "MotorHero",
6
6
  "license": "UNLICENSED",
@@ -28,6 +28,14 @@ export interface AppShellProps {
28
28
  sidebarFooter?: ReactNode | ((collapsed: boolean) => ReactNode)
29
29
  /** Above the header, full width of the content column — `UpdateBanner` goes here. */
30
30
  banner?: ReactNode
31
+ /**
32
+ * Merged into the sidebar (desktop and mobile drawer), e.g.
33
+ * `bg-sidebar text-sidebar-foreground border-sidebar-border`. Inner dividers
34
+ * follow the sidebar's border color.
35
+ */
36
+ sidebarClassName?: string
37
+ /** Merged into the top header bar. */
38
+ headerClassName?: string
31
39
  children: ReactNode
32
40
  }
33
41
 
@@ -47,6 +55,8 @@ export function AppShell({
47
55
  defaultCollapsed = false,
48
56
  sidebarFooter,
49
57
  banner,
58
+ sidebarClassName,
59
+ headerClassName,
50
60
  children,
51
61
  }: AppShellProps) {
52
62
  const [collapsed, setCollapsed] = useState(defaultCollapsed)
@@ -68,24 +78,29 @@ export function AppShell({
68
78
  <div className="flex h-screen overflow-hidden bg-background">
69
79
  {/* Desktop sidebar */}
70
80
  <aside
81
+ data-slot="sidebar"
71
82
  className={cn(
72
83
  "hidden shrink-0 flex-col border-r bg-card transition-all duration-300 md:flex",
73
84
  collapsed ? "w-16" : "w-60",
85
+ sidebarClassName,
74
86
  )}
75
87
  >
76
- <div className="flex h-14 shrink-0 items-center border-b px-4">
88
+ <div className="flex h-14 shrink-0 items-center border-b border-inherit px-4" data-slot="sidebar-brand">
77
89
  {collapsed ? (brandCollapsed ?? brand) : brand}
78
90
  </div>
79
- <div className="flex-1 overflow-y-auto px-2 py-4">{nav(collapsed)}</div>
91
+ <div className="flex-1 overflow-y-auto px-2 py-4" data-slot="sidebar-content">
92
+ {nav(collapsed)}
93
+ </div>
80
94
  {sidebarFooter && (
81
- <div className="border-t px-3 py-2" data-slot="sidebar-footer">
95
+ <div className="border-t border-inherit px-3 py-2" data-slot="sidebar-footer">
82
96
  {typeof sidebarFooter === "function" ? sidebarFooter(collapsed) : sidebarFooter}
83
97
  </div>
84
98
  )}
85
99
  {collapsible && (
86
- <div className="border-t p-2">
100
+ <div className="border-t border-inherit p-2">
87
101
  <button
88
102
  type="button"
103
+ data-slot="sidebar-toggle"
89
104
  onClick={() => setCollapsed((v) => !v)}
90
105
  className="flex w-full items-center justify-center rounded-md px-2 py-2 text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
91
106
  aria-label={collapsed ? "Expandir menu" : "Recolher menu"}
@@ -106,21 +121,30 @@ export function AppShell({
106
121
  >
107
122
  <div className="absolute inset-0 bg-black/50" />
108
123
  <div
124
+ data-slot="sidebar-drawer"
109
125
  className={cn(
110
126
  "absolute left-0 top-0 flex h-full w-64 flex-col border-r bg-card transition-transform duration-300",
111
127
  mobileOpen ? "translate-x-0" : "-translate-x-full",
128
+ sidebarClassName,
112
129
  )}
113
130
  onClick={(e) => e.stopPropagation()}
114
131
  >
115
- <div className="flex h-14 shrink-0 items-center border-b px-4">{brand}</div>
116
- <div className="flex-1 overflow-y-auto px-2 py-4">{nav(false, () => setMobileOpen(false))}</div>
132
+ <div className="flex h-14 shrink-0 items-center border-b border-inherit px-4" data-slot="sidebar-brand">
133
+ {brand}
134
+ </div>
135
+ <div className="flex-1 overflow-y-auto px-2 py-4" data-slot="sidebar-content">
136
+ {nav(false, () => setMobileOpen(false))}
137
+ </div>
117
138
  </div>
118
139
  </div>
119
140
 
120
141
  {/* Main column */}
121
142
  <div className="flex flex-1 flex-col overflow-hidden">
122
143
  {banner}
123
- <header className="flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4">
144
+ <header
145
+ data-slot="header"
146
+ className={cn("flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4", headerClassName)}
147
+ >
124
148
  <button
125
149
  type="button"
126
150
  onClick={() => setMobileOpen(true)}
@@ -116,7 +116,10 @@ export function Combobox({
116
116
 
117
117
  const handleOpenChange = (next: boolean) => {
118
118
  setOpen(next);
119
- if (!next) setSearch("");
119
+ if (!next) {
120
+ setSearch("");
121
+ onSearchChange?.("");
122
+ }
120
123
  };
121
124
 
122
125
  const handleSelect = (next: string) => {
@@ -73,6 +73,10 @@ export function MultiCombobox({
73
73
  const [open, setOpen] = React.useState(false)
74
74
  const isDesktop = useIsDesktop()
75
75
  const isServer = onSearchChange !== undefined
76
+ const handleOpenChange = (next: boolean) => {
77
+ setOpen(next)
78
+ if (!next) onSearchChange?.("")
79
+ }
76
80
  // Em modo servidor `options` é só a página carregada no momento, então um
77
81
  // rótulo visto uma vez precisa sobreviver à troca de página: sem esse cache,
78
82
  // buscar (ou paginar) fazia o chip de um valor ainda selecionado sumir do
@@ -223,7 +227,7 @@ export function MultiCombobox({
223
227
 
224
228
  if (isDesktop) {
225
229
  return (
226
- <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>
230
+ <PopoverPrimitive.Root open={open} onOpenChange={handleOpenChange}>
227
231
  <PopoverPrimitive.Trigger asChild disabled={disabled}>
228
232
  {trigger}
229
233
  </PopoverPrimitive.Trigger>
@@ -242,7 +246,7 @@ export function MultiCombobox({
242
246
  }
243
247
 
244
248
  return (
245
- <DrawerPrimitive.Root open={open} onOpenChange={setOpen}>
249
+ <DrawerPrimitive.Root open={open} onOpenChange={handleOpenChange}>
246
250
  <DrawerPrimitive.Trigger asChild disabled={disabled}>
247
251
  {trigger}
248
252
  </DrawerPrimitive.Trigger>