.
This commit is contained in:
parent
99f8b5fb8e
commit
07047f9984
@ -1,12 +1,26 @@
|
||||
import { Button, Separator, Tooltip, TooltipContent, TooltipTrigger } from '@repo/shadcn-ui/components'
|
||||
import { cn } from '@repo/shadcn-ui/lib/utils'
|
||||
import { Table } from "@tanstack/react-table"
|
||||
import { ArrowDownIcon, ArrowUpIcon, CopyPlusIcon, PlusIcon, ScanIcon, TrashIcon } from 'lucide-react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from "../../locales/i18n.ts"
|
||||
import { DataTableViewOptions } from './data-table-view-options.tsx'
|
||||
import { DataTableMeta } from './data-table.tsx'
|
||||
import {
|
||||
Button,
|
||||
Separator,
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@repo/shadcn-ui/components";
|
||||
import { cn } from "@repo/shadcn-ui/lib/utils";
|
||||
import type { Table } from "@tanstack/react-table";
|
||||
import {
|
||||
ArrowDownIcon,
|
||||
ArrowUpIcon,
|
||||
CopyPlusIcon,
|
||||
PlusIcon,
|
||||
ScanIcon,
|
||||
TrashIcon,
|
||||
} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
import { useTranslation } from "../../locales/i18n.ts";
|
||||
|
||||
import type { DataTableMeta } from "./data-table.tsx";
|
||||
import { DataTableViewOptions } from "./data-table-view-options.tsx";
|
||||
|
||||
interface DataTableToolbarProps<TData> {
|
||||
table: Table<TData>;
|
||||
@ -17,7 +31,7 @@ interface DataTableToolbarProps<TData> {
|
||||
export function DataTableToolbar<TData>({
|
||||
table,
|
||||
showViewOptions = true,
|
||||
className
|
||||
className,
|
||||
}: DataTableToolbarProps<TData>) {
|
||||
const { t } = useTranslation();
|
||||
const meta = table.options.meta as DataTableMeta<TData> | undefined;
|
||||
@ -32,10 +46,7 @@ export function DataTableToolbar<TData>({
|
||||
const hasSelection = selectedCount > 0;
|
||||
|
||||
// Índices seleccionados (memoizado)
|
||||
const selectedIndexes = React.useMemo(
|
||||
() => selectedRows.map((r) => r.index),
|
||||
[selectedRows]
|
||||
);
|
||||
const selectedIndexes = React.useMemo(() => selectedRows.map((r) => r.index), [selectedRows]);
|
||||
|
||||
const handleAdd = React.useCallback(() => {
|
||||
if (!readOnly) meta?.tableOps?.onAdd?.(table);
|
||||
@ -63,25 +74,20 @@ export function DataTableToolbar<TData>({
|
||||
|
||||
// Render principal
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-between gap-2 py-2 bg-transparent",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className={cn("flex items-center justify-between gap-2 py-2 bg-transparent", className)}>
|
||||
{/* IZQUIERDA: acciones + contador */}
|
||||
<div className="flex flex-1 items-center gap-3 flex-wrap">
|
||||
{/* Botón añadir */}
|
||||
{!readOnly && meta?.tableOps?.onAdd && (
|
||||
<Button
|
||||
className='cursor-pointer'
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={'outline'}
|
||||
onClick={handleAdd}
|
||||
aria-label={t("components.datatable.actions.add")}
|
||||
className="cursor-pointer"
|
||||
onClick={handleAdd}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant={"outline"}
|
||||
>
|
||||
<PlusIcon className="size-4 mr-1" aria-hidden="true" />
|
||||
<PlusIcon aria-hidden="true" className="size-4 mr-1" />
|
||||
<span>{t("components.datatable.actions.add")}</span>
|
||||
</Button>
|
||||
)}
|
||||
@ -89,18 +95,18 @@ export function DataTableToolbar<TData>({
|
||||
{/* Acciones sobre selección */}
|
||||
{hasSelection && (
|
||||
<>
|
||||
<Separator orientation="vertical" className="h-5 mx-1" />
|
||||
<Separator className="h-5 mx-1" orientation="vertical" />
|
||||
|
||||
{!readOnly && meta?.bulkOps?.duplicateSelected && (
|
||||
<Button
|
||||
className='cursor-pointer'
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleDuplicateSelected}
|
||||
aria-label={t("components.datatable.actions.duplicate")}
|
||||
className="cursor-pointer"
|
||||
onClick={handleDuplicateSelected}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<CopyPlusIcon className="size-4 mr-1" aria-hidden="true" />
|
||||
<CopyPlusIcon aria-hidden="true" className="size-4 mr-1" />
|
||||
<span>{t("components.datatable.actions.duplicate")}</span>
|
||||
</Button>
|
||||
)}
|
||||
@ -109,18 +115,16 @@ export function DataTableToolbar<TData>({
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleMoveSelectedUp}
|
||||
aria-label={t("components.datatable.actions.move_up")}
|
||||
onClick={handleMoveSelectedUp}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<ArrowUpIcon className="size-4" aria-hidden="true" />
|
||||
<ArrowUpIcon aria-hidden="true" className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t("components.datatable.actions.move_up")}
|
||||
</TooltipContent>
|
||||
<TooltipContent>{t("components.datatable.actions.move_up")}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@ -128,71 +132,56 @@ export function DataTableToolbar<TData>({
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleMoveSelectedDown}
|
||||
aria-label={t("components.datatable.actions.move_down")}
|
||||
onClick={handleMoveSelectedDown}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<ArrowDownIcon className="size-4" aria-hidden="true" />
|
||||
<ArrowDownIcon aria-hidden="true" className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t("components.datatable.actions.move_down")}
|
||||
</TooltipContent>
|
||||
<TooltipContent>{t("components.datatable.actions.move_down")}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{!readOnly && meta?.bulkOps?.removeSelected && (
|
||||
<>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
className="h-5 mx-1 w-[1px] bg-red-500/70"
|
||||
/>
|
||||
<Separator className="h-5 mx-1 w-[1px] bg-red-500/70" orientation="vertical" />
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
onClick={handleRemoveSelected}
|
||||
aria-label={t("components.datatable.actions.remove")}
|
||||
onClick={handleRemoveSelected}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="destructive"
|
||||
>
|
||||
<TrashIcon className="size-4 mr-1" aria-hidden="true" />
|
||||
<TrashIcon aria-hidden="true" className="size-4 mr-1" />
|
||||
<span>{t("components.datatable.actions.remove")}</span>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Separator orientation="vertical" className="h-6 mx-1 bg-muted/50" />
|
||||
<Separator className="h-6 mx-1 bg-muted/50" orientation="vertical" />
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleClearSelection}
|
||||
>
|
||||
<ScanIcon className="size-4 mr-1" aria-hidden="true" />
|
||||
<Button onClick={handleClearSelection} size="sm" type="button" variant="outline">
|
||||
<ScanIcon aria-hidden="true" className="size-4 mr-1" />
|
||||
<span>{t("components.datatable.actions.clear_selection")}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t("components.datatable.actions.clear_selection")}
|
||||
</TooltipContent>
|
||||
<TooltipContent>{t("components.datatable.actions.clear_selection")}</TooltipContent>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Contador de selección */}
|
||||
<div
|
||||
className="text-sm text-muted-foreground ml-2"
|
||||
aria-live="polite"
|
||||
>
|
||||
<div aria-live="polite" className="text-sm text-muted-foreground ml-2">
|
||||
{hasSelection
|
||||
? t("components.datatable.selection_summary", {
|
||||
count: selectedCount,
|
||||
total: totalCount,
|
||||
})
|
||||
count: selectedCount,
|
||||
total: totalCount,
|
||||
})
|
||||
: t("components.datatable.selection_none", { total: totalCount })}
|
||||
</div>
|
||||
</div>
|
||||
@ -205,4 +194,4 @@ export function DataTableToolbar<TData>({
|
||||
);
|
||||
}
|
||||
|
||||
export const MemoizedDataTableToolbar = React.memo(DataTableToolbar) as typeof DataTableToolbar;
|
||||
export const MemoizedDataTableToolbar = React.memo(DataTableToolbar) as typeof DataTableToolbar;
|
||||
|
||||
@ -189,7 +189,7 @@ export function DataTable<TData, TValue>({
|
||||
<div className="overflow-hidden rounded-md border">
|
||||
<TableComp className="w-full text-sm">
|
||||
{/* CABECERA */}
|
||||
<TableHeader className="sticky top-0 z-10 bg-muted">
|
||||
<TableHeader className="sticky top-0 z-10 bg-muted/50">
|
||||
{table.getHeaderGroups().map((hg) => (
|
||||
<TableRow key={hg.id}>
|
||||
{hg.headers.map((h) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user