@nccirtu/tablefy 0.7.3 → 0.7.5

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.
@@ -9,7 +9,9 @@ interface DataTableHeaderProps<TData> {
9
9
  onSearchChange?: (value: string) => void;
10
10
  table?: TanstackTable<TData>;
11
11
  selectedCount?: number;
12
+ enableColumnVisibility?: boolean;
13
+ columnVisibilityLabel?: string;
12
14
  className?: string;
13
15
  }
14
- export declare function DataTableHeader<TData>({ title, description, actions, search, searchValue, onSearchChange, table, selectedCount, className, }: DataTableHeaderProps<TData>): import("react/jsx-runtime").JSX.Element;
16
+ export declare function DataTableHeader<TData>({ title, description, actions, search, searchValue, onSearchChange, table, selectedCount, enableColumnVisibility, columnVisibilityLabel, className, }: DataTableHeaderProps<TData>): import("react/jsx-runtime").JSX.Element;
15
17
  export {};
@@ -34,6 +34,7 @@ export interface DataTableConfig<TData> {
34
34
  desc: boolean;
35
35
  };
36
36
  enableColumnVisibility?: boolean;
37
+ columnVisibilityLabel?: string;
37
38
  density?: "compact" | "default" | "comfortable";
38
39
  bordered?: boolean;
39
40
  striped?: boolean;
@@ -6,6 +6,8 @@ export interface BaseColumnConfig<TData> {
6
6
  sortable?: boolean;
7
7
  searchable?: boolean;
8
8
  hidden?: boolean;
9
+ visibleByDefault?: boolean;
10
+ visibilityLabel?: string;
9
11
  align?: "left" | "center" | "right";
10
12
  width?: string | number;
11
13
  className?: string;
@@ -4,5 +4,7 @@ export interface ConfirmOptions {
4
4
  confirmLabel?: string;
5
5
  cancelLabel?: string;
6
6
  variant?: "destructive" | "default";
7
+ icon?: React.ReactNode;
8
+ image?: string;
7
9
  }
8
10
  export type ConfirmHandler = (options: ConfirmOptions) => Promise<boolean>;
package/dist/index.esm.js CHANGED
@@ -5,16 +5,16 @@ import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from '@
5
5
  import { cn } from '@/lib/utils';
6
6
  import { Button } from '@/components/ui/button';
7
7
  import { Input } from '@/components/ui/input';
8
- import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '@/components/ui/dropdown-menu';
9
- import { Search, X, ChevronDown, ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight, ArrowUpDown, Calendar, ExternalLink } from 'lucide-react';
8
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuCheckboxItem, DropdownMenuItem } from '@/components/ui/dropdown-menu';
9
+ import { Search, X, Columns, ChevronDown, ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight, ArrowUpDown, Calendar, ExternalLink } from 'lucide-react';
10
10
  import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@/components/ui/select';
11
11
  import { Badge } from '@/components/ui/badge';
12
12
  import { Checkbox } from '@/components/ui/checkbox';
13
13
  import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
14
14
  import { Progress } from '@/components/ui/progress';
15
- import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
15
+ import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from '@/components/ui/alert-dialog';
16
16
 
