@hznrkv/sidebar 1.0.0 → 1.1.1
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/index.js +235 -82
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -44,37 +44,79 @@ import {
|
|
|
44
44
|
SidebarFooter,
|
|
45
45
|
SidebarHeader,
|
|
46
46
|
} from "@/components/ui/sidebar"
|
|
47
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
LayoutDashboardIcon,
|
|
49
|
+
UsersIcon,
|
|
50
|
+
FolderIcon,
|
|
51
|
+
BarChart2Icon,
|
|
52
|
+
SettingsIcon,
|
|
53
|
+
BoxIcon,
|
|
54
|
+
} from "lucide-react"
|
|
48
55
|
|
|
49
56
|
const data = {
|
|
50
57
|
user: {
|
|
51
58
|
name: "Usuário",
|
|
52
|
-
email: "usuario@
|
|
59
|
+
email: "usuario@empresa.com",
|
|
53
60
|
avatar: "",
|
|
54
61
|
},
|
|
55
62
|
teams: [
|
|
56
63
|
{
|
|
57
|
-
name: "
|
|
58
|
-
logo: <
|
|
59
|
-
plan: "
|
|
64
|
+
name: "Minha Empresa",
|
|
65
|
+
logo: <BoxIcon />,
|
|
66
|
+
plan: "Pro",
|
|
60
67
|
},
|
|
61
68
|
],
|
|
62
69
|
navMain: [
|
|
63
70
|
{
|
|
64
71
|
title: "Dashboard",
|
|
65
|
-
url: "/",
|
|
72
|
+
url: "/dashboard",
|
|
66
73
|
icon: <LayoutDashboardIcon />,
|
|
67
74
|
isActive: true,
|
|
75
|
+
items: [
|
|
76
|
+
{ title: "Visão geral", url: "/dashboard" },
|
|
77
|
+
{ title: "Atividade recente", url: "/dashboard/atividade" },
|
|
78
|
+
{ title: "Relatórios", url: "/dashboard/relatorios" },
|
|
79
|
+
],
|
|
68
80
|
},
|
|
69
81
|
{
|
|
70
|
-
title: "
|
|
71
|
-
url: "/
|
|
72
|
-
icon: <
|
|
82
|
+
title: "Projetos",
|
|
83
|
+
url: "/projetos",
|
|
84
|
+
icon: <FolderIcon />,
|
|
85
|
+
items: [
|
|
86
|
+
{ title: "Todos os projetos", url: "/projetos" },
|
|
87
|
+
{ title: "Em andamento", url: "/projetos/andamento" },
|
|
88
|
+
{ title: "Arquivados", url: "/projetos/arquivados" },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
title: "Equipe",
|
|
93
|
+
url: "/equipe",
|
|
94
|
+
icon: <UsersIcon />,
|
|
95
|
+
items: [
|
|
96
|
+
{ title: "Membros", url: "/equipe" },
|
|
97
|
+
{ title: "Funções", url: "/equipe/funcoes" },
|
|
98
|
+
{ title: "Convites", url: "/equipe/convites" },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
title: "Análises",
|
|
103
|
+
url: "/analises",
|
|
104
|
+
icon: <BarChart2Icon />,
|
|
105
|
+
items: [
|
|
106
|
+
{ title: "Desempenho", url: "/analises" },
|
|
107
|
+
{ title: "Tendências", url: "/analises/tendencias" },
|
|
108
|
+
{ title: "Exportar", url: "/analises/exportar" },
|
|
109
|
+
],
|
|
73
110
|
},
|
|
74
111
|
{
|
|
75
112
|
title: "Configurações",
|
|
76
113
|
url: "/configuracoes",
|
|
77
114
|
icon: <SettingsIcon />,
|
|
115
|
+
items: [
|
|
116
|
+
{ title: "Geral", url: "/configuracoes" },
|
|
117
|
+
{ title: "Segurança", url: "/configuracoes/seguranca" },
|
|
118
|
+
{ title: "Integrações", url: "/configuracoes/integracoes" },
|
|
119
|
+
],
|
|
78
120
|
},
|
|
79
121
|
],
|
|
80
122
|
}
|
|
@@ -98,7 +140,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|
|
98
140
|
|
|
99
141
|
"src/components/nav-main.tsx": `"use client"
|
|
100
142
|
|
|
101
|
-
import {
|
|
143
|
+
import { useState } from "react"
|
|
102
144
|
import {
|
|
103
145
|
Collapsible,
|
|
104
146
|
CollapsibleContent,
|
|
@@ -114,6 +156,7 @@ import {
|
|
|
114
156
|
SidebarMenuSubButton,
|
|
115
157
|
SidebarMenuSubItem,
|
|
116
158
|
} from "@/components/ui/sidebar"
|
|
159
|
+
import { ChevronRightIcon } from "lucide-react"
|
|
117
160
|
|
|
118
161
|
type NavItem = {
|
|
119
162
|
title: string
|
|
@@ -123,43 +166,52 @@ type NavItem = {
|
|
|
123
166
|
items?: { title: string; url: string }[]
|
|
124
167
|
}
|
|
125
168
|
|
|
169
|
+
function NavItemCollapsible({ item }: { item: NavItem }) {
|
|
170
|
+
const [open, setOpen] = useState(false)
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<Collapsible
|
|
174
|
+
open={open}
|
|
175
|
+
onOpenChange={setOpen}
|
|
176
|
+
className="group/collapsible"
|
|
177
|
+
>
|
|
178
|
+
<SidebarMenuItem>
|
|
179
|
+
<CollapsibleTrigger asChild>
|
|
180
|
+
<SidebarMenuButton tooltip={item.title}>
|
|
181
|
+
{item.icon}
|
|
182
|
+
<span>{item.title}</span>
|
|
183
|
+
<ChevronRightIcon className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
|
184
|
+
</SidebarMenuButton>
|
|
185
|
+
</CollapsibleTrigger>
|
|
186
|
+
<CollapsibleContent>
|
|
187
|
+
<SidebarMenuSub>
|
|
188
|
+
{item.items?.map((subItem) => (
|
|
189
|
+
<SidebarMenuSubItem key={subItem.title}>
|
|
190
|
+
<SidebarMenuSubButton asChild>
|
|
191
|
+
<a href={subItem.url}>
|
|
192
|
+
<span>{subItem.title}</span>
|
|
193
|
+
</a>
|
|
194
|
+
</SidebarMenuSubButton>
|
|
195
|
+
</SidebarMenuSubItem>
|
|
196
|
+
))}
|
|
197
|
+
</SidebarMenuSub>
|
|
198
|
+
</CollapsibleContent>
|
|
199
|
+
</SidebarMenuItem>
|
|
200
|
+
</Collapsible>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
126
204
|
export function NavMain({ items }: { items: NavItem[] }) {
|
|
127
205
|
return (
|
|
128
206
|
<SidebarGroup>
|
|
129
|
-
<SidebarGroupLabel>
|
|
207
|
+
<SidebarGroupLabel>Módulos</SidebarGroupLabel>
|
|
130
208
|
<SidebarMenu>
|
|
131
209
|
{items.map((item) =>
|
|
132
|
-
item.items
|
|
133
|
-
<
|
|
134
|
-
key={item.title}
|
|
135
|
-
asChild
|
|
136
|
-
defaultOpen={item.isActive}
|
|
137
|
-
className="group/collapsible"
|
|
138
|
-
>
|
|
139
|
-
<SidebarMenuItem>
|
|
140
|
-
<CollapsibleTrigger asChild>
|
|
141
|
-
<SidebarMenuButton tooltip={item.title}>
|
|
142
|
-
{item.icon}
|
|
143
|
-
<span>{item.title}</span>
|
|
144
|
-
<ChevronRightIcon className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
|
145
|
-
</SidebarMenuButton>
|
|
146
|
-
</CollapsibleTrigger>
|
|
147
|
-
<CollapsibleContent>
|
|
148
|
-
<SidebarMenuSub>
|
|
149
|
-
{item.items.map((sub) => (
|
|
150
|
-
<SidebarMenuSubItem key={sub.title}>
|
|
151
|
-
<SidebarMenuSubButton asChild>
|
|
152
|
-
<a href={sub.url}>{sub.title}</a>
|
|
153
|
-
</SidebarMenuSubButton>
|
|
154
|
-
</SidebarMenuSubItem>
|
|
155
|
-
))}
|
|
156
|
-
</SidebarMenuSub>
|
|
157
|
-
</CollapsibleContent>
|
|
158
|
-
</SidebarMenuItem>
|
|
159
|
-
</Collapsible>
|
|
210
|
+
item.items ? (
|
|
211
|
+
<NavItemCollapsible key={item.title} item={item} />
|
|
160
212
|
) : (
|
|
161
213
|
<SidebarMenuItem key={item.title}>
|
|
162
|
-
<SidebarMenuButton
|
|
214
|
+
<SidebarMenuButton tooltip={item.title} asChild>
|
|
163
215
|
<a href={item.url}>
|
|
164
216
|
{item.icon}
|
|
165
217
|
<span>{item.title}</span>
|
|
@@ -177,14 +229,10 @@ export function NavMain({ items }: { items: NavItem[] }) {
|
|
|
177
229
|
"src/components/nav-user.tsx": `"use client"
|
|
178
230
|
|
|
179
231
|
import {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
LogOutIcon,
|
|
185
|
-
SparklesIcon,
|
|
186
|
-
} from "lucide-react"
|
|
187
|
-
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
|
232
|
+
Avatar,
|
|
233
|
+
AvatarFallback,
|
|
234
|
+
AvatarImage,
|
|
235
|
+
} from "@/components/ui/avatar"
|
|
188
236
|
import {
|
|
189
237
|
DropdownMenu,
|
|
190
238
|
DropdownMenuContent,
|
|
@@ -200,10 +248,17 @@ import {
|
|
|
200
248
|
SidebarMenuItem,
|
|
201
249
|
useSidebar,
|
|
202
250
|
} from "@/components/ui/sidebar"
|
|
251
|
+
import { ChevronsUpDownIcon, SparklesIcon, BadgeCheckIcon, CreditCardIcon, BellIcon, LogOutIcon } from "lucide-react"
|
|
203
252
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
253
|
+
export function NavUser({
|
|
254
|
+
user,
|
|
255
|
+
}: {
|
|
256
|
+
user: {
|
|
257
|
+
name: string
|
|
258
|
+
email: string
|
|
259
|
+
avatar: string
|
|
260
|
+
}
|
|
261
|
+
}) {
|
|
207
262
|
const { isMobile } = useSidebar()
|
|
208
263
|
|
|
209
264
|
return (
|
|
@@ -217,19 +272,17 @@ export function NavUser({ user }: { user: User }) {
|
|
|
217
272
|
>
|
|
218
273
|
<Avatar className="h-8 w-8 rounded-lg">
|
|
219
274
|
<AvatarImage src={user.avatar} alt={user.name} />
|
|
220
|
-
<AvatarFallback className="rounded-lg">
|
|
221
|
-
{user.name.slice(0, 2).toUpperCase()}
|
|
222
|
-
</AvatarFallback>
|
|
275
|
+
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
|
223
276
|
</Avatar>
|
|
224
277
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
|
225
|
-
<span className="truncate font-
|
|
278
|
+
<span className="truncate font-medium">{user.name}</span>
|
|
226
279
|
<span className="truncate text-xs">{user.email}</span>
|
|
227
280
|
</div>
|
|
228
281
|
<ChevronsUpDownIcon className="ml-auto size-4" />
|
|
229
282
|
</SidebarMenuButton>
|
|
230
283
|
</DropdownMenuTrigger>
|
|
231
284
|
<DropdownMenuContent
|
|
232
|
-
className="w-
|
|
285
|
+
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
|
|
233
286
|
side={isMobile ? "bottom" : "right"}
|
|
234
287
|
align="end"
|
|
235
288
|
sideOffset={4}
|
|
@@ -238,12 +291,10 @@ export function NavUser({ user }: { user: User }) {
|
|
|
238
291
|
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
|
239
292
|
<Avatar className="h-8 w-8 rounded-lg">
|
|
240
293
|
<AvatarImage src={user.avatar} alt={user.name} />
|
|
241
|
-
<AvatarFallback className="rounded-lg">
|
|
242
|
-
{user.name.slice(0, 2).toUpperCase()}
|
|
243
|
-
</AvatarFallback>
|
|
294
|
+
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
|
244
295
|
</Avatar>
|
|
245
296
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
|
246
|
-
<span className="truncate font-
|
|
297
|
+
<span className="truncate font-medium">{user.name}</span>
|
|
247
298
|
<span className="truncate text-xs">{user.email}</span>
|
|
248
299
|
</div>
|
|
249
300
|
</div>
|
|
@@ -252,28 +303,28 @@ export function NavUser({ user }: { user: User }) {
|
|
|
252
303
|
<DropdownMenuGroup>
|
|
253
304
|
<DropdownMenuItem>
|
|
254
305
|
<SparklesIcon />
|
|
255
|
-
Upgrade
|
|
306
|
+
Upgrade to Pro
|
|
256
307
|
</DropdownMenuItem>
|
|
257
308
|
</DropdownMenuGroup>
|
|
258
309
|
<DropdownMenuSeparator />
|
|
259
310
|
<DropdownMenuGroup>
|
|
260
311
|
<DropdownMenuItem>
|
|
261
312
|
<BadgeCheckIcon />
|
|
262
|
-
|
|
313
|
+
Account
|
|
263
314
|
</DropdownMenuItem>
|
|
264
315
|
<DropdownMenuItem>
|
|
265
316
|
<CreditCardIcon />
|
|
266
|
-
|
|
317
|
+
Billing
|
|
267
318
|
</DropdownMenuItem>
|
|
268
319
|
<DropdownMenuItem>
|
|
269
320
|
<BellIcon />
|
|
270
|
-
|
|
321
|
+
Notifications
|
|
271
322
|
</DropdownMenuItem>
|
|
272
323
|
</DropdownMenuGroup>
|
|
273
324
|
<DropdownMenuSeparator />
|
|
274
325
|
<DropdownMenuItem>
|
|
275
326
|
<LogOutIcon />
|
|
276
|
-
|
|
327
|
+
Log out
|
|
277
328
|
</DropdownMenuItem>
|
|
278
329
|
</DropdownMenuContent>
|
|
279
330
|
</DropdownMenu>
|
|
@@ -286,13 +337,13 @@ export function NavUser({ user }: { user: User }) {
|
|
|
286
337
|
"src/components/team-switcher.tsx": `"use client"
|
|
287
338
|
|
|
288
339
|
import * as React from "react"
|
|
289
|
-
import { ChevronsUpDownIcon, PlusIcon } from "lucide-react"
|
|
290
340
|
import {
|
|
291
341
|
DropdownMenu,
|
|
292
342
|
DropdownMenuContent,
|
|
293
343
|
DropdownMenuItem,
|
|
294
344
|
DropdownMenuLabel,
|
|
295
345
|
DropdownMenuSeparator,
|
|
346
|
+
DropdownMenuShortcut,
|
|
296
347
|
DropdownMenuTrigger,
|
|
297
348
|
} from "@/components/ui/dropdown-menu"
|
|
298
349
|
import {
|
|
@@ -301,12 +352,21 @@ import {
|
|
|
301
352
|
SidebarMenuItem,
|
|
302
353
|
useSidebar,
|
|
303
354
|
} from "@/components/ui/sidebar"
|
|
355
|
+
import { ChevronsUpDownIcon, PlusIcon } from "lucide-react"
|
|
304
356
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
357
|
+
export function TeamSwitcher({
|
|
358
|
+
teams,
|
|
359
|
+
}: {
|
|
360
|
+
teams: {
|
|
361
|
+
name: string
|
|
362
|
+
logo: React.ReactNode
|
|
363
|
+
plan: string
|
|
364
|
+
}[]
|
|
365
|
+
}) {
|
|
308
366
|
const { isMobile } = useSidebar()
|
|
309
|
-
const [
|
|
367
|
+
const [activeTeam, setActiveTeam] = React.useState(teams[0])
|
|
368
|
+
|
|
369
|
+
if (!activeTeam) return null
|
|
310
370
|
|
|
311
371
|
return (
|
|
312
372
|
<SidebarMenu>
|
|
@@ -317,18 +377,18 @@ export function TeamSwitcher({ teams }: { teams: Team[] }) {
|
|
|
317
377
|
size="lg"
|
|
318
378
|
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
|
319
379
|
>
|
|
320
|
-
<div className="flex aspect-square size-8 items-center justify-center rounded-
|
|
321
|
-
{
|
|
380
|
+
<div className="flex aspect-square size-8 items-center justify-center rounded-full bg-sidebar-primary text-sidebar-primary-foreground">
|
|
381
|
+
{activeTeam.logo}
|
|
322
382
|
</div>
|
|
323
383
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
|
324
|
-
<span className="truncate font-
|
|
325
|
-
<span className="truncate text-xs">{
|
|
384
|
+
<span className="truncate font-medium">{activeTeam.name}</span>
|
|
385
|
+
<span className="truncate text-xs">{activeTeam.plan}</span>
|
|
326
386
|
</div>
|
|
327
387
|
<ChevronsUpDownIcon className="ml-auto" />
|
|
328
388
|
</SidebarMenuButton>
|
|
329
389
|
</DropdownMenuTrigger>
|
|
330
390
|
<DropdownMenuContent
|
|
331
|
-
className="w-
|
|
391
|
+
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
|
|
332
392
|
align="start"
|
|
333
393
|
side={isMobile ? "bottom" : "right"}
|
|
334
394
|
sideOffset={4}
|
|
@@ -336,17 +396,22 @@ export function TeamSwitcher({ teams }: { teams: Team[] }) {
|
|
|
336
396
|
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
|
337
397
|
Times
|
|
338
398
|
</DropdownMenuLabel>
|
|
339
|
-
{teams.map((team) => (
|
|
340
|
-
<DropdownMenuItem
|
|
341
|
-
|
|
399
|
+
{teams.map((team, index) => (
|
|
400
|
+
<DropdownMenuItem
|
|
401
|
+
key={team.name}
|
|
402
|
+
onClick={() => setActiveTeam(team)}
|
|
403
|
+
className="gap-2 p-2"
|
|
404
|
+
>
|
|
405
|
+
<div className="flex size-6 items-center justify-center rounded-md border">
|
|
342
406
|
{team.logo}
|
|
343
407
|
</div>
|
|
344
408
|
{team.name}
|
|
409
|
+
<DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>
|
|
345
410
|
</DropdownMenuItem>
|
|
346
411
|
))}
|
|
347
412
|
<DropdownMenuSeparator />
|
|
348
413
|
<DropdownMenuItem className="gap-2 p-2">
|
|
349
|
-
<div className="flex size-6 items-center justify-center rounded-md border bg-
|
|
414
|
+
<div className="flex size-6 items-center justify-center rounded-md border bg-transparent">
|
|
350
415
|
<PlusIcon className="size-4" />
|
|
351
416
|
</div>
|
|
352
417
|
<div className="font-medium text-muted-foreground">Adicionar time</div>
|
|
@@ -374,7 +439,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
|
|
|
374
439
|
}
|
|
375
440
|
`,
|
|
376
441
|
|
|
377
|
-
"src/app/(app)/page.tsx": `export default function Home() {
|
|
442
|
+
"src/app/(app)/dashboard/page.tsx": `export default function Home() {
|
|
378
443
|
return (
|
|
379
444
|
<div className="p-6">
|
|
380
445
|
<h1 className="text-2xl font-semibold">Dashboard</h1>
|
|
@@ -387,7 +452,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
|
|
|
387
452
|
"src/app/page.tsx": `import { redirect } from "next/navigation"
|
|
388
453
|
|
|
389
454
|
export default function Root() {
|
|
390
|
-
redirect("/")
|
|
455
|
+
redirect("/dashboard")
|
|
391
456
|
}
|
|
392
457
|
`,
|
|
393
458
|
}
|
|
@@ -459,13 +524,101 @@ async function main() {
|
|
|
459
524
|
console.log("✔ lucide-react encontrado")
|
|
460
525
|
}
|
|
461
526
|
|
|
462
|
-
// 5.
|
|
527
|
+
// 5. Patch no sidebar.tsx: centralizar verticalmente, ajustar altura ao conteúdo e efeito cápsula
|
|
528
|
+
const sidebarUiPath = path.join(cwd, "src/components/ui/sidebar.tsx")
|
|
529
|
+
if (fs.existsSync(sidebarUiPath)) {
|
|
530
|
+
let sidebarUi = fs.readFileSync(sidebarUiPath, "utf8")
|
|
531
|
+
sidebarUi = sidebarUi.replace(
|
|
532
|
+
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear",
|
|
533
|
+
"fixed top-1/2 -translate-y-1/2 z-10 hidden h-fit w-(--sidebar-width) transition-[left,right,width,height,transform] duration-300 ease-in-out"
|
|
534
|
+
)
|
|
535
|
+
sidebarUi = sidebarUi.replace(
|
|
536
|
+
"group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border",
|
|
537
|
+
"group-data-[variant=floating]:rounded-2xl group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border group-data-[collapsible=icon]:group-data-[variant=floating]:[animation:sidebar-collapse_300ms_ease-in-out_forwards] group-data-[state=expanded]:group-data-[variant=floating]:[animation:sidebar-expand_0ms_forwards]"
|
|
538
|
+
)
|
|
539
|
+
sidebarUi = sidebarUi.replace(
|
|
540
|
+
"transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8",
|
|
541
|
+
"transition-[width,height,padding] duration-200 group-has-data-[sidebar=menu-action]/menu-item:pr-8"
|
|
542
|
+
)
|
|
543
|
+
sidebarUi = sidebarUi.replace(
|
|
544
|
+
"[&>span:last-child]:truncate",
|
|
545
|
+
"[&>span:last-child]:truncate [&>span:last-child]:transition-[opacity] [&>span:last-child]:duration-100 [&>span:last-child]:ease-in group-data-[collapsible=icon]:[&>span:last-child]:opacity-0"
|
|
546
|
+
)
|
|
547
|
+
fs.writeFileSync(sidebarUiPath, sidebarUi, "utf8")
|
|
548
|
+
console.log(" ✔ src/components/ui/sidebar.tsx (centralizada + cápsula)")
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// 6. Escrever arquivos da sidebar
|
|
463
552
|
console.log("\n→ Gerando arquivos da sidebar...")
|
|
464
553
|
for (const [filePath, content] of Object.entries(FILES)) {
|
|
465
554
|
write(filePath, content)
|
|
466
555
|
console.log(` ✔ ${filePath}`)
|
|
467
556
|
}
|
|
468
557
|
|
|
558
|
+
// 7. Patch no globals.css: animação dos collapsibles
|
|
559
|
+
const globalsCssPath = path.join(cwd, "src/app/globals.css")
|
|
560
|
+
if (fs.existsSync(globalsCssPath)) {
|
|
561
|
+
let css = fs.readFileSync(globalsCssPath, "utf8")
|
|
562
|
+
const needsCollapsible = !css.includes("collapsible-down")
|
|
563
|
+
const needsCapsule = !css.includes("sidebar-collapse")
|
|
564
|
+
if (needsCollapsible || needsCapsule) {
|
|
565
|
+
const collapsibleCss = needsCollapsible ? `
|
|
566
|
+
@keyframes collapsible-down {
|
|
567
|
+
from { height: 0; opacity: 0; }
|
|
568
|
+
to { height: var(--radix-collapsible-content-height); opacity: 1; }
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
@keyframes collapsible-up {
|
|
572
|
+
from { height: var(--radix-collapsible-content-height); opacity: 1; }
|
|
573
|
+
to { height: 0; opacity: 0; }
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
[data-slot="collapsible-content"] {
|
|
577
|
+
overflow: hidden;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
[data-slot="collapsible-content"][data-state="open"] {
|
|
581
|
+
animation: collapsible-down 200ms ease-out;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
[data-slot="collapsible-content"][data-state="closed"] {
|
|
585
|
+
animation: collapsible-up 200ms ease-out;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
` : ""
|
|
589
|
+
const capsuleCss = needsCapsule ? `@keyframes sidebar-collapse {
|
|
590
|
+
0% { border-radius: calc(var(--radius) * 1.8); }
|
|
591
|
+
79% { border-radius: calc(var(--radius) * 1.8); }
|
|
592
|
+
100% { border-radius: 9999px; }
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
@keyframes sidebar-expand {
|
|
596
|
+
from { border-radius: calc(var(--radius) * 1.8); }
|
|
597
|
+
to { border-radius: calc(var(--radius) * 1.8); }
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
` : ""
|
|
601
|
+
css = css.replace(/@layer base \{/, capsuleCss + collapsibleCss + "@layer base {")
|
|
602
|
+
fs.writeFileSync(globalsCssPath, css, "utf8")
|
|
603
|
+
console.log(" ✔ src/app/globals.css (animação collapsible)")
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// 6. Patch no root layout para adicionar TooltipProvider
|
|
608
|
+
const rootLayoutPath = path.join(cwd, "src/app/layout.tsx")
|
|
609
|
+
if (fs.existsSync(rootLayoutPath)) {
|
|
610
|
+
let rootLayout = fs.readFileSync(rootLayoutPath, "utf8")
|
|
611
|
+
if (!rootLayout.includes("TooltipProvider")) {
|
|
612
|
+
rootLayout = rootLayout.replace(
|
|
613
|
+
/^(import .+from .+;\n)/m,
|
|
614
|
+
`$1import { TooltipProvider } from "@/components/ui/tooltip"\n`
|
|
615
|
+
)
|
|
616
|
+
rootLayout = rootLayout.replace(/<body([^>]*)>(\s*)\{children\}/, `<body$1>$2<TooltipProvider>{children}</TooltipProvider>`)
|
|
617
|
+
fs.writeFileSync(rootLayoutPath, rootLayout, "utf8")
|
|
618
|
+
console.log(" ✔ src/app/layout.tsx (TooltipProvider adicionado)")
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
469
622
|
console.log("\n✔ Sidebar instalada com sucesso!")
|
|
470
623
|
console.log("\nPróximo passo:\n pnpm dev\n")
|
|
471
624
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hznrkv/sidebar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "CLI para instalar a sidebar @hznrkv em projetos Next.js + Shadcn",
|
|
5
5
|
"bin": {
|
|
6
|
-
"sidebar": "./index.js"
|
|
6
|
+
"@hznrkv/sidebar": "./index.js"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
9
|
"dependencies": {
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
15
15
|
}
|
|
16
|
-
}
|
|
16
|
+
}
|