Merge pull request #43 from JurunenseDevInterno/feat-expandir-analitico
fix: botão de baximizar e minimizar
This commit is contained in:
commit
b6f13df57a
|
|
@ -34,6 +34,7 @@
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
|
"vaul": "^1.1.2",
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -11778,6 +11779,19 @@
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vaul": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-dialog": "^1.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/when-exit": {
|
"node_modules/when-exit": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.4.tgz",
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
|
"vaul": "^1.1.2",
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,17 @@ import {
|
||||||
SelectItem,
|
SelectItem,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Download, Filter, X, Search, ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react";
|
import {
|
||||||
|
Drawer,
|
||||||
|
DrawerClose,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerDescription,
|
||||||
|
DrawerFooter,
|
||||||
|
DrawerHeader,
|
||||||
|
DrawerTitle,
|
||||||
|
DrawerTrigger,
|
||||||
|
} from "@/components/ui/drawer";
|
||||||
|
import { Download, Filter, X, Search, ArrowUpDown, ArrowUp, ArrowDown, Maximize2, Minimize2 } from "lucide-react";
|
||||||
import * as XLSX from "xlsx";
|
import * as XLSX from "xlsx";
|
||||||
|
|
||||||
interface AnaliticoItem {
|
interface AnaliticoItem {
|
||||||
|
|
@ -295,6 +305,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
const [globalFilter, setGlobalFilter] = React.useState("");
|
const [globalFilter, setGlobalFilter] = React.useState("");
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [drawerOpen, setDrawerOpen] = React.useState(false);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<Record<string, string[]>>({});
|
const [columnFilters, setColumnFilters] = React.useState<Record<string, string[]>>({});
|
||||||
const [columnSorts, setColumnSorts] = React.useState<Record<string, 'asc' | 'desc' | null>>({});
|
const [columnSorts, setColumnSorts] = React.useState<Record<string, 'asc' | 'desc' | null>>({});
|
||||||
const [conditions, setConditions] = React.useState([
|
const [conditions, setConditions] = React.useState([
|
||||||
|
|
@ -810,23 +821,13 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
setGlobalFilter("");
|
setGlobalFilter("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Função para renderizar o conteúdo principal do componente (reutilizável)
|
||||||
|
const renderAnaliticoContent = (isMaximized: boolean = false) => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-none mx-auto p-2" style={{ overflowAnchor: 'none' }}>
|
<>
|
||||||
{/* Header Section */}
|
{/* Filtros Externos Ativos */}
|
||||||
<div className="mb-2">
|
|
||||||
<div className="flex items-center justify-between mb-1">
|
|
||||||
<div>
|
|
||||||
<h1 className="text-2xl font-bold text-gray-900">
|
|
||||||
Análise Analítica{filtros.linhaSelecionada ? ` - ${filtros.linhaSelecionada}` : ""}
|
|
||||||
</h1>
|
|
||||||
<p className="text-sm text-gray-500">
|
|
||||||
Relatório detalhado de transações
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Filtros Externos Ativos - Centralizado */}
|
|
||||||
{(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
|
{(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||||
<span className="text-sm font-medium text-blue-900">Filtros aplicados pela tabela DRE Gerencial:</span>
|
<span className="text-sm font-medium text-blue-900">Filtros aplicados pela tabela DRE Gerencial:</span>
|
||||||
<div className="flex flex-wrap gap-2 text-xs text-blue-800">
|
<div className="flex flex-wrap gap-2 text-xs text-blue-800">
|
||||||
|
|
@ -855,39 +856,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Controls */}
|
{/* Controls */}
|
||||||
<div className="flex gap-2 flex-wrap">
|
<div className="flex gap-2 flex-wrap mb-4">
|
||||||
{/* <Input
|
|
||||||
placeholder="Filtrar tudo..."
|
|
||||||
value={globalFilter ?? ""}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
setGlobalFilter(e.target.value)
|
|
||||||
}
|
|
||||||
className="w-64 bg-white border-gray-300 focus:border-blue-500 focus:ring-blue-500"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => setOpen(true)}
|
|
||||||
className="bg-white border-gray-300 hover:bg-blue-50 hover:border-blue-300 text-gray-700"
|
|
||||||
>
|
|
||||||
<Filter className="w-4 h-4 mr-2" />
|
|
||||||
Filtros Avançados
|
|
||||||
</Button> */}
|
|
||||||
{globalFilter && (
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onClick={clearFilters}
|
|
||||||
className="bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700 flex items-center gap-2"
|
|
||||||
>
|
|
||||||
<X className="w-4 h-4" />
|
|
||||||
Limpar Filtros
|
|
||||||
{getFilterCount() > 0 && (
|
|
||||||
<span className="bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center font-semibold">
|
|
||||||
{getFilterCount()}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
{data.length > 0 && (
|
{data.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
onClick={clearAllFilters}
|
onClick={clearAllFilters}
|
||||||
|
|
@ -915,13 +884,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
Exportar XLSX
|
Exportar XLSX
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* DataGridPro */}
|
{/* DataGridPro */}
|
||||||
<Card className="w-full h-[40vh] shadow-lg rounded-2xl" style={{ overflowAnchor: 'none' }}>
|
<Card className={`w-full shadow-lg rounded-2xl ${isMaximized ? 'h-[calc(96vh-280px)]' : 'h-[40vh]'}`} style={{ overflowAnchor: 'none' }}>
|
||||||
<CardContent className="p-4 h-full" style={{ overflowAnchor: 'none' }}>
|
<CardContent className="p-4 h-full" style={{ overflowAnchor: 'none' }}>
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
|
|
@ -1109,7 +1074,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Card de Agregação Customizado - Usando position: sticky */}
|
{/* Card de Agregação Customizado */}
|
||||||
{sortedAndFilteredData.length > 0 && (
|
{sortedAndFilteredData.length > 0 && (
|
||||||
<div
|
<div
|
||||||
ref={setAggregationCardRef}
|
ref={setAggregationCardRef}
|
||||||
|
|
@ -1167,10 +1132,164 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full max-w-none mx-auto p-2" style={{ overflowAnchor: 'none' }}>
|
||||||
|
{/* Header Section */}
|
||||||
|
<div className="mb-2">
|
||||||
|
<div className="flex items-center justify-between mb-1">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold text-gray-900">
|
||||||
|
Análise Analítica{filtros.linhaSelecionada ? ` - ${filtros.linhaSelecionada}` : ""}
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
Relatório detalhado de transações
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Filtros Externos Ativos - Centralizado */}
|
||||||
|
{(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||||
|
<span className="text-sm font-medium text-blue-900">Filtros aplicados pela tabela DRE Gerencial:</span>
|
||||||
|
<div className="flex flex-wrap gap-2 text-xs text-blue-800">
|
||||||
|
{filtrosExternos.dataInicio && filtrosExternos.dataFim && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Período: {filtrosExternos.dataInicio} a {filtrosExternos.dataFim}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtrosExternos.centroCusto && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Centro: {filtrosExternos.centroCusto}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtrosExternos.codigoGrupo && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Grupo: {filtrosExternos.codigoGrupo}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtrosExternos.codigoConta && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Conta: {filtrosExternos.codigoConta}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Controls */}
|
||||||
|
<div className="flex gap-2 flex-wrap">
|
||||||
|
{/* <Input
|
||||||
|
placeholder="Filtrar tudo..."
|
||||||
|
value={globalFilter ?? ""}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
setGlobalFilter(e.target.value)
|
||||||
|
}
|
||||||
|
className="w-64 bg-white border-gray-300 focus:border-blue-500 focus:ring-blue-500"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setOpen(true)}
|
||||||
|
className="bg-white border-gray-300 hover:bg-blue-50 hover:border-blue-300 text-gray-700"
|
||||||
|
>
|
||||||
|
<Filter className="w-4 h-4 mr-2" />
|
||||||
|
Filtros Avançados
|
||||||
|
</Button> */}
|
||||||
|
{globalFilter && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={clearFilters}
|
||||||
|
className="bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700 flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<X className="w-4 h-4" />
|
||||||
|
Limpar Filtros
|
||||||
|
{getFilterCount() > 0 && (
|
||||||
|
<span className="bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center font-semibold">
|
||||||
|
{getFilterCount()}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{data.length > 0 && (
|
||||||
|
<Button
|
||||||
|
onClick={clearAllFilters}
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
Limpar Filtros
|
||||||
|
{getFilterCount() > 0 && (
|
||||||
|
<span className="bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center font-semibold">
|
||||||
|
{getFilterCount()}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
onClick={exportToExcel}
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
disabled={sortedAndFilteredData.length === 0}
|
||||||
|
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-green-50 hover:border-green-300 text-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
<Download className="h-4 w-4" />
|
||||||
|
Exportar XLSX
|
||||||
|
</Button>
|
||||||
|
<Drawer open={drawerOpen} onOpenChange={setDrawerOpen}>
|
||||||
|
<DrawerTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-blue-50 hover:border-blue-300 text-gray-700"
|
||||||
|
>
|
||||||
|
<Maximize2 className="h-4 w-4" />
|
||||||
|
Maximizar
|
||||||
|
</Button>
|
||||||
|
</DrawerTrigger>
|
||||||
|
<DrawerContent className="max-h-[96vh] h-[96vh]">
|
||||||
|
<DrawerHeader className="flex-shrink-0">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex-1">
|
||||||
|
<DrawerTitle className="text-2xl font-bold text-gray-900">
|
||||||
|
Análise Analítica{filtros.linhaSelecionada ? ` - ${filtros.linhaSelecionada}` : ""}
|
||||||
|
</DrawerTitle>
|
||||||
|
<DrawerDescription>
|
||||||
|
Relatório detalhado de transações - Versão Maximizada
|
||||||
|
</DrawerDescription>
|
||||||
|
</div>
|
||||||
|
<DrawerClose asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="flex items-center gap-2 bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700"
|
||||||
|
>
|
||||||
|
<Minimize2 className="h-4 w-4" />
|
||||||
|
Minimizar
|
||||||
|
</Button>
|
||||||
|
</DrawerClose>
|
||||||
|
</div>
|
||||||
|
</DrawerHeader>
|
||||||
|
<div className="flex-1 overflow-y-auto px-4 pb-4">
|
||||||
|
{renderAnaliticoContent(true)}
|
||||||
|
</div>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Conteúdo Principal - Versão Normal */}
|
||||||
|
{renderAnaliticoContent(false)}
|
||||||
|
|
||||||
{/* Advanced Filters Dialog */}
|
{/* Advanced Filters Dialog */}
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import { Drawer as DrawerPrimitive } from "vaul"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Drawer = DrawerPrimitive.Root
|
||||||
|
|
||||||
|
const DrawerTrigger = DrawerPrimitive.Trigger
|
||||||
|
|
||||||
|
const DrawerClose = DrawerPrimitive.Close
|
||||||
|
|
||||||
|
const DrawerPortal = DrawerPrimitive.Portal
|
||||||
|
|
||||||
|
const DrawerOverlay = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DrawerPrimitive.Overlay>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DrawerPrimitive.Overlay
|
||||||
|
ref={ref}
|
||||||
|
className={cn("fixed inset-0 z-50 bg-black/80", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
|
||||||
|
|
||||||
|
const DrawerContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DrawerPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<DrawerPortal>
|
||||||
|
<DrawerOverlay />
|
||||||
|
<DrawerPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
|
||||||
|
{children}
|
||||||
|
</DrawerPrimitive.Content>
|
||||||
|
</DrawerPortal>
|
||||||
|
))
|
||||||
|
DrawerContent.displayName = "DrawerContent"
|
||||||
|
|
||||||
|
const DrawerHeader = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
DrawerHeader.displayName = "DrawerHeader"
|
||||||
|
|
||||||
|
const DrawerFooter = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
DrawerFooter.displayName = "DrawerFooter"
|
||||||
|
|
||||||
|
const DrawerTitle = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DrawerPrimitive.Title>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DrawerPrimitive.Title
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"text-lg font-semibold leading-none tracking-tight",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DrawerTitle.displayName = DrawerPrimitive.Title.displayName
|
||||||
|
|
||||||
|
const DrawerDescription = React.forwardRef<
|
||||||
|
React.ElementRef<typeof DrawerPrimitive.Description>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<DrawerPrimitive.Description
|
||||||
|
ref={ref}
|
||||||
|
className={cn("text-sm text-muted-foreground", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
|
||||||
|
|
||||||
|
export {
|
||||||
|
Drawer,
|
||||||
|
DrawerPortal,
|
||||||
|
DrawerOverlay,
|
||||||
|
DrawerTrigger,
|
||||||
|
DrawerClose,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerHeader,
|
||||||
|
DrawerFooter,
|
||||||
|
DrawerTitle,
|
||||||
|
DrawerDescription,
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue