@freitas-ds/react 0.1.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/dist/index.mjs ADDED
@@ -0,0 +1,2728 @@
1
+ import { AlertTriangle, ArrowUpDown, CalendarIcon, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsUpDown, Circle, CircleAlert, CircleCheck, CircleX, Inbox, Info, LoaderCircle, LogOut, MoreHorizontal, Search, Settings, User, X } from "lucide-react";
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
6
+ import * as React from "react";
7
+ import { Slot } from "@radix-ui/react-slot";
8
+ import { cva } from "class-variance-authority";
9
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
10
+ import { DayPicker } from "react-day-picker";
11
+ import { ptBR } from "react-day-picker/locale";
12
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
13
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
14
+ import { Command } from "cmdk";
15
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
16
+ import { format } from "date-fns";
17
+ import { ptBR as ptBR$1 } from "date-fns/locale";
18
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
19
+ import { useForm } from "@tanstack/react-form";
20
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
21
+ import * as SelectPrimitive from "@radix-ui/react-select";
22
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
23
+ import * as SwitchPrimitive from "@radix-ui/react-switch";
24
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
25
+ import * as ToastPrimitive from "@radix-ui/react-toast";
26
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
27
+ import { applyTheme, resolveTheme } from "@freitas-ds/theme";
28
+ //#region src/utils/cn.ts
29
+ function cn(...inputs) {
30
+ return twMerge(clsx(inputs));
31
+ }
32
+ //#endregion
33
+ //#region src/components/action-bar.tsx
34
+ function ActionBar({ selectedCount, label, onClearSelection, className, children, ...props }) {
35
+ if (selectedCount <= 0) return null;
36
+ return /* @__PURE__ */ jsxs("div", {
37
+ className: cn("flex flex-col gap-3 rounded-fds-lg border border-primary/30 bg-primary-container p-3 text-on-primary-container", "sm:flex-row sm:items-center sm:justify-between", className),
38
+ ...props,
39
+ children: [/* @__PURE__ */ jsxs("div", {
40
+ className: "flex min-w-0 items-center gap-3",
41
+ children: [onClearSelection ? /* @__PURE__ */ jsx("button", {
42
+ type: "button",
43
+ onClick: onClearSelection,
44
+ className: cn("flex size-7 shrink-0 items-center justify-center rounded-fds-md", "text-on-primary-container/80 transition-colors", "hover:bg-primary/10 hover:text-on-primary-container", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/35"),
45
+ "aria-label": "Limpar seleção",
46
+ children: /* @__PURE__ */ jsx(X, { className: "size-4" })
47
+ }) : null, /* @__PURE__ */ jsx("p", {
48
+ className: "body-sm font-medium",
49
+ children: label ?? `${selectedCount} item(ns) selecionado(s)`
50
+ })]
51
+ }), children ? /* @__PURE__ */ jsx("div", {
52
+ className: "flex flex-wrap items-center gap-2",
53
+ children
54
+ }) : null]
55
+ });
56
+ }
57
+ //#endregion
58
+ //#region src/components/alert.tsx
59
+ const alertToneClasses = {
60
+ neutral: "border-border bg-muted text-on-surface",
61
+ info: "border-info/30 bg-info-container text-on-info-container",
62
+ success: "border-success/30 bg-success-container text-on-success-container",
63
+ warning: "border-warning/30 bg-warning-container text-on-warning-container",
64
+ danger: "border-error/30 bg-error-container text-on-error-container"
65
+ };
66
+ const iconToneClasses = {
67
+ neutral: "text-muted-foreground",
68
+ info: "text-info",
69
+ success: "text-success",
70
+ warning: "text-warning",
71
+ danger: "text-error"
72
+ };
73
+ const defaultIcons = {
74
+ neutral: /* @__PURE__ */ jsx(Info, { className: "size-4" }),
75
+ info: /* @__PURE__ */ jsx(Info, { className: "size-4" }),
76
+ success: /* @__PURE__ */ jsx(CircleCheck, { className: "size-4" }),
77
+ warning: /* @__PURE__ */ jsx(CircleAlert, { className: "size-4" }),
78
+ danger: /* @__PURE__ */ jsx(CircleX, { className: "size-4" })
79
+ };
80
+ function Alert({ className, tone = "info", title, description, icon, children, ...props }) {
81
+ const currentIcon = icon === false ? null : icon ?? defaultIcons[tone];
82
+ return /* @__PURE__ */ jsxs("div", {
83
+ role: "status",
84
+ className: cn("relative flex gap-3 rounded-fds-lg border p-4", alertToneClasses[tone], className),
85
+ ...props,
86
+ children: [currentIcon ? /* @__PURE__ */ jsx("div", {
87
+ className: cn("mt-0.5 shrink-0", iconToneClasses[tone]),
88
+ children: currentIcon
89
+ }) : null, /* @__PURE__ */ jsxs("div", {
90
+ className: "min-w-0 flex-1",
91
+ children: [
92
+ title ? /* @__PURE__ */ jsx("h3", {
93
+ className: "body-sm font-semibold leading-5",
94
+ children: title
95
+ }) : null,
96
+ description ? /* @__PURE__ */ jsx("p", {
97
+ className: cn("body-sm", title && "mt-1"),
98
+ children: description
99
+ }) : null,
100
+ children ? /* @__PURE__ */ jsx("div", {
101
+ className: title || description ? "mt-2" : "",
102
+ children
103
+ }) : null
104
+ ]
105
+ })]
106
+ });
107
+ }
108
+ //#endregion
109
+ //#region src/components/button.tsx
110
+ const buttonVariants = cva([
111
+ "inline-flex items-center justify-center gap-2",
112
+ "rounded-fds-md",
113
+ "font-medium",
114
+ "transition-colors duration-150",
115
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface",
116
+ "disabled:pointer-events-none disabled:opacity-50"
117
+ ], {
118
+ variants: {
119
+ variant: {
120
+ primary: "bg-primary text-on-primary hover:brightness-95",
121
+ secondary: "bg-secondary text-on-secondary hover:brightness-95",
122
+ tertiary: "bg-tertiary text-on-tertiary hover:brightness-95",
123
+ danger: "bg-error text-on-error hover:brightness-95",
124
+ outline: "border border-outline bg-transparent text-on-surface hover:bg-surface-container",
125
+ ghost: "bg-transparent text-on-surface hover:bg-surface-container"
126
+ },
127
+ size: {
128
+ sm: "h-8 px-3 text-sm",
129
+ md: "h-10 px-4 text-sm",
130
+ lg: "h-12 px-6 text-base"
131
+ },
132
+ fullWidth: {
133
+ true: "w-full",
134
+ false: ""
135
+ }
136
+ },
137
+ defaultVariants: {
138
+ variant: "primary",
139
+ size: "md",
140
+ fullWidth: false
141
+ }
142
+ });
143
+ const Button = React.forwardRef(({ className, variant, size, fullWidth, loading = false, disabled, asChild = false, children, ...props }, ref) => {
144
+ return /* @__PURE__ */ jsx(asChild ? Slot : "button", {
145
+ ref,
146
+ className: cn(buttonVariants({
147
+ variant,
148
+ size,
149
+ fullWidth
150
+ }), className),
151
+ disabled: disabled || loading,
152
+ "aria-busy": loading,
153
+ ...props,
154
+ children: loading ? "Carregando..." : children
155
+ });
156
+ });
157
+ Button.displayName = "Button";
158
+ //#endregion
159
+ //#region src/components/alert-dialog.tsx
160
+ const AlertDialog = AlertDialogPrimitive.Root;
161
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
162
+ const AlertDialogPortal = AlertDialogPrimitive.Portal;
163
+ const AlertDialogCancel = AlertDialogPrimitive.Cancel;
164
+ const AlertDialogAction = AlertDialogPrimitive.Action;
165
+ const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => {
166
+ return /* @__PURE__ */ jsx(AlertDialogPrimitive.Overlay, {
167
+ ref,
168
+ className: cn("fixed inset-0 z-50 bg-black/45", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", className),
169
+ ...props
170
+ });
171
+ });
172
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
173
+ const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => {
174
+ return /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [/* @__PURE__ */ jsx(AlertDialogOverlay, {}), /* @__PURE__ */ jsx(AlertDialogPrimitive.Content, {
175
+ ref,
176
+ className: cn("fixed left-1/2 top-1/2 z-50 grid w-[calc(100%-2rem)] max-w-md", "-translate-x-1/2 -translate-y-1/2 gap-4", "rounded-fds-lg border border-border bg-popover p-6 text-popover-foreground shadow-lg", "duration-200", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", className),
177
+ ...props
178
+ })] });
179
+ });
180
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
181
+ function AlertDialogHeader({ className, ...props }) {
182
+ return /* @__PURE__ */ jsx("div", {
183
+ className: cn("flex flex-col gap-1.5 text-left", className),
184
+ ...props
185
+ });
186
+ }
187
+ function AlertDialogFooter({ className, ...props }) {
188
+ return /* @__PURE__ */ jsx("div", {
189
+ className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className),
190
+ ...props
191
+ });
192
+ }
193
+ const AlertDialogTitle = React.forwardRef(({ className, ...props }, ref) => {
194
+ return /* @__PURE__ */ jsx(AlertDialogPrimitive.Title, {
195
+ ref,
196
+ className: cn("h3 text-on-surface", className),
197
+ ...props
198
+ });
199
+ });
200
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
201
+ const AlertDialogDescription = React.forwardRef(({ className, ...props }, ref) => {
202
+ return /* @__PURE__ */ jsx(AlertDialogPrimitive.Description, {
203
+ ref,
204
+ className: cn("body-sm text-muted", className),
205
+ ...props
206
+ });
207
+ });
208
+ AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
209
+ function AlertDialogCancelButton({ className, ...props }) {
210
+ return /* @__PURE__ */ jsx(AlertDialogPrimitive.Cancel, {
211
+ className: cn(buttonVariants({
212
+ variant: "outline",
213
+ size: "md"
214
+ }), className),
215
+ ...props
216
+ });
217
+ }
218
+ function AlertDialogActionButton({ className, variant = "danger", ...props }) {
219
+ return /* @__PURE__ */ jsx(AlertDialogPrimitive.Action, {
220
+ className: cn(buttonVariants({
221
+ variant,
222
+ size: "md"
223
+ }), className),
224
+ ...props
225
+ });
226
+ }
227
+ //#endregion
228
+ //#region src/components/app-shell.tsx
229
+ function AppShell({ sidebar, topbar, children, className, ...props }) {
230
+ return /* @__PURE__ */ jsxs("div", {
231
+ className: cn("h-dvh overflow-hidden bg-surface text-on-surface", "grid grid-cols-1 md:grid-cols-[16rem_minmax(0,1fr)]", className),
232
+ ...props,
233
+ children: [sidebar ? /* @__PURE__ */ jsx("aside", {
234
+ className: "hidden h-dvh min-h-0 overflow-hidden border-r border-border bg-card md:block",
235
+ children: sidebar
236
+ }) : null, /* @__PURE__ */ jsxs("div", {
237
+ className: "flex min-h-0 min-w-0 flex-col",
238
+ children: [topbar ? /* @__PURE__ */ jsx("header", {
239
+ className: "shrink-0 border-b border-border bg-surface/90 backdrop-blur",
240
+ children: topbar
241
+ }) : null, /* @__PURE__ */ jsx("main", {
242
+ className: "min-h-0 min-w-0 flex-1 overflow-y-auto",
243
+ children
244
+ })]
245
+ })]
246
+ });
247
+ }
248
+ function AppShellContent({ className, ...props }) {
249
+ return /* @__PURE__ */ jsx("div", {
250
+ className: cn("mx-auto flex w-full max-w-6xl flex-col gap-8 px-6 py-8", className),
251
+ ...props
252
+ });
253
+ }
254
+ //#endregion
255
+ //#region src/components/avatar.tsx
256
+ const Avatar = React.forwardRef(({ className, ...props }, ref) => {
257
+ return /* @__PURE__ */ jsx(AvatarPrimitive.Root, {
258
+ ref,
259
+ className: cn("relative flex size-10 shrink-0 overflow-hidden rounded-fds-full", className),
260
+ ...props
261
+ });
262
+ });
263
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
264
+ const AvatarImage = React.forwardRef(({ className, ...props }, ref) => {
265
+ return /* @__PURE__ */ jsx(AvatarPrimitive.Image, {
266
+ ref,
267
+ className: cn("aspect-square size-full object-cover", className),
268
+ ...props
269
+ });
270
+ });
271
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
272
+ const AvatarFallback = React.forwardRef(({ className, ...props }, ref) => {
273
+ return /* @__PURE__ */ jsx(AvatarPrimitive.Fallback, {
274
+ ref,
275
+ className: cn("flex size-full items-center justify-center rounded-fds-full", "bg-primary-container text-sm font-semibold text-on-primary-container", className),
276
+ ...props
277
+ });
278
+ });
279
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
280
+ function getInitials(name) {
281
+ return name.trim().split(/\s+/).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("");
282
+ }
283
+ //#endregion
284
+ //#region src/components/badge.tsx
285
+ const badgeVariants = cva([
286
+ "inline-flex w-fit shrink-0 items-center gap-1",
287
+ "rounded-fds-full border px-2 py-0.5",
288
+ "text-xs font-medium leading-5",
289
+ "transition-colors duration-150"
290
+ ], {
291
+ variants: {
292
+ tone: {
293
+ neutral: "border-border bg-muted text-muted-foreground",
294
+ primary: "border-transparent bg-primary-container text-on-primary-container",
295
+ secondary: "border-transparent bg-secondary-container text-on-secondary-container",
296
+ success: "border-transparent bg-success-container text-on-success-container",
297
+ warning: "border-transparent bg-warning-container text-on-warning-container",
298
+ info: "border-transparent bg-info-container text-on-info-container",
299
+ danger: "border-transparent bg-error-container text-on-error-container"
300
+ },
301
+ variant: {
302
+ soft: "",
303
+ outline: "bg-transparent",
304
+ solid: ""
305
+ }
306
+ },
307
+ compoundVariants: [
308
+ {
309
+ tone: "primary",
310
+ variant: "solid",
311
+ className: "border-transparent bg-primary text-on-primary"
312
+ },
313
+ {
314
+ tone: "secondary",
315
+ variant: "solid",
316
+ className: "border-transparent bg-secondary text-on-secondary"
317
+ },
318
+ {
319
+ tone: "success",
320
+ variant: "solid",
321
+ className: "border-transparent bg-success text-on-success"
322
+ },
323
+ {
324
+ tone: "warning",
325
+ variant: "solid",
326
+ className: "border-transparent bg-warning text-on-warning"
327
+ },
328
+ {
329
+ tone: "info",
330
+ variant: "solid",
331
+ className: "border-transparent bg-info text-on-info"
332
+ },
333
+ {
334
+ tone: "danger",
335
+ variant: "solid",
336
+ className: "border-transparent bg-error text-on-error"
337
+ },
338
+ {
339
+ tone: "neutral",
340
+ variant: "outline",
341
+ className: "border-border text-on-surface"
342
+ },
343
+ {
344
+ tone: "primary",
345
+ variant: "outline",
346
+ className: "border-primary text-primary"
347
+ },
348
+ {
349
+ tone: "secondary",
350
+ variant: "outline",
351
+ className: "border-secondary text-secondary"
352
+ },
353
+ {
354
+ tone: "success",
355
+ variant: "outline",
356
+ className: "border-success text-success"
357
+ },
358
+ {
359
+ tone: "warning",
360
+ variant: "outline",
361
+ className: "border-warning text-warning"
362
+ },
363
+ {
364
+ tone: "info",
365
+ variant: "outline",
366
+ className: "border-info text-info"
367
+ },
368
+ {
369
+ tone: "danger",
370
+ variant: "outline",
371
+ className: "border-error text-error"
372
+ }
373
+ ],
374
+ defaultVariants: {
375
+ tone: "neutral",
376
+ variant: "soft"
377
+ }
378
+ });
379
+ function Badge({ className, tone, variant, ...props }) {
380
+ return /* @__PURE__ */ jsx("span", {
381
+ className: cn(badgeVariants({
382
+ tone,
383
+ variant
384
+ }), className),
385
+ ...props
386
+ });
387
+ }
388
+ //#endregion
389
+ //#region src/components/breadcrumb.tsx
390
+ function Breadcrumb({ className, ...props }) {
391
+ return /* @__PURE__ */ jsx("nav", {
392
+ "aria-label": "Breadcrumb",
393
+ className: cn("flex", className),
394
+ ...props
395
+ });
396
+ }
397
+ function BreadcrumbList({ className, ...props }) {
398
+ return /* @__PURE__ */ jsx("ol", {
399
+ className: cn("flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground", className),
400
+ ...props
401
+ });
402
+ }
403
+ function BreadcrumbItem({ className, ...props }) {
404
+ return /* @__PURE__ */ jsx("li", {
405
+ className: cn("inline-flex items-center gap-1.5", className),
406
+ ...props
407
+ });
408
+ }
409
+ function BreadcrumbLink({ className, ...props }) {
410
+ return /* @__PURE__ */ jsx("a", {
411
+ className: cn("transition-colors hover:text-on-surface", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", className),
412
+ ...props
413
+ });
414
+ }
415
+ function BreadcrumbPage({ className, ...props }) {
416
+ return /* @__PURE__ */ jsx("span", {
417
+ "aria-current": "page",
418
+ className: cn("font-medium text-on-surface", className),
419
+ ...props
420
+ });
421
+ }
422
+ function BreadcrumbSeparator({ children, className, ...props }) {
423
+ return /* @__PURE__ */ jsx("li", {
424
+ role: "presentation",
425
+ "aria-hidden": "true",
426
+ className: cn("text-muted-foreground", className),
427
+ ...props,
428
+ children: children ?? /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
429
+ });
430
+ }
431
+ function BreadcrumbEllipsis({ className, ...props }) {
432
+ return /* @__PURE__ */ jsxs("span", {
433
+ role: "presentation",
434
+ "aria-hidden": "true",
435
+ className: cn("flex size-9 items-center justify-center", className),
436
+ ...props,
437
+ children: [/* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
438
+ className: "sr-only",
439
+ children: "Mais"
440
+ })]
441
+ });
442
+ }
443
+ //#endregion
444
+ //#region src/components/calendar.tsx
445
+ function Calendar({ className, classNames, locale = ptBR, showOutsideDays = true, navLayout = "after", components, ...props }) {
446
+ return /* @__PURE__ */ jsx(DayPicker, {
447
+ locale,
448
+ showOutsideDays,
449
+ navLayout,
450
+ className: cn("p-3", className),
451
+ classNames: {
452
+ root: "w-fit",
453
+ months: "flex flex-col gap-4",
454
+ month: "space-y-4",
455
+ month_caption: "flex h-8 items-center justify-center px-8",
456
+ caption_label: "body-sm font-semibold text-on-surface",
457
+ nav: "absolute right-3 top-3 flex items-center gap-1",
458
+ button_previous: cn(buttonVariants({
459
+ variant: "ghost",
460
+ size: "sm"
461
+ }), "size-8 p-0"),
462
+ button_next: cn(buttonVariants({
463
+ variant: "ghost",
464
+ size: "sm"
465
+ }), "size-8 p-0"),
466
+ month_grid: "w-full border-collapse space-y-1",
467
+ weekdays: "flex",
468
+ weekday: "flex size-9 items-center justify-center rounded-fds-sm caption font-medium text-muted",
469
+ week: "mt-1 flex w-full",
470
+ day: "size-9 p-0 text-center body-sm",
471
+ day_button: cn("flex size-9 items-center justify-center rounded-fds-md body-sm outline-none", "transition-colors duration-150", "hover:bg-accent hover:text-accent-foreground", "focus-visible:ring-2 focus-visible:ring-ring/35"),
472
+ selected: "[&>button]:bg-primary [&>button]:text-on-primary",
473
+ today: "[&>button]:border [&>button]:border-primary",
474
+ outside: "text-muted opacity-45",
475
+ disabled: "pointer-events-none text-muted opacity-35",
476
+ range_start: "[&>button]:rounded-r-none [&>button]:bg-primary [&>button]:text-on-primary",
477
+ range_middle: "[&>button]:rounded-none [&>button]:bg-primary-container [&>button]:text-on-primary-container",
478
+ range_end: "[&>button]:rounded-l-none [&>button]:bg-primary [&>button]:text-on-primary",
479
+ hidden: "invisible",
480
+ ...classNames
481
+ },
482
+ components: {
483
+ Chevron: ({ orientation, className, ...iconProps }) => orientation === "left" ? /* @__PURE__ */ jsx(ChevronLeft, {
484
+ className: cn("size-4", className),
485
+ ...iconProps
486
+ }) : /* @__PURE__ */ jsx(ChevronRight, {
487
+ className: cn("size-4", className),
488
+ ...iconProps
489
+ }),
490
+ ...components
491
+ },
492
+ ...props
493
+ });
494
+ }
495
+ //#endregion
496
+ //#region src/components/card.tsx
497
+ function Card({ className, ...props }) {
498
+ return /* @__PURE__ */ jsx("div", {
499
+ className: cn("rounded-fds-lg border border-border bg-card text-card-foreground shadow-sm", "p-6", className),
500
+ ...props
501
+ });
502
+ }
503
+ function CardHeader({ className, ...props }) {
504
+ return /* @__PURE__ */ jsx("div", {
505
+ className: cn("mb-5 flex flex-col gap-1.5", className),
506
+ ...props
507
+ });
508
+ }
509
+ function CardContent({ className, ...props }) {
510
+ return /* @__PURE__ */ jsx("div", {
511
+ className: cn("body", className),
512
+ ...props
513
+ });
514
+ }
515
+ function CardFooter({ className, ...props }) {
516
+ return /* @__PURE__ */ jsx("div", {
517
+ className: cn("mt-6 flex flex-wrap items-center gap-3", className),
518
+ ...props
519
+ });
520
+ }
521
+ //#endregion
522
+ //#region src/components/label.tsx
523
+ function Label({ className, children, required = false, requiredIndicator = "*", showRequiredIndicator = true, ...props }) {
524
+ return /* @__PURE__ */ jsxs("label", {
525
+ className: cn("body-sm font-medium text-on-surface", "disabled:pointer-events-none disabled:opacity-50", className),
526
+ ...props,
527
+ children: [children, required ? /* @__PURE__ */ jsxs(Fragment, { children: [showRequiredIndicator ? /* @__PURE__ */ jsxs(Fragment, { children: [" ", /* @__PURE__ */ jsx("span", {
528
+ className: "ml-1 text-error",
529
+ "aria-hidden": "true",
530
+ children: requiredIndicator
531
+ })] }) : null, /* @__PURE__ */ jsx("span", {
532
+ className: "sr-only",
533
+ children: " obrigatório"
534
+ })] }) : null]
535
+ });
536
+ }
537
+ //#endregion
538
+ //#region src/components/checkbox.tsx
539
+ const Checkbox = React.forwardRef(({ className, error = false, ...props }, ref) => {
540
+ return /* @__PURE__ */ jsx(CheckboxPrimitive.Root, {
541
+ ref,
542
+ className: cn("peer size-4 shrink-0 rounded-sm border border-input bg-transparent shadow-sm", "transition-[color,box-shadow,border-color,background-color] duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:cursor-not-allowed disabled:opacity-50", "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-on-primary", error && "border-destructive focus-visible:ring-destructive/25 data-[state=checked]:border-destructive data-[state=checked]:bg-destructive data-[state=checked]:text-destructive-foreground", className),
543
+ ...props,
544
+ children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, {
545
+ className: "flex items-center justify-center text-current",
546
+ children: /* @__PURE__ */ jsx(Check, { className: "size-3.5" })
547
+ })
548
+ });
549
+ });
550
+ Checkbox.displayName = "Checkbox";
551
+ function CheckboxField({ id, label, description, errorMessage, required, className, ...props }) {
552
+ const generatedId = React.useId();
553
+ const fieldId = id ?? generatedId;
554
+ const descriptionId = description ? `${fieldId}-description` : void 0;
555
+ const errorId = errorMessage ? `${fieldId}-error` : void 0;
556
+ const describedBy = [descriptionId, errorId].filter(Boolean).join(" ") || void 0;
557
+ return /* @__PURE__ */ jsxs("div", {
558
+ className: cn("flex flex-col gap-1.5", className),
559
+ children: [/* @__PURE__ */ jsxs("div", {
560
+ className: "flex items-start gap-3",
561
+ children: [/* @__PURE__ */ jsx(Checkbox, {
562
+ id: fieldId,
563
+ required,
564
+ "aria-describedby": describedBy,
565
+ "aria-invalid": errorMessage ? true : void 0,
566
+ error: Boolean(errorMessage),
567
+ ...props
568
+ }), /* @__PURE__ */ jsxs("div", {
569
+ className: "grid gap-1 leading-none",
570
+ children: [/* @__PURE__ */ jsx(Label, {
571
+ htmlFor: fieldId,
572
+ required,
573
+ className: cn(props.disabled && "cursor-not-allowed opacity-60"),
574
+ children: label
575
+ }), description ? /* @__PURE__ */ jsx("p", {
576
+ id: descriptionId,
577
+ className: "caption text-muted",
578
+ children: description
579
+ }) : null]
580
+ })]
581
+ }), errorMessage ? /* @__PURE__ */ jsx("p", {
582
+ id: errorId,
583
+ className: "caption text-destructive",
584
+ role: "alert",
585
+ children: errorMessage
586
+ }) : null]
587
+ });
588
+ }
589
+ //#endregion
590
+ //#region src/components/combobox.tsx
591
+ function isGroupedOptions$1(options) {
592
+ return options.length > 0 && "options" in options[0];
593
+ }
594
+ function flattenOptions(options) {
595
+ if (isGroupedOptions$1(options)) return options.flatMap((group) => group.options);
596
+ return options;
597
+ }
598
+ const Combobox = React.forwardRef(({ id, name, value, defaultValue, onValueChange, placeholder = "Selecione uma opção", searchPlaceholder = "Buscar...", emptyMessage = "Nenhum resultado encontrado.", options, actions, disabled = false, required = false, className, contentClassName, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-label": ariaLabel }, ref) => {
599
+ const [open, setOpen] = React.useState(false);
600
+ const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");
601
+ const selectedValue = value ?? internalValue;
602
+ const isInvalid = ariaInvalid === true || ariaInvalid === "true";
603
+ const selectedOption = React.useMemo(() => flattenOptions(options), [options]).find((option) => option.value === selectedValue);
604
+ function handleSelect(nextValue) {
605
+ if (value === void 0) setInternalValue(nextValue);
606
+ onValueChange?.(nextValue);
607
+ setOpen(false);
608
+ }
609
+ return /* @__PURE__ */ jsxs(PopoverPrimitive.Root, {
610
+ open,
611
+ onOpenChange: setOpen,
612
+ children: [
613
+ name ? /* @__PURE__ */ jsx("input", {
614
+ type: "hidden",
615
+ name,
616
+ value: selectedValue,
617
+ required
618
+ }) : null,
619
+ /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, {
620
+ asChild: true,
621
+ children: /* @__PURE__ */ jsxs("button", {
622
+ ref,
623
+ id,
624
+ type: "button",
625
+ role: "combobox",
626
+ disabled,
627
+ "aria-label": ariaLabel ?? selectedOption?.label ?? placeholder,
628
+ "aria-haspopup": "listbox",
629
+ "aria-expanded": open,
630
+ "aria-describedby": ariaDescribedBy,
631
+ "aria-invalid": ariaInvalid,
632
+ "aria-required": required ? true : void 0,
633
+ className: cn("flex h-9 w-full items-center justify-between gap-2 whitespace-nowrap", "rounded-fds-md border border-input bg-transparent px-3 py-2", "body-sm text-on-surface shadow-sm outline-none", "transition-[color,box-shadow,border-color,background-color] duration-150", "hover:bg-accent", "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:cursor-not-allowed disabled:opacity-50", !selectedOption && "text-muted-foreground", isInvalid && "border-destructive focus-visible:border-destructive focus-visible:ring-destructive/25", className),
634
+ children: [/* @__PURE__ */ jsx("span", {
635
+ className: "min-w-0 truncate text-left",
636
+ children: selectedOption ? selectedOption.label : placeholder
637
+ }), /* @__PURE__ */ jsx(ChevronsUpDown, {
638
+ "aria-hidden": "true",
639
+ className: "size-4 shrink-0 text-muted-foreground opacity-70"
640
+ })]
641
+ })
642
+ }),
643
+ /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
644
+ align: "start",
645
+ sideOffset: 4,
646
+ className: cn("z-50 w-(--radix-popover-trigger-width) overflow-hidden", "rounded-fds-md border border-border bg-popover text-popover-foreground shadow-md", contentClassName),
647
+ children: /* @__PURE__ */ jsxs(Command, {
648
+ loop: true,
649
+ filter: (itemValue, search, keywords) => {
650
+ const normalizedSearch = search.toLowerCase().trim();
651
+ return [itemValue, ...keywords ?? []].join(" ").toLowerCase().includes(normalizedSearch) ? 1 : 0;
652
+ },
653
+ className: "flex max-h-80 w-full flex-col overflow-hidden",
654
+ children: [
655
+ /* @__PURE__ */ jsxs("div", {
656
+ className: "flex items-center border-b border-border px-3",
657
+ children: [/* @__PURE__ */ jsx(Search, {
658
+ "aria-hidden": "true",
659
+ className: "mr-2 size-4 shrink-0 text-muted-foreground"
660
+ }), /* @__PURE__ */ jsx(Command.Input, {
661
+ placeholder: searchPlaceholder,
662
+ className: cn("h-10 w-full bg-transparent py-3 text-sm outline-none", "placeholder:text-muted-foreground", "disabled:cursor-not-allowed disabled:opacity-50")
663
+ })]
664
+ }),
665
+ /* @__PURE__ */ jsxs(Command.List, {
666
+ className: "max-h-60 overflow-y-auto overflow-x-hidden p-1",
667
+ children: [/* @__PURE__ */ jsx(Command.Empty, {
668
+ className: "px-3 py-6 text-center text-sm text-muted-foreground",
669
+ children: emptyMessage
670
+ }), isGroupedOptions$1(options) ? options.map((group, groupIndex) => /* @__PURE__ */ jsxs(Command.Group, {
671
+ heading: group.label,
672
+ className: cn("[&_[cmdk-group-heading]]:px-2", "[&_[cmdk-group-heading]]:py-1.5", "[&_[cmdk-group-heading]]:caption", "[&_[cmdk-group-heading]]:mono", "[&_[cmdk-group-heading]]:uppercase", "[&_[cmdk-group-heading]]:tracking-[0.12em]", "[&_[cmdk-group-heading]]:text-muted-foreground"),
673
+ children: [groupIndex > 0 ? /* @__PURE__ */ jsx("div", { className: "my-1 h-px bg-border" }) : null, group.options.map((option) => /* @__PURE__ */ jsx(ComboboxItem, {
674
+ option,
675
+ selected: option.value === selectedValue,
676
+ onSelect: handleSelect
677
+ }, option.value))]
678
+ }, group.label)) : options.map((option) => /* @__PURE__ */ jsx(ComboboxItem, {
679
+ option,
680
+ selected: option.value === selectedValue,
681
+ onSelect: handleSelect
682
+ }, option.value))]
683
+ }),
684
+ actions ? /* @__PURE__ */ jsx("div", {
685
+ className: "border-t border-border p-1.5",
686
+ children: actions
687
+ }) : null
688
+ ]
689
+ })
690
+ }) })
691
+ ]
692
+ });
693
+ });
694
+ Combobox.displayName = "Combobox";
695
+ function ComboboxItem({ option, selected, onSelect }) {
696
+ return /* @__PURE__ */ jsxs(Command.Item, {
697
+ value: option.value,
698
+ keywords: [option.label, option.description ?? ""],
699
+ disabled: option.disabled,
700
+ onSelect: () => onSelect(option.value),
701
+ className: cn("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 pr-8", "text-sm outline-none", "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground", "data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50"),
702
+ children: [/* @__PURE__ */ jsxs("span", {
703
+ className: "flex min-w-0 flex-col",
704
+ children: [/* @__PURE__ */ jsx("span", {
705
+ className: "truncate font-medium leading-5",
706
+ children: option.label
707
+ }), option.description ? /* @__PURE__ */ jsx("span", {
708
+ className: "truncate text-xs leading-4 text-muted-foreground",
709
+ children: option.description
710
+ }) : null]
711
+ }), selected ? /* @__PURE__ */ jsx(Check, { className: "absolute right-2 size-4 text-primary" }) : null]
712
+ });
713
+ }
714
+ //#endregion
715
+ //#region src/components/dialog.tsx
716
+ const Dialog = DialogPrimitive.Root;
717
+ const DialogTrigger = DialogPrimitive.Trigger;
718
+ const DialogPortal = DialogPrimitive.Portal;
719
+ const DialogClose = DialogPrimitive.Close;
720
+ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => {
721
+ return /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
722
+ ref,
723
+ className: cn("fixed inset-0 z-50 bg-black/45", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", className),
724
+ ...props
725
+ });
726
+ });
727
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
728
+ const DialogContent = React.forwardRef(({ className, children, showCloseButton = true, ...props }, ref) => {
729
+ return /* @__PURE__ */ jsxs(DialogPortal, { children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
730
+ ref,
731
+ className: cn("fixed left-1/2 top-1/2 z-50 grid w-[calc(100%-2rem)] max-w-lg", "-translate-x-1/2 -translate-y-1/2 gap-4", "rounded-fds-lg border border-border bg-popover p-6 text-popover-foreground shadow-lg", "duration-200", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", className),
732
+ ...props,
733
+ children: [children, showCloseButton ? /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
734
+ className: cn("absolute right-4 top-4 rounded-sm opacity-70", "transition-opacity hover:opacity-100", "focus:outline-none focus:ring-2 focus:ring-ring/35", "disabled:pointer-events-none"),
735
+ children: [/* @__PURE__ */ jsx(X, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
736
+ className: "sr-only",
737
+ children: "Fechar"
738
+ })]
739
+ }) : null]
740
+ })] });
741
+ });
742
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
743
+ function DialogHeader({ className, ...props }) {
744
+ return /* @__PURE__ */ jsx("div", {
745
+ className: cn("flex flex-col gap-1.5 text-left", className),
746
+ ...props
747
+ });
748
+ }
749
+ function DialogFooter({ className, ...props }) {
750
+ return /* @__PURE__ */ jsx("div", {
751
+ className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className),
752
+ ...props
753
+ });
754
+ }
755
+ const DialogTitle = React.forwardRef(({ className, ...props }, ref) => {
756
+ return /* @__PURE__ */ jsx(DialogPrimitive.Title, {
757
+ ref,
758
+ className: cn("h3 text-on-surface", className),
759
+ ...props
760
+ });
761
+ });
762
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
763
+ const DialogDescription = React.forwardRef(({ className, ...props }, ref) => {
764
+ return /* @__PURE__ */ jsx(DialogPrimitive.Description, {
765
+ ref,
766
+ className: cn("body-sm text-muted", className),
767
+ ...props
768
+ });
769
+ });
770
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
771
+ //#endregion
772
+ //#region src/components/kbd.tsx
773
+ const kbdVariants = cva([
774
+ "inline-flex items-center justify-center",
775
+ "rounded-sm border border-border bg-muted",
776
+ "font-mono font-medium text-muted-foreground shadow-sm",
777
+ "select-none"
778
+ ], {
779
+ variants: { size: {
780
+ sm: "h-5 min-w-5 px-1 text-[0.6875rem]",
781
+ md: "h-6 min-w-6 px-1.5 text-xs"
782
+ } },
783
+ defaultVariants: { size: "sm" }
784
+ });
785
+ function Kbd({ className, size, ...props }) {
786
+ return /* @__PURE__ */ jsx("kbd", {
787
+ className: cn(kbdVariants({ size }), className),
788
+ ...props
789
+ });
790
+ }
791
+ //#endregion
792
+ //#region src/components/command-menu.tsx
793
+ function CommandMenu({ open, defaultOpen = false, onOpenChange, title = "Menu de comandos", description = "Busque telas e execute ações rápidas.", placeholder = "Buscar comando, tela ou ação...", emptyMessage = "Nenhum comando encontrado.", groups, closeOnSelect = true }) {
794
+ const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
795
+ const currentOpen = open ?? internalOpen;
796
+ function handleOpenChange(nextOpen) {
797
+ if (open === void 0) setInternalOpen(nextOpen);
798
+ onOpenChange?.(nextOpen);
799
+ }
800
+ function handleSelect(item) {
801
+ item.onSelect?.();
802
+ if (closeOnSelect) handleOpenChange(false);
803
+ }
804
+ return /* @__PURE__ */ jsx(Dialog, {
805
+ open: currentOpen,
806
+ onOpenChange: handleOpenChange,
807
+ children: /* @__PURE__ */ jsxs(DialogContent, {
808
+ showCloseButton: false,
809
+ className: "max-w-2xl overflow-hidden p-0",
810
+ children: [
811
+ /* @__PURE__ */ jsx(DialogTitle, {
812
+ className: "sr-only",
813
+ children: title
814
+ }),
815
+ /* @__PURE__ */ jsx(DialogDescription, {
816
+ className: "sr-only",
817
+ children: description
818
+ }),
819
+ /* @__PURE__ */ jsxs(Command, {
820
+ loop: true,
821
+ className: "flex max-h-[70dvh] flex-col overflow-hidden bg-popover text-popover-foreground",
822
+ children: [/* @__PURE__ */ jsxs("div", {
823
+ className: "flex items-center border-b border-border px-4",
824
+ children: [/* @__PURE__ */ jsx(Search, {
825
+ "aria-hidden": "true",
826
+ className: "mr-3 size-4 shrink-0 text-muted-foreground"
827
+ }), /* @__PURE__ */ jsx(Command.Input, {
828
+ placeholder,
829
+ className: cn("h-12 w-full bg-transparent py-3 body-sm outline-none", "placeholder:text-muted-foreground", "disabled:cursor-not-allowed disabled:opacity-50")
830
+ })]
831
+ }), /* @__PURE__ */ jsxs(Command.List, {
832
+ className: "max-h-[26rem] overflow-y-auto overflow-x-hidden p-2",
833
+ children: [/* @__PURE__ */ jsx(Command.Empty, {
834
+ className: "px-4 py-10 text-center body-sm text-muted",
835
+ children: emptyMessage
836
+ }), groups.map((group) => /* @__PURE__ */ jsx(Command.Group, {
837
+ heading: group.label,
838
+ className: cn("overflow-hidden", "[&_[cmdk-group-heading]]:px-2", "[&_[cmdk-group-heading]]:py-2", "[&_[cmdk-group-heading]]:caption", "[&_[cmdk-group-heading]]:mono", "[&_[cmdk-group-heading]]:uppercase", "[&_[cmdk-group-heading]]:tracking-[0.12em]", "[&_[cmdk-group-heading]]:text-muted"),
839
+ children: group.items.map((item) => /* @__PURE__ */ jsxs(Command.Item, {
840
+ value: item.value,
841
+ keywords: [
842
+ item.label,
843
+ item.description ?? "",
844
+ ...item.keywords ?? []
845
+ ],
846
+ disabled: item.disabled,
847
+ onSelect: () => handleSelect(item),
848
+ className: cn("relative flex cursor-default select-none items-center gap-3 rounded-fds-md px-3 py-2.5", "body-sm outline-none transition-colors duration-100", "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground", "data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50"),
849
+ children: [
850
+ item.icon ? /* @__PURE__ */ jsx("span", {
851
+ className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground",
852
+ children: item.icon
853
+ }) : null,
854
+ /* @__PURE__ */ jsxs("span", {
855
+ className: "flex min-w-0 flex-1 flex-col",
856
+ children: [/* @__PURE__ */ jsx("span", {
857
+ className: "truncate font-medium",
858
+ children: item.label
859
+ }), item.description ? /* @__PURE__ */ jsx("span", {
860
+ className: "truncate caption text-muted",
861
+ children: item.description
862
+ }) : null]
863
+ }),
864
+ item.shortcut ? /* @__PURE__ */ jsx("span", {
865
+ className: "ml-auto flex shrink-0 items-center gap-1",
866
+ children: Array.isArray(item.shortcut) ? item.shortcut.map((key) => /* @__PURE__ */ jsx(Kbd, { children: key }, key)) : /* @__PURE__ */ jsx(Kbd, { children: item.shortcut })
867
+ }) : null
868
+ ]
869
+ }, item.value))
870
+ }, group.label))]
871
+ })]
872
+ })
873
+ ]
874
+ })
875
+ });
876
+ }
877
+ //#endregion
878
+ //#region src/components/empty-state.tsx
879
+ function EmptyState({ className, icon, title, description, action, ...props }) {
880
+ return /* @__PURE__ */ jsxs("div", {
881
+ className: cn("flex min-h-56 flex-col items-center justify-center rounded-fds-lg border border-dashed border-border bg-muted/40 p-8 text-center", className),
882
+ ...props,
883
+ children: [
884
+ /* @__PURE__ */ jsx("div", {
885
+ className: "mb-4 flex size-12 items-center justify-center rounded-fds-full bg-surface text-muted-foreground",
886
+ children: icon ?? /* @__PURE__ */ jsx(Inbox, { className: "size-6" })
887
+ }),
888
+ /* @__PURE__ */ jsx("h3", {
889
+ className: "body font-semibold text-on-surface",
890
+ children: title
891
+ }),
892
+ description ? /* @__PURE__ */ jsx("p", {
893
+ className: "mt-1 max-w-md body-sm text-muted",
894
+ children: description
895
+ }) : null,
896
+ action ? /* @__PURE__ */ jsx("div", {
897
+ className: "mt-5",
898
+ children: action
899
+ }) : null
900
+ ]
901
+ });
902
+ }
903
+ //#endregion
904
+ //#region src/components/skeleton.tsx
905
+ function Skeleton({ className, ...props }) {
906
+ return /* @__PURE__ */ jsx("div", {
907
+ "aria-hidden": "true",
908
+ className: cn("animate-pulse rounded-fds-md bg-muted", className),
909
+ ...props
910
+ });
911
+ }
912
+ //#endregion
913
+ //#region src/components/table.tsx
914
+ function TableContainer({ className, ...props }) {
915
+ return /* @__PURE__ */ jsx("div", {
916
+ className: cn("w-full overflow-hidden rounded-fds-lg border border-border bg-card", className),
917
+ ...props
918
+ });
919
+ }
920
+ function TableScrollArea({ className, ...props }) {
921
+ return /* @__PURE__ */ jsx("div", {
922
+ className: cn("w-full overflow-auto", className),
923
+ ...props
924
+ });
925
+ }
926
+ const Table = React.forwardRef(({ className, ...props }, ref) => {
927
+ return /* @__PURE__ */ jsx("table", {
928
+ ref,
929
+ className: cn("w-full caption-bottom border-collapse text-sm", className),
930
+ ...props
931
+ });
932
+ });
933
+ Table.displayName = "Table";
934
+ const TableHeader = React.forwardRef(({ className, ...props }, ref) => {
935
+ return /* @__PURE__ */ jsx("thead", {
936
+ ref,
937
+ className: cn("border-b border-border bg-muted/60", className),
938
+ ...props
939
+ });
940
+ });
941
+ TableHeader.displayName = "TableHeader";
942
+ const TableBody = React.forwardRef(({ className, ...props }, ref) => {
943
+ return /* @__PURE__ */ jsx("tbody", {
944
+ ref,
945
+ className: cn("[&_tr:last-child]:border-0", className),
946
+ ...props
947
+ });
948
+ });
949
+ TableBody.displayName = "TableBody";
950
+ const TableFooter = React.forwardRef(({ className, ...props }, ref) => {
951
+ return /* @__PURE__ */ jsx("tfoot", {
952
+ ref,
953
+ className: cn("border-t border-border bg-muted/60 font-medium", className),
954
+ ...props
955
+ });
956
+ });
957
+ TableFooter.displayName = "TableFooter";
958
+ const TableRow = React.forwardRef(({ className, ...props }, ref) => {
959
+ return /* @__PURE__ */ jsx("tr", {
960
+ ref,
961
+ className: cn("border-b border-border transition-colors", "hover:bg-muted/60", "data-[state=selected]:bg-muted", className),
962
+ ...props
963
+ });
964
+ });
965
+ TableRow.displayName = "TableRow";
966
+ const TableHead = React.forwardRef(({ className, ...props }, ref) => {
967
+ return /* @__PURE__ */ jsx("th", {
968
+ ref,
969
+ className: cn("h-10 px-4 text-left align-middle", "caption font-semibold uppercase tracking-[0.08em] text-muted-foreground", "[&:has([role=checkbox])]:pr-0", className),
970
+ ...props
971
+ });
972
+ });
973
+ TableHead.displayName = "TableHead";
974
+ const TableCell = React.forwardRef(({ className, ...props }, ref) => {
975
+ return /* @__PURE__ */ jsx("td", {
976
+ ref,
977
+ className: cn("px-4 py-3 align-middle body-sm", "[&:has([role=checkbox])]:pr-0", className),
978
+ ...props
979
+ });
980
+ });
981
+ TableCell.displayName = "TableCell";
982
+ const TableCaption = React.forwardRef(({ className, ...props }, ref) => {
983
+ return /* @__PURE__ */ jsx("caption", {
984
+ ref,
985
+ className: cn("mt-4 caption text-muted", className),
986
+ ...props
987
+ });
988
+ });
989
+ TableCaption.displayName = "TableCaption";
990
+ //#endregion
991
+ //#region src/components/data-table.tsx
992
+ function getCellValue(row, column) {
993
+ if (column.cell) return column.cell(row);
994
+ if (typeof column.accessor === "function") return column.accessor(row);
995
+ if (column.accessor) return row[column.accessor];
996
+ return null;
997
+ }
998
+ function renderCellValue(value) {
999
+ if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || React.isValidElement(value)) return value;
1000
+ return String(value);
1001
+ }
1002
+ function compareSortValues(first, second) {
1003
+ if (first === second) return 0;
1004
+ if (first === null || first === void 0) return 1;
1005
+ if (second === null || second === void 0) return -1;
1006
+ const normalizedFirst = first instanceof Date ? first.getTime() : first;
1007
+ const normalizedSecond = second instanceof Date ? second.getTime() : second;
1008
+ if (typeof normalizedFirst === "number" && typeof normalizedSecond === "number") return normalizedFirst - normalizedSecond;
1009
+ return String(normalizedFirst).localeCompare(String(normalizedSecond), "pt-BR", {
1010
+ numeric: true,
1011
+ sensitivity: "base"
1012
+ });
1013
+ }
1014
+ function getNextSortState(currentSort, columnId) {
1015
+ if (currentSort?.id !== columnId) return {
1016
+ id: columnId,
1017
+ direction: "asc"
1018
+ };
1019
+ if (currentSort.direction === "asc") return {
1020
+ id: columnId,
1021
+ direction: "desc"
1022
+ };
1023
+ }
1024
+ function DataTable({ columns, data, getRowId = (_row, index) => String(index), selectedRowIds, defaultSelectedRowIds = [], onSelectedRowIdsChange, sort, defaultSort, onSortChange, onRowClick, emptyState, loading = false, loadingRows = 5, "aria-label": ariaLabel = "Tabela de dados", className }) {
1025
+ const [internalSelectedRowIds, setInternalSelectedRowIds] = React.useState(defaultSelectedRowIds);
1026
+ const [internalSort, setInternalSort] = React.useState(defaultSort);
1027
+ const currentSelectedRowIds = selectedRowIds ?? internalSelectedRowIds;
1028
+ const currentSort = sort ?? internalSort;
1029
+ const selectable = Boolean(selectedRowIds || onSelectedRowIdsChange);
1030
+ const rowIds = React.useMemo(() => data.map((row, index) => getRowId(row, index)), [data, getRowId]);
1031
+ const selectedRows = new Set(currentSelectedRowIds);
1032
+ const selectedVisibleRows = rowIds.filter((rowId) => selectedRows.has(rowId));
1033
+ const allVisibleSelected = rowIds.length > 0 && selectedVisibleRows.length === rowIds.length;
1034
+ const someVisibleSelected = selectedVisibleRows.length > 0 && selectedVisibleRows.length < rowIds.length;
1035
+ const sortedData = React.useMemo(() => {
1036
+ if (!currentSort) return data;
1037
+ const sortedColumn = columns.find((column) => column.id === currentSort.id);
1038
+ if (!sortedColumn?.sortable) return data;
1039
+ return [...data].sort((first, second) => {
1040
+ const result = compareSortValues(sortedColumn.sortValue ? sortedColumn.sortValue(first) : getCellValue(first, sortedColumn)?.toString(), sortedColumn.sortValue ? sortedColumn.sortValue(second) : getCellValue(second, sortedColumn)?.toString());
1041
+ return currentSort.direction === "asc" ? result : result * -1;
1042
+ });
1043
+ }, [
1044
+ columns,
1045
+ currentSort,
1046
+ data
1047
+ ]);
1048
+ function updateSelectedRowIds(nextSelectedRowIds) {
1049
+ if (selectedRowIds === void 0) setInternalSelectedRowIds(nextSelectedRowIds);
1050
+ onSelectedRowIdsChange?.(nextSelectedRowIds);
1051
+ }
1052
+ function updateSort(nextSort) {
1053
+ if (sort === void 0) setInternalSort(nextSort);
1054
+ onSortChange?.(nextSort);
1055
+ }
1056
+ function toggleRow(rowId) {
1057
+ const nextSelectedRows = new Set(currentSelectedRowIds);
1058
+ if (nextSelectedRows.has(rowId)) nextSelectedRows.delete(rowId);
1059
+ else nextSelectedRows.add(rowId);
1060
+ updateSelectedRowIds(Array.from(nextSelectedRows));
1061
+ }
1062
+ function toggleAllVisibleRows() {
1063
+ if (allVisibleSelected) {
1064
+ updateSelectedRowIds(currentSelectedRowIds.filter((rowId) => !rowIds.includes(rowId)));
1065
+ return;
1066
+ }
1067
+ updateSelectedRowIds(Array.from(new Set([...currentSelectedRowIds, ...rowIds])));
1068
+ }
1069
+ const columnCount = columns.length + (selectable ? 1 : 0);
1070
+ return /* @__PURE__ */ jsx(TableContainer, {
1071
+ className,
1072
+ children: /* @__PURE__ */ jsx(TableScrollArea, { children: /* @__PURE__ */ jsxs(Table, {
1073
+ "aria-label": ariaLabel,
1074
+ children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [selectable ? /* @__PURE__ */ jsx(TableHead, {
1075
+ className: "w-12",
1076
+ children: /* @__PURE__ */ jsx(Checkbox, {
1077
+ "aria-label": "Selecionar todas as linhas",
1078
+ checked: someVisibleSelected ? "indeterminate" : allVisibleSelected,
1079
+ disabled: loading || rowIds.length === 0,
1080
+ onCheckedChange: toggleAllVisibleRows
1081
+ })
1082
+ }) : null, columns.map((column) => {
1083
+ const isSorted = currentSort?.id === column.id;
1084
+ const SortIcon = isSorted ? currentSort.direction === "asc" ? ChevronUp : ChevronDown : ArrowUpDown;
1085
+ return /* @__PURE__ */ jsx(TableHead, {
1086
+ className: cn(column.align === "center" && "text-center", column.align === "right" && "text-right", column.headerClassName),
1087
+ "aria-sort": isSorted ? currentSort.direction === "asc" ? "ascending" : "descending" : void 0,
1088
+ children: column.sortable ? /* @__PURE__ */ jsxs("button", {
1089
+ type: "button",
1090
+ className: cn("inline-flex items-center gap-1 rounded-fds-sm", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", column.align === "right" && "ml-auto", column.align === "center" && "mx-auto"),
1091
+ onClick: () => updateSort(getNextSortState(currentSort, column.id)),
1092
+ children: [column.header, /* @__PURE__ */ jsx(SortIcon, {
1093
+ className: "size-3.5",
1094
+ "aria-hidden": "true"
1095
+ })]
1096
+ }) : column.header
1097
+ }, column.id);
1098
+ })] }) }), /* @__PURE__ */ jsxs(TableBody, { children: [
1099
+ loading ? Array.from({ length: loadingRows }, (_, rowIndex) => /* @__PURE__ */ jsx(TableRow, { children: Array.from({ length: columnCount }, (_, cellIndex) => /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-full" }) }, `loading-${rowIndex}-${cellIndex}`)) }, `loading-${rowIndex}`)) : null,
1100
+ !loading && sortedData.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, {
1101
+ colSpan: columnCount,
1102
+ children: emptyState ?? /* @__PURE__ */ jsx(EmptyState, {
1103
+ className: "border-0 bg-transparent",
1104
+ title: "Nenhum registro encontrado",
1105
+ description: "Ajuste os filtros ou cadastre um novo item."
1106
+ })
1107
+ }) }) : null,
1108
+ !loading ? sortedData.map((row, index) => {
1109
+ const rowId = getRowId(row, index);
1110
+ const isSelected = selectedRows.has(rowId);
1111
+ return /* @__PURE__ */ jsxs(TableRow, {
1112
+ "data-state": isSelected ? "selected" : void 0,
1113
+ className: cn(onRowClick && "cursor-pointer"),
1114
+ onClick: () => onRowClick?.(row, rowId),
1115
+ children: [selectable ? /* @__PURE__ */ jsx(TableCell, {
1116
+ onClick: (event) => event.stopPropagation(),
1117
+ children: /* @__PURE__ */ jsx(Checkbox, {
1118
+ "aria-label": `Selecionar linha ${index + 1}`,
1119
+ checked: isSelected,
1120
+ onCheckedChange: () => toggleRow(rowId)
1121
+ })
1122
+ }) : null, columns.map((column) => /* @__PURE__ */ jsx(TableCell, {
1123
+ className: cn(column.align === "center" && "text-center", column.align === "right" && "text-right", column.className),
1124
+ children: renderCellValue(getCellValue(row, column))
1125
+ }, column.id))]
1126
+ }, rowId);
1127
+ }) : null
1128
+ ] })]
1129
+ }) })
1130
+ });
1131
+ }
1132
+ //#endregion
1133
+ //#region src/components/filter-bar.tsx
1134
+ function FilterBar({ label = "Filtros", className, children, ...props }) {
1135
+ return /* @__PURE__ */ jsxs("div", {
1136
+ className: cn("flex flex-col gap-3 rounded-fds-lg border border-border bg-muted/40 p-3", className),
1137
+ ...props,
1138
+ children: [label ? /* @__PURE__ */ jsx("p", {
1139
+ className: "caption mono uppercase tracking-[0.12em] text-muted",
1140
+ children: label
1141
+ }) : null, /* @__PURE__ */ jsx("div", {
1142
+ className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4",
1143
+ children
1144
+ })]
1145
+ });
1146
+ }
1147
+ function FilterBarItem({ label, className, children, ...props }) {
1148
+ return /* @__PURE__ */ jsxs("div", {
1149
+ className: cn("grid gap-1.5", className),
1150
+ ...props,
1151
+ children: [/* @__PURE__ */ jsx("span", {
1152
+ className: "caption font-medium text-muted",
1153
+ children: label
1154
+ }), children]
1155
+ });
1156
+ }
1157
+ //#endregion
1158
+ //#region src/components/pagination.tsx
1159
+ function range(start, end) {
1160
+ const length = end - start + 1;
1161
+ return Array.from({ length }, (_, index) => index + start);
1162
+ }
1163
+ function getPaginationItems(page, totalPages, siblingCount) {
1164
+ if (siblingCount + 5 >= totalPages) return range(1, totalPages);
1165
+ const leftSiblingIndex = Math.max(page - siblingCount, 1);
1166
+ const rightSiblingIndex = Math.min(page + siblingCount, totalPages);
1167
+ const shouldShowLeftEllipsis = leftSiblingIndex > 2;
1168
+ const shouldShowRightEllipsis = rightSiblingIndex < totalPages - 1;
1169
+ const firstPageIndex = 1;
1170
+ const lastPageIndex = totalPages;
1171
+ if (!shouldShowLeftEllipsis && shouldShowRightEllipsis) return [
1172
+ ...range(1, 3 + 2 * siblingCount),
1173
+ "ellipsis",
1174
+ totalPages
1175
+ ];
1176
+ if (shouldShowLeftEllipsis && !shouldShowRightEllipsis) return [
1177
+ firstPageIndex,
1178
+ "ellipsis",
1179
+ ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages)
1180
+ ];
1181
+ return [
1182
+ firstPageIndex,
1183
+ "ellipsis",
1184
+ ...range(leftSiblingIndex, rightSiblingIndex),
1185
+ "ellipsis",
1186
+ lastPageIndex
1187
+ ];
1188
+ }
1189
+ function Pagination({ page, totalPages, onPageChange, siblingCount = 1, className }) {
1190
+ const items = getPaginationItems(page, totalPages, siblingCount);
1191
+ function goToPage(nextPage) {
1192
+ if (nextPage < 1 || nextPage > totalPages || nextPage === page) return;
1193
+ onPageChange?.(nextPage);
1194
+ }
1195
+ return /* @__PURE__ */ jsxs("nav", {
1196
+ "aria-label": "Paginação",
1197
+ className: cn("flex flex-wrap items-center justify-between gap-3", className),
1198
+ children: [/* @__PURE__ */ jsxs("p", {
1199
+ className: "caption text-muted",
1200
+ children: [
1201
+ "Página ",
1202
+ page,
1203
+ " de ",
1204
+ totalPages
1205
+ ]
1206
+ }), /* @__PURE__ */ jsxs("div", {
1207
+ className: "flex items-center gap-1",
1208
+ children: [
1209
+ /* @__PURE__ */ jsx(Button, {
1210
+ type: "button",
1211
+ variant: "outline",
1212
+ size: "sm",
1213
+ disabled: page <= 1,
1214
+ onClick: () => goToPage(page - 1),
1215
+ "aria-label": "Página anterior",
1216
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" })
1217
+ }),
1218
+ items.map((item, index) => {
1219
+ if (item === "ellipsis") {
1220
+ const previousItem = items[index - 1];
1221
+ const nextItem = items[index + 1];
1222
+ return /* @__PURE__ */ jsx("span", {
1223
+ className: "flex size-8 items-center justify-center text-muted-foreground",
1224
+ "aria-hidden": "true",
1225
+ children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" })
1226
+ }, `ellipsis-${previousItem}-${nextItem}`);
1227
+ }
1228
+ const isCurrent = item === page;
1229
+ return /* @__PURE__ */ jsx(Button, {
1230
+ type: "button",
1231
+ variant: isCurrent ? "primary" : "ghost",
1232
+ size: "sm",
1233
+ onClick: () => goToPage(item),
1234
+ "aria-current": isCurrent ? "page" : void 0,
1235
+ className: "size-8 px-0",
1236
+ children: item
1237
+ }, item);
1238
+ }),
1239
+ /* @__PURE__ */ jsx(Button, {
1240
+ type: "button",
1241
+ variant: "outline",
1242
+ size: "sm",
1243
+ disabled: page >= totalPages,
1244
+ onClick: () => goToPage(page + 1),
1245
+ "aria-label": "Próxima página",
1246
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
1247
+ })
1248
+ ]
1249
+ })]
1250
+ });
1251
+ }
1252
+ //#endregion
1253
+ //#region src/components/search-input.tsx
1254
+ const SearchInput = React.forwardRef(({ className, containerClassName, value, defaultValue = "", onValueChange, onChange, onClear, clearable = true, placeholder = "Buscar...", disabled, ...props }, ref) => {
1255
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
1256
+ const currentValue = value ?? internalValue;
1257
+ const hasValue = currentValue.length > 0;
1258
+ function handleChange(event) {
1259
+ const nextValue = event.target.value;
1260
+ if (value === void 0) setInternalValue(nextValue);
1261
+ onValueChange?.(nextValue);
1262
+ onChange?.(event);
1263
+ }
1264
+ function handleClear() {
1265
+ if (value === void 0) setInternalValue("");
1266
+ onValueChange?.("");
1267
+ onClear?.();
1268
+ }
1269
+ return /* @__PURE__ */ jsxs("div", {
1270
+ className: cn("relative w-full", containerClassName),
1271
+ children: [
1272
+ /* @__PURE__ */ jsx(Search, {
1273
+ "aria-hidden": "true",
1274
+ className: "pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"
1275
+ }),
1276
+ /* @__PURE__ */ jsx("input", {
1277
+ ref,
1278
+ type: "search",
1279
+ value: currentValue,
1280
+ onChange: handleChange,
1281
+ placeholder,
1282
+ disabled,
1283
+ className: cn("h-9 w-full rounded-fds-md border border-input bg-transparent", "pl-9 pr-9 body-sm text-on-surface shadow-sm outline-none", "transition-[color,box-shadow,border-color,background-color] duration-150", "placeholder:text-muted-foreground", "hover:bg-accent", "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:cursor-not-allowed disabled:opacity-50", className),
1284
+ ...props
1285
+ }),
1286
+ clearable && hasValue && !disabled ? /* @__PURE__ */ jsx("button", {
1287
+ type: "button",
1288
+ onClick: handleClear,
1289
+ className: cn("absolute right-2 top-1/2 flex size-6 -translate-y-1/2 items-center justify-center", "rounded-sm text-muted-foreground transition-colors", "hover:bg-accent hover:text-accent-foreground", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35"),
1290
+ "aria-label": "Limpar busca",
1291
+ children: /* @__PURE__ */ jsx(X, { className: "size-4" })
1292
+ }) : null
1293
+ ]
1294
+ });
1295
+ });
1296
+ SearchInput.displayName = "SearchInput";
1297
+ //#endregion
1298
+ //#region src/components/toolbar.tsx
1299
+ function Toolbar({ className, ...props }) {
1300
+ return /* @__PURE__ */ jsx("div", {
1301
+ className: cn("flex flex-col gap-4 rounded-fds-lg border border-border bg-card p-4", "lg:flex-row lg:items-center lg:justify-between", className),
1302
+ ...props
1303
+ });
1304
+ }
1305
+ function ToolbarSection({ className, ...props }) {
1306
+ return /* @__PURE__ */ jsx("div", {
1307
+ className: cn("flex min-w-0 flex-1 flex-col gap-3 sm:flex-row sm:items-center", className),
1308
+ ...props
1309
+ });
1310
+ }
1311
+ function ToolbarActions({ className, ...props }) {
1312
+ return /* @__PURE__ */ jsx("div", {
1313
+ className: cn("flex shrink-0 flex-wrap items-center gap-2", className),
1314
+ ...props
1315
+ });
1316
+ }
1317
+ function ToolbarTitle({ title, description, className, ...props }) {
1318
+ return /* @__PURE__ */ jsxs("div", {
1319
+ className: cn("min-w-0", className),
1320
+ ...props,
1321
+ children: [/* @__PURE__ */ jsx("h3", {
1322
+ className: "body-sm font-semibold text-on-surface",
1323
+ children: title
1324
+ }), description ? /* @__PURE__ */ jsx("p", {
1325
+ className: "caption text-muted",
1326
+ children: description
1327
+ }) : null]
1328
+ });
1329
+ }
1330
+ //#endregion
1331
+ //#region src/components/data-view.tsx
1332
+ function isPlainStateContent(content) {
1333
+ return Boolean(content && typeof content === "object" && !Array.isArray(content) && !("type" in content) && "title" in content);
1334
+ }
1335
+ function renderStateContent(content, fallbackIcon) {
1336
+ if (isPlainStateContent(content)) {
1337
+ const { retryLabel = "Tentar novamente", onRetry, action, icon, ...emptyStateProps } = content;
1338
+ return /* @__PURE__ */ jsx(EmptyState, {
1339
+ icon: icon ?? fallbackIcon,
1340
+ action: action ?? (onRetry ? /* @__PURE__ */ jsx(Button, {
1341
+ type: "button",
1342
+ variant: "outline",
1343
+ onClick: onRetry,
1344
+ children: retryLabel
1345
+ }) : void 0),
1346
+ ...emptyStateProps
1347
+ });
1348
+ }
1349
+ return content;
1350
+ }
1351
+ function renderSearch(search) {
1352
+ if (typeof search === "object" && search && !Array.isArray(search) && !("type" in search)) return /* @__PURE__ */ jsx(SearchInput, {
1353
+ placeholder: "Buscar...",
1354
+ ...search
1355
+ });
1356
+ return search;
1357
+ }
1358
+ function isPaginationProps(pagination) {
1359
+ return Boolean(pagination && typeof pagination === "object" && !Array.isArray(pagination) && !("type" in pagination) && "page" in pagination && "totalPages" in pagination);
1360
+ }
1361
+ function renderPagination(pagination) {
1362
+ if (isPaginationProps(pagination)) return /* @__PURE__ */ jsx(Pagination, { ...pagination });
1363
+ return pagination;
1364
+ }
1365
+ function DataViewRoot({ title, description, search, filters, actions, selectedCount = 0, selectedActions, selectedLabel, onClearSelection, empty, loading = false, loadingLabel = "Carregando dados", error, pagination, className, children, ...props }) {
1366
+ const hasHeader = title || description || actions;
1367
+ const hasToolbar = search || filters;
1368
+ return /* @__PURE__ */ jsxs("section", {
1369
+ className: cn("flex w-full flex-col gap-4", className),
1370
+ ...props,
1371
+ children: [
1372
+ hasHeader ? /* @__PURE__ */ jsx(DataViewHeader, {
1373
+ title,
1374
+ description,
1375
+ actions
1376
+ }) : null,
1377
+ hasToolbar ? /* @__PURE__ */ jsx(DataViewToolbar, {
1378
+ search,
1379
+ filters
1380
+ }) : null,
1381
+ /* @__PURE__ */ jsx(ActionBar, {
1382
+ selectedCount,
1383
+ label: selectedLabel,
1384
+ onClearSelection,
1385
+ children: selectedActions
1386
+ }),
1387
+ /* @__PURE__ */ jsx(DataViewContent, { children: loading ? /* @__PURE__ */ jsxs("div", {
1388
+ className: "grid gap-3 rounded-fds-lg border border-border bg-card p-4",
1389
+ role: "status",
1390
+ "aria-label": loadingLabel,
1391
+ children: [
1392
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-44" }),
1393
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" }),
1394
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" }),
1395
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-3/4" })
1396
+ ]
1397
+ }) : error ? renderStateContent(error, /* @__PURE__ */ jsx(AlertTriangle, { className: "size-6" })) : children ? children : empty ? renderStateContent(empty) : null }),
1398
+ pagination ? /* @__PURE__ */ jsx(DataViewPagination, { children: renderPagination(pagination) }) : null
1399
+ ]
1400
+ });
1401
+ }
1402
+ function DataViewHeader({ title, description, actions, className, ...props }) {
1403
+ return /* @__PURE__ */ jsxs("div", {
1404
+ className: cn("flex flex-col gap-3 border-b border-border pb-4", "md:flex-row md:items-end md:justify-between", className),
1405
+ ...props,
1406
+ children: [/* @__PURE__ */ jsxs("div", {
1407
+ className: "min-w-0",
1408
+ children: [title ? /* @__PURE__ */ jsx("h2", {
1409
+ className: "h2 truncate",
1410
+ children: title
1411
+ }) : null, description ? /* @__PURE__ */ jsx("p", {
1412
+ className: "mt-1 body-sm text-muted",
1413
+ children: description
1414
+ }) : null]
1415
+ }), actions ? /* @__PURE__ */ jsx("div", {
1416
+ className: "flex shrink-0 flex-wrap items-center gap-2",
1417
+ children: actions
1418
+ }) : null]
1419
+ });
1420
+ }
1421
+ function DataViewToolbar({ title, description, search, filters, actions, className, ...props }) {
1422
+ return /* @__PURE__ */ jsxs(Toolbar, {
1423
+ className,
1424
+ ...props,
1425
+ children: [
1426
+ /* @__PURE__ */ jsxs(ToolbarSection, { children: [title ? /* @__PURE__ */ jsx(ToolbarTitle, {
1427
+ title,
1428
+ description
1429
+ }) : null, search ? /* @__PURE__ */ jsx("div", {
1430
+ className: "min-w-64 flex-1",
1431
+ children: renderSearch(search)
1432
+ }) : null] }),
1433
+ actions ? /* @__PURE__ */ jsx(ToolbarActions, { children: actions }) : null,
1434
+ filters ? /* @__PURE__ */ jsx("div", {
1435
+ className: "basis-full",
1436
+ children: /* @__PURE__ */ jsx(FilterBar, { children: filters })
1437
+ }) : null
1438
+ ]
1439
+ });
1440
+ }
1441
+ function DataViewContent({ className, ...props }) {
1442
+ return /* @__PURE__ */ jsx("div", {
1443
+ className: cn("min-w-0", className),
1444
+ ...props
1445
+ });
1446
+ }
1447
+ function DataViewEmpty(props) {
1448
+ return /* @__PURE__ */ jsx(EmptyState, { ...props });
1449
+ }
1450
+ function DataViewPagination({ className, ...props }) {
1451
+ return /* @__PURE__ */ jsx("div", {
1452
+ className: cn("rounded-fds-lg border border-border bg-card p-3", className),
1453
+ ...props
1454
+ });
1455
+ }
1456
+ //#endregion
1457
+ //#region src/components/popover.tsx
1458
+ const Popover = PopoverPrimitive.Root;
1459
+ const PopoverTrigger = PopoverPrimitive.Trigger;
1460
+ const PopoverAnchor = PopoverPrimitive.Anchor;
1461
+ const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => {
1462
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
1463
+ ref,
1464
+ align,
1465
+ sideOffset,
1466
+ className: cn("z-50 w-72 rounded-fds-md border border-border bg-popover p-4 text-popover-foreground shadow-md", "outline-none", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-1", "data-[side=top]:slide-in-from-bottom-1", className),
1467
+ ...props
1468
+ }) });
1469
+ });
1470
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1471
+ //#endregion
1472
+ //#region src/components/date-picker.tsx
1473
+ function formatDate(date) {
1474
+ return format(date, "dd/MM/yyyy", { locale: ptBR$1 });
1475
+ }
1476
+ function DatePicker({ value, defaultValue, onValueChange, placeholder = "Selecionar data", disabled = false, required = false, clearable = true, className, calendarClassName, "aria-label": ariaLabel = "Selecionar data", "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }) {
1477
+ const [open, setOpen] = React.useState(false);
1478
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
1479
+ const selectedDate = value ?? internalValue;
1480
+ const isInvalid = ariaInvalid === true || ariaInvalid === "true";
1481
+ function updateDate(date) {
1482
+ if (value === void 0) setInternalValue(date);
1483
+ onValueChange?.(date);
1484
+ }
1485
+ function handleSelect(date) {
1486
+ updateDate(date);
1487
+ if (date) setOpen(false);
1488
+ }
1489
+ function handleClear(event) {
1490
+ event.stopPropagation();
1491
+ updateDate(void 0);
1492
+ }
1493
+ return /* @__PURE__ */ jsxs(Popover, {
1494
+ open,
1495
+ onOpenChange: setOpen,
1496
+ children: [/* @__PURE__ */ jsxs("div", {
1497
+ className: "relative w-full",
1498
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
1499
+ asChild: true,
1500
+ children: /* @__PURE__ */ jsxs(Button, {
1501
+ type: "button",
1502
+ variant: "outline",
1503
+ disabled,
1504
+ "aria-label": ariaLabel,
1505
+ "aria-describedby": ariaDescribedBy,
1506
+ "aria-invalid": ariaInvalid,
1507
+ "data-required": required ? "" : void 0,
1508
+ className: cn("h-10 w-full justify-start px-3 text-left font-normal", !selectedDate && "text-muted", isInvalid && "border-error focus-visible:ring-error", clearable && selectedDate && "pr-10", className),
1509
+ children: [/* @__PURE__ */ jsx(CalendarIcon, {
1510
+ "aria-hidden": "true",
1511
+ className: "size-4"
1512
+ }), /* @__PURE__ */ jsx("span", {
1513
+ className: "min-w-0 truncate",
1514
+ children: selectedDate ? formatDate(selectedDate) : placeholder
1515
+ })]
1516
+ })
1517
+ }), clearable && selectedDate && !disabled ? /* @__PURE__ */ jsx("button", {
1518
+ type: "button",
1519
+ "aria-label": "Limpar data",
1520
+ className: cn("absolute right-2 top-1/2 flex size-7 -translate-y-1/2 items-center justify-center rounded-sm", "text-muted transition-colors hover:bg-accent hover:text-on-surface", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35"),
1521
+ onClick: handleClear,
1522
+ children: /* @__PURE__ */ jsx(X, {
1523
+ "aria-hidden": "true",
1524
+ className: "size-4"
1525
+ })
1526
+ }) : null]
1527
+ }), /* @__PURE__ */ jsx(PopoverContent, {
1528
+ align: "start",
1529
+ className: "w-auto p-0",
1530
+ children: /* @__PURE__ */ jsx(Calendar, {
1531
+ mode: "single",
1532
+ selected: selectedDate,
1533
+ onSelect: handleSelect,
1534
+ disabled,
1535
+ className: calendarClassName,
1536
+ autoFocus: true
1537
+ })
1538
+ })]
1539
+ });
1540
+ }
1541
+ //#endregion
1542
+ //#region src/components/date-range-picker.tsx
1543
+ function formatRange(range) {
1544
+ if (!range?.from) return;
1545
+ if (!range.to) return formatDate(range.from);
1546
+ return `${formatDate(range.from)} - ${formatDate(range.to)}`;
1547
+ }
1548
+ function DateRangePicker({ value, defaultValue, onValueChange, placeholder = "Selecionar período", disabled = false, clearable = true, className, calendarClassName, "aria-label": ariaLabel = "Selecionar período", "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }) {
1549
+ const [open, setOpen] = React.useState(false);
1550
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
1551
+ const selectedRange = value ?? internalValue;
1552
+ const label = formatRange(selectedRange);
1553
+ const isInvalid = ariaInvalid === true || ariaInvalid === "true";
1554
+ function updateRange(range) {
1555
+ if (value === void 0) setInternalValue(range);
1556
+ onValueChange?.(range);
1557
+ }
1558
+ function handleClear(event) {
1559
+ event.stopPropagation();
1560
+ updateRange(void 0);
1561
+ }
1562
+ return /* @__PURE__ */ jsxs(Popover, {
1563
+ open,
1564
+ onOpenChange: setOpen,
1565
+ children: [/* @__PURE__ */ jsxs("div", {
1566
+ className: "relative w-full",
1567
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
1568
+ asChild: true,
1569
+ children: /* @__PURE__ */ jsxs(Button, {
1570
+ type: "button",
1571
+ variant: "outline",
1572
+ disabled,
1573
+ "aria-label": ariaLabel,
1574
+ "aria-describedby": ariaDescribedBy,
1575
+ "aria-invalid": ariaInvalid,
1576
+ className: cn("h-10 w-full justify-start px-3 text-left font-normal", !label && "text-muted", isInvalid && "border-error focus-visible:ring-error", clearable && label && "pr-10", className),
1577
+ children: [/* @__PURE__ */ jsx(CalendarIcon, {
1578
+ "aria-hidden": "true",
1579
+ className: "size-4"
1580
+ }), /* @__PURE__ */ jsx("span", {
1581
+ className: "min-w-0 truncate",
1582
+ children: label ?? placeholder
1583
+ })]
1584
+ })
1585
+ }), clearable && label && !disabled ? /* @__PURE__ */ jsx("button", {
1586
+ type: "button",
1587
+ "aria-label": "Limpar período",
1588
+ className: cn("absolute right-2 top-1/2 flex size-7 -translate-y-1/2 items-center justify-center rounded-sm", "text-muted transition-colors hover:bg-accent hover:text-on-surface", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35"),
1589
+ onClick: handleClear,
1590
+ children: /* @__PURE__ */ jsx(X, {
1591
+ "aria-hidden": "true",
1592
+ className: "size-4"
1593
+ })
1594
+ }) : null]
1595
+ }), /* @__PURE__ */ jsx(PopoverContent, {
1596
+ align: "start",
1597
+ className: "w-auto p-0",
1598
+ children: /* @__PURE__ */ jsx(Calendar, {
1599
+ mode: "range",
1600
+ selected: selectedRange,
1601
+ onSelect: updateRange,
1602
+ disabled,
1603
+ className: calendarClassName,
1604
+ autoFocus: true
1605
+ })
1606
+ })]
1607
+ });
1608
+ }
1609
+ //#endregion
1610
+ //#region src/components/dropdown-menu.tsx
1611
+ const DropdownMenu = DropdownMenuPrimitive.Root;
1612
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1613
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
1614
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
1615
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
1616
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
1617
+ const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => {
1618
+ return /* @__PURE__ */ jsxs(DropdownMenuPrimitive.SubTrigger, {
1619
+ ref,
1620
+ className: cn("flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none", "focus:bg-accent focus:text-accent-foreground", "data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", inset && "pl-8", className),
1621
+ ...props,
1622
+ children: [children, /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto size-4" })]
1623
+ });
1624
+ });
1625
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
1626
+ const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => {
1627
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.SubContent, {
1628
+ ref,
1629
+ className: cn("z-50 min-w-40 overflow-hidden rounded-fds-md border border-border bg-popover p-1 text-popover-foreground shadow-md", className),
1630
+ ...props
1631
+ });
1632
+ });
1633
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
1634
+ const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
1635
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.Content, {
1636
+ ref,
1637
+ sideOffset,
1638
+ className: cn("z-50 min-w-44 overflow-hidden rounded-fds-md border border-border bg-popover p-1 text-popover-foreground shadow-md", className),
1639
+ ...props
1640
+ }) });
1641
+ });
1642
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
1643
+ const DropdownMenuItem = React.forwardRef(({ className, inset, tone = "default", ...props }, ref) => {
1644
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Item, {
1645
+ ref,
1646
+ className: cn("relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none", "transition-colors duration-100", "focus:bg-accent focus:text-accent-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", tone === "danger" && "text-error focus:bg-error-container focus:text-on-error-container", className),
1647
+ ...props
1648
+ });
1649
+ });
1650
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
1651
+ const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => {
1652
+ return /* @__PURE__ */ jsxs(DropdownMenuPrimitive.CheckboxItem, {
1653
+ ref,
1654
+ className: cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none", "transition-colors duration-100", "focus:bg-accent focus:text-accent-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
1655
+ checked,
1656
+ ...props,
1657
+ children: [/* @__PURE__ */ jsx("span", {
1658
+ className: "absolute left-2 flex size-4 items-center justify-center",
1659
+ children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4" }) })
1660
+ }), children]
1661
+ });
1662
+ });
1663
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
1664
+ const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => {
1665
+ return /* @__PURE__ */ jsxs(DropdownMenuPrimitive.RadioItem, {
1666
+ ref,
1667
+ className: cn("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none", "transition-colors duration-100", "focus:bg-accent focus:text-accent-foreground", "data-disabled:pointer-events-none data-[disabled]:opacity-50", className),
1668
+ ...props,
1669
+ children: [/* @__PURE__ */ jsx("span", {
1670
+ className: "absolute left-2 flex size-4 items-center justify-center",
1671
+ children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Circle, { className: "size-2 fill-current" }) })
1672
+ }), children]
1673
+ });
1674
+ });
1675
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
1676
+ const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => {
1677
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Label, {
1678
+ ref,
1679
+ className: cn("px-2 py-1.5 caption mono uppercase tracking-[0.12em] text-muted-foreground", inset && "pl-8", className),
1680
+ ...props
1681
+ });
1682
+ });
1683
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
1684
+ const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => {
1685
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Separator, {
1686
+ ref,
1687
+ className: cn("-mx-1 my-1 h-px bg-border", className),
1688
+ ...props
1689
+ });
1690
+ });
1691
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
1692
+ function DropdownMenuShortcut({ className, ...props }) {
1693
+ return /* @__PURE__ */ jsx("span", {
1694
+ className: cn("ml-auto text-xs tracking-widest text-muted", className),
1695
+ ...props
1696
+ });
1697
+ }
1698
+ //#endregion
1699
+ //#region src/components/form.tsx
1700
+ const FormContext = React.createContext(null);
1701
+ const FormFieldContext = React.createContext(null);
1702
+ const FormItemContext = React.createContext(null);
1703
+ function useFormFieldContext() {
1704
+ const fieldContext = React.useContext(FormFieldContext);
1705
+ const itemContext = React.useContext(FormItemContext);
1706
+ if (!fieldContext) throw new Error("Form field components must be used inside <FormFieldController>.");
1707
+ const fieldId = itemContext?.id ?? fieldContext.name;
1708
+ const descriptionId = `${fieldId}-description`;
1709
+ const messageId = `${fieldId}-message`;
1710
+ const error = fieldContext.field.state.meta.errors.find(Boolean);
1711
+ return {
1712
+ ...fieldContext,
1713
+ fieldId,
1714
+ descriptionId,
1715
+ messageId,
1716
+ error,
1717
+ hasError: Boolean(error)
1718
+ };
1719
+ }
1720
+ function getErrorMessage(error) {
1721
+ if (!error) return;
1722
+ if (typeof error === "string") return error;
1723
+ if (Array.isArray(error)) return getErrorMessage(error.find(Boolean));
1724
+ if (typeof error === "object" && "message" in error) return String(error.message);
1725
+ return String(error);
1726
+ }
1727
+ function Form({ form, children }) {
1728
+ return /* @__PURE__ */ jsx(FormContext.Provider, {
1729
+ value: { form },
1730
+ children
1731
+ });
1732
+ }
1733
+ function FormFieldController({ form, name, validators, children }) {
1734
+ const context = React.useContext(FormContext);
1735
+ const formApi = form ?? context?.form;
1736
+ if (!formApi) throw new Error("FormFieldController requires a form prop or a parent <Form>.");
1737
+ const Field = formApi.Field;
1738
+ return /* @__PURE__ */ jsx(Field, {
1739
+ name,
1740
+ validators,
1741
+ children: (field) => /* @__PURE__ */ jsx(FormFieldContext.Provider, {
1742
+ value: {
1743
+ field,
1744
+ name
1745
+ },
1746
+ children: children(field)
1747
+ })
1748
+ });
1749
+ }
1750
+ function FormItem({ className, ...props }) {
1751
+ const id = React.useId();
1752
+ return /* @__PURE__ */ jsx(FormItemContext.Provider, {
1753
+ value: { id },
1754
+ children: /* @__PURE__ */ jsx("div", {
1755
+ className: cn("grid gap-1.5", className),
1756
+ ...props
1757
+ })
1758
+ });
1759
+ }
1760
+ function FormLabel({ className, ...props }) {
1761
+ const { fieldId, hasError } = useFormFieldContext();
1762
+ return /* @__PURE__ */ jsx(Label, {
1763
+ htmlFor: fieldId,
1764
+ className: cn(hasError && "text-destructive", className),
1765
+ ...props
1766
+ });
1767
+ }
1768
+ function FormControl({ children }) {
1769
+ const { fieldId, descriptionId, messageId, hasError } = useFormFieldContext();
1770
+ const describedBy = hasError ? `${descriptionId} ${messageId}` : descriptionId;
1771
+ return React.cloneElement(children, {
1772
+ id: children.props.id ?? fieldId,
1773
+ "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" "),
1774
+ "aria-invalid": hasError ? true : children.props["aria-invalid"]
1775
+ });
1776
+ }
1777
+ function FormDescription({ className, ...props }) {
1778
+ const { descriptionId } = useFormFieldContext();
1779
+ return /* @__PURE__ */ jsx("p", {
1780
+ id: descriptionId,
1781
+ className: cn("caption text-muted", className),
1782
+ ...props
1783
+ });
1784
+ }
1785
+ function FormMessage({ className, children, ...props }) {
1786
+ const { messageId, error } = useFormFieldContext();
1787
+ const body = children ?? getErrorMessage(error);
1788
+ if (!body) return null;
1789
+ return /* @__PURE__ */ jsx("p", {
1790
+ id: messageId,
1791
+ className: cn("caption text-destructive", className),
1792
+ role: "alert",
1793
+ ...props,
1794
+ children: body
1795
+ });
1796
+ }
1797
+ function getInputFieldProps(field) {
1798
+ return {
1799
+ name: field.name,
1800
+ value: field.state.value ?? "",
1801
+ onBlur: field.handleBlur,
1802
+ onChange: (event) => field.handleChange(event.target.value)
1803
+ };
1804
+ }
1805
+ function getSelectFieldProps(field) {
1806
+ return {
1807
+ value: field.state.value ?? "",
1808
+ onValueChange: (value) => field.handleChange(value)
1809
+ };
1810
+ }
1811
+ function getCheckboxFieldProps(field) {
1812
+ return {
1813
+ checked: Boolean(field.state.value),
1814
+ onCheckedChange: (value) => field.handleChange(value === true)
1815
+ };
1816
+ }
1817
+ function getRadioGroupFieldProps(field) {
1818
+ return {
1819
+ value: field.state.value ?? "",
1820
+ onValueChange: (value) => field.handleChange(value)
1821
+ };
1822
+ }
1823
+ function getSwitchFieldProps(field) {
1824
+ return {
1825
+ checked: Boolean(field.state.value),
1826
+ onCheckedChange: (value) => field.handleChange(value)
1827
+ };
1828
+ }
1829
+ function getDatePickerFieldProps(field) {
1830
+ return {
1831
+ value: field.state.value,
1832
+ onValueChange: (value) => field.handleChange(value)
1833
+ };
1834
+ }
1835
+ //#endregion
1836
+ //#region src/components/form-field.tsx
1837
+ function FormField({ id, label, helperText, error, required = false, className, children }) {
1838
+ const generatedId = React.useId();
1839
+ const fieldId = id ?? generatedId;
1840
+ const helperId = helperText ? `${fieldId}-helper` : void 0;
1841
+ const errorId = error ? `${fieldId}-error` : void 0;
1842
+ const describedBy = [helperId, errorId].filter(Boolean).join(" ") || void 0;
1843
+ const child = React.Children.only(children);
1844
+ const control = React.cloneElement(child, {
1845
+ id: child.props.id ?? fieldId,
1846
+ required: child.props.required ?? required,
1847
+ "aria-required": child.props["aria-required"] ?? (required ? true : void 0),
1848
+ "aria-describedby": describedBy,
1849
+ "aria-invalid": error ? true : child.props["aria-invalid"]
1850
+ });
1851
+ return /* @__PURE__ */ jsxs("div", {
1852
+ className: cn("flex w-full flex-col gap-1.5", className),
1853
+ children: [
1854
+ /* @__PURE__ */ jsx(Label, {
1855
+ htmlFor: fieldId,
1856
+ required,
1857
+ children: label
1858
+ }),
1859
+ control,
1860
+ helperText && !error ? /* @__PURE__ */ jsx("p", {
1861
+ id: helperId,
1862
+ className: "caption text-muted",
1863
+ children: helperText
1864
+ }) : null,
1865
+ error ? /* @__PURE__ */ jsx("p", {
1866
+ id: errorId,
1867
+ className: "caption text-error",
1868
+ role: "alert",
1869
+ children: error
1870
+ }) : null
1871
+ ]
1872
+ });
1873
+ }
1874
+ //#endregion
1875
+ //#region src/components/input.tsx
1876
+ const inputVariants = cva([
1877
+ "flex h-10 w-full",
1878
+ "rounded-fds-md border bg-surface px-3 py-2",
1879
+ "body-sm text-on-surface",
1880
+ "transition-colors duration-150",
1881
+ "placeholder:text-on-surface-variant",
1882
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-surface",
1883
+ "disabled:cursor-not-allowed disabled:opacity-50"
1884
+ ], {
1885
+ variants: { state: {
1886
+ default: "border-outline focus-visible:border-ring focus-visible:ring-ring",
1887
+ error: "border-error focus-visible:border-error focus-visible:ring-error"
1888
+ } },
1889
+ defaultVariants: { state: "default" }
1890
+ });
1891
+ const Input = React.forwardRef(({ className, state, ...props }, ref) => {
1892
+ return /* @__PURE__ */ jsx("input", {
1893
+ ref,
1894
+ className: cn(inputVariants({ state: props["aria-invalid"] === true || props["aria-invalid"] === "true" ? "error" : state }), className),
1895
+ ...props
1896
+ });
1897
+ });
1898
+ Input.displayName = "Input";
1899
+ //#endregion
1900
+ //#region src/components/native-select.tsx
1901
+ const nativeSelectVariants = cva([
1902
+ "h-9 w-full appearance-none",
1903
+ "rounded-fds-md border border-input bg-transparent px-3 py-2 pr-9",
1904
+ "body-sm text-on-surface shadow-sm outline-none",
1905
+ "transition-[color,box-shadow,border-color,background-color] duration-150",
1906
+ "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/35",
1907
+ "disabled:cursor-not-allowed disabled:opacity-50"
1908
+ ], {
1909
+ variants: {
1910
+ state: {
1911
+ default: "",
1912
+ error: "border-destructive focus-visible:border-destructive focus-visible:ring-destructive/25"
1913
+ },
1914
+ fieldSize: {
1915
+ sm: "h-8 px-2 pr-8 text-sm",
1916
+ md: "h-9 px-3 pr-9 text-sm",
1917
+ lg: "h-10 px-4 pr-10 text-base"
1918
+ }
1919
+ },
1920
+ defaultVariants: {
1921
+ state: "default",
1922
+ fieldSize: "md"
1923
+ }
1924
+ });
1925
+ const NativeSelect = React.forwardRef(({ className, state, fieldSize, placeholder = "Selecione uma opção", options, children, ...props }, ref) => {
1926
+ return /* @__PURE__ */ jsxs("div", {
1927
+ className: "relative w-full",
1928
+ children: [/* @__PURE__ */ jsxs("select", {
1929
+ ref,
1930
+ className: cn(nativeSelectVariants({
1931
+ state: props["aria-invalid"] === true || props["aria-invalid"] === "true" ? "error" : state,
1932
+ fieldSize
1933
+ }), className),
1934
+ defaultValue: props.defaultValue ?? "",
1935
+ ...props,
1936
+ children: [placeholder ? /* @__PURE__ */ jsx("option", {
1937
+ value: "",
1938
+ disabled: true,
1939
+ children: placeholder
1940
+ }) : null, options ? options.map((option) => /* @__PURE__ */ jsx("option", {
1941
+ value: option.value,
1942
+ disabled: option.disabled,
1943
+ children: option.label
1944
+ }, option.value)) : children]
1945
+ }), /* @__PURE__ */ jsx("span", {
1946
+ "aria-hidden": "true",
1947
+ className: "pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground",
1948
+ children: /* @__PURE__ */ jsxs("svg", {
1949
+ width: "16",
1950
+ height: "16",
1951
+ viewBox: "0 0 24 24",
1952
+ fill: "none",
1953
+ stroke: "currentColor",
1954
+ strokeWidth: "2",
1955
+ strokeLinecap: "round",
1956
+ strokeLinejoin: "round",
1957
+ children: [/* @__PURE__ */ jsx("title", { children: "▾" }), /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })]
1958
+ })
1959
+ })]
1960
+ });
1961
+ });
1962
+ NativeSelect.displayName = "NativeSelect";
1963
+ //#endregion
1964
+ //#region src/components/page-header.tsx
1965
+ function PageHeader({ className, eyebrow, title, description, actions, ...props }) {
1966
+ return /* @__PURE__ */ jsxs("div", {
1967
+ className: cn("flex flex-col gap-4 border-b border-border pb-6", "md:flex-row md:items-end md:justify-between", className),
1968
+ ...props,
1969
+ children: [/* @__PURE__ */ jsxs("div", {
1970
+ className: "min-w-0",
1971
+ children: [
1972
+ eyebrow ? /* @__PURE__ */ jsx("div", {
1973
+ className: "mb-2 caption mono uppercase tracking-[0.12em] text-muted",
1974
+ children: eyebrow
1975
+ }) : null,
1976
+ /* @__PURE__ */ jsx("h1", {
1977
+ className: "h1 truncate",
1978
+ children: title
1979
+ }),
1980
+ description ? /* @__PURE__ */ jsx("p", {
1981
+ className: "mt-2 max-w-3xl body text-muted",
1982
+ children: description
1983
+ }) : null
1984
+ ]
1985
+ }), actions ? /* @__PURE__ */ jsx("div", {
1986
+ className: "flex shrink-0 flex-wrap items-center gap-2",
1987
+ children: actions
1988
+ }) : null]
1989
+ });
1990
+ }
1991
+ //#endregion
1992
+ //#region src/components/radio-group.tsx
1993
+ const RadioGroup = React.forwardRef(({ className, options, error = false, ...props }, ref) => {
1994
+ const generatedId = React.useId();
1995
+ return /* @__PURE__ */ jsx(RadioGroupPrimitive.Root, {
1996
+ ref,
1997
+ className: cn("grid gap-2", className),
1998
+ ...props,
1999
+ children: options.map((option) => {
2000
+ const itemId = `${generatedId}-${option.value}`;
2001
+ return /* @__PURE__ */ jsxs("div", {
2002
+ className: cn("flex items-start gap-3 rounded-fds-md border border-border p-3", "transition-colors duration-150", "has-data-[state=checked]:border-primary", "has-data-[state=checked]:bg-primary-container", option.disabled && "opacity-60"),
2003
+ children: [/* @__PURE__ */ jsx(RadioGroupPrimitive.Item, {
2004
+ id: itemId,
2005
+ value: option.value,
2006
+ disabled: option.disabled,
2007
+ className: cn("mt-0.5 size-4 shrink-0 rounded-full border border-input bg-transparent shadow-sm", "transition-[color,box-shadow,border-color,background-color] duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:cursor-not-allowed disabled:opacity-50", "data-[state=checked]:border-primary", error && "border-destructive focus-visible:ring-destructive/25"),
2008
+ children: /* @__PURE__ */ jsx(RadioGroupPrimitive.Indicator, {
2009
+ className: "flex size-full items-center justify-center",
2010
+ children: /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-primary" })
2011
+ })
2012
+ }), /* @__PURE__ */ jsxs("label", {
2013
+ htmlFor: itemId,
2014
+ className: "grid flex-1 gap-1",
2015
+ children: [/* @__PURE__ */ jsx("span", {
2016
+ className: "body-sm font-medium text-on-surface",
2017
+ children: option.label
2018
+ }), option.description ? /* @__PURE__ */ jsx("span", {
2019
+ className: "caption text-muted",
2020
+ children: option.description
2021
+ }) : null]
2022
+ })]
2023
+ }, option.value);
2024
+ })
2025
+ });
2026
+ });
2027
+ RadioGroup.displayName = "RadioGroup";
2028
+ //#endregion
2029
+ //#region src/components/select.tsx
2030
+ function isGroupedOptions(options) {
2031
+ return options.length > 0 && "options" in options[0];
2032
+ }
2033
+ const Select = React.forwardRef(({ id, placeholder = "Selecione uma opção", options, className, contentClassName, disabled, required, name, value, defaultValue, onValueChange, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, ...props }, ref) => {
2034
+ const isInvalid = ariaInvalid === true || ariaInvalid === "true";
2035
+ return /* @__PURE__ */ jsxs(SelectPrimitive.Root, {
2036
+ disabled,
2037
+ required,
2038
+ name,
2039
+ value,
2040
+ defaultValue,
2041
+ onValueChange,
2042
+ ...props,
2043
+ children: [/* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
2044
+ ref,
2045
+ id,
2046
+ "aria-describedby": ariaDescribedBy,
2047
+ "aria-invalid": ariaInvalid,
2048
+ "aria-required": required ? true : void 0,
2049
+ className: cn("flex h-9 w-full items-center justify-between gap-2 whitespace-nowrap", "rounded-fds-md border border-input bg-transparent px-3 py-2", "body-sm text-on-surface shadow-sm outline-none", "transition-[color,box-shadow,border-color,background-color] duration-150", "data-placeholder:text-muted-foreground", "hover:bg-accent", "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:cursor-not-allowed disabled:opacity-50", isInvalid && "border-destructive focus-visible:border-destructive focus-visible:ring-destructive/25", className),
2050
+ children: [/* @__PURE__ */ jsx("span", {
2051
+ className: "min-w-0 truncate text-left",
2052
+ children: /* @__PURE__ */ jsx(SelectPrimitive.Value, { placeholder })
2053
+ }), /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
2054
+ asChild: true,
2055
+ children: /* @__PURE__ */ jsx(ChevronDown, {
2056
+ "aria-hidden": "true",
2057
+ className: "size-4 shrink-0 text-muted-foreground opacity-70"
2058
+ })
2059
+ })]
2060
+ }), /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(SelectPrimitive.Content, {
2061
+ position: "popper",
2062
+ sideOffset: 4,
2063
+ align: "start",
2064
+ className: cn("relative z-50 max-h-72 min-w-(--radix-select-trigger-width) overflow-hidden", "rounded-fds-md border border-border bg-popover text-popover-foreground", "shadow-md", contentClassName),
2065
+ children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, {
2066
+ className: "p-1",
2067
+ children: isGroupedOptions(options) ? options.map((group, groupIndex) => /* @__PURE__ */ jsxs(SelectPrimitive.Group, { children: [
2068
+ groupIndex > 0 ? /* @__PURE__ */ jsx(SelectPrimitive.Separator, { className: "my-1 h-px bg-border" }) : null,
2069
+ /* @__PURE__ */ jsx(SelectPrimitive.Label, {
2070
+ className: "px-2 py-1.5 caption mono uppercase tracking-[0.12em] text-muted-foreground",
2071
+ children: group.label
2072
+ }),
2073
+ group.options.map((option) => /* @__PURE__ */ jsx(SelectItem, { option }, option.value))
2074
+ ] }, group.label)) : options.map((option) => /* @__PURE__ */ jsx(SelectItem, { option }, option.value))
2075
+ })
2076
+ }) })]
2077
+ });
2078
+ });
2079
+ Select.displayName = "Select";
2080
+ function SelectItem({ option }) {
2081
+ return /* @__PURE__ */ jsxs(SelectPrimitive.Item, {
2082
+ value: option.value,
2083
+ disabled: option.disabled,
2084
+ className: cn("relative flex w-full cursor-default select-none items-center", "rounded-sm py-1.5 pl-2 pr-8 outline-none", "text-sm", "transition-colors duration-100", "data-highlighted:bg-accent data-highlighted:text-accent-foreground", "data-disabled:pointer-events-none data-disabled:opacity-50"),
2085
+ children: [/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children: /* @__PURE__ */ jsx("span", {
2086
+ className: "truncate",
2087
+ children: option.label
2088
+ }) }), /* @__PURE__ */ jsx("span", {
2089
+ className: "absolute right-2 flex size-4 items-center justify-center",
2090
+ children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4 text-primary" }) })
2091
+ })]
2092
+ });
2093
+ }
2094
+ //#endregion
2095
+ //#region src/components/separator.tsx
2096
+ const Separator = React.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => {
2097
+ return /* @__PURE__ */ jsx(SeparatorPrimitive.Root, {
2098
+ ref,
2099
+ decorative,
2100
+ orientation,
2101
+ className: cn("shrink-0 bg-border", orientation === "horizontal" ? "h-px w-full" : "h-full w-px", className),
2102
+ ...props
2103
+ });
2104
+ });
2105
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
2106
+ //#endregion
2107
+ //#region src/components/sheet.tsx
2108
+ const Sheet = DialogPrimitive.Root;
2109
+ const SheetTrigger = DialogPrimitive.Trigger;
2110
+ const SheetClose = DialogPrimitive.Close;
2111
+ const SheetPortal = DialogPrimitive.Portal;
2112
+ const SheetOverlay = React.forwardRef(({ className, ...props }, ref) => {
2113
+ return /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
2114
+ ref,
2115
+ className: cn("fixed inset-0 z-50 bg-black/45", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", className),
2116
+ ...props
2117
+ });
2118
+ });
2119
+ SheetOverlay.displayName = DialogPrimitive.Overlay.displayName;
2120
+ const sheetVariants = cva([
2121
+ "fixed z-50 gap-4 bg-popover text-popover-foreground shadow-lg",
2122
+ "transition ease-in-out",
2123
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
2124
+ "data-[state=closed]:duration-300 data-[state=open]:duration-500"
2125
+ ], {
2126
+ variants: { side: {
2127
+ top: [
2128
+ "inset-x-0 top-0 border-b border-border",
2129
+ "data-[state=closed]:slide-out-to-top",
2130
+ "data-[state=open]:slide-in-from-top"
2131
+ ],
2132
+ bottom: [
2133
+ "inset-x-0 bottom-0 border-t border-border",
2134
+ "data-[state=closed]:slide-out-to-bottom",
2135
+ "data-[state=open]:slide-in-from-bottom"
2136
+ ],
2137
+ left: [
2138
+ "inset-y-0 left-0 h-full w-3/4 border-r border-border sm:max-w-sm",
2139
+ "data-[state=closed]:slide-out-to-left",
2140
+ "data-[state=open]:slide-in-from-left"
2141
+ ],
2142
+ right: [
2143
+ "inset-y-0 right-0 h-full w-3/4 border-l border-border sm:max-w-sm",
2144
+ "data-[state=closed]:slide-out-to-right",
2145
+ "data-[state=open]:slide-in-from-right"
2146
+ ]
2147
+ } },
2148
+ defaultVariants: { side: "right" }
2149
+ });
2150
+ const SheetContent = React.forwardRef(({ side = "right", className, children, showCloseButton = true, ...props }, ref) => {
2151
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
2152
+ ref,
2153
+ className: cn(sheetVariants({ side }), className),
2154
+ ...props,
2155
+ children: [children, showCloseButton ? /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
2156
+ className: cn("absolute right-4 top-4 rounded-sm opacity-70", "transition-opacity hover:opacity-100", "focus:outline-none focus:ring-2 focus:ring-ring/35", "disabled:pointer-events-none"),
2157
+ children: [/* @__PURE__ */ jsx(X, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
2158
+ className: "sr-only",
2159
+ children: "Fechar"
2160
+ })]
2161
+ }) : null]
2162
+ })] });
2163
+ });
2164
+ SheetContent.displayName = DialogPrimitive.Content.displayName;
2165
+ function SheetHeader({ className, ...props }) {
2166
+ return /* @__PURE__ */ jsx("div", {
2167
+ className: cn("flex flex-col gap-1.5 text-left", className),
2168
+ ...props
2169
+ });
2170
+ }
2171
+ function SheetFooter({ className, ...props }) {
2172
+ return /* @__PURE__ */ jsx("div", {
2173
+ className: cn("mt-auto flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className),
2174
+ ...props
2175
+ });
2176
+ }
2177
+ const SheetTitle = React.forwardRef(({ className, ...props }, ref) => {
2178
+ return /* @__PURE__ */ jsx(DialogPrimitive.Title, {
2179
+ ref,
2180
+ className: cn("h3 text-on-surface", className),
2181
+ ...props
2182
+ });
2183
+ });
2184
+ SheetTitle.displayName = DialogPrimitive.Title.displayName;
2185
+ const SheetDescription = React.forwardRef(({ className, ...props }, ref) => {
2186
+ return /* @__PURE__ */ jsx(DialogPrimitive.Description, {
2187
+ ref,
2188
+ className: cn("body-sm text-muted", className),
2189
+ ...props
2190
+ });
2191
+ });
2192
+ SheetDescription.displayName = DialogPrimitive.Description.displayName;
2193
+ //#endregion
2194
+ //#region src/components/sidebar.tsx
2195
+ function Sidebar({ className, ...props }) {
2196
+ return /* @__PURE__ */ jsx("div", {
2197
+ className: cn("flex h-full min-h-0 flex-col bg-card text-card-foreground", className),
2198
+ ...props
2199
+ });
2200
+ }
2201
+ function SidebarHeader({ className, ...props }) {
2202
+ return /* @__PURE__ */ jsx("div", {
2203
+ className: cn("flex min-h-16 items-center border-b border-border px-4", className),
2204
+ ...props
2205
+ });
2206
+ }
2207
+ function SidebarBrand({ title, description, icon, className, ...props }) {
2208
+ return /* @__PURE__ */ jsxs("div", {
2209
+ className: cn("flex min-w-0 items-center gap-3", className),
2210
+ ...props,
2211
+ children: [icon ? /* @__PURE__ */ jsx("div", {
2212
+ className: "flex size-9 shrink-0 items-center justify-center rounded-fds-md bg-primary text-on-primary",
2213
+ children: icon
2214
+ }) : null, /* @__PURE__ */ jsxs("div", {
2215
+ className: "min-w-0",
2216
+ children: [/* @__PURE__ */ jsx("p", {
2217
+ className: "truncate body-sm font-semibold text-on-surface",
2218
+ children: title
2219
+ }), description ? /* @__PURE__ */ jsx("p", {
2220
+ className: "truncate caption text-muted",
2221
+ children: description
2222
+ }) : null]
2223
+ })]
2224
+ });
2225
+ }
2226
+ function SidebarContent({ className, ...props }) {
2227
+ return /* @__PURE__ */ jsx("div", {
2228
+ className: cn("min-h-0 flex-1 overflow-y-auto px-3 py-4", className),
2229
+ ...props
2230
+ });
2231
+ }
2232
+ function SidebarSection({ title, className, children, ...props }) {
2233
+ return /* @__PURE__ */ jsxs("div", {
2234
+ className: cn("grid gap-1", className),
2235
+ ...props,
2236
+ children: [title ? /* @__PURE__ */ jsx("p", {
2237
+ className: "px-3 pb-2 caption mono uppercase tracking-[0.12em] text-muted",
2238
+ children: title
2239
+ }) : null, children]
2240
+ });
2241
+ }
2242
+ const SidebarNavItem = React.forwardRef(({ icon, active = false, asChild = false, className, children, ...props }, ref) => {
2243
+ return /* @__PURE__ */ jsxs(asChild ? Slot : "button", {
2244
+ ref,
2245
+ className: cn("flex h-9 w-full items-center gap-3 rounded-fds-md px-3 text-left body-sm", "transition-colors duration-150", "hover:bg-accent hover:text-accent-foreground", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:pointer-events-none disabled:opacity-50", active ? "bg-primary-container text-on-primary-container" : "text-muted-foreground", className),
2246
+ ...props,
2247
+ children: [icon ? /* @__PURE__ */ jsx("span", {
2248
+ className: "flex size-4 shrink-0 items-center justify-center",
2249
+ children: icon
2250
+ }) : null, /* @__PURE__ */ jsx("span", {
2251
+ className: "min-w-0 truncate",
2252
+ children
2253
+ })]
2254
+ });
2255
+ });
2256
+ SidebarNavItem.displayName = "SidebarNavItem";
2257
+ function SidebarFooter({ className, ...props }) {
2258
+ return /* @__PURE__ */ jsx("div", {
2259
+ className: cn("border-t border-border p-3", className),
2260
+ ...props
2261
+ });
2262
+ }
2263
+ //#endregion
2264
+ //#region src/components/spinner.tsx
2265
+ const spinnerVariants = cva("animate-spin", {
2266
+ variants: {
2267
+ size: {
2268
+ sm: "size-4",
2269
+ md: "size-5",
2270
+ lg: "size-7"
2271
+ },
2272
+ tone: {
2273
+ current: "text-current",
2274
+ primary: "text-primary",
2275
+ muted: "text-muted-foreground",
2276
+ danger: "text-error",
2277
+ success: "text-success",
2278
+ warning: "text-warning",
2279
+ info: "text-info"
2280
+ }
2281
+ },
2282
+ defaultVariants: {
2283
+ size: "md",
2284
+ tone: "current"
2285
+ }
2286
+ });
2287
+ function Spinner({ className, size, tone, ...props }) {
2288
+ return /* @__PURE__ */ jsx(LoaderCircle, {
2289
+ role: "status",
2290
+ "aria-label": "Carregando",
2291
+ className: cn(spinnerVariants({
2292
+ size,
2293
+ tone
2294
+ }), className),
2295
+ ...props
2296
+ });
2297
+ }
2298
+ //#endregion
2299
+ //#region src/components/status-badge.tsx
2300
+ const statusConfig = {
2301
+ active: {
2302
+ label: "Ativo",
2303
+ tone: "success"
2304
+ },
2305
+ inactive: {
2306
+ label: "Inativo",
2307
+ tone: "neutral"
2308
+ },
2309
+ pending: {
2310
+ label: "Pendente",
2311
+ tone: "warning"
2312
+ },
2313
+ completed: {
2314
+ label: "Concluído",
2315
+ tone: "success"
2316
+ },
2317
+ canceled: {
2318
+ label: "Cancelado",
2319
+ tone: "danger"
2320
+ },
2321
+ draft: {
2322
+ label: "Rascunho",
2323
+ tone: "info"
2324
+ },
2325
+ blocked: {
2326
+ label: "Bloqueado",
2327
+ tone: "danger"
2328
+ },
2329
+ archived: {
2330
+ label: "Arquivado",
2331
+ tone: "secondary"
2332
+ }
2333
+ };
2334
+ function StatusBadge({ status, label, tone, variant = "soft", ...props }) {
2335
+ const config = statusConfig[status];
2336
+ return /* @__PURE__ */ jsx(Badge, {
2337
+ tone: tone ?? config.tone,
2338
+ variant,
2339
+ ...props,
2340
+ children: label ?? config.label
2341
+ });
2342
+ }
2343
+ //#endregion
2344
+ //#region src/components/switch.tsx
2345
+ const Switch = React.forwardRef(({ className, error = false, ...props }, ref) => {
2346
+ return /* @__PURE__ */ jsx(SwitchPrimitive.Root, {
2347
+ ref,
2348
+ className: cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-transparent shadow-sm", "transition-colors duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:cursor-not-allowed disabled:opacity-50", "data-[state=unchecked]:bg-input", "data-[state=checked]:bg-primary", error && "focus-visible:ring-destructive/25", className),
2349
+ ...props,
2350
+ children: /* @__PURE__ */ jsx(SwitchPrimitive.Thumb, { className: cn("pointer-events-none block size-4 rounded-full bg-surface shadow-sm ring-0", "transition-transform duration-150", "data-[state=checked]:translate-x-4", "data-[state=unchecked]:translate-x-0") })
2351
+ });
2352
+ });
2353
+ Switch.displayName = "Switch";
2354
+ function SwitchField({ id, label, description, errorMessage, required, className, ...props }) {
2355
+ const generatedId = React.useId();
2356
+ const fieldId = id ?? generatedId;
2357
+ const descriptionId = description ? `${fieldId}-description` : void 0;
2358
+ const errorId = errorMessage ? `${fieldId}-error` : void 0;
2359
+ const describedBy = [descriptionId, errorId].filter(Boolean).join(" ") || void 0;
2360
+ return /* @__PURE__ */ jsxs("div", {
2361
+ className: cn("flex flex-col gap-1.5", className),
2362
+ children: [/* @__PURE__ */ jsxs("div", {
2363
+ className: "flex items-start justify-between gap-4 rounded-fds-md border border-border p-3",
2364
+ children: [/* @__PURE__ */ jsxs("div", {
2365
+ className: "grid gap-1",
2366
+ children: [/* @__PURE__ */ jsx(Label, {
2367
+ htmlFor: fieldId,
2368
+ required,
2369
+ className: cn(props.disabled && "cursor-not-allowed opacity-60"),
2370
+ children: label
2371
+ }), description ? /* @__PURE__ */ jsx("p", {
2372
+ id: descriptionId,
2373
+ className: "caption text-muted",
2374
+ children: description
2375
+ }) : null]
2376
+ }), /* @__PURE__ */ jsx(Switch, {
2377
+ id: fieldId,
2378
+ required,
2379
+ "aria-describedby": describedBy,
2380
+ "aria-invalid": errorMessage ? true : void 0,
2381
+ error: Boolean(errorMessage),
2382
+ ...props
2383
+ })]
2384
+ }), errorMessage ? /* @__PURE__ */ jsx("p", {
2385
+ id: errorId,
2386
+ className: "caption text-destructive",
2387
+ role: "alert",
2388
+ children: errorMessage
2389
+ }) : null]
2390
+ });
2391
+ }
2392
+ //#endregion
2393
+ //#region src/components/tabs.tsx
2394
+ const Tabs = TabsPrimitive.Root;
2395
+ const TabsList = React.forwardRef(({ className, ...props }, ref) => {
2396
+ return /* @__PURE__ */ jsx(TabsPrimitive.List, {
2397
+ ref,
2398
+ className: cn("inline-flex h-9 items-center justify-center rounded-fds-md bg-muted p-1 text-muted-foreground", className),
2399
+ ...props
2400
+ });
2401
+ });
2402
+ TabsList.displayName = TabsPrimitive.List.displayName;
2403
+ const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => {
2404
+ return /* @__PURE__ */ jsx(TabsPrimitive.Trigger, {
2405
+ ref,
2406
+ className: cn("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1 text-sm font-medium", "transition-all duration-150", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", "disabled:pointer-events-none disabled:opacity-50", "data-[state=active]:bg-surface", "data-[state=active]:text-on-surface", "data-[state=active]:shadow-sm", className),
2407
+ ...props
2408
+ });
2409
+ });
2410
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
2411
+ const TabsContent = React.forwardRef(({ className, ...props }, ref) => {
2412
+ return /* @__PURE__ */ jsx(TabsPrimitive.Content, {
2413
+ ref,
2414
+ className: cn("mt-4 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/35", className),
2415
+ ...props
2416
+ });
2417
+ });
2418
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
2419
+ //#endregion
2420
+ //#region src/components/textarea.tsx
2421
+ const textareaVariants = cva([
2422
+ "flex min-h-24 w-full",
2423
+ "rounded-fds-md border bg-surface px-3 py-2",
2424
+ "body-sm text-on-surface",
2425
+ "transition-colors duration-150",
2426
+ "placeholder:text-on-surface-variant",
2427
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-surface",
2428
+ "disabled:cursor-not-allowed disabled:opacity-50"
2429
+ ], {
2430
+ variants: { state: {
2431
+ default: "border-outline focus-visible:border-ring focus-visible:ring-ring",
2432
+ error: "border-error focus-visible:border-error focus-visible:ring-error"
2433
+ } },
2434
+ defaultVariants: { state: "default" }
2435
+ });
2436
+ const Textarea = React.forwardRef(({ className, state, ...props }, ref) => {
2437
+ return /* @__PURE__ */ jsx("textarea", {
2438
+ ref,
2439
+ className: cn(textareaVariants({ state: props["aria-invalid"] === true || props["aria-invalid"] === "true" ? "error" : state }), className),
2440
+ ...props
2441
+ });
2442
+ });
2443
+ Textarea.displayName = "Textarea";
2444
+ //#endregion
2445
+ //#region src/components/toast.tsx
2446
+ const toneClasses = {
2447
+ default: "border-border bg-popover text-popover-foreground",
2448
+ success: "border-success/30 bg-success-container text-on-success-container",
2449
+ warning: "border-warning/30 bg-warning-container text-on-warning-container",
2450
+ info: "border-info/30 bg-info-container text-on-info-container",
2451
+ danger: "border-error/30 bg-error-container text-on-error-container"
2452
+ };
2453
+ function normalizeTone(tone = "default") {
2454
+ return tone === "error" ? "danger" : tone;
2455
+ }
2456
+ const ToastProvider = ToastPrimitive.Provider;
2457
+ const ToastAction = ToastPrimitive.Action;
2458
+ const ToastViewport = React.forwardRef(({ className, ...props }, ref) => {
2459
+ return /* @__PURE__ */ jsx(ToastPrimitive.Viewport, {
2460
+ ref,
2461
+ className: cn("fixed inset-x-0 bottom-0 z-50 flex max-h-screen w-full flex-col-reverse gap-2 p-4", "sm:inset-auto sm:bottom-4 sm:right-4 sm:max-w-sm", className),
2462
+ ...props
2463
+ });
2464
+ });
2465
+ ToastViewport.displayName = ToastPrimitive.Viewport.displayName;
2466
+ const Toast = React.forwardRef(({ className, tone = "default", role, ...props }, ref) => {
2467
+ const currentTone = normalizeTone(tone);
2468
+ const semanticRole = role ?? (currentTone === "danger" || currentTone === "warning" ? "alert" : "status");
2469
+ return /* @__PURE__ */ jsx(ToastPrimitive.Root, {
2470
+ ref,
2471
+ role: semanticRole,
2472
+ className: cn("group pointer-events-auto relative grid w-full gap-2 overflow-hidden rounded-fds-lg border p-4 pr-11 shadow-lg", "transition-all duration-200", "data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x)", "data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:transition-transform", "data-[swipe=end]:animate-out data-[swipe=end]:slide-out-to-right-full", "data-[state=open]:animate-in data-[state=open]:slide-in-from-bottom-full", "data-[state=closed]:animate-out data-[state=closed]:fade-out-80", "sm:data-[state=open]:slide-in-from-right-full", toneClasses[currentTone], className),
2473
+ ...props
2474
+ });
2475
+ });
2476
+ Toast.displayName = ToastPrimitive.Root.displayName;
2477
+ const ToastTitle = React.forwardRef(({ className, ...props }, ref) => {
2478
+ return /* @__PURE__ */ jsx(ToastPrimitive.Title, {
2479
+ ref,
2480
+ className: cn("body-sm font-semibold leading-5", className),
2481
+ ...props
2482
+ });
2483
+ });
2484
+ ToastTitle.displayName = ToastPrimitive.Title.displayName;
2485
+ const ToastDescription = React.forwardRef(({ className, ...props }, ref) => {
2486
+ return /* @__PURE__ */ jsx(ToastPrimitive.Description, {
2487
+ ref,
2488
+ className: cn("body-sm opacity-90", className),
2489
+ ...props
2490
+ });
2491
+ });
2492
+ ToastDescription.displayName = ToastPrimitive.Description.displayName;
2493
+ const ToastClose = React.forwardRef(({ className, "aria-label": ariaLabel = "Fechar notificação", children, ...props }, ref) => {
2494
+ return /* @__PURE__ */ jsx(ToastPrimitive.Close, {
2495
+ ref,
2496
+ "aria-label": ariaLabel,
2497
+ className: cn("absolute right-3 top-3 rounded-sm opacity-75 transition-opacity hover:opacity-100", "focus:outline-none focus:ring-2 focus:ring-ring/35", "disabled:pointer-events-none", className),
2498
+ ...props,
2499
+ children: children ?? /* @__PURE__ */ jsx(X, {
2500
+ "aria-hidden": "true",
2501
+ className: "size-4"
2502
+ })
2503
+ });
2504
+ });
2505
+ ToastClose.displayName = ToastPrimitive.Close.displayName;
2506
+ //#endregion
2507
+ //#region src/hooks/use-toast.ts
2508
+ const ToastContext = React.createContext(null);
2509
+ function useToast() {
2510
+ const context = React.useContext(ToastContext);
2511
+ if (!context) throw new Error("useToast deve ser usado dentro de <Toaster>.");
2512
+ return context;
2513
+ }
2514
+ //#endregion
2515
+ //#region src/components/toaster.tsx
2516
+ let toastCounter = 0;
2517
+ function createToastId() {
2518
+ toastCounter += 1;
2519
+ return `toast-${toastCounter}`;
2520
+ }
2521
+ function Toaster({ children, duration = 5e3, swipeDirection = "right" }) {
2522
+ const [toasts, setToasts] = React.useState([]);
2523
+ const dismiss = React.useCallback((id) => {
2524
+ setToasts((current) => current.map((toast) => toast.id === id ? {
2525
+ ...toast,
2526
+ open: false
2527
+ } : toast));
2528
+ }, []);
2529
+ const remove = React.useCallback((id) => {
2530
+ setToasts((current) => current.filter((toast) => toast.id !== id));
2531
+ }, []);
2532
+ const toast = React.useCallback((input) => {
2533
+ const id = createToastId();
2534
+ setToasts((current) => [...current, {
2535
+ ...input,
2536
+ id,
2537
+ open: true
2538
+ }]);
2539
+ return {
2540
+ id,
2541
+ dismiss: () => dismiss(id)
2542
+ };
2543
+ }, [dismiss]);
2544
+ const value = React.useMemo(() => ({
2545
+ toasts,
2546
+ toast,
2547
+ dismiss
2548
+ }), [
2549
+ toasts,
2550
+ toast,
2551
+ dismiss
2552
+ ]);
2553
+ return /* @__PURE__ */ jsx(ToastContext.Provider, {
2554
+ value,
2555
+ children: /* @__PURE__ */ jsxs(ToastProvider, {
2556
+ duration,
2557
+ swipeDirection,
2558
+ children: [
2559
+ children,
2560
+ toasts.map((toast) => /* @__PURE__ */ jsxs(Toast, {
2561
+ open: toast.open,
2562
+ tone: toast.tone,
2563
+ duration: toast.duration,
2564
+ onOpenChange: (open) => {
2565
+ if (!open) dismiss(toast.id);
2566
+ },
2567
+ onAnimationEnd: () => {
2568
+ if (!toast.open) remove(toast.id);
2569
+ },
2570
+ children: [
2571
+ toast.title ? /* @__PURE__ */ jsx(ToastTitle, { children: toast.title }) : null,
2572
+ toast.description ? /* @__PURE__ */ jsx(ToastDescription, { children: toast.description }) : null,
2573
+ toast.action,
2574
+ /* @__PURE__ */ jsx(ToastClose, {})
2575
+ ]
2576
+ }, toast.id)),
2577
+ /* @__PURE__ */ jsx(ToastViewport, {})
2578
+ ]
2579
+ })
2580
+ });
2581
+ }
2582
+ //#endregion
2583
+ //#region src/components/tooltip.tsx
2584
+ const TooltipProvider = TooltipPrimitive.Provider;
2585
+ const TooltipRoot = TooltipPrimitive.Root;
2586
+ const TooltipTrigger = TooltipPrimitive.Trigger;
2587
+ function Tooltip({ children, content, side = "top", align = "center", delayDuration = 300, className }) {
2588
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, {
2589
+ delayDuration,
2590
+ children: /* @__PURE__ */ jsxs(TooltipPrimitive.Root, { children: [/* @__PURE__ */ jsx(TooltipPrimitive.Trigger, {
2591
+ asChild: true,
2592
+ children
2593
+ }), /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Content, {
2594
+ side,
2595
+ align,
2596
+ sideOffset: 6,
2597
+ className: cn("z-50 overflow-hidden rounded-fds-md border border-border", "bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md", "data-[state=delayed-open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=delayed-open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=delayed-open]:zoom-in-95", className),
2598
+ children: content
2599
+ }) })] })
2600
+ });
2601
+ }
2602
+ //#endregion
2603
+ //#region src/components/topbar.tsx
2604
+ function Topbar({ start, center, end, className, children, ...props }) {
2605
+ return /* @__PURE__ */ jsx("div", {
2606
+ className: cn("flex min-h-16 items-center gap-4 px-6", className),
2607
+ ...props,
2608
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
2609
+ /* @__PURE__ */ jsx("div", {
2610
+ className: "flex min-w-0 flex-1 items-center gap-3",
2611
+ children: start
2612
+ }),
2613
+ center ? /* @__PURE__ */ jsx("div", {
2614
+ className: "hidden min-w-0 flex-1 items-center justify-center lg:flex",
2615
+ children: center
2616
+ }) : null,
2617
+ /* @__PURE__ */ jsx("div", {
2618
+ className: "flex min-w-0 flex-1 items-center justify-end gap-2",
2619
+ children: end
2620
+ })
2621
+ ] })
2622
+ });
2623
+ }
2624
+ //#endregion
2625
+ //#region src/components/user-menu.tsx
2626
+ const defaultItems = [{
2627
+ label: "Perfil",
2628
+ icon: /* @__PURE__ */ jsx(User, { className: "size-4" })
2629
+ }, {
2630
+ label: "Configurações",
2631
+ icon: /* @__PURE__ */ jsx(Settings, { className: "size-4" }),
2632
+ shortcut: "⌘,"
2633
+ }];
2634
+ const defaultFooterItems = [{
2635
+ label: "Sair",
2636
+ icon: /* @__PURE__ */ jsx(LogOut, { className: "size-4" }),
2637
+ tone: "danger"
2638
+ }];
2639
+ function UserMenu({ name, email, avatarUrl, initials, items = defaultItems, footerItems = defaultFooterItems }) {
2640
+ const fallback = initials ?? getInitials(name);
2641
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
2642
+ asChild: true,
2643
+ children: /* @__PURE__ */ jsxs(Button, {
2644
+ variant: "ghost",
2645
+ size: "sm",
2646
+ className: "h-10 gap-3 px-2",
2647
+ children: [/* @__PURE__ */ jsxs(Avatar, {
2648
+ className: "size-7",
2649
+ children: [/* @__PURE__ */ jsx(AvatarImage, {
2650
+ src: avatarUrl,
2651
+ alt: name
2652
+ }), /* @__PURE__ */ jsx(AvatarFallback, {
2653
+ className: "text-xs",
2654
+ children: fallback
2655
+ })]
2656
+ }), /* @__PURE__ */ jsxs("span", {
2657
+ className: "hidden min-w-0 flex-col items-start sm:flex",
2658
+ children: [/* @__PURE__ */ jsx("span", {
2659
+ className: "max-w-32 truncate text-sm font-medium leading-4",
2660
+ children: name
2661
+ }), email ? /* @__PURE__ */ jsx("span", {
2662
+ className: "max-w-32 truncate text-xs font-normal leading-4 text-muted-foreground",
2663
+ children: email
2664
+ }) : null]
2665
+ })]
2666
+ })
2667
+ }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
2668
+ align: "end",
2669
+ className: "w-64",
2670
+ children: [
2671
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: /* @__PURE__ */ jsxs("div", {
2672
+ className: "flex min-w-0 items-center gap-3",
2673
+ children: [/* @__PURE__ */ jsxs(Avatar, {
2674
+ className: "size-9",
2675
+ children: [/* @__PURE__ */ jsx(AvatarImage, {
2676
+ src: avatarUrl,
2677
+ alt: name
2678
+ }), /* @__PURE__ */ jsx(AvatarFallback, { children: fallback })]
2679
+ }), /* @__PURE__ */ jsxs("div", {
2680
+ className: "min-w-0",
2681
+ children: [/* @__PURE__ */ jsx("p", {
2682
+ className: "truncate body-sm font-semibold normal-case tracking-normal text-on-surface",
2683
+ children: name
2684
+ }), email ? /* @__PURE__ */ jsx("p", {
2685
+ className: "truncate caption normal-case tracking-normal text-muted",
2686
+ children: email
2687
+ }) : null]
2688
+ })]
2689
+ }) }),
2690
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2691
+ items.map((item) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
2692
+ disabled: item.disabled,
2693
+ tone: item.tone,
2694
+ onSelect: item.onSelect,
2695
+ children: [
2696
+ item.icon,
2697
+ item.label,
2698
+ item.shortcut ? /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: item.shortcut }) : null
2699
+ ]
2700
+ }, item.label)),
2701
+ footerItems.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), footerItems.map((item) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
2702
+ disabled: item.disabled,
2703
+ tone: item.tone,
2704
+ onSelect: item.onSelect,
2705
+ children: [
2706
+ item.icon,
2707
+ item.label,
2708
+ item.shortcut ? /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: item.shortcut }) : null
2709
+ ]
2710
+ }, item.label))] }) : null
2711
+ ]
2712
+ })] });
2713
+ }
2714
+ //#endregion
2715
+ //#region src/provider/freitas-provider.tsx
2716
+ function FreitasProvider({ theme, children }) {
2717
+ const resolvedTheme = React.useMemo(() => {
2718
+ return resolveTheme(theme);
2719
+ }, [theme]);
2720
+ React.useEffect(() => {
2721
+ applyTheme(resolvedTheme);
2722
+ }, [resolvedTheme]);
2723
+ return /* @__PURE__ */ jsx(Fragment, { children });
2724
+ }
2725
+ //#endregion
2726
+ export { ActionBar, Alert, AlertDialog, AlertDialogAction, AlertDialogActionButton, AlertDialogCancel, AlertDialogCancelButton, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AppShell, AppShellContent, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, Card, CardContent, CardFooter, CardHeader, Checkbox, CheckboxField, Combobox, CommandMenu, DataTable, DataViewRoot as DataView, DataViewRoot, DataViewContent, DataViewEmpty, DataViewHeader, DataViewPagination, DataViewToolbar, DatePicker, DateRangePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FilterBar, FilterBarItem, Form, FormControl, FormDescription, FormField, FormFieldController, FormItem, FormLabel, FormMessage, FreitasProvider, Input, Kbd, Label, NativeSelect, PageHeader, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RadioGroup, SearchInput, Select, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarBrand, SidebarContent, SidebarFooter, SidebarHeader, SidebarNavItem, SidebarSection, Skeleton, Spinner, StatusBadge, Switch, SwitchField, Table, TableBody, TableCaption, TableCell, TableContainer, TableFooter, TableHead, TableHeader, TableRow, TableScrollArea, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastContext, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, Toolbar, ToolbarActions, ToolbarSection, ToolbarTitle, Tooltip, TooltipProvider, TooltipRoot, TooltipTrigger, Topbar, UserMenu, buttonVariants, formatDate, getCheckboxFieldProps, getDatePickerFieldProps, getInitials, getInputFieldProps, getRadioGroupFieldProps, getSelectFieldProps, getSwitchFieldProps, useForm, useToast };
2727
+
2728
+ //# sourceMappingURL=index.mjs.map