17
- function DataTableHeader({ title, description, actions = [], search, searchValue = "", onSearchChange, table, selectedCount = 0, className, }) {
17
+ function DataTableHeader({ title, description, actions = [], search, searchValue = "", onSearchChange, table, selectedCount = 0, enableColumnVisibility = false, columnVisibilityLabel = "Spalten", className, }) {
18
18
  const normalActions = actions.filter((a) => !a.bulk && !a.hidden);
19
19
  const bulkActions = actions.filter((a) => a.bulk && !a.hidden);
20
20
  const showBulkActions = selectedCount > 0 && bulkActions.length > 0;
@@ -48,7 +48,14 @@ function DataTableHeader({ title, description, actions = [], search, searchValue
48
48
  return null;
49
49
  }
50
50
  return (jsxs("div", { className: cn("flex flex-col gap-4", className), children: [(title || description) && (jsxs("div", { className: "space-y-1", children: [title && (jsx("h2", { className: "text-xl font-semibold tracking-tight", children: title })), description && (jsx("p", { className: "text-sm text-muted-foreground", children: description }))] })), (search?.enabled || normalActions.length > 0 || showBulkActions) && (jsxs("div", { className: "flex items-center justify-between gap-4 mb-4", children: [search?.enabled && (jsxs("div", { className: "relative max-w-sm flex-1", children: [jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), jsx(Input, { placeholder: search.placeholder || "Suchen...", value: searchValue, onChange: (e) => onSearchChange?.(e.target.value), className: "pl-9 pr-9" }), searchValue && (jsx("button", { onClick: () => onSearchChange?.(""), className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground", children: jsx(X, { className: "h-4 w-4" }) }))] })), jsxs("div", { className: "flex items-center gap-2", children: [showBulkActions && (jsxs("span", { className: "text-sm text-muted-foreground", children: [selectedCount, " ausgew\u00E4hlt"] })), showBulkActions &&
51
- bulkActions.map((action, index) => renderAction(action, index)), normalActions.length > 0 &&
51
+ bulkActions.map((action, index) => renderAction(action, index)), enableColumnVisibility && table && (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "outline", size: "default", children: [jsx(Columns, { className: "h-4 w-4" }), jsx("span", { className: "ml-2", children: columnVisibilityLabel }), jsx(ChevronDown, { className: "ml-2 h-4 w-4" })] }) }), jsxs(DropdownMenuContent, { align: "end", className: "w-[200px]", children: [jsx(DropdownMenuLabel, { children: columnVisibilityLabel }), jsx(DropdownMenuSeparator, {}), table
52
+ .getAllColumns()
53
+ .filter((column) => column.getCanHide())
54
+ .map((column) => {
55
+ const meta = column.columnDef.meta;
56
+ const label = meta?.visibilityLabel || column.id;
57
+ return (jsx(DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange: (value) => column.toggleVisibility(!!value), children: label }, column.id));
58
+ })] })] })), normalActions.length > 0 &&
52
59
  normalActions.map((action, index) => renderAction(action, index))] })] }))] }));
53
60
  }
54
61
 
