@motor-hero/ui-kit 0.15.1 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/theme-provider.tsx","../src/components/mode-toggle.tsx","../src/components/empty-state.tsx","../src/components/confirm-dialog.tsx","../src/components/page-header.tsx","../src/components/status-dot.tsx","../src/components/status-badge.tsx","../src/components/progress-bar.tsx","../src/components/form-field.tsx","../src/components/form-dialog.tsx","../src/lib/utils.ts","../src/components/auth-card.tsx","../src/components/pagination.tsx","../src/components/table-skeleton.tsx","../src/components/search-input.tsx","../src/components/password-input.tsx","../src/components/stat-card.tsx","../src/components/data-table-wrapper.tsx","../src/components/mobile-card-list.tsx","../src/components/responsive-data-view.tsx","../src/components/toaster.tsx","../src/components/app-shell.tsx","../src/components/sidebar-nav.tsx","../src/components/types.tsx","../src/components/user-menu.tsx","../src/components/row-actions-menu.tsx","../src/lib/api-error.ts","../src/hooks/use-disclosure.ts","../src/hooks/use-toast.ts"],"sourcesContent":["import { createContext, useContext, useEffect, useState } from \"react\"\n\ntype Theme = \"dark\" | \"light\" | \"system\"\n\ntype ThemeProviderProps = {\n children: React.ReactNode\n defaultTheme?: Theme\n storageKey?: string\n}\n\ntype ThemeProviderState = {\n theme: Theme\n setTheme: (theme: Theme) => void\n}\n\nconst initialState: ThemeProviderState = {\n theme: \"system\",\n setTheme: () => null,\n}\n\nconst ThemeProviderContext = createContext<ThemeProviderState>(initialState)\n\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"ui-theme\",\n ...props\n}: ThemeProviderProps) {\n const [theme, setTheme] = useState<Theme>(\n () => (localStorage.getItem(storageKey) as Theme) || defaultTheme\n )\n\n useEffect(() => {\n const root = window.document.documentElement\n root.classList.remove(\"light\", \"dark\")\n if (theme === \"system\") {\n const systemTheme = window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\"\n root.classList.add(systemTheme)\n return\n }\n root.classList.add(theme)\n }, [theme])\n\n const value = {\n theme,\n setTheme: (theme: Theme) => {\n localStorage.setItem(storageKey, theme)\n setTheme(theme)\n },\n }\n\n return (\n <ThemeProviderContext.Provider {...props} value={value}>\n {children}\n </ThemeProviderContext.Provider>\n )\n}\n\nexport function useTheme() {\n const context = useContext(ThemeProviderContext)\n if (context === undefined) {\n throw new Error(\"useTheme must be used within a ThemeProvider\")\n }\n return context\n}\n\nexport type { Theme, ThemeProviderProps, ThemeProviderState }\n","import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { Moon, Sun, Monitor } from \"lucide-react\"\nimport { useTheme } from \"./theme-provider\"\n\nexport function ModeToggle() {\n const { setTheme } = useTheme()\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n className=\"relative inline-flex h-9 w-9 items-center justify-center rounded-md border border-input bg-background text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-label=\"Alternar tema\"\n >\n <Sun className=\"h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0\" />\n <Moon className=\"absolute inset-0 m-auto h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100\" />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align=\"end\"\n className=\"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n <DropdownMenu.Item\n className=\"flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n onClick={() => setTheme(\"light\")}\n >\n <Sun className=\"h-4 w-4\" /> Claro\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n onClick={() => setTheme(\"dark\")}\n >\n <Moon className=\"h-4 w-4\" /> Escuro\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n onClick={() => setTheme(\"system\")}\n >\n <Monitor className=\"h-4 w-4\" /> Sistema\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface EmptyStateProps {\n icon?: ReactNode\n title: string\n description?: string\n action?: ReactNode\n className?: string\n}\n\nexport function EmptyState({ icon, title, description, action, className }: EmptyStateProps) {\n return (\n <div className={`flex flex-col items-center justify-center py-16 text-center ${className ?? \"\"}`}>\n {icon && <div className=\"mb-4 text-muted-foreground\">{icon}</div>}\n <h3 className=\"text-lg font-semibold tracking-tight\">{title}</h3>\n {description && (\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{description}</p>\n )}\n {action && <div className=\"mt-4\">{action}</div>}\n </div>\n )\n}\n","import * as AlertDialog from \"@radix-ui/react-alert-dialog\"\nimport type { ReactNode } from \"react\"\n\ninterface ConfirmDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onConfirm: () => void\n title: string\n description: ReactNode\n confirmLabel?: string\n cancelLabel?: string\n loading?: boolean\n variant?: \"default\" | \"destructive\"\n}\n\nexport function ConfirmDialog({\n open,\n onOpenChange,\n onConfirm,\n title,\n description,\n confirmLabel = \"Confirmar\",\n cancelLabel = \"Cancelar\",\n loading = false,\n variant = \"default\",\n}: ConfirmDialogProps) {\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange}>\n <AlertDialog.Portal>\n <AlertDialog.Overlay className=\"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <AlertDialog.Content className=\"fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\">\n <div className=\"flex flex-col space-y-2 text-center sm:text-left\">\n <AlertDialog.Title className=\"text-lg font-semibold\">{title}</AlertDialog.Title>\n <AlertDialog.Description className=\"text-sm text-muted-foreground\">\n {description}\n </AlertDialog.Description>\n </div>\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <AlertDialog.Cancel className=\"inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 cursor-pointer\">\n {cancelLabel}\n </AlertDialog.Cancel>\n <AlertDialog.Action\n onClick={onConfirm}\n disabled={loading}\n className={`inline-flex h-9 items-center justify-center rounded-md px-4 text-sm font-medium shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 cursor-pointer ${\n variant === \"destructive\"\n ? \"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\"\n }`}\n >\n {loading ? \"Aguarde...\" : confirmLabel}\n </AlertDialog.Action>\n </div>\n </AlertDialog.Content>\n </AlertDialog.Portal>\n </AlertDialog.Root>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface PageHeaderProps {\n title: string\n description?: string\n action?: ReactNode\n className?: string\n}\n\nexport function PageHeader({ title, description, action, className }: PageHeaderProps) {\n return (\n <div\n className={`flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between ${className ?? \"\"}`}\n >\n <div className=\"min-w-0\">\n <h1 className=\"truncate text-2xl font-semibold tracking-tight\">\n {title}\n </h1>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n )\n}\n","interface StatusDotProps {\n active: boolean\n label?: string\n className?: string\n}\n\nexport function StatusDot({ active, label, className }: StatusDotProps) {\n return (\n <span className={`inline-flex items-center gap-2 ${className ?? \"\"}`}>\n <span\n className={`h-2 w-2 rounded-full ${active ? \"bg-green-500\" : \"bg-red-500\"}`}\n />\n {label && <span>{label}</span>}\n </span>\n )\n}\n","import type { ReactNode } from \"react\"\n\nexport type StatusBadgeVariant =\n | \"neutral\"\n | \"info\"\n | \"success\"\n | \"danger\"\n | \"warning\"\n\ninterface StatusBadgeProps {\n variant?: StatusBadgeVariant\n dot?: boolean\n className?: string\n children: ReactNode\n}\n\nconst variantClasses: Record<\n StatusBadgeVariant,\n { badge: string; dot: string }\n> = {\n neutral: {\n badge: \"bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300\",\n dot: \"bg-gray-400\",\n },\n info: {\n badge: \"bg-blue-100 text-blue-700 dark:bg-blue-950 dark:text-blue-400\",\n dot: \"bg-blue-500\",\n },\n success: {\n badge: \"bg-green-100 text-green-700 dark:bg-green-950 dark:text-green-400\",\n dot: \"bg-green-500\",\n },\n danger: {\n badge: \"bg-red-100 text-red-700 dark:bg-red-950 dark:text-red-400\",\n dot: \"bg-red-500\",\n },\n warning: {\n badge: \"bg-amber-100 text-amber-700 dark:bg-amber-950 dark:text-amber-400\",\n dot: \"bg-amber-500\",\n },\n}\n\nexport function StatusBadge({\n variant = \"neutral\",\n dot = true,\n className,\n children,\n}: StatusBadgeProps) {\n const classes = variantClasses[variant]\n\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-md px-2 py-0.5 text-xs font-medium ${classes.badge} ${className ?? \"\"}`}\n >\n {dot && (\n <span\n className={`inline-block h-1.5 w-1.5 shrink-0 rounded-full ${classes.dot}`}\n />\n )}\n {children}\n </span>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface ProgressBarProps {\n value: number\n size?: \"sm\" | \"md\"\n label?: ReactNode\n valueLabel?: ReactNode\n className?: string\n indicatorClassName?: string\n}\n\nconst sizeClasses = {\n sm: \"h-1.5\",\n md: \"h-2\",\n} as const\n\nexport function ProgressBar({\n value,\n size = \"md\",\n label,\n valueLabel,\n className,\n indicatorClassName,\n}: ProgressBarProps) {\n const clamped = Math.min(100, Math.max(0, value))\n\n return (\n <div className={`space-y-1.5 ${className ?? \"\"}`}>\n {(label || valueLabel) && (\n <div className=\"flex items-baseline justify-between gap-2\">\n {label && (\n <span className=\"text-sm text-muted-foreground\">{label}</span>\n )}\n {valueLabel && (\n <span className=\"text-sm font-semibold\">{valueLabel}</span>\n )}\n </div>\n )}\n <div\n className={`w-full overflow-hidden rounded-full bg-muted ${sizeClasses[size]}`}\n >\n <div\n className={`h-full rounded-full transition-all duration-300 ${indicatorClassName ?? \"bg-primary\"}`}\n style={{ width: `${clamped}%` }}\n />\n </div>\n </div>\n )\n}\n","import { type ReactElement, type ReactNode, cloneElement, isValidElement, useId } from \"react\"\n\ninterface FormFieldProps {\n label: string\n htmlFor?: string\n error?: string\n required?: boolean\n children: ReactNode\n className?: string\n}\n\nexport function FormField({ label, htmlFor, error, required, children, className }: FormFieldProps) {\n const errorId = useId()\n\n // Wire accessibility onto the control: mark it invalid and point it at the\n // error message so screen readers announce both.\n const field =\n error && isValidElement(children)\n ? cloneElement(children as ReactElement<Record<string, unknown>>, {\n \"aria-invalid\": true,\n \"aria-describedby\": [\n (children.props as Record<string, unknown>)[\"aria-describedby\"],\n errorId,\n ]\n .filter(Boolean)\n .join(\" \"),\n })\n : children\n\n return (\n <div className={`space-y-2 ${className ?? \"\"}`}>\n <label\n htmlFor={htmlFor}\n className=\"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {required && <span className=\"ml-1 text-destructive\">*</span>}\n </label>\n {field}\n {error && (\n <p id={errorId} className=\"text-sm text-destructive\">\n {error}\n </p>\n )}\n </div>\n )\n}\n","import * as Dialog from \"@radix-ui/react-dialog\"\nimport { X } from \"lucide-react\"\nimport * as React from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport { cn } from \"../lib/utils\"\n\ninterface FormDialogLayoutProps {\n title: string\n children: ReactNode\n onSubmit: (e: React.FormEvent) => void\n submitLabel?: string\n cancelLabel?: string\n onCancel: () => void\n isSubmitting?: boolean\n isDisabled?: boolean\n}\n\nexport function FormDialogLayout({\n title,\n children,\n onSubmit,\n submitLabel = \"Salvar\",\n cancelLabel = \"Cancelar\",\n onCancel,\n isSubmitting = false,\n isDisabled = false,\n}: FormDialogLayoutProps) {\n return (\n <form onSubmit={onSubmit}>\n <div className=\"flex flex-col space-y-1.5 text-center sm:text-left\">\n <h2 className=\"text-lg font-semibold leading-none tracking-tight\">{title}</h2>\n </div>\n <div className=\"space-y-4 py-4\">{children}</div>\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n {cancelLabel}\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting || isDisabled}\n className=\"inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90 cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n {isSubmitting ? \"Salvando...\" : submitLabel}\n </button>\n </div>\n </form>\n )\n}\n\nconst sizeClasses = {\n sm: \"sm:max-w-sm\",\n md: \"sm:max-w-md\",\n lg: \"sm:max-w-lg\",\n xl: \"sm:max-w-xl\",\n \"2xl\": \"sm:max-w-2xl\",\n} as const\n\nexport type FormDialogSize = keyof typeof sizeClasses\n\ninterface FormDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: string\n description?: ReactNode\n children: ReactNode\n footer?: ReactNode\n /** When provided, the dialog renders a <form> wrapping body + footer. */\n onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void\n size?: FormDialogSize\n className?: string\n}\n\n/**\n * Standardized, responsive modal:\n * - mobile: bottom sheet (full width, up to 92vh tall)\n * - desktop: centered dialog (up to 90vh tall)\n * Header and footer stay fixed; only the body scrolls.\n *\n * Also fixes the known Radix bug where `body { pointer-events: none }`\n * can persist after closing a dialog that contained a Select/Popover,\n * which would otherwise make the rest of the page unclickable.\n */\nexport function FormDialog({\n open,\n onOpenChange,\n title,\n description,\n children,\n footer,\n onSubmit,\n size = \"lg\",\n className,\n}: FormDialogProps) {\n React.useEffect(() => {\n if (open) return\n const id = window.setTimeout(() => {\n if (document.body.style.pointerEvents === \"none\") {\n document.body.style.pointerEvents = \"\"\n }\n }, 0)\n return () => window.clearTimeout(id)\n }, [open])\n\n const body = (\n <>\n <div className=\"flex shrink-0 items-start justify-between gap-4 border-b px-6 py-3\">\n <div className=\"min-w-0 space-y-1\">\n <Dialog.Title className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </Dialog.Title>\n {description && (\n <Dialog.Description className=\"text-sm text-muted-foreground\">\n {description}\n </Dialog.Description>\n )}\n </div>\n <Dialog.Close\n className=\"-mr-1 shrink-0 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n aria-label=\"Fechar\"\n >\n <X className=\"h-5 w-5\" />\n </Dialog.Close>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">{children}</div>\n {footer && (\n <div className=\"flex shrink-0 flex-col-reverse gap-2 border-t px-6 py-3 sm:flex-row sm:justify-end\">\n {footer}\n </div>\n )}\n </>\n )\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <Dialog.Content\n onCloseAutoFocus={() => {\n document.body.style.pointerEvents = \"\"\n }}\n className={cn(\n \"fixed z-50 flex max-h-[92vh] flex-col bg-background shadow-lg outline-none\",\n \"inset-x-0 bottom-0 rounded-t-2xl\",\n \"sm:inset-x-auto sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:max-h-[92vh] sm:w-full sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-lg\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n sizeClasses[size],\n className,\n )}\n >\n {onSubmit ? (\n <form\n onSubmit={onSubmit}\n className=\"flex min-h-0 flex-1 flex-col\"\n >\n {body}\n </form>\n ) : (\n body\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import type { ReactNode } from \"react\"\n\ninterface AuthCardProps {\n title: string\n description?: string\n children: ReactNode\n footer?: ReactNode\n}\n\nexport function AuthCard({ title, description, children, footer }: AuthCardProps) {\n return (\n <div className=\"flex min-h-screen items-center justify-center px-4\">\n <div className=\"w-full max-w-sm rounded-lg border bg-card p-6 shadow-sm\">\n <div className=\"mb-6 text-center\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"mt-1 text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n <div className=\"space-y-4\">{children}</div>\n {footer && <div className=\"mt-4\">{footer}</div>}\n </div>\n </div>\n )\n}\n","interface PaginationProps {\n page: number\n onPageChange: (page: number) => void\n hasNextPage: boolean\n hasPreviousPage: boolean\n className?: string\n}\n\nexport function Pagination({ page, onPageChange, hasNextPage, hasPreviousPage, className }: PaginationProps) {\n return (\n <div className={`flex items-center justify-end gap-4 ${className ?? \"\"}`}>\n <button\n type=\"button\"\n onClick={() => onPageChange(page - 1)}\n disabled={!hasPreviousPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Anterior\n </button>\n <span className=\"text-sm text-muted-foreground\">Página {page}</span>\n <button\n type=\"button\"\n onClick={() => onPageChange(page + 1)}\n disabled={!hasNextPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Próximo\n </button>\n </div>\n )\n}\n","interface TableSkeletonProps {\n rows?: number\n columns?: number\n}\n\nexport function TableSkeleton({ rows = 5, columns = 4 }: TableSkeletonProps) {\n return (\n <>\n {Array.from({ length: rows }).map((_, i) => (\n <tr key={i} className=\"border-b transition-colors\">\n {Array.from({ length: columns }).map((_, j) => (\n <td key={j} className=\"p-4 align-middle\">\n <div className=\"h-5 w-full animate-pulse rounded bg-muted\" />\n </td>\n ))}\n </tr>\n ))}\n </>\n )\n}\n","import * as React from \"react\"\n\ninterface SearchInputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n containerClassName?: string\n}\n\nexport const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(\n ({ containerClassName, className, ...props }, ref) => {\n return (\n <div className={`relative flex-1 ${containerClassName ?? \"\"}`}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n <input\n ref={ref}\n type=\"text\"\n className={`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 pl-10 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${className ?? \"\"}`}\n {...props}\n />\n </div>\n )\n }\n)\nSearchInput.displayName = \"SearchInput\"\n","import { Eye, EyeOff } from \"lucide-react\"\nimport * as React from \"react\"\n\ninterface PasswordInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n containerClassName?: string\n}\n\nexport const PasswordInput = React.forwardRef<\n HTMLInputElement,\n PasswordInputProps\n>(({ containerClassName, className, ...props }, ref) => {\n const [visible, setVisible] = React.useState(false)\n\n return (\n <div className={`relative ${containerClassName ?? \"\"}`}>\n <input\n ref={ref}\n type={visible ? \"text\" : \"password\"}\n className={`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 pr-10 text-base shadow-sm transition-all duration-200 placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive md:text-sm ${className ?? \"\"}`}\n {...props}\n />\n <button\n type=\"button\"\n onClick={() => setVisible((prev) => !prev)}\n aria-label={visible ? \"Ocultar senha\" : \"Mostrar senha\"}\n tabIndex={-1}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground transition-colors hover:text-foreground\"\n >\n {visible ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </button>\n </div>\n )\n})\nPasswordInput.displayName = \"PasswordInput\"\n","import type { ReactNode } from \"react\"\n\ninterface StatCardProps {\n label: string\n value: ReactNode\n detail?: string\n icon?: ReactNode\n isLoading?: boolean\n}\n\nexport function StatCard({ label, value, detail, icon, isLoading }: StatCardProps) {\n if (isLoading) {\n return (\n <div className=\"rounded-lg border bg-card p-6 shadow-sm\">\n <div className=\"flex items-center justify-between pb-2\">\n <div className=\"h-4 w-24 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-4 animate-pulse rounded bg-muted\" />\n </div>\n <div className=\"mt-2 h-7 w-16 animate-pulse rounded bg-muted\" />\n <div className=\"mt-1 h-4 w-20 animate-pulse rounded bg-muted\" />\n </div>\n )\n }\n\n return (\n <div className=\"rounded-lg border bg-card p-6 shadow-sm\">\n <div className=\"flex items-center justify-between pb-2\">\n <span className=\"text-sm font-medium text-muted-foreground\">{label}</span>\n {icon && <span className=\"text-muted-foreground\">{icon}</span>}\n </div>\n <div className=\"text-2xl font-bold\">{value}</div>\n {detail && <p className=\"text-xs text-muted-foreground\">{detail}</p>}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface DataTableWrapperProps {\n children: ReactNode\n isEmpty: boolean\n isLoading: boolean\n emptyIcon?: ReactNode\n emptyTitle?: string\n emptyDescription?: string\n page?: number\n onPageChange?: (page: number) => void\n hasNextPage?: boolean\n hasPreviousPage?: boolean\n}\n\nexport function DataTableWrapper({\n children,\n isEmpty,\n isLoading,\n emptyIcon,\n emptyTitle = \"Nenhum registro encontrado\",\n emptyDescription,\n page,\n onPageChange,\n hasNextPage = false,\n hasPreviousPage = false,\n}: DataTableWrapperProps) {\n return (\n <div className=\"space-y-4\">\n <div className=\"overflow-x-auto rounded-md border\">{children}</div>\n\n {!isLoading && isEmpty && (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n {emptyIcon && <div className=\"mb-4 text-muted-foreground\">{emptyIcon}</div>}\n <h3 className=\"text-lg font-semibold tracking-tight\">{emptyTitle}</h3>\n {emptyDescription && (\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{emptyDescription}</p>\n )}\n </div>\n )}\n\n {page !== undefined && onPageChange && (\n <div className=\"flex items-center justify-end gap-4\">\n <button\n type=\"button\"\n onClick={() => onPageChange(page - 1)}\n disabled={!hasPreviousPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Anterior\n </button>\n <span className=\"text-sm text-muted-foreground\">Página {page}</span>\n <button\n type=\"button\"\n onClick={() => onPageChange(page + 1)}\n disabled={!hasNextPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Próximo\n </button>\n </div>\n )}\n </div>\n )\n}\n","import { type MouseEvent, type ReactNode, type TouchEvent, useRef } from \"react\"\n\ninterface MobileCardListProps<T> {\n data: T[]\n renderCard: (item: T, index: number) => ReactNode\n keyExtractor: (item: T) => string\n isLoading?: boolean\n loadingCount?: number\n className?: string\n}\n\n// Movimento (px) acima do qual o gesto é tratado como scroll, não tap.\nconst SCROLL_THRESHOLD = 8\n\nexport function MobileCardList<T>({\n data,\n renderCard,\n keyExtractor,\n isLoading = false,\n loadingCount = 5,\n className,\n}: MobileCardListProps<T>) {\n // Guard contra tap acidental durante o scroll: se o dedo se moveu além do\n // threshold, o clique seguinte (ex.: botão de ações dentro do card) é\n // cancelado na fase de captura, antes de chegar no elemento interativo.\n const start = useRef<{ x: number; y: number } | null>(null)\n const scrolled = useRef(false)\n\n const onTouchStart = (e: TouchEvent<HTMLDivElement>) => {\n const t = e.touches[0]\n start.current = { x: t.clientX, y: t.clientY }\n scrolled.current = false\n }\n\n const onTouchMove = (e: TouchEvent<HTMLDivElement>) => {\n if (!start.current) return\n const t = e.touches[0]\n if (\n Math.abs(t.clientX - start.current.x) > SCROLL_THRESHOLD ||\n Math.abs(t.clientY - start.current.y) > SCROLL_THRESHOLD\n ) {\n scrolled.current = true\n }\n }\n\n const onClickCapture = (e: MouseEvent<HTMLDivElement>) => {\n if (scrolled.current) {\n e.preventDefault()\n e.stopPropagation()\n }\n }\n\n if (isLoading) {\n return (\n <div className={`space-y-3 ${className ?? \"\"}`}>\n {Array.from({ length: loadingCount }).map((_, i) => (\n <div key={i} className=\"rounded-xl border p-4\">\n <div className=\"space-y-3\">\n <div className=\"flex justify-between\">\n <div className=\"h-5 w-32 animate-pulse rounded bg-muted\" />\n <div className=\"h-5 w-16 animate-pulse rounded bg-muted\" />\n </div>\n <div className=\"h-4 w-48 animate-pulse rounded bg-muted\" />\n <div className=\"flex justify-between\">\n <div className=\"h-4 w-24 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-20 animate-pulse rounded bg-muted\" />\n </div>\n </div>\n </div>\n ))}\n </div>\n )\n }\n\n return (\n <div\n className={`space-y-3 ${className ?? \"\"}`}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onClickCapture={onClickCapture}\n >\n {data.map((item, index) => (\n <div\n key={keyExtractor(item)}\n className=\"rounded-xl border p-4 transition-all duration-150 hover:border-foreground/20 active:scale-[0.99]\"\n >\n {renderCard(item, index)}\n </div>\n ))}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface ResponsiveDataViewProps {\n table: ReactNode\n cards: ReactNode\n isEmpty: boolean\n isLoading: boolean\n emptyIcon?: ReactNode\n emptyTitle?: string\n emptyDescription?: string\n pagination?: ReactNode\n}\n\nexport function ResponsiveDataView({\n table, cards, isEmpty, isLoading, emptyIcon, emptyTitle = \"Nenhum registro encontrado\", emptyDescription, pagination,\n}: ResponsiveDataViewProps) {\n return (\n <div className=\"space-y-4\">\n <div className=\"hidden overflow-x-auto rounded-md border md:block\">{table}</div>\n <div className=\"md:hidden\">{cards}</div>\n {!isLoading && isEmpty && (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n {emptyIcon && <div className=\"mb-4 text-muted-foreground\">{emptyIcon}</div>}\n <h3 className=\"text-lg font-semibold tracking-tight\">{emptyTitle}</h3>\n {emptyDescription && <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{emptyDescription}</p>}\n </div>\n )}\n {pagination}\n </div>\n )\n}\n","import { useTheme } from \"./theme-provider\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nexport function Toaster(props: ToasterProps) {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-md\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n success:\n \"group-[.toaster]:!bg-background group-[.toaster]:!text-foreground group-[.toaster]:!border-success/40\",\n error:\n \"group-[.toaster]:!bg-background group-[.toaster]:!text-foreground group-[.toaster]:!border-destructive/40\",\n },\n }}\n {...props}\n />\n )\n}\n","import { ChevronLeft, ChevronRight, Menu } from \"lucide-react\"\nimport { type ReactNode, useState } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport { SidebarNav, type NavItem } from \"./sidebar-nav\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\nimport { UserMenu, type AppUser, type UserMenuItem } from \"./user-menu\"\n\nexport interface AppShellProps {\n brand: ReactNode\n brandCollapsed?: ReactNode\n navItems: NavItem[]\n activePath: string\n isActive?: (item: NavItem, activePath: string) => boolean\n isAdmin?: boolean\n user?: AppUser\n userMenuItems?: UserMenuItem[]\n onLogout?: () => void\n renderLink?: RenderLink\n headerActions?: ReactNode\n collapsible?: boolean\n defaultCollapsed?: boolean\n children: ReactNode\n}\n\nexport function AppShell({\n brand,\n brandCollapsed,\n navItems,\n activePath,\n isActive,\n isAdmin = false,\n user,\n userMenuItems,\n onLogout,\n renderLink = defaultRenderLink,\n headerActions,\n collapsible = true,\n defaultCollapsed = false,\n children,\n}: AppShellProps) {\n const [collapsed, setCollapsed] = useState(defaultCollapsed)\n const [mobileOpen, setMobileOpen] = useState(false)\n\n const nav = (isCollapsed: boolean, onNavigate?: () => void) => (\n <SidebarNav\n items={navItems}\n activePath={activePath}\n isActive={isActive}\n isAdmin={isAdmin}\n isCollapsed={isCollapsed}\n renderLink={renderLink}\n onNavigate={onNavigate}\n />\n )\n\n return (\n <div className=\"flex h-screen overflow-hidden bg-background\">\n {/* Desktop sidebar */}\n <aside\n className={cn(\n \"hidden shrink-0 flex-col border-r bg-card transition-all duration-300 md:flex\",\n collapsed ? \"w-16\" : \"w-60\",\n )}\n >\n <div className=\"flex h-14 shrink-0 items-center border-b px-4\">\n {collapsed ? (brandCollapsed ?? brand) : brand}\n </div>\n <div className=\"flex-1 overflow-y-auto px-2 py-4\">{nav(collapsed)}</div>\n {collapsible && (\n <div className=\"border-t p-2\">\n <button\n type=\"button\"\n onClick={() => setCollapsed((v) => !v)}\n className=\"flex w-full items-center justify-center rounded-md px-2 py-2 text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground\"\n aria-label={collapsed ? \"Expandir menu\" : \"Recolher menu\"}\n >\n {collapsed ? <ChevronRight className=\"h-4 w-4\" /> : <ChevronLeft className=\"h-4 w-4\" />}\n </button>\n </div>\n )}\n </aside>\n\n {/* Mobile drawer */}\n <div\n className={cn(\n \"fixed inset-0 z-50 transition-opacity duration-300 md:hidden\",\n mobileOpen ? \"pointer-events-auto opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n onClick={() => setMobileOpen(false)}\n >\n <div className=\"absolute inset-0 bg-black/50\" />\n <div\n className={cn(\n \"absolute left-0 top-0 flex h-full w-64 flex-col border-r bg-card transition-transform duration-300\",\n mobileOpen ? \"translate-x-0\" : \"-translate-x-full\",\n )}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex h-14 shrink-0 items-center border-b px-4\">{brand}</div>\n <div className=\"flex-1 overflow-y-auto px-2 py-4\">{nav(false, () => setMobileOpen(false))}</div>\n </div>\n </div>\n\n {/* Main column */}\n <div className=\"flex flex-1 flex-col overflow-hidden\">\n <header className=\"flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4\">\n <button\n type=\"button\"\n onClick={() => setMobileOpen(true)}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md border border-input bg-background shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground md:hidden\"\n aria-label=\"Abrir menu\"\n >\n <Menu className=\"h-4 w-4\" />\n </button>\n <div className=\"ml-auto flex items-center gap-2\">\n {headerActions}\n {(user || onLogout) && (\n <UserMenu user={user} items={userMenuItems} onLogout={onLogout} renderLink={renderLink} />\n )}\n </div>\n </header>\n <main className=\"flex-1 overflow-y-auto\">{children}</main>\n </div>\n </div>\n )\n}\n","import { Fragment, type ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\n\nexport interface NavItem {\n label: string\n href: string\n icon?: ReactNode\n adminOnly?: boolean\n}\n\nexport interface SidebarNavProps {\n items: NavItem[]\n activePath: string\n isActive?: (item: NavItem, activePath: string) => boolean\n isAdmin?: boolean\n isCollapsed?: boolean\n renderLink?: RenderLink\n onNavigate?: () => void\n}\n\nfunction defaultIsActive(item: NavItem, activePath: string): boolean {\n if (item.href === \"/\") return activePath === \"/\"\n return activePath === item.href || activePath.startsWith(item.href + \"/\")\n}\n\nexport function SidebarNav({\n items,\n activePath,\n isActive = defaultIsActive,\n isAdmin = false,\n isCollapsed = false,\n renderLink = defaultRenderLink,\n onNavigate,\n}: SidebarNavProps) {\n const visible = items.filter((item) => !item.adminOnly || isAdmin)\n\n return (\n <nav className=\"flex flex-col gap-1\">\n {visible.map((item) => {\n const active = isActive(item, activePath)\n const link = renderLink({\n href: item.href,\n onClick: onNavigate,\n title: isCollapsed ? item.label : undefined,\n \"aria-current\": active ? \"page\" : undefined,\n className: cn(\n \"flex cursor-pointer items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors\",\n active\n ? \"bg-accent text-accent-foreground font-semibold\"\n : \"text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n isCollapsed && \"justify-center px-2\",\n ),\n children: (\n <>\n {item.icon && <span className=\"shrink-0\">{item.icon}</span>}\n {!isCollapsed && <span className=\"truncate\">{item.label}</span>}\n </>\n ),\n })\n return <Fragment key={item.href}>{link}</Fragment>\n })}\n </nav>\n )\n}\n","import type { ReactNode } from \"react\"\n\nexport interface RenderLinkProps {\n href: string\n className?: string\n children: ReactNode\n onClick?: () => void\n title?: string\n \"aria-current\"?: \"page\"\n}\n\nexport type RenderLink = (props: RenderLinkProps) => ReactNode\n\nexport const defaultRenderLink: RenderLink = ({ children, ...props }) => (\n <a {...props}>{children}</a>\n)\n","import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { LogOut, User } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\n\nexport interface AppUser {\n name?: string\n email?: string\n avatarUrl?: string\n}\n\nexport interface UserMenuItem {\n label: string\n icon?: ReactNode\n href?: string\n onClick?: () => void\n}\n\nexport interface UserMenuProps {\n user?: AppUser\n items?: UserMenuItem[]\n onLogout?: () => void\n logoutLabel?: string\n renderLink?: RenderLink\n align?: \"start\" | \"center\" | \"end\"\n}\n\nfunction initials(user?: AppUser): string {\n const source = user?.name?.trim() || user?.email?.trim()\n if (!source) return \"\"\n const parts = source.split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n return source.slice(0, 2).toUpperCase()\n}\n\nconst itemClass =\n \"flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n\nexport function UserMenu({\n user,\n items = [],\n onLogout,\n logoutLabel = \"Sair\",\n renderLink = defaultRenderLink,\n align = \"end\",\n}: UserMenuProps) {\n const label = initials(user)\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-9 w-9 items-center justify-center overflow-hidden rounded-full border border-input bg-background text-xs font-semibold shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-label=\"Menu do usuário\"\n data-testid=\"user-menu\"\n >\n {user?.avatarUrl ? (\n <img src={user.avatarUrl} alt={user.name ?? user.email ?? \"Avatar\"} className=\"h-full w-full object-cover\" />\n ) : label ? (\n <span>{label}</span>\n ) : (\n <User className=\"h-4 w-4\" />\n )}\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align={align}\n sideOffset={6}\n className=\"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n {(user?.name || user?.email) && (\n <>\n <div className=\"px-2 py-1.5\">\n {user.name && <p className=\"truncate text-sm font-medium\">{user.name}</p>}\n {user.email && <p className=\"truncate text-xs text-muted-foreground\">{user.email}</p>}\n </div>\n <DropdownMenu.Separator className=\"-mx-1 my-1 h-px bg-border\" />\n </>\n )}\n\n {items.map((item) =>\n item.href ? (\n <DropdownMenu.Item key={item.label} asChild>\n {renderLink({ href: item.href, className: itemClass, children: (\n <>\n {item.icon}\n {item.label}\n </>\n ) })}\n </DropdownMenu.Item>\n ) : (\n <DropdownMenu.Item key={item.label} className={itemClass} onClick={item.onClick}>\n {item.icon}\n {item.label}\n </DropdownMenu.Item>\n ),\n )}\n\n {onLogout && (\n <>\n {items.length > 0 && <DropdownMenu.Separator className=\"-mx-1 my-1 h-px bg-border\" />}\n <DropdownMenu.Item className={cn(itemClass, \"text-destructive focus:bg-destructive/10\")} onClick={onLogout}>\n <LogOut className=\"h-4 w-4\" />\n {logoutLabel}\n </DropdownMenu.Item>\n </>\n )}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )\n}\n","import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { MoreVertical } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\n\nexport interface RowAction {\n label: string\n icon?: ReactNode\n onClick?: () => void\n href?: string\n destructive?: boolean\n disabled?: boolean\n}\n\nexport interface RowActionsMenuProps {\n actions: RowAction[]\n disabled?: boolean\n align?: \"start\" | \"center\" | \"end\"\n label?: string\n renderLink?: RenderLink\n}\n\nconst itemClass =\n \"flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50\"\n\nexport function RowActionsMenu({\n actions,\n disabled = false,\n align = \"end\",\n label = \"Ações\",\n renderLink = defaultRenderLink,\n}: RowActionsMenuProps) {\n if (actions.length === 0) return null\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n disabled={disabled}\n aria-label={label}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\"\n >\n <MoreVertical className=\"h-4 w-4\" />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align={align}\n sideOffset={6}\n className=\"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n {actions.map((action) => {\n const cls = cn(itemClass, action.destructive && \"text-destructive focus:bg-destructive/10\")\n return action.href ? (\n <DropdownMenu.Item key={action.label} asChild disabled={action.disabled}>\n {renderLink({\n href: action.href,\n className: cls,\n children: (\n <>\n {action.icon}\n {action.label}\n </>\n ),\n })}\n </DropdownMenu.Item>\n ) : (\n <DropdownMenu.Item\n key={action.label}\n className={cls}\n disabled={action.disabled}\n onClick={action.onClick}\n >\n {action.icon}\n {action.label}\n </DropdownMenu.Item>\n )\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )\n}\n","export function extractApiError(err: any, fallbackMessage = \"Ocorreu um erro inesperado.\"): string {\n const detail = err?.body?.detail || err?.message\n if (Array.isArray(detail) && detail.length > 0) {\n return detail[0].msg\n }\n return detail || fallbackMessage\n}\n","import { useCallback, useState } from \"react\"\n\nexport function useDisclosure(initial = false) {\n const [open, setOpen] = useState(initial)\n const onOpen = useCallback(() => setOpen(true), [])\n const onClose = useCallback(() => setOpen(false), [])\n const onToggle = useCallback(() => setOpen((v) => !v), [])\n return { open, onOpen, onClose, onToggle, setOpen }\n}\n","import { toast } from \"sonner\"\nimport { useCallback } from \"react\"\n\ntype ToastStatus = \"success\" | \"error\" | \"info\" | \"warning\"\n\nexport function useCustomToast() {\n const showToast = useCallback(\n (title: string, description?: string, status: ToastStatus = \"success\") => {\n switch (status) {\n case \"success\":\n toast.success(title, { description })\n break\n case \"error\":\n toast.error(title, { description })\n break\n case \"info\":\n toast.info(title, { description })\n break\n case \"warning\":\n toast.warning(title, { description })\n break\n }\n },\n [],\n )\n\n return showToast\n}\n\nexport { toast }\n"],"mappings":";AAAA,SAAS,eAAe,YAAY,WAAW,gBAAgB;AAsD3D;AAvCJ,IAAM,eAAmC;AAAA,EACvC,OAAO;AAAA,EACP,UAAU,MAAM;AAClB;AAEA,IAAM,uBAAuB,cAAkC,YAAY;AAEpE,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,eAAe;AAAA,EACf,aAAa;AAAA,EACb,GAAG;AACL,GAAuB;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI;AAAA,IACxB,MAAO,aAAa,QAAQ,UAAU,KAAe;AAAA,EACvD;AAEA,YAAU,MAAM;AACd,UAAM,OAAO,OAAO,SAAS;AAC7B,SAAK,UAAU,OAAO,SAAS,MAAM;AACrC,QAAI,UAAU,UAAU;AACtB,YAAM,cAAc,OAAO,WAAW,8BAA8B,EAAE,UAClE,SACA;AACJ,WAAK,UAAU,IAAI,WAAW;AAC9B;AAAA,IACF;AACA,SAAK,UAAU,IAAI,KAAK;AAAA,EAC1B,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,UAAU,CAACA,WAAiB;AAC1B,mBAAa,QAAQ,YAAYA,MAAK;AACtC,eAASA,MAAK;AAAA,IAChB;AAAA,EACF;AAEA,SACE,oBAAC,qBAAqB,UAArB,EAA+B,GAAG,OAAO,OACvC,UACH;AAEJ;AAEO,SAAS,WAAW;AACzB,QAAM,UAAU,WAAW,oBAAoB;AAC/C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;;;AClEA,YAAY,kBAAkB;AAC9B,SAAS,MAAM,KAAK,eAAe;AAS3B,SAKE,OAAAC,MALF;AAND,SAAS,aAAa;AAC3B,QAAM,EAAE,SAAS,IAAI,SAAS;AAE9B,SACE,qBAAc,mBAAb,EACC;AAAA,oBAAAA,KAAc,sBAAb,EAAqB,SAAO,MAC3B;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,cAAW;AAAA,QAEX;AAAA,0BAAAA,KAAC,OAAI,WAAU,0EAAyE;AAAA,UACxF,gBAAAA,KAAC,QAAK,WAAU,iGAAgG;AAAA;AAAA;AAAA,IAClH,GACF;AAAA,IACA,gBAAAA,KAAc,qBAAb,EACC;AAAA,MAAc;AAAA,MAAb;AAAA,QACC,OAAM;AAAA,QACN,WAAU;AAAA,QAEV;AAAA;AAAA,YAAc;AAAA,YAAb;AAAA,cACC,WAAU;AAAA,cACV,SAAS,MAAM,SAAS,OAAO;AAAA,cAE/B;AAAA,gCAAAA,KAAC,OAAI,WAAU,WAAU;AAAA,gBAAE;AAAA;AAAA;AAAA,UAC7B;AAAA,UACA;AAAA,YAAc;AAAA,YAAb;AAAA,cACC,WAAU;AAAA,cACV,SAAS,MAAM,SAAS,MAAM;AAAA,cAE9B;AAAA,gCAAAA,KAAC,QAAK,WAAU,WAAU;AAAA,gBAAE;AAAA;AAAA;AAAA,UAC9B;AAAA,UACA;AAAA,YAAc;AAAA,YAAb;AAAA,cACC,WAAU;AAAA,cACV,SAAS,MAAM,SAAS,QAAQ;AAAA,cAEhC;AAAA,gCAAAA,KAAC,WAAQ,WAAU,WAAU;AAAA,gBAAE;AAAA;AAAA;AAAA,UACjC;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;;;AClCI,SACW,OAAAC,MADX,QAAAC,aAAA;AAFG,SAAS,WAAW,EAAE,MAAM,OAAO,aAAa,QAAQ,UAAU,GAAoB;AAC3F,SACE,gBAAAA,MAAC,SAAI,WAAW,+DAA+D,aAAa,EAAE,IAC3F;AAAA,YAAQ,gBAAAD,KAAC,SAAI,WAAU,8BAA8B,gBAAK;AAAA,IAC3D,gBAAAA,KAAC,QAAG,WAAU,wCAAwC,iBAAM;AAAA,IAC3D,eACC,gBAAAA,KAAC,OAAE,WAAU,+CAA+C,uBAAY;AAAA,IAEzE,UAAU,gBAAAA,KAAC,SAAI,WAAU,QAAQ,kBAAO;AAAA,KAC3C;AAEJ;;;ACrBA,YAAY,iBAAiB;AA6BrB,gBAAAE,MAEE,QAAAC,aAFF;AAdD,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd,UAAU;AAAA,EACV,UAAU;AACZ,GAAuB;AACrB,SACE,gBAAAD,KAAa,kBAAZ,EAAiB,MAAY,cAC5B,0BAAAC,MAAa,oBAAZ,EACC;AAAA,oBAAAD,KAAa,qBAAZ,EAAoB,WAAU,0JAAyJ;AAAA,IACxL,gBAAAC,MAAa,qBAAZ,EAAoB,WAAU,ufAC7B;AAAA,sBAAAA,MAAC,SAAI,WAAU,oDACb;AAAA,wBAAAD,KAAa,mBAAZ,EAAkB,WAAU,yBAAyB,iBAAM;AAAA,QAC5D,gBAAAA,KAAa,yBAAZ,EAAwB,WAAU,iCAChC,uBACH;AAAA,SACF;AAAA,MACA,gBAAAC,MAAC,SAAI,WAAU,0DACb;AAAA,wBAAAD,KAAa,oBAAZ,EAAmB,WAAU,sUAC3B,uBACH;AAAA,QACA,gBAAAA;AAAA,UAAa;AAAA,UAAZ;AAAA,YACC,SAAS;AAAA,YACT,UAAU;AAAA,YACV,WAAW,oPACT,YAAY,gBACR,uEACA,wDACN;AAAA,YAEC,oBAAU,eAAe;AAAA;AAAA,QAC5B;AAAA,SACF;AAAA,OACF;AAAA,KACF,GACF;AAEJ;;;AC3CM,SACE,OAAAE,MADF,QAAAC,aAAA;AALC,SAAS,WAAW,EAAE,OAAO,aAAa,QAAQ,UAAU,GAAoB;AACrF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,sEAAsE,aAAa,EAAE;AAAA,MAEhG;AAAA,wBAAAA,MAAC,SAAI,WAAU,WACb;AAAA,0BAAAD,KAAC,QAAG,WAAU,kDACX,iBACH;AAAA,UACC,eACC,gBAAAA,KAAC,OAAE,WAAU,iCAAiC,uBAAY;AAAA,WAE9D;AAAA,QACC,UAAU,gBAAAA,KAAC,SAAI,WAAU,YAAY,kBAAO;AAAA;AAAA;AAAA,EAC/C;AAEJ;;;ACjBI,SACE,OAAAE,MADF,QAAAC,aAAA;AAFG,SAAS,UAAU,EAAE,QAAQ,OAAO,UAAU,GAAmB;AACtE,SACE,gBAAAA,MAAC,UAAK,WAAW,kCAAkC,aAAa,EAAE,IAChE;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,wBAAwB,SAAS,iBAAiB,YAAY;AAAA;AAAA,IAC3E;AAAA,IACC,SAAS,gBAAAA,KAAC,UAAM,iBAAM;AAAA,KACzB;AAEJ;;;ACoCI,SAII,OAAAE,MAJJ,QAAAC,aAAA;AAnCJ,IAAM,iBAGF;AAAA,EACF,SAAS;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEO,SAAS,YAAY;AAAA,EAC1B,UAAU;AAAA,EACV,MAAM;AAAA,EACN;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,UAAU,eAAe,OAAO;AAEtC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,+EAA+E,QAAQ,KAAK,IAAI,aAAa,EAAE;AAAA,MAEzH;AAAA,eACC,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,kDAAkD,QAAQ,GAAG;AAAA;AAAA,QAC1E;AAAA,QAED;AAAA;AAAA;AAAA,EACH;AAEJ;;;ACjCQ,SAEI,OAAAE,MAFJ,QAAAC,aAAA;AAlBR,IAAM,cAAc;AAAA,EAClB,IAAI;AAAA,EACJ,IAAI;AACN;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,UAAU,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AAEhD,SACE,gBAAAA,MAAC,SAAI,WAAW,eAAe,aAAa,EAAE,IAC1C;AAAA,cAAS,eACT,gBAAAA,MAAC,SAAI,WAAU,6CACZ;AAAA,eACC,gBAAAD,KAAC,UAAK,WAAU,iCAAiC,iBAAM;AAAA,MAExD,cACC,gBAAAA,KAAC,UAAK,WAAU,yBAAyB,sBAAW;AAAA,OAExD;AAAA,IAEF,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,gDAAgD,YAAY,IAAI,CAAC;AAAA,QAE5E,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,mDAAmD,sBAAsB,YAAY;AAAA,YAChG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI;AAAA;AAAA,QAChC;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;;;AChDA,SAA4C,cAAc,gBAAgB,aAAa;AA+BjF,SAKe,OAAAE,MALf,QAAAC,aAAA;AApBC,SAAS,UAAU,EAAE,OAAO,SAAS,OAAO,UAAU,UAAU,UAAU,GAAmB;AAClG,QAAM,UAAU,MAAM;AAItB,QAAM,QACJ,SAAS,eAAe,QAAQ,IAC5B,aAAa,UAAmD;AAAA,IAC9D,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,MACjB,SAAS,MAAkC,kBAAkB;AAAA,MAC9D;AAAA,IACF,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,EACb,CAAC,IACD;AAEN,SACE,gBAAAA,MAAC,SAAI,WAAW,aAAa,aAAa,EAAE,IAC1C;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAU;AAAA,QAET;AAAA;AAAA,UACA,YAAY,gBAAAD,KAAC,UAAK,WAAU,yBAAwB,eAAC;AAAA;AAAA;AAAA,IACxD;AAAA,IACC;AAAA,IACA,SACC,gBAAAA,KAAC,OAAE,IAAI,SAAS,WAAU,4BACvB,iBACH;AAAA,KAEJ;AAEJ;;;AC9CA,YAAY,YAAY;AACxB,SAAS,SAAS;AAClB,YAAY,WAAW;;;ACFvB,SAA0B,YAAY;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;AD0BQ,SA8EJ,UA9EI,OAAAE,OAGF,QAAAC,aAHE;AAbD,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAAA,EACd;AAAA,EACA,eAAe;AAAA,EACf,aAAa;AACf,GAA0B;AACxB,SACE,gBAAAA,MAAC,UAAK,UACJ;AAAA,oBAAAD,MAAC,SAAI,WAAU,sDACb,0BAAAA,MAAC,QAAG,WAAU,qDAAqD,iBAAM,GAC3E;AAAA,IACA,gBAAAA,MAAC,SAAI,WAAU,kBAAkB,UAAS;AAAA,IAC1C,gBAAAC,MAAC,SAAI,WAAU,0DACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAU,gBAAgB;AAAA,UAC1B,WAAU;AAAA,UAET,yBAAe,gBAAgB;AAAA;AAAA,MAClC;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,IAAME,eAAc;AAAA,EAClB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AACT;AA2BO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AACF,GAAoB;AAClB,EAAM,gBAAU,MAAM;AACpB,QAAI,KAAM;AACV,UAAM,KAAK,OAAO,WAAW,MAAM;AACjC,UAAI,SAAS,KAAK,MAAM,kBAAkB,QAAQ;AAChD,iBAAS,KAAK,MAAM,gBAAgB;AAAA,MACtC;AAAA,IACF,GAAG,CAAC;AACJ,WAAO,MAAM,OAAO,aAAa,EAAE;AAAA,EACrC,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,OACJ,gBAAAD,MAAA,YACE;AAAA,oBAAAA,MAAC,SAAI,WAAU,sEACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,qBACb;AAAA,wBAAAD,MAAQ,cAAP,EAAa,WAAU,qDACrB,iBACH;AAAA,QACC,eACC,gBAAAA,MAAQ,oBAAP,EAAmB,WAAU,iCAC3B,uBACH;AAAA,SAEJ;AAAA,MACA,gBAAAA;AAAA,QAAQ;AAAA,QAAP;AAAA,UACC,WAAU;AAAA,UACV,cAAW;AAAA,UAEX,0BAAAA,MAAC,KAAE,WAAU,WAAU;AAAA;AAAA,MACzB;AAAA,OACF;AAAA,IACA,gBAAAA,MAAC,SAAI,WAAU,4CAA4C,UAAS;AAAA,IACnE,UACC,gBAAAA,MAAC,SAAI,WAAU,sFACZ,kBACH;AAAA,KAEJ;AAGF,SACE,gBAAAA,MAAQ,aAAP,EAAY,MAAY,cACvB,0BAAAC,MAAQ,eAAP,EACC;AAAA,oBAAAD,MAAQ,gBAAP,EAAe,WAAU,0JAAyJ;AAAA,IACnL,gBAAAA;AAAA,MAAQ;AAAA,MAAP;AAAA,QACC,kBAAkB,MAAM;AACtB,mBAAS,KAAK,MAAM,gBAAgB;AAAA,QACtC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACAE,aAAY,IAAI;AAAA,UAChB;AAAA,QACF;AAAA,QAEC,qBACC,gBAAAF;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,WAAU;AAAA,YAET;AAAA;AAAA,QACH,IAEA;AAAA;AAAA,IAEJ;AAAA,KACF,GACF;AAEJ;;;AE3JQ,SACE,OAAAG,OADF,QAAAC,cAAA;AAJD,SAAS,SAAS,EAAE,OAAO,aAAa,UAAU,OAAO,GAAkB;AAChF,SACE,gBAAAD,MAAC,SAAI,WAAU,sDACb,0BAAAC,OAAC,SAAI,WAAU,2DACb;AAAA,oBAAAA,OAAC,SAAI,WAAU,oBACb;AAAA,sBAAAD,MAAC,QAAG,WAAU,yCAAyC,iBAAM;AAAA,MAC5D,eACC,gBAAAA,MAAC,OAAE,WAAU,sCAAsC,uBAAY;AAAA,OAEnE;AAAA,IACA,gBAAAA,MAAC,SAAI,WAAU,aAAa,UAAS;AAAA,IACpC,UAAU,gBAAAA,MAAC,SAAI,WAAU,QAAQ,kBAAO;AAAA,KAC3C,GACF;AAEJ;;;ACbM,gBAAAE,OAQA,QAAAC,cARA;AAHC,SAAS,WAAW,EAAE,MAAM,cAAc,aAAa,iBAAiB,UAAU,GAAoB;AAC3G,SACE,gBAAAA,OAAC,SAAI,WAAW,uCAAuC,aAAa,EAAE,IACpE;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,aAAa,OAAO,CAAC;AAAA,QACpC,UAAU,CAAC;AAAA,QACX,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,IACA,gBAAAC,OAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,MAAQ;AAAA,OAAK;AAAA,IAC7D,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,aAAa,OAAO,CAAC;AAAA,QACpC,UAAU,CAAC;AAAA,QACX,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;;;ACvBI,qBAAAE,WAKU,OAAAC,aALV;AAFG,SAAS,cAAc,EAAE,OAAO,GAAG,UAAU,EAAE,GAAuB;AAC3E,SACE,gBAAAA,MAAAD,WAAA,EACG,gBAAM,KAAK,EAAE,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,MACpC,gBAAAC,MAAC,QAAW,WAAU,8BACnB,gBAAM,KAAK,EAAE,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAACC,IAAG,MACvC,gBAAAD,MAAC,QAAW,WAAU,oBACpB,0BAAAA,MAAC,SAAI,WAAU,6CAA4C,KADpD,CAET,CACD,KALM,CAMT,CACD,GACH;AAEJ;;;ACnBA,YAAYE,YAAW;AAUf,SAYE,OAAAC,OAZF,QAAAC,cAAA;AAJD,IAAM,cAAoB;AAAA,EAC/B,CAAC,EAAE,oBAAoB,WAAW,GAAG,MAAM,GAAG,QAAQ;AACpD,WACE,gBAAAA,OAAC,SAAI,WAAW,mBAAmB,sBAAsB,EAAE,IACzD;AAAA,sBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAM;AAAA,UACN,QAAO;AAAA,UACP,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,QAAO;AAAA,UACP,aAAY;AAAA,UACZ,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,WAAU;AAAA,UAEV;AAAA,4BAAAD,MAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,YAC9B,gBAAAA,MAAC,UAAK,GAAE,kBAAiB;AAAA;AAAA;AAAA,MAC3B;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,MAAK;AAAA,UACL,WAAW,+QAA+Q,aAAa,EAAE;AAAA,UACxS,GAAG;AAAA;AAAA,MACN;AAAA,OACF;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;;;ACnC1B,SAAS,KAAK,cAAc;AAC5B,YAAYE,YAAW;AAcnB,SACE,OAAAC,OADF,QAAAC,cAAA;AAPG,IAAM,gBAAsB,kBAGjC,CAAC,EAAE,oBAAoB,WAAW,GAAG,MAAM,GAAG,QAAQ;AACtD,QAAM,CAAC,SAAS,UAAU,IAAU,gBAAS,KAAK;AAElD,SACE,gBAAAA,OAAC,SAAI,WAAW,YAAY,sBAAsB,EAAE,IAClD;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM,UAAU,SAAS;AAAA,QACzB,WAAW,kXAAkX,aAAa,EAAE;AAAA,QAC3Y,GAAG;AAAA;AAAA,IACN;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI;AAAA,QACzC,cAAY,UAAU,kBAAkB;AAAA,QACxC,UAAU;AAAA,QACV,WAAU;AAAA,QAET,oBAAU,gBAAAA,MAAC,UAAO,WAAU,WAAU,IAAK,gBAAAA,MAAC,OAAI,WAAU,WAAU;AAAA;AAAA,IACvE;AAAA,KACF;AAEJ,CAAC;AACD,cAAc,cAAc;;;ACpBpB,SACE,OAAAE,OADF,QAAAC,cAAA;AAJD,SAAS,SAAS,EAAE,OAAO,OAAO,QAAQ,MAAM,UAAU,GAAkB;AACjF,MAAI,WAAW;AACb,WACE,gBAAAA,OAAC,SAAI,WAAU,2CACb;AAAA,sBAAAA,OAAC,SAAI,WAAU,0CACb;AAAA,wBAAAD,MAAC,SAAI,WAAU,2CAA0C;AAAA,QACzD,gBAAAA,MAAC,SAAI,WAAU,0CAAyC;AAAA,SAC1D;AAAA,MACA,gBAAAA,MAAC,SAAI,WAAU,gDAA+C;AAAA,MAC9D,gBAAAA,MAAC,SAAI,WAAU,gDAA+C;AAAA,OAChE;AAAA,EAEJ;AAEA,SACE,gBAAAC,OAAC,SAAI,WAAU,2CACb;AAAA,oBAAAA,OAAC,SAAI,WAAU,0CACb;AAAA,sBAAAD,MAAC,UAAK,WAAU,6CAA6C,iBAAM;AAAA,MAClE,QAAQ,gBAAAA,MAAC,UAAK,WAAU,yBAAyB,gBAAK;AAAA,OACzD;AAAA,IACA,gBAAAA,MAAC,SAAI,WAAU,sBAAsB,iBAAM;AAAA,IAC1C,UAAU,gBAAAA,MAAC,OAAE,WAAU,iCAAiC,kBAAO;AAAA,KAClE;AAEJ;;;ACLM,gBAAAE,OAGE,QAAAC,cAHF;AAdC,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,kBAAkB;AACpB,GAA0B;AACxB,SACE,gBAAAA,OAAC,SAAI,WAAU,aACb;AAAA,oBAAAD,MAAC,SAAI,WAAU,qCAAqC,UAAS;AAAA,IAE5D,CAAC,aAAa,WACb,gBAAAC,OAAC,SAAI,WAAU,+DACZ;AAAA,mBAAa,gBAAAD,MAAC,SAAI,WAAU,8BAA8B,qBAAU;AAAA,MACrE,gBAAAA,MAAC,QAAG,WAAU,wCAAwC,sBAAW;AAAA,MAChE,oBACC,gBAAAA,MAAC,OAAE,WAAU,+CAA+C,4BAAiB;AAAA,OAEjF;AAAA,IAGD,SAAS,UAAa,gBACrB,gBAAAC,OAAC,SAAI,WAAU,uCACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,aAAa,OAAO,CAAC;AAAA,UACpC,UAAU,CAAC;AAAA,UACX,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACA,gBAAAC,OAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,QAAQ;AAAA,SAAK;AAAA,MAC7D,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,aAAa,OAAO,CAAC;AAAA,UACpC,UAAU,CAAC;AAAA,UACX,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,OACF;AAAA,KAEJ;AAEJ;;;AChEA,SAA2D,cAAc;AA0D3D,SACE,OAAAE,OADF,QAAAC,cAAA;AA9Cd,IAAM,mBAAmB;AAElB,SAAS,eAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AACF,GAA2B;AAIzB,QAAM,QAAQ,OAAwC,IAAI;AAC1D,QAAM,WAAW,OAAO,KAAK;AAE7B,QAAM,eAAe,CAAC,MAAkC;AACtD,UAAM,IAAI,EAAE,QAAQ,CAAC;AACrB,UAAM,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AAC7C,aAAS,UAAU;AAAA,EACrB;AAEA,QAAM,cAAc,CAAC,MAAkC;AACrD,QAAI,CAAC,MAAM,QAAS;AACpB,UAAM,IAAI,EAAE,QAAQ,CAAC;AACrB,QACE,KAAK,IAAI,EAAE,UAAU,MAAM,QAAQ,CAAC,IAAI,oBACxC,KAAK,IAAI,EAAE,UAAU,MAAM,QAAQ,CAAC,IAAI,kBACxC;AACA,eAAS,UAAU;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,iBAAiB,CAAC,MAAkC;AACxD,QAAI,SAAS,SAAS;AACpB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,WAAW;AACb,WACE,gBAAAD,MAAC,SAAI,WAAW,aAAa,aAAa,EAAE,IACzC,gBAAM,KAAK,EAAE,QAAQ,aAAa,CAAC,EAAE,IAAI,CAAC,GAAG,MAC5C,gBAAAA,MAAC,SAAY,WAAU,yBACrB,0BAAAC,OAAC,SAAI,WAAU,aACb;AAAA,sBAAAA,OAAC,SAAI,WAAU,wBACb;AAAA,wBAAAD,MAAC,SAAI,WAAU,2CAA0C;AAAA,QACzD,gBAAAA,MAAC,SAAI,WAAU,2CAA0C;AAAA,SAC3D;AAAA,MACA,gBAAAA,MAAC,SAAI,WAAU,2CAA0C;AAAA,MACzD,gBAAAC,OAAC,SAAI,WAAU,wBACb;AAAA,wBAAAD,MAAC,SAAI,WAAU,2CAA0C;AAAA,QACzD,gBAAAA,MAAC,SAAI,WAAU,2CAA0C;AAAA,SAC3D;AAAA,OACF,KAXQ,CAYV,CACD,GACH;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,aAAa,aAAa,EAAE;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MAEC,eAAK,IAAI,CAAC,MAAM,UACf,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAET,qBAAW,MAAM,KAAK;AAAA;AAAA,QAHlB,aAAa,IAAI;AAAA,MAIxB,CACD;AAAA;AAAA,EACH;AAEJ;;;ACzEM,gBAAAE,OAGE,QAAAC,cAHF;AALC,SAAS,mBAAmB;AAAA,EACjC;AAAA,EAAO;AAAA,EAAO;AAAA,EAAS;AAAA,EAAW;AAAA,EAAW,aAAa;AAAA,EAA8B;AAAA,EAAkB;AAC5G,GAA4B;AAC1B,SACE,gBAAAA,OAAC,SAAI,WAAU,aACb;AAAA,oBAAAD,MAAC,SAAI,WAAU,qDAAqD,iBAAM;AAAA,IAC1E,gBAAAA,MAAC,SAAI,WAAU,aAAa,iBAAM;AAAA,IACjC,CAAC,aAAa,WACb,gBAAAC,OAAC,SAAI,WAAU,+DACZ;AAAA,mBAAa,gBAAAD,MAAC,SAAI,WAAU,8BAA8B,qBAAU;AAAA,MACrE,gBAAAA,MAAC,QAAG,WAAU,wCAAwC,sBAAW;AAAA,MAChE,oBAAoB,gBAAAA,MAAC,OAAE,WAAU,+CAA+C,4BAAiB;AAAA,OACpG;AAAA,IAED;AAAA,KACH;AAEJ;;;AC7BA,SAAS,WAAW,cAAc;AAQ9B,gBAAAE,aAAA;AAJG,SAAS,QAAQ,OAAqB;AAC3C,QAAM,EAAE,QAAQ,SAAS,IAAI,SAAS;AAEtC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MACV,cAAc;AAAA,QACZ,YAAY;AAAA,UACV,OACE;AAAA,UACF,aAAa;AAAA,UACb,cACE;AAAA,UACF,cACE;AAAA,UACF,SACE;AAAA,UACF,OACE;AAAA,QACJ;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;AC9BA,SAAS,aAAa,cAAc,YAAY;AAChD,SAAyB,YAAAC,iBAAgB;;;ACDzC,SAAS,YAAAC,iBAAgC;;;ACcvC,gBAAAC,aAAA;AADK,IAAM,oBAAgC,CAAC,EAAE,UAAU,GAAG,MAAM,MACjE,gBAAAA,MAAC,OAAG,GAAG,OAAQ,UAAS;;;ADyCd,qBAAAC,WACgB,OAAAC,OADhB,QAAAC,cAAA;AAjCZ,SAAS,gBAAgB,MAAe,YAA6B;AACnE,MAAI,KAAK,SAAS,IAAK,QAAO,eAAe;AAC7C,SAAO,eAAe,KAAK,QAAQ,WAAW,WAAW,KAAK,OAAO,GAAG;AAC1E;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AACF,GAAoB;AAClB,QAAM,UAAU,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,aAAa,OAAO;AAEjE,SACE,gBAAAD,MAAC,SAAI,WAAU,uBACZ,kBAAQ,IAAI,CAAC,SAAS;AACrB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,OAAO,WAAW;AAAA,MACtB,MAAM,KAAK;AAAA,MACX,SAAS;AAAA,MACT,OAAO,cAAc,KAAK,QAAQ;AAAA,MAClC,gBAAgB,SAAS,SAAS;AAAA,MAClC,WAAW;AAAA,QACT;AAAA,QACA,SACI,mDACA;AAAA,QACJ,eAAe;AAAA,MACjB;AAAA,MACA,UACE,gBAAAC,OAAAF,WAAA,EACG;AAAA,aAAK,QAAQ,gBAAAC,MAAC,UAAK,WAAU,YAAY,eAAK,MAAK;AAAA,QACnD,CAAC,eAAe,gBAAAA,MAAC,UAAK,WAAU,YAAY,eAAK,OAAM;AAAA,SAC1D;AAAA,IAEJ,CAAC;AACD,WAAO,gBAAAA,MAACD,WAAA,EAA0B,kBAAZ,KAAK,IAAY;AAAA,EACzC,CAAC,GACH;AAEJ;;;AEjEA,YAAYG,mBAAkB;AAC9B,SAAS,QAAQ,YAAY;AA2DjB,SAeA,YAAAC,WAfA,OAAAC,OAgBE,QAAAC,cAhBF;AA/BZ,SAAS,SAAS,MAAwB;AACxC,QAAM,SAAS,MAAM,MAAM,KAAK,KAAK,MAAM,OAAO,KAAK;AACvD,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,OAAO,MAAM,KAAK;AAChC,MAAI,MAAM,UAAU,EAAG,SAAQ,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,GAAG,YAAY;AACtE,SAAO,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY;AACxC;AAEA,IAAM,YACJ;AAEK,SAAS,SAAS;AAAA,EACvB;AAAA,EACA,QAAQ,CAAC;AAAA,EACT;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb,QAAQ;AACV,GAAkB;AAChB,QAAM,QAAQ,SAAS,IAAI;AAE3B,SACE,gBAAAA,OAAc,oBAAb,EACC;AAAA,oBAAAD,MAAc,uBAAb,EAAqB,SAAO,MAC3B,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,cAAW;AAAA,QACX,eAAY;AAAA,QAEX,gBAAM,YACL,gBAAAA,MAAC,SAAI,KAAK,KAAK,WAAW,KAAK,KAAK,QAAQ,KAAK,SAAS,UAAU,WAAU,8BAA6B,IACzG,QACF,gBAAAA,MAAC,UAAM,iBAAM,IAEb,gBAAAA,MAAC,QAAK,WAAU,WAAU;AAAA;AAAA,IAE9B,GACF;AAAA,IACA,gBAAAA,MAAc,sBAAb,EACC,0BAAAC;AAAA,MAAc;AAAA,MAAb;AAAA,QACC;AAAA,QACA,YAAY;AAAA,QACZ,WAAU;AAAA,QAER;AAAA,iBAAM,QAAQ,MAAM,UACpB,gBAAAA,OAAAF,WAAA,EACE;AAAA,4BAAAE,OAAC,SAAI,WAAU,eACZ;AAAA,mBAAK,QAAQ,gBAAAD,MAAC,OAAE,WAAU,gCAAgC,eAAK,MAAK;AAAA,cACpE,KAAK,SAAS,gBAAAA,MAAC,OAAE,WAAU,0CAA0C,eAAK,OAAM;AAAA,eACnF;AAAA,YACA,gBAAAA,MAAc,yBAAb,EAAuB,WAAU,6BAA4B;AAAA,aAChE;AAAA,UAGD,MAAM;AAAA,YAAI,CAAC,SACV,KAAK,OACH,gBAAAA,MAAc,oBAAb,EAAmC,SAAO,MACxC,qBAAW,EAAE,MAAM,KAAK,MAAM,WAAW,WAAW,UACnD,gBAAAC,OAAAF,WAAA,EACG;AAAA,mBAAK;AAAA,cACL,KAAK;AAAA,eACR,EACA,CAAC,KANmB,KAAK,KAO7B,IAEA,gBAAAE,OAAc,oBAAb,EAAmC,WAAW,WAAW,SAAS,KAAK,SACrE;AAAA,mBAAK;AAAA,cACL,KAAK;AAAA,iBAFgB,KAAK,KAG7B;AAAA,UAEJ;AAAA,UAEC,YACC,gBAAAA,OAAAF,WAAA,EACG;AAAA,kBAAM,SAAS,KAAK,gBAAAC,MAAc,yBAAb,EAAuB,WAAU,6BAA4B;AAAA,YACnF,gBAAAC,OAAc,oBAAb,EAAkB,WAAW,GAAG,WAAW,0CAA0C,GAAG,SAAS,UAChG;AAAA,8BAAAD,MAAC,UAAO,WAAU,WAAU;AAAA,cAC3B;AAAA,eACH;AAAA,aACF;AAAA;AAAA;AAAA,IAEJ,GACF;AAAA,KACF;AAEJ;;;AHtEI,gBAAAE,OAcE,QAAAC,cAdF;AApBG,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB;AACF,GAAkB;AAChB,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,gBAAgB;AAC3D,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,KAAK;AAElD,QAAM,MAAM,CAAC,aAAsB,eACjC,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAGF,SACE,gBAAAC,OAAC,SAAI,WAAU,+CAEb;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,YAAY,SAAS;AAAA,QACvB;AAAA,QAEA;AAAA,0BAAAD,MAAC,SAAI,WAAU,iDACZ,sBAAa,kBAAkB,QAAS,OAC3C;AAAA,UACA,gBAAAA,MAAC,SAAI,WAAU,oCAAoC,cAAI,SAAS,GAAE;AAAA,UACjE,eACC,gBAAAA,MAAC,SAAI,WAAU,gBACb,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;AAAA,cACrC,WAAU;AAAA,cACV,cAAY,YAAY,kBAAkB;AAAA,cAEzC,sBAAY,gBAAAA,MAAC,gBAAa,WAAU,WAAU,IAAK,gBAAAA,MAAC,eAAY,WAAU,WAAU;AAAA;AAAA,UACvF,GACF;AAAA;AAAA;AAAA,IAEJ;AAAA,IAGA,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,aAAa,oCAAoC;AAAA,QACnD;AAAA,QACA,SAAS,MAAM,cAAc,KAAK;AAAA,QAElC;AAAA,0BAAAD,MAAC,SAAI,WAAU,gCAA+B;AAAA,UAC9C,gBAAAC;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,aAAa,kBAAkB;AAAA,cACjC;AAAA,cACA,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,cAElC;AAAA,gCAAAD,MAAC,SAAI,WAAU,iDAAiD,iBAAM;AAAA,gBACtE,gBAAAA,MAAC,SAAI,WAAU,oCAAoC,cAAI,OAAO,MAAM,cAAc,KAAK,CAAC,GAAE;AAAA;AAAA;AAAA,UAC5F;AAAA;AAAA;AAAA,IACF;AAAA,IAGA,gBAAAC,OAAC,SAAI,WAAU,wCACb;AAAA,sBAAAA,OAAC,YAAO,WAAU,qEAChB;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM,cAAc,IAAI;AAAA,YACjC,WAAU;AAAA,YACV,cAAW;AAAA,YAEX,0BAAAA,MAAC,QAAK,WAAU,WAAU;AAAA;AAAA,QAC5B;AAAA,QACA,gBAAAC,OAAC,SAAI,WAAU,mCACZ;AAAA;AAAA,WACC,QAAQ,aACR,gBAAAD,MAAC,YAAS,MAAY,OAAO,eAAe,UAAoB,YAAwB;AAAA,WAE5F;AAAA,SACF;AAAA,MACA,gBAAAA,MAAC,UAAK,WAAU,0BAA0B,UAAS;AAAA,OACrD;AAAA,KACF;AAEJ;;;AI9HA,YAAYG,mBAAkB;AAC9B,SAAS,oBAAoB;AA4CnB,SAiBU,YAAAC,WAjBV,OAAAC,OAiBU,QAAAC,cAjBV;AArBV,IAAMC,aACJ;AAEK,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa;AACf,GAAwB;AACtB,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SACE,gBAAAD,OAAc,oBAAb,EACC;AAAA,oBAAAD,MAAc,uBAAb,EAAqB,SAAO,MAC3B,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL;AAAA,QACA,cAAY;AAAA,QACZ,WAAU;AAAA,QAEV,0BAAAA,MAAC,gBAAa,WAAU,WAAU;AAAA;AAAA,IACpC,GACF;AAAA,IACA,gBAAAA,MAAc,sBAAb,EACC,0BAAAA;AAAA,MAAc;AAAA,MAAb;AAAA,QACC;AAAA,QACA,YAAY;AAAA,QACZ,WAAU;AAAA,QAET,kBAAQ,IAAI,CAAC,WAAW;AACvB,gBAAM,MAAM,GAAGE,YAAW,OAAO,eAAe,0CAA0C;AAC1F,iBAAO,OAAO,OACZ,gBAAAF,MAAc,oBAAb,EAAqC,SAAO,MAAC,UAAU,OAAO,UAC5D,qBAAW;AAAA,YACV,MAAM,OAAO;AAAA,YACb,WAAW;AAAA,YACX,UACE,gBAAAC,OAAAF,WAAA,EACG;AAAA,qBAAO;AAAA,cACP,OAAO;AAAA,eACV;AAAA,UAEJ,CAAC,KAVqB,OAAO,KAW/B,IAEA,gBAAAE;AAAA,YAAc;AAAA,YAAb;AAAA,cAEC,WAAW;AAAA,cACX,UAAU,OAAO;AAAA,cACjB,SAAS,OAAO;AAAA,cAEf;AAAA,uBAAO;AAAA,gBACP,OAAO;AAAA;AAAA;AAAA,YANH,OAAO;AAAA,UAOd;AAAA,QAEJ,CAAC;AAAA;AAAA,IACH,GACF;AAAA,KACF;AAEJ;;;ACrFO,SAAS,gBAAgB,KAAU,kBAAkB,+BAAuC;AACjG,QAAM,SAAS,KAAK,MAAM,UAAU,KAAK;AACzC,MAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AAC9C,WAAO,OAAO,CAAC,EAAE;AAAA,EACnB;AACA,SAAO,UAAU;AACnB;;;ACNA,SAAS,aAAa,YAAAE,iBAAgB;AAE/B,SAAS,cAAc,UAAU,OAAO;AAC7C,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,OAAO;AACxC,QAAM,SAAS,YAAY,MAAM,QAAQ,IAAI,GAAG,CAAC,CAAC;AAClD,QAAM,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,CAAC,CAAC;AACpD,QAAM,WAAW,YAAY,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;AACzD,SAAO,EAAE,MAAM,QAAQ,SAAS,UAAU,QAAQ;AACpD;;;ACRA,SAAS,aAAa;AACtB,SAAS,eAAAC,oBAAmB;AAIrB,SAAS,iBAAiB;AAC/B,QAAM,YAAYA;AAAA,IAChB,CAAC,OAAe,aAAsB,SAAsB,cAAc;AACxE,cAAQ,QAAQ;AAAA,QACd,KAAK;AACH,gBAAM,QAAQ,OAAO,EAAE,YAAY,CAAC;AACpC;AAAA,QACF,KAAK;AACH,gBAAM,MAAM,OAAO,EAAE,YAAY,CAAC;AAClC;AAAA,QACF,KAAK;AACH,gBAAM,KAAK,OAAO,EAAE,YAAY,CAAC;AACjC;AAAA,QACF,KAAK;AACH,gBAAM,QAAQ,OAAO,EAAE,YAAY,CAAC;AACpC;AAAA,MACJ;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":["theme","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","sizeClasses","jsx","jsxs","jsx","jsxs","Fragment","jsx","_","React","jsx","jsxs","React","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","useState","Fragment","jsx","Fragment","jsx","jsxs","DropdownMenu","Fragment","jsx","jsxs","jsx","jsxs","useState","DropdownMenu","Fragment","jsx","jsxs","itemClass","useState","useCallback"]}
1
+ {"version":3,"sources":["../src/components/theme-provider.tsx","../src/components/mode-toggle.tsx","../src/components/empty-state.tsx","../src/components/confirm-dialog.tsx","../src/components/page-header.tsx","../src/components/status-dot.tsx","../src/components/status-badge.tsx","../src/components/progress-bar.tsx","../src/components/form-field.tsx","../src/components/form-dialog.tsx","../src/lib/utils.ts","../src/components/auth-card.tsx","../src/components/pagination.tsx","../src/components/table-skeleton.tsx","../src/components/search-input.tsx","../src/components/password-input.tsx","../src/components/combobox.tsx","../src/components/stat-card.tsx","../src/components/data-table-wrapper.tsx","../src/components/mobile-card-list.tsx","../src/components/responsive-data-view.tsx","../src/components/toaster.tsx","../src/components/app-shell.tsx","../src/components/sidebar-nav.tsx","../src/components/types.tsx","../src/components/user-menu.tsx","../src/components/row-actions-menu.tsx","../src/lib/api-error.ts","../src/hooks/use-disclosure.ts","../src/hooks/use-toast.ts"],"sourcesContent":["import { createContext, useContext, useEffect, useState } from \"react\"\n\ntype Theme = \"dark\" | \"light\" | \"system\"\n\ntype ThemeProviderProps = {\n children: React.ReactNode\n defaultTheme?: Theme\n storageKey?: string\n}\n\ntype ThemeProviderState = {\n theme: Theme\n setTheme: (theme: Theme) => void\n}\n\nconst initialState: ThemeProviderState = {\n theme: \"system\",\n setTheme: () => null,\n}\n\nconst ThemeProviderContext = createContext<ThemeProviderState>(initialState)\n\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"ui-theme\",\n ...props\n}: ThemeProviderProps) {\n const [theme, setTheme] = useState<Theme>(\n () => (localStorage.getItem(storageKey) as Theme) || defaultTheme\n )\n\n useEffect(() => {\n const root = window.document.documentElement\n root.classList.remove(\"light\", \"dark\")\n if (theme === \"system\") {\n const systemTheme = window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\"\n root.classList.add(systemTheme)\n return\n }\n root.classList.add(theme)\n }, [theme])\n\n const value = {\n theme,\n setTheme: (theme: Theme) => {\n localStorage.setItem(storageKey, theme)\n setTheme(theme)\n },\n }\n\n return (\n <ThemeProviderContext.Provider {...props} value={value}>\n {children}\n </ThemeProviderContext.Provider>\n )\n}\n\nexport function useTheme() {\n const context = useContext(ThemeProviderContext)\n if (context === undefined) {\n throw new Error(\"useTheme must be used within a ThemeProvider\")\n }\n return context\n}\n\nexport type { Theme, ThemeProviderProps, ThemeProviderState }\n","import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { Moon, Sun, Monitor } from \"lucide-react\"\nimport { useTheme } from \"./theme-provider\"\n\nexport function ModeToggle() {\n const { setTheme } = useTheme()\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n className=\"relative inline-flex h-9 w-9 items-center justify-center rounded-md border border-input bg-background text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-label=\"Alternar tema\"\n >\n <Sun className=\"h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0\" />\n <Moon className=\"absolute inset-0 m-auto h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100\" />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align=\"end\"\n className=\"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n <DropdownMenu.Item\n className=\"flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n onClick={() => setTheme(\"light\")}\n >\n <Sun className=\"h-4 w-4\" /> Claro\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n onClick={() => setTheme(\"dark\")}\n >\n <Moon className=\"h-4 w-4\" /> Escuro\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n onClick={() => setTheme(\"system\")}\n >\n <Monitor className=\"h-4 w-4\" /> Sistema\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface EmptyStateProps {\n icon?: ReactNode\n title: string\n description?: string\n action?: ReactNode\n className?: string\n}\n\nexport function EmptyState({ icon, title, description, action, className }: EmptyStateProps) {\n return (\n <div className={`flex flex-col items-center justify-center py-16 text-center ${className ?? \"\"}`}>\n {icon && <div className=\"mb-4 text-muted-foreground\">{icon}</div>}\n <h3 className=\"text-lg font-semibold tracking-tight\">{title}</h3>\n {description && (\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{description}</p>\n )}\n {action && <div className=\"mt-4\">{action}</div>}\n </div>\n )\n}\n","import * as AlertDialog from \"@radix-ui/react-alert-dialog\"\nimport type { ReactNode } from \"react\"\n\ninterface ConfirmDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onConfirm: () => void\n title: string\n description: ReactNode\n confirmLabel?: string\n cancelLabel?: string\n loading?: boolean\n variant?: \"default\" | \"destructive\"\n}\n\nexport function ConfirmDialog({\n open,\n onOpenChange,\n onConfirm,\n title,\n description,\n confirmLabel = \"Confirmar\",\n cancelLabel = \"Cancelar\",\n loading = false,\n variant = \"default\",\n}: ConfirmDialogProps) {\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange}>\n <AlertDialog.Portal>\n <AlertDialog.Overlay className=\"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <AlertDialog.Content className=\"fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\">\n <div className=\"flex flex-col space-y-2 text-center sm:text-left\">\n <AlertDialog.Title className=\"text-lg font-semibold\">{title}</AlertDialog.Title>\n <AlertDialog.Description className=\"text-sm text-muted-foreground\">\n {description}\n </AlertDialog.Description>\n </div>\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <AlertDialog.Cancel className=\"inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 cursor-pointer\">\n {cancelLabel}\n </AlertDialog.Cancel>\n <AlertDialog.Action\n onClick={onConfirm}\n disabled={loading}\n className={`inline-flex h-9 items-center justify-center rounded-md px-4 text-sm font-medium shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 cursor-pointer ${\n variant === \"destructive\"\n ? \"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\"\n }`}\n >\n {loading ? \"Aguarde...\" : confirmLabel}\n </AlertDialog.Action>\n </div>\n </AlertDialog.Content>\n </AlertDialog.Portal>\n </AlertDialog.Root>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface PageHeaderProps {\n title: string\n description?: string\n action?: ReactNode\n className?: string\n}\n\nexport function PageHeader({ title, description, action, className }: PageHeaderProps) {\n return (\n <div\n className={`flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between ${className ?? \"\"}`}\n >\n <div className=\"min-w-0\">\n <h1 className=\"truncate text-2xl font-semibold tracking-tight\">\n {title}\n </h1>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n )\n}\n","interface StatusDotProps {\n active: boolean\n label?: string\n className?: string\n}\n\nexport function StatusDot({ active, label, className }: StatusDotProps) {\n return (\n <span className={`inline-flex items-center gap-2 ${className ?? \"\"}`}>\n <span\n className={`h-2 w-2 rounded-full ${active ? \"bg-green-500\" : \"bg-red-500\"}`}\n />\n {label && <span>{label}</span>}\n </span>\n )\n}\n","import type { ReactNode } from \"react\"\n\nexport type StatusBadgeVariant =\n | \"neutral\"\n | \"info\"\n | \"success\"\n | \"danger\"\n | \"warning\"\n\ninterface StatusBadgeProps {\n variant?: StatusBadgeVariant\n dot?: boolean\n className?: string\n children: ReactNode\n}\n\nconst variantClasses: Record<\n StatusBadgeVariant,\n { badge: string; dot: string }\n> = {\n neutral: {\n badge: \"bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300\",\n dot: \"bg-gray-400\",\n },\n info: {\n badge: \"bg-blue-100 text-blue-700 dark:bg-blue-950 dark:text-blue-400\",\n dot: \"bg-blue-500\",\n },\n success: {\n badge: \"bg-green-100 text-green-700 dark:bg-green-950 dark:text-green-400\",\n dot: \"bg-green-500\",\n },\n danger: {\n badge: \"bg-red-100 text-red-700 dark:bg-red-950 dark:text-red-400\",\n dot: \"bg-red-500\",\n },\n warning: {\n badge: \"bg-amber-100 text-amber-700 dark:bg-amber-950 dark:text-amber-400\",\n dot: \"bg-amber-500\",\n },\n}\n\nexport function StatusBadge({\n variant = \"neutral\",\n dot = true,\n className,\n children,\n}: StatusBadgeProps) {\n const classes = variantClasses[variant]\n\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-md px-2 py-0.5 text-xs font-medium ${classes.badge} ${className ?? \"\"}`}\n >\n {dot && (\n <span\n className={`inline-block h-1.5 w-1.5 shrink-0 rounded-full ${classes.dot}`}\n />\n )}\n {children}\n </span>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface ProgressBarProps {\n value: number\n size?: \"sm\" | \"md\"\n label?: ReactNode\n valueLabel?: ReactNode\n className?: string\n indicatorClassName?: string\n}\n\nconst sizeClasses = {\n sm: \"h-1.5\",\n md: \"h-2\",\n} as const\n\nexport function ProgressBar({\n value,\n size = \"md\",\n label,\n valueLabel,\n className,\n indicatorClassName,\n}: ProgressBarProps) {\n const clamped = Math.min(100, Math.max(0, value))\n\n return (\n <div className={`space-y-1.5 ${className ?? \"\"}`}>\n {(label || valueLabel) && (\n <div className=\"flex items-baseline justify-between gap-2\">\n {label && (\n <span className=\"text-sm text-muted-foreground\">{label}</span>\n )}\n {valueLabel && (\n <span className=\"text-sm font-semibold\">{valueLabel}</span>\n )}\n </div>\n )}\n <div\n className={`w-full overflow-hidden rounded-full bg-muted ${sizeClasses[size]}`}\n >\n <div\n className={`h-full rounded-full transition-all duration-300 ${indicatorClassName ?? \"bg-primary\"}`}\n style={{ width: `${clamped}%` }}\n />\n </div>\n </div>\n )\n}\n","import { type ReactElement, type ReactNode, cloneElement, isValidElement, useId } from \"react\"\n\ninterface FormFieldProps {\n label: string\n htmlFor?: string\n error?: string\n required?: boolean\n children: ReactNode\n className?: string\n}\n\nexport function FormField({ label, htmlFor, error, required, children, className }: FormFieldProps) {\n const errorId = useId()\n\n // Wire accessibility onto the control: mark it invalid and point it at the\n // error message so screen readers announce both.\n const field =\n error && isValidElement(children)\n ? cloneElement(children as ReactElement<Record<string, unknown>>, {\n \"aria-invalid\": true,\n \"aria-describedby\": [\n (children.props as Record<string, unknown>)[\"aria-describedby\"],\n errorId,\n ]\n .filter(Boolean)\n .join(\" \"),\n })\n : children\n\n return (\n <div className={`space-y-2 ${className ?? \"\"}`}>\n <label\n htmlFor={htmlFor}\n className=\"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {required && <span className=\"ml-1 text-destructive\">*</span>}\n </label>\n {field}\n {error && (\n <p id={errorId} className=\"text-sm text-destructive\">\n {error}\n </p>\n )}\n </div>\n )\n}\n","import * as Dialog from \"@radix-ui/react-dialog\"\nimport { X } from \"lucide-react\"\nimport * as React from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport { cn } from \"../lib/utils\"\n\ninterface FormDialogLayoutProps {\n title: string\n children: ReactNode\n onSubmit: (e: React.FormEvent) => void\n submitLabel?: string\n cancelLabel?: string\n onCancel: () => void\n isSubmitting?: boolean\n isDisabled?: boolean\n}\n\nexport function FormDialogLayout({\n title,\n children,\n onSubmit,\n submitLabel = \"Salvar\",\n cancelLabel = \"Cancelar\",\n onCancel,\n isSubmitting = false,\n isDisabled = false,\n}: FormDialogLayoutProps) {\n return (\n <form onSubmit={onSubmit}>\n <div className=\"flex flex-col space-y-1.5 text-center sm:text-left\">\n <h2 className=\"text-lg font-semibold leading-none tracking-tight\">{title}</h2>\n </div>\n <div className=\"space-y-4 py-4\">{children}</div>\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n {cancelLabel}\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting || isDisabled}\n className=\"inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90 cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n {isSubmitting ? \"Salvando...\" : submitLabel}\n </button>\n </div>\n </form>\n )\n}\n\nconst sizeClasses = {\n sm: \"sm:max-w-sm\",\n md: \"sm:max-w-md\",\n lg: \"sm:max-w-lg\",\n xl: \"sm:max-w-xl\",\n \"2xl\": \"sm:max-w-2xl\",\n} as const\n\nexport type FormDialogSize = keyof typeof sizeClasses\n\ninterface FormDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: string\n description?: ReactNode\n children: ReactNode\n footer?: ReactNode\n /** When provided, the dialog renders a <form> wrapping body + footer. */\n onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void\n size?: FormDialogSize\n className?: string\n}\n\n/**\n * Standardized, responsive modal:\n * - mobile: bottom sheet (full width, up to 92vh tall)\n * - desktop: centered dialog (up to 90vh tall)\n * Header and footer stay fixed; only the body scrolls.\n *\n * Also fixes the known Radix bug where `body { pointer-events: none }`\n * can persist after closing a dialog that contained a Select/Popover,\n * which would otherwise make the rest of the page unclickable.\n */\nexport function FormDialog({\n open,\n onOpenChange,\n title,\n description,\n children,\n footer,\n onSubmit,\n size = \"lg\",\n className,\n}: FormDialogProps) {\n React.useEffect(() => {\n if (open) return\n const id = window.setTimeout(() => {\n if (document.body.style.pointerEvents === \"none\") {\n document.body.style.pointerEvents = \"\"\n }\n }, 0)\n return () => window.clearTimeout(id)\n }, [open])\n\n const body = (\n <>\n <div className=\"flex shrink-0 items-start justify-between gap-4 border-b px-6 py-3\">\n <div className=\"min-w-0 space-y-1\">\n <Dialog.Title className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </Dialog.Title>\n {description && (\n <Dialog.Description className=\"text-sm text-muted-foreground\">\n {description}\n </Dialog.Description>\n )}\n </div>\n <Dialog.Close\n className=\"-mr-1 shrink-0 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n aria-label=\"Fechar\"\n >\n <X className=\"h-5 w-5\" />\n </Dialog.Close>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">{children}</div>\n {footer && (\n <div className=\"flex shrink-0 flex-col-reverse gap-2 border-t px-6 py-3 sm:flex-row sm:justify-end\">\n {footer}\n </div>\n )}\n </>\n )\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\" />\n <Dialog.Content\n onCloseAutoFocus={() => {\n document.body.style.pointerEvents = \"\"\n }}\n className={cn(\n \"fixed z-50 flex max-h-[92vh] flex-col bg-background shadow-lg outline-none\",\n \"inset-x-0 bottom-0 rounded-t-2xl\",\n \"sm:inset-x-auto sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:max-h-[92vh] sm:w-full sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-lg\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n sizeClasses[size],\n className,\n )}\n >\n {onSubmit ? (\n <form\n onSubmit={onSubmit}\n className=\"flex min-h-0 flex-1 flex-col\"\n >\n {body}\n </form>\n ) : (\n body\n )}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import type { ReactNode } from \"react\"\n\ninterface AuthCardProps {\n title: string\n description?: string\n children: ReactNode\n footer?: ReactNode\n}\n\nexport function AuthCard({ title, description, children, footer }: AuthCardProps) {\n return (\n <div className=\"flex min-h-screen items-center justify-center px-4\">\n <div className=\"w-full max-w-sm rounded-lg border bg-card p-6 shadow-sm\">\n <div className=\"mb-6 text-center\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"mt-1 text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n <div className=\"space-y-4\">{children}</div>\n {footer && <div className=\"mt-4\">{footer}</div>}\n </div>\n </div>\n )\n}\n","interface PaginationProps {\n page: number\n onPageChange: (page: number) => void\n hasNextPage: boolean\n hasPreviousPage: boolean\n className?: string\n}\n\nexport function Pagination({ page, onPageChange, hasNextPage, hasPreviousPage, className }: PaginationProps) {\n return (\n <div className={`flex items-center justify-end gap-4 ${className ?? \"\"}`}>\n <button\n type=\"button\"\n onClick={() => onPageChange(page - 1)}\n disabled={!hasPreviousPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Anterior\n </button>\n <span className=\"text-sm text-muted-foreground\">Página {page}</span>\n <button\n type=\"button\"\n onClick={() => onPageChange(page + 1)}\n disabled={!hasNextPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Próximo\n </button>\n </div>\n )\n}\n","interface TableSkeletonProps {\n rows?: number\n columns?: number\n}\n\nexport function TableSkeleton({ rows = 5, columns = 4 }: TableSkeletonProps) {\n return (\n <>\n {Array.from({ length: rows }).map((_, i) => (\n <tr key={i} className=\"border-b transition-colors\">\n {Array.from({ length: columns }).map((_, j) => (\n <td key={j} className=\"p-4 align-middle\">\n <div className=\"h-5 w-full animate-pulse rounded bg-muted\" />\n </td>\n ))}\n </tr>\n ))}\n </>\n )\n}\n","import * as React from \"react\"\n\ninterface SearchInputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n containerClassName?: string\n}\n\nexport const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(\n ({ containerClassName, className, ...props }, ref) => {\n return (\n <div className={`relative flex-1 ${containerClassName ?? \"\"}`}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n <input\n ref={ref}\n type=\"text\"\n className={`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 pl-10 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${className ?? \"\"}`}\n {...props}\n />\n </div>\n )\n }\n)\nSearchInput.displayName = \"SearchInput\"\n","import { Eye, EyeOff } from \"lucide-react\"\nimport * as React from \"react\"\n\ninterface PasswordInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n containerClassName?: string\n}\n\nexport const PasswordInput = React.forwardRef<\n HTMLInputElement,\n PasswordInputProps\n>(({ containerClassName, className, ...props }, ref) => {\n const [visible, setVisible] = React.useState(false)\n\n return (\n <div className={`relative ${containerClassName ?? \"\"}`}>\n <input\n ref={ref}\n type={visible ? \"text\" : \"password\"}\n className={`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 pr-10 text-base shadow-sm transition-all duration-200 placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive md:text-sm ${className ?? \"\"}`}\n {...props}\n />\n <button\n type=\"button\"\n onClick={() => setVisible((prev) => !prev)}\n aria-label={visible ? \"Ocultar senha\" : \"Mostrar senha\"}\n tabIndex={-1}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground transition-colors hover:text-foreground\"\n >\n {visible ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </button>\n </div>\n )\n})\nPasswordInput.displayName = \"PasswordInput\"\n","import * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { Command as CommandPrimitive } from \"cmdk\"\nimport { Check, ChevronsUpDown, Search } from \"lucide-react\"\nimport * as React from \"react\"\nimport { cn } from \"../lib/utils\"\n\nexport interface ComboboxOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface ComboboxProps {\n options: ComboboxOption[]\n value?: string\n onChange: (value: string) => void \n placeholder?: string \n searchPlaceholder?: string \n emptyMessage?: string\n disabled?: boolean\n id?: string\n className?: string\n \"aria-invalid\"?: boolean | \"true\" | \"false\"\n \"aria-describedby\"?: string\n}\n\nexport function Combobox({\n options,\n value,\n onChange,\n placeholder = \"Selecione...\",\n searchPlaceholder = \"Buscar...\",\n emptyMessage = \"Nenhum resultado encontrado.\",\n disabled,\n id,\n className,\n \"aria-invalid\": ariaInvalid,\n \"aria-describedby\": ariaDescribedby,\n}: ComboboxProps) {\n const [open, setOpen] = React.useState(false)\n const selected = options.find((option) => option.value === value)\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen} modal>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n id={id}\n role=\"combobox\"\n aria-expanded={open}\n aria-invalid={ariaInvalid}\n aria-describedby={ariaDescribedby}\n disabled={disabled}\n className={cn(\n \"flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive\",\n className,\n )}\n >\n <span\n className={cn(\"truncate\", !selected && \"text-muted-foreground\")}\n >\n {selected ? selected.label : placeholder}\n </span>\n <ChevronsUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </button>\n </PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n align=\"start\"\n sideOffset={4}\n className=\"z-50 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-md\"\n style={{ width: \"var(--radix-popover-trigger-width)\" }}\n >\n <CommandPrimitive className=\"flex h-full w-full flex-col overflow-hidden\">\n <div className=\"flex items-center border-b px-3\">\n <Search className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n placeholder={searchPlaceholder}\n className=\"flex h-9 w-full bg-transparent py-2 text-sm outline-none placeholder:text-muted-foreground\"\n />\n </div>\n <CommandPrimitive.List className=\"max-h-60 overflow-y-auto overflow-x-hidden p-1\">\n <CommandPrimitive.Empty className=\"py-6 text-center text-sm text-muted-foreground\">\n {emptyMessage}\n </CommandPrimitive.Empty>\n {options.map((option) => (\n <CommandPrimitive.Item\n key={option.value}\n value={option.label}\n disabled={option.disabled}\n onSelect={() => {\n onChange(option.value)\n setOpen(false)\n }}\n className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 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\"\n >\n <Check\n className={cn(\n \"h-4 w-4 shrink-0\",\n value === option.value ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <span className=\"truncate\">{option.label}</span>\n </CommandPrimitive.Item>\n ))}\n </CommandPrimitive.List>\n </CommandPrimitive>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface StatCardProps {\n label: string\n value: ReactNode\n detail?: string\n icon?: ReactNode\n isLoading?: boolean\n}\n\nexport function StatCard({ label, value, detail, icon, isLoading }: StatCardProps) {\n if (isLoading) {\n return (\n <div className=\"rounded-lg border bg-card p-6 shadow-sm\">\n <div className=\"flex items-center justify-between pb-2\">\n <div className=\"h-4 w-24 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-4 animate-pulse rounded bg-muted\" />\n </div>\n <div className=\"mt-2 h-7 w-16 animate-pulse rounded bg-muted\" />\n <div className=\"mt-1 h-4 w-20 animate-pulse rounded bg-muted\" />\n </div>\n )\n }\n\n return (\n <div className=\"rounded-lg border bg-card p-6 shadow-sm\">\n <div className=\"flex items-center justify-between pb-2\">\n <span className=\"text-sm font-medium text-muted-foreground\">{label}</span>\n {icon && <span className=\"text-muted-foreground\">{icon}</span>}\n </div>\n <div className=\"text-2xl font-bold\">{value}</div>\n {detail && <p className=\"text-xs text-muted-foreground\">{detail}</p>}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface DataTableWrapperProps {\n children: ReactNode\n isEmpty: boolean\n isLoading: boolean\n emptyIcon?: ReactNode\n emptyTitle?: string\n emptyDescription?: string\n page?: number\n onPageChange?: (page: number) => void\n hasNextPage?: boolean\n hasPreviousPage?: boolean\n}\n\nexport function DataTableWrapper({\n children,\n isEmpty,\n isLoading,\n emptyIcon,\n emptyTitle = \"Nenhum registro encontrado\",\n emptyDescription,\n page,\n onPageChange,\n hasNextPage = false,\n hasPreviousPage = false,\n}: DataTableWrapperProps) {\n return (\n <div className=\"space-y-4\">\n <div className=\"overflow-x-auto rounded-md border\">{children}</div>\n\n {!isLoading && isEmpty && (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n {emptyIcon && <div className=\"mb-4 text-muted-foreground\">{emptyIcon}</div>}\n <h3 className=\"text-lg font-semibold tracking-tight\">{emptyTitle}</h3>\n {emptyDescription && (\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{emptyDescription}</p>\n )}\n </div>\n )}\n\n {page !== undefined && onPageChange && (\n <div className=\"flex items-center justify-end gap-4\">\n <button\n type=\"button\"\n onClick={() => onPageChange(page - 1)}\n disabled={!hasPreviousPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Anterior\n </button>\n <span className=\"text-sm text-muted-foreground\">Página {page}</span>\n <button\n type=\"button\"\n onClick={() => onPageChange(page + 1)}\n disabled={!hasNextPage}\n className=\"inline-flex h-8 items-center justify-center rounded-md border border-input bg-background px-3 text-xs font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer disabled:pointer-events-none disabled:opacity-50\"\n >\n Próximo\n </button>\n </div>\n )}\n </div>\n )\n}\n","import { type MouseEvent, type ReactNode, type TouchEvent, useRef } from \"react\"\n\ninterface MobileCardListProps<T> {\n data: T[]\n renderCard: (item: T, index: number) => ReactNode\n keyExtractor: (item: T) => string\n isLoading?: boolean\n loadingCount?: number\n className?: string\n}\n\n// Movimento (px) acima do qual o gesto é tratado como scroll, não tap.\nconst SCROLL_THRESHOLD = 8\n\nexport function MobileCardList<T>({\n data,\n renderCard,\n keyExtractor,\n isLoading = false,\n loadingCount = 5,\n className,\n}: MobileCardListProps<T>) {\n // Guard contra tap acidental durante o scroll: se o dedo se moveu além do\n // threshold, o clique seguinte (ex.: botão de ações dentro do card) é\n // cancelado na fase de captura, antes de chegar no elemento interativo.\n const start = useRef<{ x: number; y: number } | null>(null)\n const scrolled = useRef(false)\n\n const onTouchStart = (e: TouchEvent<HTMLDivElement>) => {\n const t = e.touches[0]\n start.current = { x: t.clientX, y: t.clientY }\n scrolled.current = false\n }\n\n const onTouchMove = (e: TouchEvent<HTMLDivElement>) => {\n if (!start.current) return\n const t = e.touches[0]\n if (\n Math.abs(t.clientX - start.current.x) > SCROLL_THRESHOLD ||\n Math.abs(t.clientY - start.current.y) > SCROLL_THRESHOLD\n ) {\n scrolled.current = true\n }\n }\n\n const onClickCapture = (e: MouseEvent<HTMLDivElement>) => {\n if (scrolled.current) {\n e.preventDefault()\n e.stopPropagation()\n }\n }\n\n if (isLoading) {\n return (\n <div className={`space-y-3 ${className ?? \"\"}`}>\n {Array.from({ length: loadingCount }).map((_, i) => (\n <div key={i} className=\"rounded-xl border p-4\">\n <div className=\"space-y-3\">\n <div className=\"flex justify-between\">\n <div className=\"h-5 w-32 animate-pulse rounded bg-muted\" />\n <div className=\"h-5 w-16 animate-pulse rounded bg-muted\" />\n </div>\n <div className=\"h-4 w-48 animate-pulse rounded bg-muted\" />\n <div className=\"flex justify-between\">\n <div className=\"h-4 w-24 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-20 animate-pulse rounded bg-muted\" />\n </div>\n </div>\n </div>\n ))}\n </div>\n )\n }\n\n return (\n <div\n className={`space-y-3 ${className ?? \"\"}`}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onClickCapture={onClickCapture}\n >\n {data.map((item, index) => (\n <div\n key={keyExtractor(item)}\n className=\"rounded-xl border p-4 transition-all duration-150 hover:border-foreground/20 active:scale-[0.99]\"\n >\n {renderCard(item, index)}\n </div>\n ))}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\ninterface ResponsiveDataViewProps {\n table: ReactNode\n cards: ReactNode\n isEmpty: boolean\n isLoading: boolean\n emptyIcon?: ReactNode\n emptyTitle?: string\n emptyDescription?: string\n pagination?: ReactNode\n}\n\nexport function ResponsiveDataView({\n table, cards, isEmpty, isLoading, emptyIcon, emptyTitle = \"Nenhum registro encontrado\", emptyDescription, pagination,\n}: ResponsiveDataViewProps) {\n return (\n <div className=\"space-y-4\">\n <div className=\"hidden overflow-x-auto rounded-md border md:block\">{table}</div>\n <div className=\"md:hidden\">{cards}</div>\n {!isLoading && isEmpty && (\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n {emptyIcon && <div className=\"mb-4 text-muted-foreground\">{emptyIcon}</div>}\n <h3 className=\"text-lg font-semibold tracking-tight\">{emptyTitle}</h3>\n {emptyDescription && <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{emptyDescription}</p>}\n </div>\n )}\n {pagination}\n </div>\n )\n}\n","import { useTheme } from \"./theme-provider\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nexport function Toaster(props: ToasterProps) {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-md\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n success:\n \"group-[.toaster]:!bg-background group-[.toaster]:!text-foreground group-[.toaster]:!border-success/40\",\n error:\n \"group-[.toaster]:!bg-background group-[.toaster]:!text-foreground group-[.toaster]:!border-destructive/40\",\n },\n }}\n {...props}\n />\n )\n}\n","import { ChevronLeft, ChevronRight, Menu } from \"lucide-react\"\nimport { type ReactNode, useState } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport { SidebarNav, type NavItem } from \"./sidebar-nav\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\nimport { UserMenu, type AppUser, type UserMenuItem } from \"./user-menu\"\n\nexport interface AppShellProps {\n brand: ReactNode\n brandCollapsed?: ReactNode\n navItems: NavItem[]\n activePath: string\n isActive?: (item: NavItem, activePath: string) => boolean\n isAdmin?: boolean\n user?: AppUser\n userMenuItems?: UserMenuItem[]\n onLogout?: () => void\n renderLink?: RenderLink\n headerActions?: ReactNode\n collapsible?: boolean\n defaultCollapsed?: boolean\n children: ReactNode\n}\n\nexport function AppShell({\n brand,\n brandCollapsed,\n navItems,\n activePath,\n isActive,\n isAdmin = false,\n user,\n userMenuItems,\n onLogout,\n renderLink = defaultRenderLink,\n headerActions,\n collapsible = true,\n defaultCollapsed = false,\n children,\n}: AppShellProps) {\n const [collapsed, setCollapsed] = useState(defaultCollapsed)\n const [mobileOpen, setMobileOpen] = useState(false)\n\n const nav = (isCollapsed: boolean, onNavigate?: () => void) => (\n <SidebarNav\n items={navItems}\n activePath={activePath}\n isActive={isActive}\n isAdmin={isAdmin}\n isCollapsed={isCollapsed}\n renderLink={renderLink}\n onNavigate={onNavigate}\n />\n )\n\n return (\n <div className=\"flex h-screen overflow-hidden bg-background\">\n {/* Desktop sidebar */}\n <aside\n className={cn(\n \"hidden shrink-0 flex-col border-r bg-card transition-all duration-300 md:flex\",\n collapsed ? \"w-16\" : \"w-60\",\n )}\n >\n <div className=\"flex h-14 shrink-0 items-center border-b px-4\">\n {collapsed ? (brandCollapsed ?? brand) : brand}\n </div>\n <div className=\"flex-1 overflow-y-auto px-2 py-4\">{nav(collapsed)}</div>\n {collapsible && (\n <div className=\"border-t p-2\">\n <button\n type=\"button\"\n onClick={() => setCollapsed((v) => !v)}\n className=\"flex w-full items-center justify-center rounded-md px-2 py-2 text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground\"\n aria-label={collapsed ? \"Expandir menu\" : \"Recolher menu\"}\n >\n {collapsed ? <ChevronRight className=\"h-4 w-4\" /> : <ChevronLeft className=\"h-4 w-4\" />}\n </button>\n </div>\n )}\n </aside>\n\n {/* Mobile drawer */}\n <div\n className={cn(\n \"fixed inset-0 z-50 transition-opacity duration-300 md:hidden\",\n mobileOpen ? \"pointer-events-auto opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n onClick={() => setMobileOpen(false)}\n >\n <div className=\"absolute inset-0 bg-black/50\" />\n <div\n className={cn(\n \"absolute left-0 top-0 flex h-full w-64 flex-col border-r bg-card transition-transform duration-300\",\n mobileOpen ? \"translate-x-0\" : \"-translate-x-full\",\n )}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex h-14 shrink-0 items-center border-b px-4\">{brand}</div>\n <div className=\"flex-1 overflow-y-auto px-2 py-4\">{nav(false, () => setMobileOpen(false))}</div>\n </div>\n </div>\n\n {/* Main column */}\n <div className=\"flex flex-1 flex-col overflow-hidden\">\n <header className=\"flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4\">\n <button\n type=\"button\"\n onClick={() => setMobileOpen(true)}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md border border-input bg-background shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground md:hidden\"\n aria-label=\"Abrir menu\"\n >\n <Menu className=\"h-4 w-4\" />\n </button>\n <div className=\"ml-auto flex items-center gap-2\">\n {headerActions}\n {(user || onLogout) && (\n <UserMenu user={user} items={userMenuItems} onLogout={onLogout} renderLink={renderLink} />\n )}\n </div>\n </header>\n <main className=\"flex-1 overflow-y-auto\">{children}</main>\n </div>\n </div>\n )\n}\n","import { Fragment, type ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\n\nexport interface NavItem {\n label: string\n href: string\n icon?: ReactNode\n adminOnly?: boolean\n}\n\nexport interface SidebarNavProps {\n items: NavItem[]\n activePath: string\n isActive?: (item: NavItem, activePath: string) => boolean\n isAdmin?: boolean\n isCollapsed?: boolean\n renderLink?: RenderLink\n onNavigate?: () => void\n}\n\nfunction defaultIsActive(item: NavItem, activePath: string): boolean {\n if (item.href === \"/\") return activePath === \"/\"\n return activePath === item.href || activePath.startsWith(item.href + \"/\")\n}\n\nexport function SidebarNav({\n items,\n activePath,\n isActive = defaultIsActive,\n isAdmin = false,\n isCollapsed = false,\n renderLink = defaultRenderLink,\n onNavigate,\n}: SidebarNavProps) {\n const visible = items.filter((item) => !item.adminOnly || isAdmin)\n\n return (\n <nav className=\"flex flex-col gap-1\">\n {visible.map((item) => {\n const active = isActive(item, activePath)\n const link = renderLink({\n href: item.href,\n onClick: onNavigate,\n title: isCollapsed ? item.label : undefined,\n \"aria-current\": active ? \"page\" : undefined,\n className: cn(\n \"flex cursor-pointer items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors\",\n active\n ? \"bg-accent text-accent-foreground font-semibold\"\n : \"text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n isCollapsed && \"justify-center px-2\",\n ),\n children: (\n <>\n {item.icon && <span className=\"shrink-0\">{item.icon}</span>}\n {!isCollapsed && <span className=\"truncate\">{item.label}</span>}\n </>\n ),\n })\n return <Fragment key={item.href}>{link}</Fragment>\n })}\n </nav>\n )\n}\n","import type { ReactNode } from \"react\"\n\nexport interface RenderLinkProps {\n href: string\n className?: string\n children: ReactNode\n onClick?: () => void\n title?: string\n \"aria-current\"?: \"page\"\n}\n\nexport type RenderLink = (props: RenderLinkProps) => ReactNode\n\nexport const defaultRenderLink: RenderLink = ({ children, ...props }) => (\n <a {...props}>{children}</a>\n)\n","import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { LogOut, User } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\n\nexport interface AppUser {\n name?: string\n email?: string\n avatarUrl?: string\n}\n\nexport interface UserMenuItem {\n label: string\n icon?: ReactNode\n href?: string\n onClick?: () => void\n}\n\nexport interface UserMenuProps {\n user?: AppUser\n items?: UserMenuItem[]\n onLogout?: () => void\n logoutLabel?: string\n renderLink?: RenderLink\n align?: \"start\" | \"center\" | \"end\"\n}\n\nfunction initials(user?: AppUser): string {\n const source = user?.name?.trim() || user?.email?.trim()\n if (!source) return \"\"\n const parts = source.split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n return source.slice(0, 2).toUpperCase()\n}\n\nconst itemClass =\n \"flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent\"\n\nexport function UserMenu({\n user,\n items = [],\n onLogout,\n logoutLabel = \"Sair\",\n renderLink = defaultRenderLink,\n align = \"end\",\n}: UserMenuProps) {\n const label = initials(user)\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-9 w-9 items-center justify-center overflow-hidden rounded-full border border-input bg-background text-xs font-semibold shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-label=\"Menu do usuário\"\n data-testid=\"user-menu\"\n >\n {user?.avatarUrl ? (\n <img src={user.avatarUrl} alt={user.name ?? user.email ?? \"Avatar\"} className=\"h-full w-full object-cover\" />\n ) : label ? (\n <span>{label}</span>\n ) : (\n <User className=\"h-4 w-4\" />\n )}\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align={align}\n sideOffset={6}\n className=\"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n {(user?.name || user?.email) && (\n <>\n <div className=\"px-2 py-1.5\">\n {user.name && <p className=\"truncate text-sm font-medium\">{user.name}</p>}\n {user.email && <p className=\"truncate text-xs text-muted-foreground\">{user.email}</p>}\n </div>\n <DropdownMenu.Separator className=\"-mx-1 my-1 h-px bg-border\" />\n </>\n )}\n\n {items.map((item) =>\n item.href ? (\n <DropdownMenu.Item key={item.label} asChild>\n {renderLink({ href: item.href, className: itemClass, children: (\n <>\n {item.icon}\n {item.label}\n </>\n ) })}\n </DropdownMenu.Item>\n ) : (\n <DropdownMenu.Item key={item.label} className={itemClass} onClick={item.onClick}>\n {item.icon}\n {item.label}\n </DropdownMenu.Item>\n ),\n )}\n\n {onLogout && (\n <>\n {items.length > 0 && <DropdownMenu.Separator className=\"-mx-1 my-1 h-px bg-border\" />}\n <DropdownMenu.Item className={cn(itemClass, \"text-destructive focus:bg-destructive/10\")} onClick={onLogout}>\n <LogOut className=\"h-4 w-4\" />\n {logoutLabel}\n </DropdownMenu.Item>\n </>\n )}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )\n}\n","import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { MoreVertical } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../lib/utils\"\nimport type { RenderLink } from \"./types\"\nimport { defaultRenderLink } from \"./types\"\n\nexport interface RowAction {\n label: string\n icon?: ReactNode\n onClick?: () => void\n href?: string\n destructive?: boolean\n disabled?: boolean\n}\n\nexport interface RowActionsMenuProps {\n actions: RowAction[]\n disabled?: boolean\n align?: \"start\" | \"center\" | \"end\"\n label?: string\n renderLink?: RenderLink\n}\n\nconst itemClass =\n \"flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50\"\n\nexport function RowActionsMenu({\n actions,\n disabled = false,\n align = \"end\",\n label = \"Ações\",\n renderLink = defaultRenderLink,\n}: RowActionsMenuProps) {\n if (actions.length === 0) return null\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n disabled={disabled}\n aria-label={label}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\"\n >\n <MoreVertical className=\"h-4 w-4\" />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align={align}\n sideOffset={6}\n className=\"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n {actions.map((action) => {\n const cls = cn(itemClass, action.destructive && \"text-destructive focus:bg-destructive/10\")\n return action.href ? (\n <DropdownMenu.Item key={action.label} asChild disabled={action.disabled}>\n {renderLink({\n href: action.href,\n className: cls,\n children: (\n <>\n {action.icon}\n {action.label}\n </>\n ),\n })}\n </DropdownMenu.Item>\n ) : (\n <DropdownMenu.Item\n key={action.label}\n className={cls}\n disabled={action.disabled}\n onClick={action.onClick}\n >\n {action.icon}\n {action.label}\n </DropdownMenu.Item>\n )\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )\n}\n","export function extractApiError(err: any, fallbackMessage = \"Ocorreu um erro inesperado.\"): string {\n const detail = err?.body?.detail || err?.message\n if (Array.isArray(detail) && detail.length > 0) {\n return detail[0].msg\n }\n return detail || fallbackMessage\n}\n","import { useCallback, useState } from \"react\"\n\nexport function useDisclosure(initial = false) {\n const [open, setOpen] = useState(initial)\n const onOpen = useCallback(() => setOpen(true), [])\n const onClose = useCallback(() => setOpen(false), [])\n const onToggle = useCallback(() => setOpen((v) => !v), [])\n return { open, onOpen, onClose, onToggle, setOpen }\n}\n","import { toast } from \"sonner\"\nimport { useCallback } from \"react\"\n\ntype ToastStatus = \"success\" | \"error\" | \"info\" | \"warning\"\n\nexport function useCustomToast() {\n const showToast = useCallback(\n (title: string, description?: string, status: ToastStatus = \"success\") => {\n switch (status) {\n case \"success\":\n toast.success(title, { description })\n break\n case \"error\":\n toast.error(title, { description })\n break\n case \"info\":\n toast.info(title, { description })\n break\n case \"warning\":\n toast.warning(title, { description })\n break\n }\n },\n [],\n )\n\n return showToast\n}\n\nexport { toast }\n"],"mappings":"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","names":["theme","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","sizeClasses","jsx","jsxs","jsx","jsxs","Fragment","jsx","_","React","jsx","jsxs","React","jsx","jsxs","React","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","useState","Fragment","jsx","Fragment","jsx","jsxs","DropdownMenu","Fragment","jsx","jsxs","jsx","jsxs","useState","DropdownMenu","Fragment","jsx","jsxs","itemClass","useState","useCallback"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motor-hero/ui-kit",
3
- "version": "0.15.1",
3
+ "version": "0.16.1",
4
4
  "description": "Componentes React reutilizáveis para o ecossistema MotorHero — shadcn/ui + Tailwind CSS v4",
5
5
  "author": "MotorHero",
6
6
  "license": "UNLICENSED",
@@ -58,8 +58,10 @@
58
58
  "@radix-ui/react-alert-dialog": "^1.1.0",
59
59
  "@radix-ui/react-dialog": "^1.1.0",
60
60
  "@radix-ui/react-dropdown-menu": "^2.1.0",
61
+ "@radix-ui/react-popover": "^1.1.16",
61
62
  "@radix-ui/react-slot": "^1.1.0",
62
63
  "class-variance-authority": "^0.7.0",
64
+ "cmdk": "^1.1.1",
63
65
  "sonner": "^2.0.7"
64
66
  },
65
67
  "devDependencies": {
@@ -0,0 +1,112 @@
1
+ import * as PopoverPrimitive from "@radix-ui/react-popover"
2
+ import { Command as CommandPrimitive } from "cmdk"
3
+ import { Check, ChevronsUpDown, Search } from "lucide-react"
4
+ import * as React from "react"
5
+ import { cn } from "../lib/utils"
6
+
7
+ export interface ComboboxOption {
8
+ value: string
9
+ label: string
10
+ disabled?: boolean
11
+ }
12
+
13
+ export interface ComboboxProps {
14
+ options: ComboboxOption[]
15
+ value?: string
16
+ onChange: (value: string) => void
17
+ placeholder?: string
18
+ searchPlaceholder?: string
19
+ emptyMessage?: string
20
+ disabled?: boolean
21
+ id?: string
22
+ className?: string
23
+ "aria-invalid"?: boolean | "true" | "false"
24
+ "aria-describedby"?: string
25
+ }
26
+
27
+ export function Combobox({
28
+ options,
29
+ value,
30
+ onChange,
31
+ placeholder = "Selecione...",
32
+ searchPlaceholder = "Buscar...",
33
+ emptyMessage = "Nenhum resultado encontrado.",
34
+ disabled,
35
+ id,
36
+ className,
37
+ "aria-invalid": ariaInvalid,
38
+ "aria-describedby": ariaDescribedby,
39
+ }: ComboboxProps) {
40
+ const [open, setOpen] = React.useState(false)
41
+ const selected = options.find((option) => option.value === value)
42
+
43
+ return (
44
+ <PopoverPrimitive.Root open={open} onOpenChange={setOpen} modal>
45
+ <PopoverPrimitive.Trigger asChild>
46
+ <button
47
+ type="button"
48
+ id={id}
49
+ role="combobox"
50
+ aria-expanded={open}
51
+ aria-invalid={ariaInvalid}
52
+ aria-describedby={ariaDescribedby}
53
+ disabled={disabled}
54
+ className={cn(
55
+ "flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive",
56
+ className,
57
+ )}
58
+ >
59
+ <span
60
+ className={cn("truncate", !selected && "text-muted-foreground")}
61
+ >
62
+ {selected ? selected.label : placeholder}
63
+ </span>
64
+ <ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50" />
65
+ </button>
66
+ </PopoverPrimitive.Trigger>
67
+ <PopoverPrimitive.Portal>
68
+ <PopoverPrimitive.Content
69
+ align="start"
70
+ sideOffset={4}
71
+ className="z-50 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-md"
72
+ style={{ width: "var(--radix-popover-trigger-width)" }}
73
+ >
74
+ <CommandPrimitive className="flex h-full w-full flex-col overflow-hidden">
75
+ <div className="flex items-center border-b px-3">
76
+ <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
77
+ <CommandPrimitive.Input
78
+ placeholder={searchPlaceholder}
79
+ className="flex h-9 w-full bg-transparent py-2 text-sm outline-none placeholder:text-muted-foreground"
80
+ />
81
+ </div>
82
+ <CommandPrimitive.List className="max-h-60 overflow-y-auto overflow-x-hidden p-1">
83
+ <CommandPrimitive.Empty className="py-6 text-center text-sm text-muted-foreground">
84
+ {emptyMessage}
85
+ </CommandPrimitive.Empty>
86
+ {options.map((option) => (
87
+ <CommandPrimitive.Item
88
+ key={option.value}
89
+ value={option.label}
90
+ disabled={option.disabled}
91
+ onSelect={() => {
92
+ onChange(option.value)
93
+ setOpen(false)
94
+ }}
95
+ className="relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 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"
96
+ >
97
+ <Check
98
+ className={cn(
99
+ "h-4 w-4 shrink-0",
100
+ value === option.value ? "opacity-100" : "opacity-0",
101
+ )}
102
+ />
103
+ <span className="truncate">{option.label}</span>
104
+ </CommandPrimitive.Item>
105
+ ))}
106
+ </CommandPrimitive.List>
107
+ </CommandPrimitive>
108
+ </PopoverPrimitive.Content>
109
+ </PopoverPrimitive.Portal>
110
+ </PopoverPrimitive.Root>
111
+ )
112
+ }
package/src/index.ts CHANGED
@@ -19,6 +19,8 @@ export { Pagination } from "./components/pagination"
19
19
  export { TableSkeleton } from "./components/table-skeleton"
20
20
  export { SearchInput } from "./components/search-input"
21
21
  export { PasswordInput } from "./components/password-input"
22
+ export { Combobox } from "./components/combobox"
23
+ export type { ComboboxOption, ComboboxProps } from "./components/combobox"
22
24
  export { StatCard } from "./components/stat-card"
23
25
  export { DataTableWrapper } from "./components/data-table-wrapper"
24
26
  export { MobileCardList } from "./components/mobile-card-list"