@motor-hero/ui-kit 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/row-actions-menu.d.ts +19 -0
- package/dist/components/row-actions-menu.d.ts.map +1 -0
- package/dist/index.cjs +62 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/mode-toggle.tsx +2 -2
- package/src/components/row-actions-menu.tsx +86 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { RenderLink } from "./types";
|
|
3
|
+
export interface RowAction {
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
onClick?: () => void;
|
|
7
|
+
href?: string;
|
|
8
|
+
destructive?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface RowActionsMenuProps {
|
|
12
|
+
actions: RowAction[];
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
align?: "start" | "center" | "end";
|
|
15
|
+
label?: string;
|
|
16
|
+
renderLink?: RenderLink;
|
|
17
|
+
}
|
|
18
|
+
export declare function RowActionsMenu({ actions, disabled, align, label, renderLink, }: RowActionsMenuProps): import("react/jsx-runtime").JSX.Element | null;
|
|
19
|
+
//# sourceMappingURL=row-actions-menu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-actions-menu.d.ts","sourceRoot":"","sources":["../../src/components/row-actions-menu.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB;AAKD,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,QAAgB,EAChB,KAAa,EACb,KAAe,EACf,UAA8B,GAC/B,EAAE,mBAAmB,kDAoDrB"}
|
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
PageHeader: () => PageHeader,
|
|
43
43
|
Pagination: () => Pagination,
|
|
44
44
|
ResponsiveDataView: () => ResponsiveDataView,
|
|
45
|
+
RowActionsMenu: () => RowActionsMenu,
|
|
45
46
|
SearchInput: () => SearchInput,
|
|
46
47
|
SidebarNav: () => SidebarNav,
|
|
47
48
|
StatCard: () => StatCard,
|
|
@@ -115,11 +116,11 @@ function ModeToggle() {
|
|
|
115
116
|
"button",
|
|
116
117
|
{
|
|
117
118
|
type: "button",
|
|
118
|
-
className: "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",
|
|
119
|
+
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",
|
|
119
120
|
"aria-label": "Alternar tema",
|
|
120
121
|
children: [
|
|
121
122
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Sun, { className: "h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" }),
|
|
122
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Moon, { className: "absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" })
|
|
123
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Moon, { className: "absolute inset-0 m-auto h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" })
|
|
123
124
|
]
|
|
124
125
|
}
|
|
125
126
|
) }),
|
|
@@ -772,6 +773,64 @@ function AppShell({
|
|
|
772
773
|
] });
|
|
773
774
|
}
|
|
774
775
|
|
|
776
|
+
// src/components/row-actions-menu.tsx
|
|
777
|
+
var DropdownMenu3 = __toESM(require("@radix-ui/react-dropdown-menu"), 1);
|
|
778
|
+
var import_lucide_react4 = require("lucide-react");
|
|
779
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
780
|
+
var itemClass2 = "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";
|
|
781
|
+
function RowActionsMenu({
|
|
782
|
+
actions,
|
|
783
|
+
disabled = false,
|
|
784
|
+
align = "end",
|
|
785
|
+
label = "A\xE7\xF5es",
|
|
786
|
+
renderLink = defaultRenderLink
|
|
787
|
+
}) {
|
|
788
|
+
if (actions.length === 0) return null;
|
|
789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu3.Root, { children: [
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenu3.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
791
|
+
"button",
|
|
792
|
+
{
|
|
793
|
+
type: "button",
|
|
794
|
+
disabled,
|
|
795
|
+
"aria-label": label,
|
|
796
|
+
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",
|
|
797
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react4.MoreVertical, { className: "h-4 w-4" })
|
|
798
|
+
}
|
|
799
|
+
) }),
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenu3.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
801
|
+
DropdownMenu3.Content,
|
|
802
|
+
{
|
|
803
|
+
align,
|
|
804
|
+
sideOffset: 6,
|
|
805
|
+
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",
|
|
806
|
+
children: actions.map((action) => {
|
|
807
|
+
const cls = cn(itemClass2, action.destructive && "text-destructive focus:bg-destructive/10");
|
|
808
|
+
return action.href ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenu3.Item, { asChild: true, disabled: action.disabled, children: renderLink({
|
|
809
|
+
href: action.href,
|
|
810
|
+
className: cls,
|
|
811
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
812
|
+
action.icon,
|
|
813
|
+
action.label
|
|
814
|
+
] })
|
|
815
|
+
}) }, action.label) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
816
|
+
DropdownMenu3.Item,
|
|
817
|
+
{
|
|
818
|
+
className: cls,
|
|
819
|
+
disabled: action.disabled,
|
|
820
|
+
onClick: action.onClick,
|
|
821
|
+
children: [
|
|
822
|
+
action.icon,
|
|
823
|
+
action.label
|
|
824
|
+
]
|
|
825
|
+
},
|
|
826
|
+
action.label
|
|
827
|
+
);
|
|
828
|
+
})
|
|
829
|
+
}
|
|
830
|
+
) })
|
|
831
|
+
] });
|
|
832
|
+
}
|
|
833
|
+
|
|
775
834
|
// src/lib/api-error.ts
|
|
776
835
|
function extractApiError(err, fallbackMessage = "Ocorreu um erro inesperado.") {
|
|
777
836
|
const detail = err?.body?.detail || err?.message;
|
|
@@ -830,6 +889,7 @@ function useCustomToast() {
|
|
|
830
889
|
PageHeader,
|
|
831
890
|
Pagination,
|
|
832
891
|
ResponsiveDataView,
|
|
892
|
+
RowActionsMenu,
|
|
833
893
|
SearchInput,
|
|
834
894
|
SidebarNav,
|
|
835
895
|
StatCard,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../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/form-field.tsx","../src/components/form-dialog.tsx","../src/components/auth-card.tsx","../src/components/pagination.tsx","../src/components/table-skeleton.tsx","../src/components/search-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/lib/utils.ts","../src/components/sidebar-nav.tsx","../src/components/types.tsx","../src/components/user-menu.tsx","../src/lib/api-error.ts","../src/hooks/use-disclosure.ts","../src/hooks/use-toast.ts"],"sourcesContent":["// Theme\nexport { ThemeProvider, useTheme } from \"./components/theme-provider\"\nexport type { Theme, ThemeProviderProps, ThemeProviderState } from \"./components/theme-provider\"\n\n// Components\nexport { ModeToggle } from \"./components/mode-toggle\"\nexport { EmptyState } from \"./components/empty-state\"\nexport { ConfirmDialog } from \"./components/confirm-dialog\"\nexport { PageHeader } from \"./components/page-header\"\nexport { StatusDot } from \"./components/status-dot\"\nexport { FormField } from \"./components/form-field\"\nexport { FormDialogLayout } from \"./components/form-dialog\"\nexport { AuthCard } from \"./components/auth-card\"\nexport { Pagination } from \"./components/pagination\"\nexport { TableSkeleton } from \"./components/table-skeleton\"\nexport { SearchInput } from \"./components/search-input\"\nexport { StatCard } from \"./components/stat-card\"\nexport { DataTableWrapper } from \"./components/data-table-wrapper\"\nexport { MobileCardList } from \"./components/mobile-card-list\"\nexport { ResponsiveDataView } from \"./components/responsive-data-view\"\nexport { Toaster } from \"./components/toaster\"\n\n// App shell\nexport { AppShell } from \"./components/app-shell\"\nexport type { AppShellProps } from \"./components/app-shell\"\nexport { SidebarNav } from \"./components/sidebar-nav\"\nexport type { NavItem, SidebarNavProps } from \"./components/sidebar-nav\"\nexport { UserMenu } from \"./components/user-menu\"\nexport type { AppUser, UserMenuItem, UserMenuProps } from \"./components/user-menu\"\nexport { defaultRenderLink } from \"./components/types\"\nexport type { RenderLink, RenderLinkProps } from \"./components/types\"\n\n// Utilities\nexport { cn } from \"./lib/utils\"\nexport { extractApiError } from \"./lib/api-error\"\n\n// Hooks\nexport { useDisclosure } from \"./hooks/use-disclosure\"\nexport { useCustomToast, toast } from \"./hooks/use-toast\"\n","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=\"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 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 className={`flex items-center justify-between ${className ?? \"\"}`}>\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {action && <div>{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\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 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 {children}\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\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","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 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 { ReactNode } 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\nexport function MobileCardList<T>({\n data,\n renderCard,\n keyExtractor,\n isLoading = false,\n loadingCount = 5,\n className,\n}: MobileCardListProps<T>) {\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 className={`space-y-3 ${className ?? \"\"}`}>\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 { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\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 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","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","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","_","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Sonner","import_lucide_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","DropdownMenu","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_sonner","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../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/form-field.tsx","../src/components/form-dialog.tsx","../src/components/auth-card.tsx","../src/components/pagination.tsx","../src/components/table-skeleton.tsx","../src/components/search-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/lib/utils.ts","../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":["// Theme\nexport { ThemeProvider, useTheme } from \"./components/theme-provider\"\nexport type { Theme, ThemeProviderProps, ThemeProviderState } from \"./components/theme-provider\"\n\n// Components\nexport { ModeToggle } from \"./components/mode-toggle\"\nexport { EmptyState } from \"./components/empty-state\"\nexport { ConfirmDialog } from \"./components/confirm-dialog\"\nexport { PageHeader } from \"./components/page-header\"\nexport { StatusDot } from \"./components/status-dot\"\nexport { FormField } from \"./components/form-field\"\nexport { FormDialogLayout } from \"./components/form-dialog\"\nexport { AuthCard } from \"./components/auth-card\"\nexport { Pagination } from \"./components/pagination\"\nexport { TableSkeleton } from \"./components/table-skeleton\"\nexport { SearchInput } from \"./components/search-input\"\nexport { StatCard } from \"./components/stat-card\"\nexport { DataTableWrapper } from \"./components/data-table-wrapper\"\nexport { MobileCardList } from \"./components/mobile-card-list\"\nexport { ResponsiveDataView } from \"./components/responsive-data-view\"\nexport { Toaster } from \"./components/toaster\"\n\n// App shell\nexport { AppShell } from \"./components/app-shell\"\nexport type { AppShellProps } from \"./components/app-shell\"\nexport { SidebarNav } from \"./components/sidebar-nav\"\nexport type { NavItem, SidebarNavProps } from \"./components/sidebar-nav\"\nexport { UserMenu } from \"./components/user-menu\"\nexport type { AppUser, UserMenuItem, UserMenuProps } from \"./components/user-menu\"\nexport { RowActionsMenu } from \"./components/row-actions-menu\"\nexport type { RowAction, RowActionsMenuProps } from \"./components/row-actions-menu\"\nexport { defaultRenderLink } from \"./components/types\"\nexport type { RenderLink, RenderLinkProps } from \"./components/types\"\n\n// Utilities\nexport { cn } from \"./lib/utils\"\nexport { extractApiError } from \"./lib/api-error\"\n\n// Hooks\nexport { useDisclosure } from \"./hooks/use-disclosure\"\nexport { useCustomToast, toast } from \"./hooks/use-toast\"\n","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 className={`flex items-center justify-between ${className ?? \"\"}`}>\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {action && <div>{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\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 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 {children}\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\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","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 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 { ReactNode } 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\nexport function MobileCardList<T>({\n data,\n renderCard,\n keyExtractor,\n isLoading = false,\n loadingCount = 5,\n className,\n}: MobileCardListProps<T>) {\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 className={`space-y-3 ${className ?? \"\"}`}>\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 { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\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 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","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","_","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Sonner","import_lucide_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","DropdownMenu","import_lucide_react","import_jsx_runtime","import_jsx_runtime","DropdownMenu","import_lucide_react","import_jsx_runtime","itemClass","import_react","import_sonner","import_react"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export { SidebarNav } from "./components/sidebar-nav";
|
|
|
22
22
|
export type { NavItem, SidebarNavProps } from "./components/sidebar-nav";
|
|
23
23
|
export { UserMenu } from "./components/user-menu";
|
|
24
24
|
export type { AppUser, UserMenuItem, UserMenuProps } from "./components/user-menu";
|
|
25
|
+
export { RowActionsMenu } from "./components/row-actions-menu";
|
|
26
|
+
export type { RowAction, RowActionsMenuProps } from "./components/row-actions-menu";
|
|
25
27
|
export { defaultRenderLink } from "./components/types";
|
|
26
28
|
export type { RenderLink, RenderLinkProps } from "./components/types";
|
|
27
29
|
export { cn } from "./lib/utils";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AACrE,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAGhG,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAG9C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGrE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGjD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AACrE,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAGhG,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAG9C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGrE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGjD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -53,11 +53,11 @@ function ModeToggle() {
|
|
|
53
53
|
"button",
|
|
54
54
|
{
|
|
55
55
|
type: "button",
|
|
56
|
-
className: "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",
|
|
56
|
+
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",
|
|
57
57
|
"aria-label": "Alternar tema",
|
|
58
58
|
children: [
|
|
59
59
|
/* @__PURE__ */ jsx2(Sun, { className: "h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" }),
|
|
60
|
-
/* @__PURE__ */ jsx2(Moon, { className: "absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" })
|
|
60
|
+
/* @__PURE__ */ jsx2(Moon, { className: "absolute inset-0 m-auto h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" })
|
|
61
61
|
]
|
|
62
62
|
}
|
|
63
63
|
) }),
|
|
@@ -710,6 +710,64 @@ function AppShell({
|
|
|
710
710
|
] });
|
|
711
711
|
}
|
|
712
712
|
|
|
713
|
+
// src/components/row-actions-menu.tsx
|
|
714
|
+
import * as DropdownMenu3 from "@radix-ui/react-dropdown-menu";
|
|
715
|
+
import { MoreVertical } from "lucide-react";
|
|
716
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
717
|
+
var itemClass2 = "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";
|
|
718
|
+
function RowActionsMenu({
|
|
719
|
+
actions,
|
|
720
|
+
disabled = false,
|
|
721
|
+
align = "end",
|
|
722
|
+
label = "A\xE7\xF5es",
|
|
723
|
+
renderLink = defaultRenderLink
|
|
724
|
+
}) {
|
|
725
|
+
if (actions.length === 0) return null;
|
|
726
|
+
return /* @__PURE__ */ jsxs18(DropdownMenu3.Root, { children: [
|
|
727
|
+
/* @__PURE__ */ jsx22(DropdownMenu3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
728
|
+
"button",
|
|
729
|
+
{
|
|
730
|
+
type: "button",
|
|
731
|
+
disabled,
|
|
732
|
+
"aria-label": label,
|
|
733
|
+
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",
|
|
734
|
+
children: /* @__PURE__ */ jsx22(MoreVertical, { className: "h-4 w-4" })
|
|
735
|
+
}
|
|
736
|
+
) }),
|
|
737
|
+
/* @__PURE__ */ jsx22(DropdownMenu3.Portal, { children: /* @__PURE__ */ jsx22(
|
|
738
|
+
DropdownMenu3.Content,
|
|
739
|
+
{
|
|
740
|
+
align,
|
|
741
|
+
sideOffset: 6,
|
|
742
|
+
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",
|
|
743
|
+
children: actions.map((action) => {
|
|
744
|
+
const cls = cn(itemClass2, action.destructive && "text-destructive focus:bg-destructive/10");
|
|
745
|
+
return action.href ? /* @__PURE__ */ jsx22(DropdownMenu3.Item, { asChild: true, disabled: action.disabled, children: renderLink({
|
|
746
|
+
href: action.href,
|
|
747
|
+
className: cls,
|
|
748
|
+
children: /* @__PURE__ */ jsxs18(Fragment5, { children: [
|
|
749
|
+
action.icon,
|
|
750
|
+
action.label
|
|
751
|
+
] })
|
|
752
|
+
}) }, action.label) : /* @__PURE__ */ jsxs18(
|
|
753
|
+
DropdownMenu3.Item,
|
|
754
|
+
{
|
|
755
|
+
className: cls,
|
|
756
|
+
disabled: action.disabled,
|
|
757
|
+
onClick: action.onClick,
|
|
758
|
+
children: [
|
|
759
|
+
action.icon,
|
|
760
|
+
action.label
|
|
761
|
+
]
|
|
762
|
+
},
|
|
763
|
+
action.label
|
|
764
|
+
);
|
|
765
|
+
})
|
|
766
|
+
}
|
|
767
|
+
) })
|
|
768
|
+
] });
|
|
769
|
+
}
|
|
770
|
+
|
|
713
771
|
// src/lib/api-error.ts
|
|
714
772
|
function extractApiError(err, fallbackMessage = "Ocorreu um erro inesperado.") {
|
|
715
773
|
const detail = err?.body?.detail || err?.message;
|
|
@@ -767,6 +825,7 @@ export {
|
|
|
767
825
|
PageHeader,
|
|
768
826
|
Pagination,
|
|
769
827
|
ResponsiveDataView,
|
|
828
|
+
RowActionsMenu,
|
|
770
829
|
SearchInput,
|
|
771
830
|
SidebarNav,
|
|
772
831
|
StatCard,
|
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/form-field.tsx","../src/components/form-dialog.tsx","../src/components/auth-card.tsx","../src/components/pagination.tsx","../src/components/table-skeleton.tsx","../src/components/search-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/lib/utils.ts","../src/components/sidebar-nav.tsx","../src/components/types.tsx","../src/components/user-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=\"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 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 className={`flex items-center justify-between ${className ?? \"\"}`}>\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {action && <div>{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\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 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 {children}\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\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","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 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 { ReactNode } 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\nexport function MobileCardList<T>({\n data,\n renderCard,\n keyExtractor,\n isLoading = false,\n loadingCount = 5,\n className,\n}: MobileCardListProps<T>) {\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 className={`space-y-3 ${className ?? \"\"}`}>\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 { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\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 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","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","jsx","_","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","useState","Fragment","jsx","Fragment","jsx","jsxs","DropdownMenu","Fragment","jsx","jsxs","jsx","jsxs","useState","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/form-field.tsx","../src/components/form-dialog.tsx","../src/components/auth-card.tsx","../src/components/pagination.tsx","../src/components/table-skeleton.tsx","../src/components/search-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/lib/utils.ts","../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 className={`flex items-center justify-between ${className ?? \"\"}`}>\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {action && <div>{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\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 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 {children}\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\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","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 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 { ReactNode } 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\nexport function MobileCardList<T>({\n data,\n renderCard,\n keyExtractor,\n isLoading = false,\n loadingCount = 5,\n className,\n}: MobileCardListProps<T>) {\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 className={`space-y-3 ${className ?? \"\"}`}>\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 { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\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 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","jsx","_","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
|
@@ -10,11 +10,11 @@ export function ModeToggle() {
|
|
|
10
10
|
<DropdownMenu.Trigger asChild>
|
|
11
11
|
<button
|
|
12
12
|
type="button"
|
|
13
|
-
className="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"
|
|
13
|
+
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"
|
|
14
14
|
aria-label="Alternar tema"
|
|
15
15
|
>
|
|
16
16
|
<Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
|
17
|
-
<Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
17
|
+
<Moon className="absolute inset-0 m-auto h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
18
18
|
</button>
|
|
19
19
|
</DropdownMenu.Trigger>
|
|
20
20
|
<DropdownMenu.Portal>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
|
|
2
|
+
import { MoreVertical } from "lucide-react"
|
|
3
|
+
import type { ReactNode } from "react"
|
|
4
|
+
import { cn } from "../lib/utils"
|
|
5
|
+
import type { RenderLink } from "./types"
|
|
6
|
+
import { defaultRenderLink } from "./types"
|
|
7
|
+
|
|
8
|
+
export interface RowAction {
|
|
9
|
+
label: string
|
|
10
|
+
icon?: ReactNode
|
|
11
|
+
onClick?: () => void
|
|
12
|
+
href?: string
|
|
13
|
+
destructive?: boolean
|
|
14
|
+
disabled?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface RowActionsMenuProps {
|
|
18
|
+
actions: RowAction[]
|
|
19
|
+
disabled?: boolean
|
|
20
|
+
align?: "start" | "center" | "end"
|
|
21
|
+
label?: string
|
|
22
|
+
renderLink?: RenderLink
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const itemClass =
|
|
26
|
+
"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"
|
|
27
|
+
|
|
28
|
+
export function RowActionsMenu({
|
|
29
|
+
actions,
|
|
30
|
+
disabled = false,
|
|
31
|
+
align = "end",
|
|
32
|
+
label = "Ações",
|
|
33
|
+
renderLink = defaultRenderLink,
|
|
34
|
+
}: RowActionsMenuProps) {
|
|
35
|
+
if (actions.length === 0) return null
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<DropdownMenu.Root>
|
|
39
|
+
<DropdownMenu.Trigger asChild>
|
|
40
|
+
<button
|
|
41
|
+
type="button"
|
|
42
|
+
disabled={disabled}
|
|
43
|
+
aria-label={label}
|
|
44
|
+
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"
|
|
45
|
+
>
|
|
46
|
+
<MoreVertical className="h-4 w-4" />
|
|
47
|
+
</button>
|
|
48
|
+
</DropdownMenu.Trigger>
|
|
49
|
+
<DropdownMenu.Portal>
|
|
50
|
+
<DropdownMenu.Content
|
|
51
|
+
align={align}
|
|
52
|
+
sideOffset={6}
|
|
53
|
+
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"
|
|
54
|
+
>
|
|
55
|
+
{actions.map((action) => {
|
|
56
|
+
const cls = cn(itemClass, action.destructive && "text-destructive focus:bg-destructive/10")
|
|
57
|
+
return action.href ? (
|
|
58
|
+
<DropdownMenu.Item key={action.label} asChild disabled={action.disabled}>
|
|
59
|
+
{renderLink({
|
|
60
|
+
href: action.href,
|
|
61
|
+
className: cls,
|
|
62
|
+
children: (
|
|
63
|
+
<>
|
|
64
|
+
{action.icon}
|
|
65
|
+
{action.label}
|
|
66
|
+
</>
|
|
67
|
+
),
|
|
68
|
+
})}
|
|
69
|
+
</DropdownMenu.Item>
|
|
70
|
+
) : (
|
|
71
|
+
<DropdownMenu.Item
|
|
72
|
+
key={action.label}
|
|
73
|
+
className={cls}
|
|
74
|
+
disabled={action.disabled}
|
|
75
|
+
onClick={action.onClick}
|
|
76
|
+
>
|
|
77
|
+
{action.icon}
|
|
78
|
+
{action.label}
|
|
79
|
+
</DropdownMenu.Item>
|
|
80
|
+
)
|
|
81
|
+
})}
|
|
82
|
+
</DropdownMenu.Content>
|
|
83
|
+
</DropdownMenu.Portal>
|
|
84
|
+
</DropdownMenu.Root>
|
|
85
|
+
)
|
|
86
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,8 @@ export { SidebarNav } from "./components/sidebar-nav"
|
|
|
27
27
|
export type { NavItem, SidebarNavProps } from "./components/sidebar-nav"
|
|
28
28
|
export { UserMenu } from "./components/user-menu"
|
|
29
29
|
export type { AppUser, UserMenuItem, UserMenuProps } from "./components/user-menu"
|
|
30
|
+
export { RowActionsMenu } from "./components/row-actions-menu"
|
|
31
|
+
export type { RowAction, RowActionsMenuProps } from "./components/row-actions-menu"
|
|
30
32
|
export { defaultRenderLink } from "./components/types"
|
|
31
33
|
export type { RenderLink, RenderLinkProps } from "./components/types"
|
|
32
34
|
|