@@ -374,7 +381,16 @@ class EmptyStateBuilder {
374
381
  function DataTable({ columns, data, config = {}, className, isLoading = false, isError = false, onRetry, }) {
375
382
  const [sorting, setSorting] = useState(config.defaultSort ? [config.defaultSort] : []);
376
383
  const [columnFilters, setColumnFilters] = useState([]);
377
- const [columnVisibility, setColumnVisibility] = useState({});
384
+ // Initialize column visibility based on visibleByDefault
385
+ const [columnVisibility, setColumnVisibility] = useState(() => {
386
+ const initialVisibility = {};
387
+ columns.forEach((column) => {
388
+ if (column.meta?.visibleByDefault === false) {
389
+ initialVisibility[column.accessorKey || column.id] = false;
390
+ }
391
+ });
392
+ return initialVisibility;
393
+ });
378
394
  const [rowSelection, setRowSelection] = useState({});
379
395
  const [globalFilter, setGlobalFilter] = useState("");
380
396
  const table = useReactTable({
@@ -422,7 +438,7 @@ function DataTable({ columns, data, config = {}, className, isLoading = false, i
422
438
  };
423
439
  const selectedCount = table.getFilteredSelectedRowModel().rows.length;
424
440
  const hasRows = table.getRowModel().rows?.length > 0;
425
- return (jsxs("div", { className: cn("flex flex-col", className), children: [jsx(DataTableHeader, { title: config.title, description: config.description, actions: config.headerActions, search: config.search, searchValue: globalFilter, onSearchChange: setGlobalFilter, table: table, selectedCount: selectedCount }), jsx("div", { className: cn("overflow-hidden", config.bordered !== false && "rounded-md border"), children: jsxs(Table, { className: cn(densityClasses[config.density || "default"], config.striped ? "[&_tr:nth-child(even)]:bg-muted/50" : "", config.hoverable !== false && "[&_tr:hover]:bg-muted/50"), children: [jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => (jsx(TableRow, { children: headerGroup.headers.map((header) => (jsx(TableHead, { children: header.isPlaceholder
441
+ return (jsxs("div", { className: cn("flex flex-col", className), children: [jsx(DataTableHeader, { title: config.title, description: config.description, actions: config.headerActions, search: config.search, searchValue: globalFilter, onSearchChange: setGlobalFilter, table: table, selectedCount: selectedCount, enableColumnVisibility: config.enableColumnVisibility, columnVisibilityLabel: config.columnVisibilityLabel }), jsx("div", { className: cn("overflow-hidden", config.bordered !== false && "rounded-md border"), children: jsxs(Table, { className: cn(densityClasses[config.density || "default"], config.striped ? "[&_tr:nth-child(even)]:bg-muted/50" : "", config.hoverable !== false && "[&_tr:hover]:bg-muted/50"), children: [jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => (jsx(TableRow, { children: headerGroup.headers.map((header) => (jsx(TableHead, { children: header.isPlaceholder
426
442
  ? null
427
443
  : flexRender(header.column.columnDef.header, header.getContext()) }, header.id))) }, headerGroup.id))) }), jsx(TableBody, { children: isLoading ? (jsx("tr", { children: jsx("td", { colSpan: columns.length, className: "h-[400px]", children: jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "flex flex-col items-center gap-4", children: [jsxs("svg", { className: "animate-spin h-8 w-8 text-muted-foreground", viewBox: "0 0 24 24", children: [jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }), jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }), jsx("span", { className: "text-sm text-muted-foreground", children: "Laden..." })] }) }) }) })) : hasRows ? (table.getRowModel().rows.map((row) => (jsx(TableRow, { "data-state": row.getIsSelected() && "selected", children: row.getVisibleCells().map((cell) => (jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id)))) : (jsx(DataTableEmpty, { config: getEmptyState(), colSpan: columns.length })) })] }) }), config.pagination?.enabled && hasRows && (jsx(DataTablePagination, { table: table, config: config.pagination }))] }));
428
444
  }
@@ -464,6 +480,14 @@ class BaseColumn {
464
480
  this.config.hidden = hidden;
465
481
  return this;
466
482
  }
483
+ visibleByDefault(visible = true) {
484
+ this.config.visibleByDefault = visible;
485
+ return this;
486
+ }
487
+ visibilityLabel(label) {
488
+ this.config.visibilityLabel = label;
489
+ return this;
490
+ }
467
491
  alignLeft() {
468
492
  this.config.align = "left";
469
493
  return this;
@@ -1726,7 +1750,10 @@ function ConfirmProvider({ children }) {
1726
1750
  setQueue((q) => q.slice(1));
1727
1751
  }
1728
1752
  };
1729
- return (jsxs(Fragment, { children: [children, jsx(Dialog, { open: !!currentRequest, onOpenChange: (open) => !open && handleCancel(), children: jsxs(DialogContent, { children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: currentRequest?.options?.title || "Bestätigung erforderlich" }), currentRequest?.options?.description && (jsx(DialogDescription, { children: currentRequest.options.description }))] }), jsxs(DialogFooter, { children: [jsx(Button, { variant: "outline", onClick: handleCancel, children: currentRequest?.options.cancelLabel || "Abbrechen" }), jsx(Button, { variant: currentRequest?.options.variant || "default", onClick: handleConfirm, children: currentRequest?.options.confirmLabel || "Bestätigen" })] })] }) })] }));
1753
+ const { title, description, confirmLabel, cancelLabel, variant, icon, image, } = currentRequest?.options || {};
1754
+ return (jsxs(Fragment, { children: [children, jsx(AlertDialog, { open: !!currentRequest, onOpenChange: (open) => !open && handleCancel(), children: jsxs(AlertDialogContent, { className: "max-w-md", children: [jsxs(AlertDialogHeader, { children: [image && (jsx("div", { className: "mb-4 flex justify-center", children: jsx("img", { src: image, alt: "Confirmation", className: "h-24 w-24 object-contain" }) })), icon && !image && (jsx("div", { className: "mb-4 flex justify-center text-6xl", children: icon })), jsx(AlertDialogTitle, { className: "text-center", children: title || "Bestätigung erforderlich" }), description && (jsx(AlertDialogDescription, { className: "text-center", children: description }))] }), jsxs(AlertDialogFooter, { className: "sm:justify-center", children: [jsx(AlertDialogCancel, { onClick: handleCancel, children: cancelLabel || "Abbrechen" }), jsx(AlertDialogAction, { onClick: handleConfirm, className: variant === "destructive"
1755
+ ? "bg-destructive text-destructive-foreground hover:bg-destructive/90"
1756
+ : "", children: confirmLabel || "Bestätigen" })] })] }) })] }));
1730
1757
  }
1731
1758
 
1732
1759
  export { AvatarGroupColumn, BadgeColumn, ButtonColumn, CheckboxColumn, ConfirmProvider, DataTable, DataTableSchema, DateColumn, DropdownColumn, EmptyStateBuilder, EnumColumn, IconColumn, ImageColumn, InputColumn, LinkColumn, NumberColumn, ProgressColumn, SelectColumn, TableSchema, AvatarGroupColumn as avatarGroupColumn, BadgeColumn as badgeColumn, ButtonColumn as buttonColumn, CheckboxColumn as checkboxColumn, confirm, DateColumn as dateColumn, DropdownColumn as dropdownColumn, EnumColumn as enumColumn, IconColumn as iconColumn, InputColumn as inputColumn };