@nccirtu/tablefy 0.7.2 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ var tooltip = require('@/components/ui/tooltip');
16
16
  var progress = require('@/components/ui/progress');
17
17
  var dialog = require('@/components/ui/dialog');
18
18
 
19
- function DataTableHeader({ title, description, actions = [], search, searchValue = "", onSearchChange, table, selectedCount = 0, className, }) {
19
+ function DataTableHeader({ title, description, actions = [], search, searchValue = "", onSearchChange, table, selectedCount = 0, enableColumnVisibility = false, columnVisibilityLabel = "Spalten", className, }) {
20
20
  const normalActions = actions.filter((a) => !a.bulk && !a.hidden);
21
21
  const bulkActions = actions.filter((a) => a.bulk && !a.hidden);
22
22
  const showBulkActions = selectedCount > 0 && bulkActions.length > 0;
@@ -50,7 +50,14 @@ function DataTableHeader({ title, description, actions = [], search, searchValue
50
50
  return null;
51
51
  }
52
52
  return (jsxRuntime.jsxs("div", { className: utils.cn("flex flex-col gap-4", className), children: [(title || description) && (jsxRuntime.jsxs("div", { className: "space-y-1", children: [title && (jsxRuntime.jsx("h2", { className: "text-xl font-semibold tracking-tight", children: title })), description && (jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: description }))] })), (search?.enabled || normalActions.length > 0 || showBulkActions) && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 mb-4", children: [search?.enabled && (jsxRuntime.jsxs("div", { className: "relative max-w-sm flex-1", children: [jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), jsxRuntime.jsx(input.Input, { placeholder: search.placeholder || "Suchen...", value: searchValue, onChange: (e) => onSearchChange?.(e.target.value), className: "pl-9 pr-9" }), searchValue && (jsxRuntime.jsx("button", { onClick: () => onSearchChange?.(""), className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground", children: jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }) }))] })), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [showBulkActions && (jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [selectedCount, " ausgew\u00E4hlt"] })), showBulkActions &&
53
- bulkActions.map((action, index) => renderAction(action, index)), normalActions.length > 0 &&
53
+ bulkActions.map((action, index) => renderAction(action, index)), enableColumnVisibility && table && (jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsxs(button.Button, { variant: "outline", size: "default", children: [jsxRuntime.jsx(lucideReact.Columns, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "ml-2", children: columnVisibilityLabel }), jsxRuntime.jsx(lucideReact.ChevronDown, { className: "ml-2 h-4 w-4" })] }) }), jsxRuntime.jsxs(dropdownMenu.DropdownMenuContent, { align: "end", className: "w-[200px]", children: [jsxRuntime.jsx(dropdownMenu.DropdownMenuLabel, { children: columnVisibilityLabel }), jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}), table
54
+ .getAllColumns()
55
+ .filter((column) => column.getCanHide())
56
+ .map((column) => {
57
+ const meta = column.columnDef.meta;
58
+ const label = meta?.visibilityLabel || column.id;
59
+ return (jsxRuntime.jsx(dropdownMenu.DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange: (value) => column.toggleVisibility(!!value), children: label }, column.id));
60
+ })] })] })), normalActions.length > 0 &&
54
61
  normalActions.map((action, index) => renderAction(action, index))] })] }))] }));
55
62
  }
56
63
 
@@ -376,7 +383,16 @@ class EmptyStateBuilder {
376
383
  function DataTable({ columns, data, config = {}, className, isLoading = false, isError = false, onRetry, }) {
377
384
  const [sorting, setSorting] = react.useState(config.defaultSort ? [config.defaultSort] : []);
378
385
  const [columnFilters, setColumnFilters] = react.useState([]);
379
- const [columnVisibility, setColumnVisibility] = react.useState({});
386
+ // Initialize column visibility based on visibleByDefault
387
+ const [columnVisibility, setColumnVisibility] = react.useState(() => {
388
+ const initialVisibility = {};
389
+ columns.forEach((column) => {
390
+ if (column.meta?.visibleByDefault === false) {
391
+ initialVisibility[column.accessorKey || column.id] = false;
392
+ }
393
+ });
394
+ return initialVisibility;
395
+ });
380
396
  const [rowSelection, setRowSelection] = react.useState({});
381
397
  const [globalFilter, setGlobalFilter] = react.useState("");
382
398
  const table$1 = reactTable.useReactTable({
@@ -424,7 +440,7 @@ function DataTable({ columns, data, config = {}, className, isLoading = false, i
424
440
  };
425
441
  const selectedCount = table$1.getFilteredSelectedRowModel().rows.length;
426
442
  const hasRows = table$1.getRowModel().rows?.length > 0;
427
- return (jsxRuntime.jsxs("div", { className: utils.cn("flex flex-col", className), children: [jsxRuntime.jsx(DataTableHeader, { title: config.title, description: config.description, actions: config.headerActions, search: config.search, searchValue: globalFilter, onSearchChange: setGlobalFilter, table: table$1, selectedCount: selectedCount }), jsxRuntime.jsx("div", { className: utils.cn("overflow-hidden", config.bordered !== false && "rounded-md border"), children: jsxRuntime.jsxs(table.Table, { className: utils.cn(densityClasses[config.density || "default"], config.striped ? "[&_tr:nth-child(even)]:bg-muted/50" : "", config.hoverable !== false && "[&_tr:hover]:bg-muted/50"), children: [jsxRuntime.jsx(table.TableHeader, { children: table$1.getHeaderGroups().map((headerGroup) => (jsxRuntime.jsx(table.TableRow, { children: headerGroup.headers.map((header) => (jsxRuntime.jsx(table.TableHead, { children: header.isPlaceholder
443
+ return (jsxRuntime.jsxs("div", { className: utils.cn("flex flex-col", className), children: [jsxRuntime.jsx(DataTableHeader, { title: config.title, description: config.description, actions: config.headerActions, search: config.search, searchValue: globalFilter, onSearchChange: setGlobalFilter, table: table$1, selectedCount: selectedCount, enableColumnVisibility: config.enableColumnVisibility, columnVisibilityLabel: config.columnVisibilityLabel }), jsxRuntime.jsx("div", { className: utils.cn("overflow-hidden", config.bordered !== false && "rounded-md border"), children: jsxRuntime.jsxs(table.Table, { className: utils.cn(densityClasses[config.density || "default"], config.striped ? "[&_tr:nth-child(even)]:bg-muted/50" : "", config.hoverable !== false && "[&_tr:hover]:bg-muted/50"), children: [jsxRuntime.jsx(table.TableHeader, { children: table$1.getHeaderGroups().map((headerGroup) => (jsxRuntime.jsx(table.TableRow, { children: headerGroup.headers.map((header) => (jsxRuntime.jsx(table.TableHead, { children: header.isPlaceholder
428
444
  ? null
429
445
  : reactTable.flexRender(header.column.columnDef.header, header.getContext()) }, header.id))) }, headerGroup.id))) }), jsxRuntime.jsx(table.TableBody, { children: isLoading ? (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { colSpan: columns.length, className: "h-[400px]", children: jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4", children: [jsxRuntime.jsxs("svg", { className: "animate-spin h-8 w-8 text-muted-foreground", viewBox: "0 0 24 24", children: [jsxRuntime.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }), jsxRuntime.jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }), jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Laden..." })] }) }) }) })) : hasRows ? (table$1.getRowModel().rows.map((row) => (jsxRuntime.jsx(table.TableRow, { "data-state": row.getIsSelected() && "selected", children: row.getVisibleCells().map((cell) => (jsxRuntime.jsx(table.TableCell, { children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id)))) : (jsxRuntime.jsx(DataTableEmpty, { config: getEmptyState(), colSpan: columns.length })) })] }) }), config.pagination?.enabled && hasRows && (jsxRuntime.jsx(DataTablePagination, { table: table$1, config: config.pagination }))] }));
430
446
  }
@@ -466,6 +482,14 @@ class BaseColumn {
466
482
  this.config.hidden = hidden;
467
483
  return this;
468
484
  }
485
+ visibleByDefault(visible = true) {
486
+ this.config.visibleByDefault = visible;
487
+ return this;
488
+ }
489
+ visibilityLabel(label) {
490
+ this.config.visibilityLabel = label;
491
+ return this;
492
+ }
469
493
  alignLeft() {
470
494
  this.config.align = "left";
471
495
  return this;
@@ -1598,60 +1622,70 @@ class SelectColumn extends BaseColumn {
1598
1622
  }
1599
1623
  }
1600
1624
 
1601
- class TextColumn extends BaseColumn {
1625
+ class EnumColumn extends BaseColumn {
1626
+ constructor(accessor) {
1627
+ super(accessor);
1628
+ this.config.asBadge = true;
1629
+ this.config.showIcon = true;
1630
+ this.config.iconPosition = "left";
1631
+ }
1602
1632
  static make(accessor) {
1603
- return new TextColumn(accessor);
1633
+ return new EnumColumn(accessor);
1604
1634
  }
1605
- formatter(fn) {
1606
- this.config.formatter = fn;
1635
+ /**
1636
+ * Define the enum options with labels, icons, and colors
1637
+ */
1638
+ options(options) {
1639
+ this.config.options = options;
1607
1640
  return this;
1608
1641
  }
1609
- prefix(prefix) {
1610
- this.config.prefix = prefix;
1642
+ /**
1643
+ * Display as plain text instead of badge
1644
+ */
1645
+ asText() {
1646
+ this.config.asBadge = false;
1611
1647
  return this;
1612
1648
  }
1613
- suffix(suffix) {
1614
- this.config.suffix = suffix;
1649
+ /**
1650
+ * Display as badge (default)
1651
+ */
1652
+ asBadge() {
1653
+ this.config.asBadge = true;
1615
1654
  return this;
1616
1655
  }
1617
- placeholder(placeholder) {
1618
- this.config.placeholder = placeholder;
1656
+ /**
1657
+ * Hide icons
1658
+ */
1659
+ hideIcon() {
1660
+ this.config.showIcon = false;
1619
1661
  return this;
1620
1662
  }
1621
- // Shortcuts für gängige Formatierungen
1622
- uppercase() {
1623
- const existingFormatter = this.config.formatter;
1624
- this.config.formatter = (value, row) => {
1625
- const result = existingFormatter ? existingFormatter(value, row) : value;
1626
- return typeof result === "string"
1627
- ? result.toUpperCase()
1628
- : result;
1629
- };
1663
+ /**
1664
+ * Show icons (default)
1665
+ */
1666
+ showIcon() {
1667
+ this.config.showIcon = true;
1630
1668
  return this;
1631
1669
  }
1632
- lowercase() {
1633
- const existingFormatter = this.config.formatter;
1634
- this.config.formatter = (value, row) => {
1635
- const result = existingFormatter ? existingFormatter(value, row) : value;
1636
- return typeof result === "string"
1637
- ? result.toLowerCase()
1638
- : result;
1639
- };
1670
+ /**
1671
+ * Set icon position
1672
+ */
1673
+ iconPosition(position) {
1674
+ this.config.iconPosition = position;
1640
1675
  return this;
1641
1676
  }
1642
- limit(chars) {
1643
- const existingFormatter = this.config.formatter;
1644
- this.config.formatter = (value, row) => {
1645
- const result = existingFormatter ? existingFormatter(value, row) : value;
1646
- if (typeof result === "string" && result.length > chars) {
1647
- return result.slice(0, chars) + "...";
1648
- }
1649
- return result;
1650
- };
1677
+ /**
1678
+ * Placeholder for unknown values
1679
+ */
1680
+ placeholder(placeholder) {
1681
+ this.config.placeholder = placeholder;
1651
1682
  return this;
1652
1683
  }
1653
1684
  build() {
1654
- const { accessor, label, sortable, prefix, suffix, placeholder, formatter, } = this.config;
1685
+ const { accessor, label, sortable, options, asBadge, showIcon, iconPosition, placeholder, } = this.config;
1686
+ if (!options || options.length === 0) {
1687
+ throw new Error(`EnumColumn "${String(accessor)}" requires options to be defined`);
1688
+ }
1655
1689
  return {
1656
1690
  accessorKey: accessor,
1657
1691
  header: ({ column }) => {
@@ -1661,92 +1695,22 @@ class TextColumn extends BaseColumn {
1661
1695
  }
1662
1696
  return (jsxRuntime.jsxs(button.Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: utils.cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsxRuntime.jsx(lucideReact.ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
1663
1697
  },
1664
- cell: ({ row, getValue }) => {
1665
- let value = getValue();
1666
- // Custom Formatter anwenden
1667
- if (formatter) {
1668
- value = formatter(value, row);
1669
- }
1670
- // Placeholder wenn leer
1671
- if (value === null || value === undefined || value === "") {
1698
+ cell: ({ getValue }) => {
1699
+ const value = getValue();
1700
+ // Find matching option
1701
+ const option = options.find((opt) => opt.value === value);
1702
+ // Handle unknown values
1703
+ if (!option) {
1672
1704
  return (jsxRuntime.jsx("span", { className: utils.cn("text-muted-foreground", this.getAlignmentClass(), this.config.cellClassName), children: placeholder || "—" }));
1673
1705
  }
1674
- // Prefix/Suffix hinzufügen
1675
- const displayValue = `${prefix || ""}${value}${suffix || ""}`;
1676
- return (jsxRuntime.jsx("span", { className: utils.cn(this.getAlignmentClass(), this.config.cellClassName), children: displayValue }));
1677
- },
1678
- };
1679
- }
1680
- }
1681
-
1682
- class ActionsColumn {
1683
- config = {
1684
- actions: [],
1685
- label: "Aktionen",
1686
- };
1687
- static make() {
1688
- return new ActionsColumn();
1689
- }
1690
- label(label) {
1691
- this.config.label = label;
1692
- return this;
1693
- }
1694
- triggerIcon(icon) {
1695
- this.config.triggerIcon = icon;
1696
- return this;
1697
- }
1698
- // Action hinzufügen
1699
- action(action) {
1700
- this.config.actions.push(action);
1701
- return this;
1702
- }
1703
- // Shortcuts für gängige Actions
1704
- view(onClick) {
1705
- return this.action({ label: "Anzeigen", onClick });
1706
- }
1707
- edit(onClick) {
1708
- return this.action({ label: "Bearbeiten", onClick });
1709
- }
1710
- delete(onClick) {
1711
- return this.action({
1712
- label: "Löschen",
1713
- onClick,
1714
- variant: "destructive",
1715
- separator: true,
1716
- });
1717
- }
1718
- link(label, href) {
1719
- return this.action({ label, href });
1720
- }
1721
- separator() {
1722
- if (this.config.actions.length > 0) {
1723
- this.config.actions[this.config.actions.length - 1].separator = true;
1724
- }
1725
- return this;
1726
- }
1727
- build() {
1728
- const { actions, label, triggerIcon } = this.config;
1729
- return {
1730
- id: "actions",
1731
- header: () => jsxRuntime.jsx("span", { className: "sr-only", children: label }),
1732
- cell: ({ row }) => {
1733
- const data = row.original;
1734
- const visibleActions = actions.filter((action) => !action.hidden || !action.hidden(data));
1735
- if (visibleActions.length === 0)
1736
- return null;
1737
- return (jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsxs(button.Button, { variant: "ghost", className: "h-10 w-10 p-0", children: [jsxRuntime.jsx("span", { className: "sr-only", children: label }), triggerIcon || jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "h-8 w-8" })] }) }), jsxRuntime.jsx(dropdownMenu.DropdownMenuContent, { align: "end", children: visibleActions.map((action, index) => (jsxRuntime.jsxs("div", { children: [action.render ? (
1738
- // Custom render function takes priority
1739
- action.render(data)) : (
1740
- // Standard menu item
1741
- jsxRuntime.jsxs(dropdownMenu.DropdownMenuItem, { disabled: action.disabled?.(data), className: utils.cn(action.variant === "destructive" &&
1742
- "text-destructive focus:text-destructive"), onClick: () => {
1743
- if (action.href) {
1744
- window.location.href = action.href(data);
1745
- }
1746
- else if (action.onClick) {
1747
- action.onClick(data);
1748
- }
1749
- }, children: [action.icon && (jsxRuntime.jsx("span", { className: "mr-2", children: action.icon })), action.label] })), action.separator && index < visibleActions.length - 1 && (jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}))] }, index))) })] }));
1706
+ const Icon = option.icon;
1707
+ const iconElement = showIcon && Icon ? jsxRuntime.jsx(Icon, { className: "h-4 w-4" }) : null;
1708
+ // Render as Badge
1709
+ if (asBadge) {
1710
+ return (jsxRuntime.jsx("div", { className: utils.cn(this.getAlignmentClass(), this.config.cellClassName), children: jsxRuntime.jsxs(badge.Badge, { variant: option.color || "default", className: utils.cn("inline-flex items-center gap-1.5", option.className), children: [iconPosition === "left" && iconElement, option.label, iconPosition === "right" && iconElement] }) }));
1711
+ }
1712
+ // Render as plain text with icon
1713
+ return (jsxRuntime.jsxs("div", { className: utils.cn("inline-flex items-center gap-2", this.getAlignmentClass(), this.config.cellClassName, option.className), children: [iconPosition === "left" && iconElement, jsxRuntime.jsx("span", { children: option.label }), iconPosition === "right" && iconElement] }));
1750
1714
  },
1751
1715
  };
1752
1716
  }
@@ -1791,7 +1755,6 @@ function ConfirmProvider({ children }) {
1791
1755
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [children, jsxRuntime.jsx(dialog.Dialog, { open: !!currentRequest, onOpenChange: (open) => !open && handleCancel(), children: jsxRuntime.jsxs(dialog.DialogContent, { children: [jsxRuntime.jsxs(dialog.DialogHeader, { children: [jsxRuntime.jsx(dialog.DialogTitle, { children: currentRequest?.options?.title || "Bestätigung erforderlich" }), currentRequest?.options?.description && (jsxRuntime.jsx(dialog.DialogDescription, { children: currentRequest.options.description }))] }), jsxRuntime.jsxs(dialog.DialogFooter, { children: [jsxRuntime.jsx(button.Button, { variant: "outline", onClick: handleCancel, children: currentRequest?.options.cancelLabel || "Abbrechen" }), jsxRuntime.jsx(button.Button, { variant: currentRequest?.options.variant || "default", onClick: handleConfirm, children: currentRequest?.options.confirmLabel || "Bestätigen" })] })] }) })] }));
1792
1756
  }
1793
1757
 
1794
- exports.ActionsColumn = ActionsColumn;
1795
1758
  exports.AvatarGroupColumn = AvatarGroupColumn;
1796
1759
  exports.BadgeColumn = BadgeColumn;
1797
1760
  exports.ButtonColumn = ButtonColumn;
@@ -1802,6 +1765,7 @@ exports.DataTableSchema = DataTableSchema;
1802
1765
  exports.DateColumn = DateColumn;
1803
1766
  exports.DropdownColumn = DropdownColumn;
1804
1767
  exports.EmptyStateBuilder = EmptyStateBuilder;
1768
+ exports.EnumColumn = EnumColumn;
1805
1769
  exports.IconColumn = IconColumn;
1806
1770
  exports.ImageColumn = ImageColumn;
1807
1771
  exports.InputColumn = InputColumn;
@@ -1810,7 +1774,6 @@ exports.NumberColumn = NumberColumn;
1810
1774
  exports.ProgressColumn = ProgressColumn;
1811
1775
  exports.SelectColumn = SelectColumn;
1812
1776
  exports.TableSchema = TableSchema;
1813
- exports.TextColumn = TextColumn;
1814
1777
  exports.avatarGroupColumn = AvatarGroupColumn;
1815
1778
  exports.badgeColumn = BadgeColumn;
1816
1779
  exports.buttonColumn = ButtonColumn;
@@ -1818,9 +1781,7 @@ exports.checkboxColumn = CheckboxColumn;
1818
1781
  exports.confirm = confirm;
1819
1782
  exports.dateColumn = DateColumn;
1820
1783
  exports.dropdownColumn = DropdownColumn;
1784
+ exports.enumColumn = EnumColumn;
1821
1785
  exports.iconColumn = IconColumn;
1822
1786
  exports.inputColumn = InputColumn;
1823
- exports.progressColumn = ProgressColumn;
1824
- exports.selectColumn = SelectColumn;
1825
- exports.textColumn = TextColumn;
1826
1787
  //# sourceMappingURL=index.js.map