ikoncomponents 1.7.6 → 1.8.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.
Files changed (149) hide show
  1. package/dist/ikoncomponents/action-menu/index.d.ts +2 -1
  2. package/dist/ikoncomponents/activity-sheet/index.d.ts +2 -1
  3. package/dist/ikoncomponents/app-breadcrumb/BreadcrumbProvider.d.ts +1 -1
  4. package/dist/ikoncomponents/app-breadcrumb/index.d.ts +2 -2
  5. package/dist/ikoncomponents/big-calendar/big-calender-event/index.d.ts +1 -1
  6. package/dist/ikoncomponents/big-calendar/big-calender-toolbar/index.d.ts +1 -1
  7. package/dist/ikoncomponents/big-calendar/index.d.ts +1 -1
  8. package/dist/ikoncomponents/buttons/index.d.ts +6 -6
  9. package/dist/ikoncomponents/combobox-input/index.d.ts +2 -1
  10. package/dist/ikoncomponents/custom-combo-dropdown/index.d.ts +1 -1
  11. package/dist/ikoncomponents/data-table/datatable-column-filter/index.d.ts +2 -1
  12. package/dist/ikoncomponents/data-table/datatable-faceted-filter/index.d.ts +2 -1
  13. package/dist/ikoncomponents/data-table/datatable-filter-menu/index.d.ts +2 -1
  14. package/dist/ikoncomponents/data-table/datatable-pagination/index.d.ts +2 -1
  15. package/dist/ikoncomponents/data-table/datatable-toolbar/index.d.ts +2 -1
  16. package/dist/ikoncomponents/data-table/index.d.ts +2 -1
  17. package/dist/ikoncomponents/file-input/index.d.ts +2 -1
  18. package/dist/ikoncomponents/fileUpload/index.d.ts +2 -1
  19. package/dist/ikoncomponents/form-fields/combobox-input/index.d.ts +2 -1
  20. package/dist/ikoncomponents/form-fields/combobox-input-value/index.d.ts +2 -1
  21. package/dist/ikoncomponents/form-fields/date-input/index.d.ts +2 -1
  22. package/dist/ikoncomponents/form-fields/file-input/index.d.ts +2 -1
  23. package/dist/ikoncomponents/form-fields/input/index.d.ts +2 -1
  24. package/dist/ikoncomponents/form-fields/multi-combobox-input/index.d.ts +2 -1
  25. package/dist/ikoncomponents/form-fields/otp-input/index.d.ts +2 -1
  26. package/dist/ikoncomponents/form-fields/phone-input/index.d.ts +2 -1
  27. package/dist/ikoncomponents/form-fields/textarea/index.d.ts +2 -1
  28. package/dist/ikoncomponents/glowing-effect/index.d.ts +2 -1
  29. package/dist/ikoncomponents/icon/index.d.ts +2 -1
  30. package/dist/ikoncomponents/image-cropper-upload/cropper-form/index.d.ts +1 -1
  31. package/dist/ikoncomponents/image-cropper-upload/cropper-form-with-modal/index.d.ts +2 -1
  32. package/dist/ikoncomponents/image-cropper-upload/index.d.ts +2 -2
  33. package/dist/ikoncomponents/loading-spinner/index.d.ts +1 -1
  34. package/dist/ikoncomponents/main-layout/RefreshContext.d.ts +1 -1
  35. package/dist/ikoncomponents/main-layout/SidebarNavContext.d.ts +1 -1
  36. package/dist/ikoncomponents/main-layout/app-sidebar.d.ts +1 -1
  37. package/dist/ikoncomponents/main-layout/app-sidebar.js +4 -1
  38. package/dist/ikoncomponents/main-layout/footer.d.ts +2 -1
  39. package/dist/ikoncomponents/main-layout/footer.js +4 -1
  40. package/dist/ikoncomponents/main-layout/header.d.ts +2 -1
  41. package/dist/ikoncomponents/main-layout/header.js +4 -1
  42. package/dist/ikoncomponents/main-layout/index.d.ts +1 -1
  43. package/dist/ikoncomponents/main-layout/index.js +9 -2
  44. package/dist/ikoncomponents/main-layout/main-sidebar.d.ts +2 -1
  45. package/dist/ikoncomponents/main-layout/main-sidebar.js +39 -22
  46. package/dist/ikoncomponents/main-layout/nav-main.d.ts +1 -1
  47. package/dist/ikoncomponents/main-layout/sidebar-expanded-context.d.ts +20 -0
  48. package/dist/ikoncomponents/main-layout/sidebar-expanded-context.js +25 -0
  49. package/dist/ikoncomponents/multi-combobox/index.d.ts +2 -1
  50. package/dist/ikoncomponents/no-data/index.d.ts +2 -1
  51. package/dist/ikoncomponents/page-wrapper/index.d.ts +2 -2
  52. package/dist/ikoncomponents/password-strength-meter/index.d.ts +2 -1
  53. package/dist/ikoncomponents/phone-input/index.d.ts +2 -1
  54. package/dist/ikoncomponents/provider-wrapper/index.d.ts +1 -1
  55. package/dist/ikoncomponents/reload-component/index.d.ts +1 -1
  56. package/dist/ikoncomponents/search-input/index.d.ts +2 -1
  57. package/dist/ikoncomponents/sheet/index.d.ts +1 -1
  58. package/dist/ikoncomponents/simple-widget/index.d.ts +2 -2
  59. package/dist/ikoncomponents/skeleton-loader/skeleton-table.d.ts +1 -1
  60. package/dist/ikoncomponents/skeleton-loader/skeleton-widget.d.ts +1 -1
  61. package/dist/ikoncomponents/table/DataTable/index.d.ts +3 -2
  62. package/dist/ikoncomponents/table/DataTable/index.js +296 -60
  63. package/dist/ikoncomponents/table/DataTableColumn/index.d.ts +3 -0
  64. package/dist/ikoncomponents/table/DataTableColumn/index.js +17 -0
  65. package/dist/ikoncomponents/table/DataTableFilter/index.d.ts +7 -0
  66. package/dist/ikoncomponents/table/DataTableFilter/index.js +95 -0
  67. package/dist/ikoncomponents/table/DataTablePageSize/index.d.ts +1 -1
  68. package/dist/ikoncomponents/table/DataTablePageSize/index.js +2 -0
  69. package/dist/ikoncomponents/table/DataTablePagination/index.d.ts +2 -2
  70. package/dist/ikoncomponents/table/DataTablePagination/index.js +3 -1
  71. package/dist/ikoncomponents/table/DataTableSearch/index.d.ts +1 -1
  72. package/dist/ikoncomponents/table/DataTableSearch/index.js +16 -4
  73. package/dist/ikoncomponents/table/index.d.ts +2 -2
  74. package/dist/ikoncomponents/table/index.js +2 -162
  75. package/dist/ikoncomponents/table/type.d.ts +83 -24
  76. package/dist/ikoncomponents/table/type.js +0 -7
  77. package/dist/ikoncomponents/tabs/index.d.ts +2 -1
  78. package/dist/ikoncomponents/theme-toggle-btn/index.d.ts +1 -1
  79. package/dist/ikoncomponents/title-progress/index.d.ts +2 -1
  80. package/dist/ikoncomponents/tooltip/index.d.ts +1 -1
  81. package/dist/ikoncomponents/twolevel-dropdown/index.d.ts +2 -1
  82. package/dist/ikoncomponents/upload-tab/index.d.ts +1 -1
  83. package/dist/ikoncomponents/widgets/index.d.ts +2 -1
  84. package/dist/ikoncomponents/work-in-progress/index.d.ts +2 -1
  85. package/dist/index.d.ts +1 -1
  86. package/dist/shadcn/accordion.d.ts +4 -4
  87. package/dist/shadcn/alert-dialog.d.ts +2 -2
  88. package/dist/shadcn/alert.d.ts +3 -3
  89. package/dist/shadcn/aspect-ratio.d.ts +1 -1
  90. package/dist/shadcn/avatar.d.ts +3 -3
  91. package/dist/shadcn/badge.d.ts +1 -1
  92. package/dist/shadcn/breadcrumb.d.ts +7 -7
  93. package/dist/shadcn/button.d.ts +1 -1
  94. package/dist/shadcn/calendar.d.ts +2 -2
  95. package/dist/shadcn/card.d.ts +7 -7
  96. package/dist/shadcn/checkbox.d.ts +1 -1
  97. package/dist/shadcn/collapsible.d.ts +3 -3
  98. package/dist/shadcn/command.d.ts +9 -9
  99. package/dist/shadcn/dialog.d.ts +10 -10
  100. package/dist/shadcn/drawer.d.ts +10 -10
  101. package/dist/shadcn/dropdown-menu.d.ts +15 -15
  102. package/dist/shadcn/form.d.ts +7 -7
  103. package/dist/shadcn/hover-card.d.ts +3 -3
  104. package/dist/shadcn/input.d.ts +1 -1
  105. package/dist/shadcn/label.d.ts +1 -1
  106. package/dist/shadcn/navigation-menu.d.ts +8 -8
  107. package/dist/shadcn/popover.d.ts +4 -4
  108. package/dist/shadcn/progress.d.ts +1 -1
  109. package/dist/shadcn/radio-group.d.ts +2 -2
  110. package/dist/shadcn/scroll-area.d.ts +2 -2
  111. package/dist/shadcn/select.d.ts +10 -10
  112. package/dist/shadcn/separator.d.ts +1 -1
  113. package/dist/shadcn/sheet.d.ts +8 -8
  114. package/dist/shadcn/sidebar.d.ts +23 -23
  115. package/dist/shadcn/skeleton.d.ts +1 -1
  116. package/dist/shadcn/slider.d.ts +1 -1
  117. package/dist/shadcn/sonner.d.ts +1 -1
  118. package/dist/shadcn/switch.d.ts +1 -1
  119. package/dist/shadcn/table.d.ts +8 -8
  120. package/dist/shadcn/tabs.d.ts +4 -4
  121. package/dist/shadcn/textarea.d.ts +1 -1
  122. package/dist/shadcn/toggle-group.d.ts +2 -2
  123. package/dist/shadcn/toggle.d.ts +1 -1
  124. package/dist/shadcn/tooltip.d.ts +4 -4
  125. package/dist/shadcn/workflow.d.ts +1 -1
  126. package/dist/styles.css +47 -28
  127. package/dist/tsconfig.build.tsbuildinfo +1 -1
  128. package/dist/utils/border-radius-provider.d.ts +1 -1
  129. package/dist/utils/font-provider.d.ts +1 -1
  130. package/dist/utils/theme-provider/index.d.ts +1 -1
  131. package/package.json +3 -2
  132. package/dist/ikoncomponents/assistant-ui/Assistant.d.ts +0 -28
  133. package/dist/ikoncomponents/assistant-ui/Assistant.js +0 -306
  134. package/dist/ikoncomponents/assistant-ui/agent-dropdown.d.ts +0 -24
  135. package/dist/ikoncomponents/assistant-ui/agent-dropdown.js +0 -16
  136. package/dist/ikoncomponents/assistant-ui/agentTextChatTransport.d.ts +0 -30
  137. package/dist/ikoncomponents/assistant-ui/agentTextChatTransport.js +0 -208
  138. package/dist/ikoncomponents/assistant-ui/attachment.d.ts +0 -4
  139. package/dist/ikoncomponents/assistant-ui/attachment.js +0 -93
  140. package/dist/ikoncomponents/assistant-ui/markdown-text.d.ts +0 -2
  141. package/dist/ikoncomponents/assistant-ui/markdown-text.js +0 -126
  142. package/dist/ikoncomponents/assistant-ui/thread.d.ts +0 -10
  143. package/dist/ikoncomponents/assistant-ui/thread.js +0 -115
  144. package/dist/ikoncomponents/assistant-ui/tool-fallback.d.ts +0 -2
  145. package/dist/ikoncomponents/assistant-ui/tool-fallback.js +0 -18
  146. package/dist/ikoncomponents/assistant-ui/tooltip-icon-button.d.ts +0 -7
  147. package/dist/ikoncomponents/assistant-ui/tooltip-icon-button.js +0 -23
  148. package/dist/utils/userType.d.ts +0 -13
  149. package/dist/utils/userType.js +0 -1
@@ -0,0 +1,95 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useMemo } from "react";
4
+ import { X, ChevronDown, Check, RotateCcw, Search, ListFilter } from "lucide-react";
5
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "../../../shadcn/dropdown-menu";
6
+ import { Button } from "../../../shadcn/button";
7
+ export function DataTableFilter({ table }) {
8
+ const [open, setOpen] = useState(false);
9
+ const [searchQuery, setSearchQuery] = useState("");
10
+ const [pendingColumns, setPendingColumns] = useState([]);
11
+ // Syncing with Table State: Which columns currently have a filter active?
12
+ const activeFilters = table.getState().columnFilters;
13
+ const activeIds = activeFilters.map((f) => f.id);
14
+ const columns = table.getAllLeafColumns().filter((col) => col.getCanFilter());
15
+ const filteredColumns = columns.filter((col) => {
16
+ if (col.id === "DTActions")
17
+ return false; // Exclude action column from filter list
18
+ const label = (typeof col.columnDef.header === "string") ? col.columnDef.header : col.id;
19
+ return label.toLowerCase().includes(searchQuery.toLowerCase());
20
+ });
21
+ const togglePendingColumn = (id) => {
22
+ setPendingColumns((prev) => prev.includes(id) ? prev.filter((c) => c !== id) : [...prev, id]);
23
+ };
24
+ return (_jsxs(DropdownMenu, { open: open, onOpenChange: (o) => {
25
+ setOpen(o);
26
+ if (o)
27
+ setPendingColumns(activeIds);
28
+ }, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "h-9 gap-2 border-border bg-background relative", children: [_jsx(ListFilter, { className: "w-4 h-4" }), "Filter", activeIds.length > 0 && (_jsx("span", { className: "absolute -top-1 -right-1 w-4 h-4 bg-foreground text-background text-[10px] rounded-full flex items-center justify-center font-bold", children: activeIds.length }))] }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-56 p-2 space-y-2", children: [_jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Filter" }), _jsxs("div", { className: "px-2 relative", children: [_jsx(Search, { className: "absolute left-4 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: "Search columns...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full h-8 pl-8 pr-2 text-xs rounded-md border border-border bg-muted/20 focus:outline-none focus:ring-1 focus:ring-foreground/30" })] }), _jsx("div", { className: "space-y-1 max-h-[300px] overflow-y-auto pr-1", children: filteredColumns.map((col) => {
29
+ const label = typeof col.columnDef.header === "string"
30
+ ? col.columnDef.header
31
+ : col.id;
32
+ const isSelected = pendingColumns.includes(col.id);
33
+ return (_jsxs("button", { onClick: () => togglePendingColumn(col.id), className: "flex w-full items-center gap-2 px-2 py-1.5 text-sm rounded-sm hover:bg-muted transition-colors", children: [_jsx("div", { className: "flex h-4 w-4 items-center justify-center rounded-sm border", style: isSelected
34
+ ? { backgroundColor: "hsl(var(--foreground))", borderColor: "hsl(var(--foreground))", color: "hsl(var(--background))" }
35
+ : { borderColor: "hsl(var(--border))" }, children: isSelected && _jsx(Check, { className: "h-3 w-3" }) }), _jsx("span", { className: "truncate", children: label })] }, col.id));
36
+ }) }), _jsxs("div", { className: "px-2 pt-2 mt-1 flex gap-2", children: [_jsx(Button, { variant: "default", size: "sm", className: "flex-1 text-xs font-medium bg-foreground text-background hover:bg-foreground/90", onClick: () => {
37
+ columns.forEach((col) => {
38
+ const wasActive = activeIds.includes(col.id);
39
+ const willActive = pendingColumns.includes(col.id);
40
+ if (willActive && !wasActive)
41
+ col.setFilterValue([]);
42
+ if (!willActive && wasActive)
43
+ col.setFilterValue(undefined);
44
+ });
45
+ setOpen(false);
46
+ }, children: "Apply" }), _jsxs(Button, { variant: "secondary", size: "sm", className: "flex-1 text-xs font-medium bg-secondary hover:bg-secondary/80 text-secondary-foreground", onClick: () => {
47
+ setPendingColumns([]);
48
+ table.resetColumnFilters();
49
+ setOpen(false);
50
+ }, children: [_jsx(RotateCcw, { className: "w-3.5 h-3.5 mr-2 inline" }), " Reset"] })] })] })] }));
51
+ }
52
+ export function FilterTagSpacer({ activeFilters, table }) {
53
+ if (!activeFilters || activeFilters.length === 0)
54
+ return null;
55
+ return (
56
+ // {/* --- ACTIVE FILTER TAGS --- */}
57
+ _jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0 overflow-x-auto", style: { scrollbarWidth: "none", msOverflowStyle: "none" }, children: activeFilters.map((filter) => (_jsx(FilterTag, { filter: filter, table: table }, filter.id))) }));
58
+ }
59
+ // --- INDIVIDUAL TAG COMPONENT WITH VALUE DROPDOWN ---
60
+ function FilterTag({ filter, table }) {
61
+ const [searchQuery, setSearchQuery] = useState("");
62
+ const column = table.getColumn(filter.id);
63
+ const colHeader = typeof (column === null || column === void 0 ? void 0 : column.columnDef.header) === "string" ? column.columnDef.header : filter.id;
64
+ const selectedValues = filter.value || [];
65
+ // Extract unique values from data
66
+ const uniqueValues = useMemo(() => {
67
+ const set = new Set();
68
+ table.getPreFilteredRowModel().flatRows.forEach((row) => {
69
+ const val = row.getValue(filter.id);
70
+ if (val !== null && val !== undefined)
71
+ set.add(val);
72
+ });
73
+ return Array.from(set).sort();
74
+ }, [table.getPreFilteredRowModel().flatRows, filter.id]);
75
+ const filteredValues = uniqueValues.filter((v) => String(v).toLowerCase().includes(searchQuery.toLowerCase()));
76
+ const toggleValue = (val) => {
77
+ const next = selectedValues.includes(val)
78
+ ? selectedValues.filter((v) => v !== val)
79
+ : [...selectedValues, val];
80
+ column.setFilterValue(next);
81
+ };
82
+ return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("div", { className: "flex items-center gap-1.5 px-3 py-1.5 h-9 bg-muted/50 border border-border rounded-full text-xs font-medium cursor-pointer hover:bg-muted/80 transition-colors flex-1 shrink min-w-[140px] max-w-fit", title: `${colHeader}: ${selectedValues.length} Selected`, children: [_jsxs("span", { className: "uppercase truncate shrink font-semibold", children: [colHeader, ":"] }), _jsxs("span", { className: "text-muted-foreground whitespace-nowrap shrink-0", children: [selectedValues.length, " Selected"] }), _jsx(ChevronDown, { className: "w-3.5 h-3.5 ml-1 opacity-50 shrink-0" }), _jsx("div", { className: "p-0.5 ml-1 rounded-full hover:bg-background/80 shrink-0", onClick: (e) => {
83
+ e.preventDefault();
84
+ e.stopPropagation();
85
+ column.setFilterValue(undefined);
86
+ }, onPointerDown: (e) => {
87
+ e.stopPropagation();
88
+ }, children: _jsx(X, { className: "w-3.5 h-3.5" }) })] }) }), _jsxs(DropdownMenuContent, { align: "start", className: "w-56 p-2 space-y-2", children: [_jsxs("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: ["Filter ", colHeader] }), _jsxs("div", { className: "px-2 relative", children: [_jsx(Search, { className: "absolute left-4 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: "Search items...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full h-8 pl-8 pr-2 text-xs rounded-md border border-border bg-muted/20 focus:outline-none focus:ring-1 focus:ring-foreground/30" })] }), _jsxs("div", { className: "space-y-1 max-h-[200px] overflow-y-auto pr-1", children: [filteredValues.map((val) => {
89
+ const isSelected = selectedValues.includes(val);
90
+ const label = String(val).trim() === "" ? "N/A" : String(val);
91
+ return (_jsxs("button", { onClick: () => toggleValue(val), className: "flex w-full items-center gap-2 px-2 py-1.5 text-sm rounded-sm hover:bg-muted transition-colors", children: [_jsx("div", { className: "flex h-4 w-4 items-center justify-center rounded-sm border", style: isSelected
92
+ ? { backgroundColor: "hsl(var(--foreground))", borderColor: "hsl(var(--foreground))", color: "hsl(var(--background))" }
93
+ : { borderColor: "hsl(var(--border))" }, children: isSelected && _jsx(Check, { className: "h-3 w-3" }) }), _jsx("span", { className: "truncate text-left", children: label })] }, String(val)));
94
+ }), filteredValues.length === 0 && (_jsx("div", { className: "px-2 py-2 text-xs text-muted-foreground text-center", children: "No items found." }))] }), selectedValues.length > 0 && (_jsx("div", { className: "px-2 pt-1 border-t", children: _jsx(Button, { variant: "ghost", size: "sm", className: "w-full text-xs", onClick: () => column.setFilterValue([]), children: "Clear Selections" }) }))] })] }));
95
+ }
@@ -1 +1 @@
1
- export declare function DataTablePageSize(): import("react/jsx-runtime").JSX.Element;
1
+ export declare function DataTablePageSize(): import("react").JSX.Element;
@@ -7,9 +7,11 @@ export function DataTablePageSize() {
7
7
  const searchParams = useSearchParams();
8
8
  const currentSize = searchParams.get("size") || "10";
9
9
  const handleSizeChange = (e) => {
10
+ // Create a new URLSearchParams instance from the current ones
10
11
  const params = new URLSearchParams(searchParams.toString());
11
12
  params.set("size", e.target.value);
12
13
  params.set("page", "1");
14
+ // Next.js navigation
13
15
  router.push(`${pathname}?${params.toString()}`);
14
16
  };
15
17
  return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "Rows per page:" }), _jsxs("select", { className: "h-9 rounded-md border border-border bg-background text-foreground px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-primary", value: currentSize, onChange: handleSizeChange, children: [_jsx("option", { value: "10", children: "10" }), _jsx("option", { value: "20", children: "20" }), _jsx("option", { value: "50", children: "50" }), _jsx("option", { value: "100", children: "100" })] })] }));
@@ -1,6 +1,6 @@
1
1
  interface PaginationProps {
2
- totalPages: number;
2
+ totalPages: number | undefined;
3
3
  currentPage: number;
4
4
  }
5
- export declare function DataTablePagination({ totalPages, currentPage }: PaginationProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function DataTablePagination({ totalPages, currentPage }: PaginationProps): import("react").JSX.Element;
6
6
  export {};
@@ -6,9 +6,11 @@ export function DataTablePagination({ totalPages, currentPage }) {
6
6
  const pathname = usePathname();
7
7
  const searchParams = useSearchParams();
8
8
  const handlePageChange = (newPage) => {
9
+ // Create a new URLSearchParams instance from the current ones
9
10
  const params = new URLSearchParams(searchParams.toString());
10
11
  params.set("page", newPage.toString());
12
+ // Next.js navigation
11
13
  router.push(`${pathname}?${params.toString()}`);
12
14
  };
13
- return (_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx("button", { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage <= 1, className: "h-9 px-3 py-1 text-sm font-medium border border-border rounded-md bg-background text-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors", children: "Previous" }), _jsxs("span", { className: "text-sm text-muted-foreground px-2", children: ["Page ", _jsx("span", { className: "font-semibold", children: currentPage }), " of", " ", _jsx("span", { className: "font-semibold", children: Math.max(totalPages, 1) })] }), _jsx("button", { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage >= totalPages, className: "h-9 px-3 py-1 text-sm font-medium border border-border rounded-md bg-background text-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors", children: "Next" })] }));
15
+ return (_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx("button", { type: "button", onClick: () => handlePageChange(currentPage - 1), disabled: currentPage <= 1, className: "h-9 px-3 py-1 text-sm font-medium border border-border rounded-md bg-background text-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors", children: "Previous" }), _jsxs("span", { className: "text-sm text-muted-foreground px-2", children: ["Page ", _jsx("span", { className: "font-semibold", children: currentPage }), " of", " ", _jsx("span", { className: "font-semibold", children: Math.max(totalPages !== null && totalPages !== void 0 ? totalPages : 1, 1) })] }), _jsx("button", { type: "button", onClick: () => handlePageChange(currentPage + 1), disabled: totalPages === undefined ? undefined : currentPage >= totalPages, className: "h-9 px-3 py-1 text-sm font-medium border border-border rounded-md bg-background text-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors", children: "Next" })] }));
14
16
  }
@@ -1 +1 @@
1
- export declare function DataTableSearch(): import("react/jsx-runtime").JSX.Element;
1
+ export declare function DataTableSearch(): import("react").JSX.Element;
@@ -1,27 +1,39 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useRouter, usePathname, useSearchParams } from "next/navigation";
4
3
  import { useState, useEffect } from "react";
4
+ import { useRouter, usePathname, useSearchParams } from "next/navigation";
5
5
  import { useDebounce } from "use-debounce";
6
6
  import { Search } from "lucide-react";
7
7
  export function DataTableSearch() {
8
8
  const router = useRouter();
9
9
  const pathname = usePathname();
10
10
  const searchParams = useSearchParams();
11
+ // 1. Initialize local state from the URL 'search' param
11
12
  const [searchTerm, setSearchTerm] = useState(searchParams.get("search") || "");
13
+ // 2. Debounce the local state (500ms delay)
12
14
  const [debouncedSearch] = useDebounce(searchTerm, 500);
15
+ // 3. Update the URL whenever the debounced value changes
13
16
  useEffect(() => {
14
17
  const params = new URLSearchParams(searchParams.toString());
15
18
  if (debouncedSearch) {
16
19
  params.set("search", debouncedSearch);
20
+ // Update the global filter in the parent component
17
21
  }
18
22
  else {
19
23
  params.delete("search");
20
24
  }
25
+ // Only navigate if the param actually changed (prevents redundant history entries)
21
26
  if (params.get("search") !== searchParams.get("search")) {
22
- params.set("page", "1");
23
- router.push(`${pathname}?${params.toString()}`);
27
+ params.set("page", "1"); // Reset to page 1 on new search
28
+ router.replace(`${pathname}?${params.toString()}`);
24
29
  }
25
30
  }, [debouncedSearch, pathname, router, searchParams]);
26
- return (_jsxs("div", { className: "relative w-full max-w-sm", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: "Search ...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), className: "flex h-9 w-full rounded-md border border-border bg-transparent pl-9 pr-3 py-1 text-sm shadow-sm transition-colors text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary" })] }));
31
+ // 4. Sync local state if the URL is changed externally (e.g., browser back button)
32
+ useEffect(() => {
33
+ const urlSearch = searchParams.get("search") || "";
34
+ if (urlSearch !== searchTerm) {
35
+ setSearchTerm(urlSearch);
36
+ }
37
+ }, [searchParams]);
38
+ return (_jsxs("div", { className: "relative max-w-sm min-w-[10%]", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: "Search ...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), className: "flex h-9 w-full rounded-md border border-border bg-transparent pl-9 pr-3 py-1 text-sm shadow-sm transition-colors text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary" })] }));
27
39
  }
@@ -1,2 +1,2 @@
1
- import { DataTableLayoutProps } from "./type";
2
- export declare function DataTableLayout<T>({ data, columns, extraTools, }: DataTableLayoutProps<T>): import("react/jsx-runtime").JSX.Element;
1
+ import type { DataTableLayoutProps } from "./type";
2
+ export declare function DataTableLayout<T>({ data, columns, extraTools, }: DataTableLayoutProps<T>): import("react").JSX.Element;
@@ -1,165 +1,5 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState, useEffect, useRef } from "react";
3
- import { LayoutGrid, List, ChevronDown, X, GripVertical, Settings2, Check, Download, RotateCcw, Search, ListFilter } from "lucide-react";
4
- import { Badge } from "../../shadcn/badge";
5
- import { Reload } from "../reload-component";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
6
2
  import { DataTable } from "./DataTable";
7
- import { DataTableSearch } from "./DataTableSearch";
8
- import { DataTablePagination } from "./DataTablePagination";
9
- import { DataTablePageSize } from "./DataTablePageSize";
10
- import { Button } from "../../shadcn/button";
11
- import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "../../shadcn/dropdown-menu";
12
3
  export function DataTableLayout({ data, columns, extraTools, }) {
13
- const { keyExtractor, totalPages, currentPage, filterComponent, actionNode, onRowClick, gridComponent, isLoading, onReload, themeColor, onLoadMore, hasMore, onFilterChange, unfilteredData, } = extraTools !== null && extraTools !== void 0 ? extraTools : {};
14
- const [viewMode, setViewMode] = useState("list");
15
- const observerTarget = useRef(null);
16
- useEffect(() => {
17
- if (viewMode !== "grid" || !onLoadMore || !hasMore)
18
- return;
19
- const observer = new IntersectionObserver((entries) => {
20
- if (entries[0].isIntersecting) {
21
- onLoadMore();
22
- }
23
- }, { threshold: 0.1 });
24
- if (observerTarget.current) {
25
- observer.observe(observerTarget.current);
26
- }
27
- return () => observer.disconnect();
28
- }, [viewMode, onLoadMore, hasMore]);
29
- const [groupedColumns, setGroupedColumns] = useState([]);
30
- const [tableFilters, setTableFilters] = useState({});
31
- const [activeFilterColumns, setActiveFilterColumns] = useState([]);
32
- const [isFilterDropdownOpen, setIsFilterDropdownOpen] = useState(false);
33
- const [pendingFilterColumns, setPendingFilterColumns] = useState([]);
34
- const [filterSearchQuery, setFilterSearchQuery] = useState("");
35
- const [columnSearchQueries, setColumnSearchQueries] = useState({});
36
- const [visibleColumns, setVisibleColumns] = useState(columns.map(col => typeof col.header === "string" ? col.header : ""));
37
- const toggleColumn = (header) => {
38
- setVisibleColumns(prev => prev.includes(header) ? prev.filter(h => h !== header) : [...prev, header]);
39
- };
40
- const handleToggleFilterValue = (column, value) => {
41
- const currentValues = tableFilters[column] || [];
42
- const nextValues = currentValues.includes(value)
43
- ? currentValues.filter(v => v !== value)
44
- : [...currentValues, value];
45
- const nextFilters = Object.assign({}, tableFilters);
46
- if (nextValues.length === 0) {
47
- delete nextFilters[column];
48
- }
49
- else {
50
- nextFilters[column] = nextValues;
51
- }
52
- setTableFilters(nextFilters);
53
- onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(nextFilters);
54
- };
55
- const removeActiveFilterColumn = (column) => {
56
- const nextActiveColumns = activeFilterColumns.filter(c => c !== column);
57
- const nextFilters = Object.assign({}, tableFilters);
58
- delete nextFilters[column];
59
- setActiveFilterColumns(nextActiveColumns);
60
- setTableFilters(nextFilters);
61
- onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(nextFilters);
62
- };
63
- const handleTogglePendingFilterColumn = (column) => {
64
- setPendingFilterColumns(prev => prev.includes(column) ? prev.filter(c => c !== column) : [...prev, column]);
65
- };
66
- const getUniqueValuesForColumn = (header) => {
67
- const col = columns.find(c => c.header === header);
68
- if (!col || !col.accessorKey)
69
- return [];
70
- const sourceData = unfilteredData || data;
71
- const values = sourceData.map(row => String(row[col.accessorKey] || ""));
72
- return Array.from(new Set(values)).filter(Boolean).sort();
73
- };
74
- const handleToggleGroup = (columnHeader) => {
75
- setGroupedColumns(prev => prev.includes(columnHeader)
76
- ? prev.filter(c => c !== columnHeader)
77
- : [...prev, columnHeader]);
78
- };
79
- const exportToCSV = () => {
80
- if (!data || data.length === 0)
81
- return;
82
- const headers = columns
83
- .filter(col => typeof col.header === "string")
84
- .map(col => col.header);
85
- const csvRows = data.map(row => columns
86
- .filter(col => typeof col.header === "string")
87
- .map(col => {
88
- const val = col.accessorKey ? row[col.accessorKey] : "";
89
- return `"${String(val).replace(/"/g, '""')}"`;
90
- })
91
- .join(","));
92
- const csvContent = [headers.join(","), ...csvRows].join("\n");
93
- const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
94
- const link = document.createElement("a");
95
- const url = URL.createObjectURL(blob);
96
- link.setAttribute("href", url);
97
- link.setAttribute("download", `table-export-${new Date().toISOString().split('T')[0]}.csv`);
98
- link.style.visibility = "hidden";
99
- document.body.appendChild(link);
100
- link.click();
101
- document.body.removeChild(link);
102
- };
103
- // data is the current page from the backend — render it directly, no client-side filtering.
104
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-4 w-full", children: [_jsx("div", { className: "flex items-center gap-2 w-full sm:w-auto sm:max-w-[200px] shrink-0", children: _jsx(DataTableSearch, {}) }), _jsxs("div", { className: "flex items-center gap-3 flex-wrap shrink-0", children: [actionNode && actionNode, filterComponent && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "h-9 gap-2 border-border bg-background", children: [_jsx(ListFilter, { className: "w-4 h-4" }), "Filter"] }) }), _jsx(DropdownMenuContent, { align: "end", className: "p-4 min-w-[200px]", children: filterComponent })] })), _jsxs(DropdownMenu, { open: isFilterDropdownOpen, onOpenChange: (open) => {
105
- setIsFilterDropdownOpen(open);
106
- if (open) {
107
- setPendingFilterColumns(activeFilterColumns);
108
- }
109
- }, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "h-9 gap-2 border-border bg-background relative", children: [_jsx(ListFilter, { className: "w-4 h-4" }), "Filter", activeFilterColumns.length > 0 && (_jsx("span", { className: "absolute -top-1 -right-1 w-4 h-4 bg-foreground text-background text-[10px] rounded-full flex items-center justify-center font-bold", children: activeFilterColumns.length }))] }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-56 p-2 space-y-2", children: [_jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Filter" }), _jsxs("div", { className: "px-2 relative", children: [_jsx(Search, { className: "absolute left-4 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: "Search columns...", value: filterSearchQuery, onChange: (e) => setFilterSearchQuery(e.target.value), className: "w-full h-8 pl-8 pr-2 text-xs rounded-md border border-border bg-muted/20 focus:outline-none focus:ring-1 focus:ring-foreground/30" })] }), _jsx("div", { className: "space-y-1 max-h-[300px] overflow-y-auto pr-1", children: columns
110
- .filter(col => {
111
- const headerText = typeof col.header === "string" ? col.header : "";
112
- return headerText && col.accessorKey && headerText.toLowerCase().includes(filterSearchQuery.toLowerCase());
113
- })
114
- .map((col, idx) => {
115
- const headerText = typeof col.header === "string" ? col.header : "";
116
- const isSelected = pendingFilterColumns.includes(headerText);
117
- return (_jsxs("button", { onClick: () => handleTogglePendingFilterColumn(headerText), className: "flex w-full items-center gap-2 px-2 py-1.5 text-sm rounded-sm hover:bg-muted transition-colors", children: [_jsx("div", { className: `flex h-4 w-4 items-center justify-center rounded-sm border`, style: isSelected ? { backgroundColor: 'hsl(var(--foreground))', borderColor: 'hsl(var(--foreground))', color: 'hsl(var(--background))' } : { borderColor: 'hsl(var(--border))' }, children: isSelected && _jsx(Check, { className: "h-3 w-3" }) }), _jsx("span", { className: "truncate", children: headerText })] }, idx));
118
- }) }), _jsxs("div", { className: "px-2 pt-2 mt-1 flex gap-2", children: [_jsx(Button, { variant: "default", size: "sm", className: "flex-1 text-xs font-medium bg-foreground text-background hover:bg-foreground/90", onClick: () => {
119
- setActiveFilterColumns(pendingFilterColumns);
120
- const removedColumns = activeFilterColumns.filter(c => !pendingFilterColumns.includes(c));
121
- const nextFilters = Object.assign({}, tableFilters);
122
- removedColumns.forEach(c => delete nextFilters[c]);
123
- setTableFilters(nextFilters);
124
- setIsFilterDropdownOpen(false);
125
- // Notify parent so it can re-fetch from the backend
126
- onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(nextFilters);
127
- }, children: "Apply" }), _jsxs(Button, { variant: "secondary", size: "sm", className: "flex-1 text-xs font-medium bg-secondary hover:bg-secondary/80 text-secondary-foreground", onClick: () => {
128
- setPendingFilterColumns([]);
129
- setActiveFilterColumns([]);
130
- setTableFilters({});
131
- setIsFilterDropdownOpen(false);
132
- // Notify parent so it can re-fetch all data without filters
133
- onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange({});
134
- }, children: [_jsx(RotateCcw, { className: "w-3.5 h-3.5 mr-2 inline" }), " Reset"] })] })] })] }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "h-9 gap-2 border-border bg-background", children: [_jsx(Settings2, { className: "w-4 h-4" }), "Columns"] }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-48 p-2", children: [_jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Toggle Columns" }), columns.map((col, idx) => {
135
- const headerText = typeof col.header === "string" ? col.header : `Column ${idx + 1}`;
136
- const isVisible = visibleColumns.includes(headerText);
137
- return (_jsxs("button", { onClick: () => toggleColumn(headerText), className: "flex w-full items-center gap-2 px-2 py-1.5 text-sm rounded-sm hover:bg-muted transition-colors", children: [_jsx("div", { className: `flex h-4 w-4 items-center justify-center rounded-sm border border-primary ${isVisible ? 'bg-primary text-primary-foreground' : 'bg-transparent'}`, children: isVisible && _jsx(Check, { className: "h-3 w-3" }) }), headerText] }, idx));
138
- })] })] }), _jsx(Button, { variant: "outline", size: "sm", className: "h-9 gap-2 border-border bg-background", onClick: exportToCSV, children: _jsx(Download, { className: "w-4 h-4" }) }), _jsxs("div", { className: "flex items-center border border-border rounded-md bg-background overflow-hidden h-9", children: [_jsx("button", { onClick: () => setViewMode("list"), className: `px-2.5 h-full flex items-center justify-center transition-colors ${viewMode === "list" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`, title: "List View", children: _jsx(List, { className: "w-4 h-4" }) }), _jsx("button", { onClick: () => setViewMode("grid"), className: `px-2.5 h-full flex items-center justify-center transition-colors ${viewMode === "grid" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`, title: "Grid View", children: _jsx(LayoutGrid, { className: "w-4 h-4" }) })] })] })] }), activeFilterColumns.length > 0 && (_jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0 overflow-x-auto", style: { scrollbarWidth: 'none', msOverflowStyle: 'none' }, children: activeFilterColumns.map(colHeader => {
139
- const selectedCount = (tableFilters[colHeader] || []).length;
140
- const searchQuery = columnSearchQueries[colHeader] || "";
141
- const uniqueValues = getUniqueValuesForColumn(colHeader);
142
- const filteredValues = uniqueValues.filter(v => v.toLowerCase().includes(searchQuery.toLowerCase()));
143
- return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("div", { className: "flex items-center gap-1.5 px-3 py-1.5 h-9 bg-muted/50 border border-border rounded-full text-xs font-medium cursor-pointer hover:bg-muted/80 transition-colors flex-1 shrink min-w-[140px] max-w-fit [&::-webkit-scrollbar]:hidden", title: `${colHeader}: ${selectedCount} Selected`, children: [_jsxs("span", { className: "uppercase truncate shrink font-semibold", children: [colHeader, ":"] }), _jsxs("span", { className: "text-muted-foreground whitespace-nowrap shrink-0", children: [selectedCount, " Selected"] }), _jsx(ChevronDown, { className: "w-3.5 h-3.5 ml-1 opacity-50 shrink-0" }), _jsx("div", { className: "p-0.5 ml-1 rounded-full hover:bg-background/80 shrink-0", onClick: (e) => {
144
- e.preventDefault();
145
- e.stopPropagation();
146
- removeActiveFilterColumn(colHeader);
147
- }, onPointerDown: (e) => {
148
- e.stopPropagation();
149
- }, children: _jsx(X, { className: "w-3.5 h-3.5" }) })] }) }), _jsxs(DropdownMenuContent, { align: "start", className: "w-56 p-2 space-y-2", children: [_jsxs("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: ["Filter ", colHeader] }), _jsxs("div", { className: "px-2 relative", children: [_jsx(Search, { className: "absolute left-4 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: "Search items...", value: searchQuery, onChange: (e) => setColumnSearchQueries(prev => (Object.assign(Object.assign({}, prev), { [colHeader]: e.target.value }))), className: "w-full h-8 pl-8 pr-2 text-xs rounded-md border border-border bg-muted/20 focus:outline-none focus:ring-1 focus:ring-foreground/30" })] }), _jsxs("div", { className: "space-y-1 max-h-[200px] overflow-y-auto pr-1", children: [filteredValues.map(val => {
150
- const isSelected = (tableFilters[colHeader] || []).includes(val);
151
- return (_jsxs("button", { onClick: () => handleToggleFilterValue(colHeader, val), className: "flex w-full items-center gap-2 px-2 py-1.5 text-sm rounded-sm hover:bg-muted transition-colors", children: [_jsx("div", { className: `flex h-4 w-4 items-center justify-center rounded-sm border`, style: isSelected ? { backgroundColor: 'hsl(var(--foreground))', borderColor: 'hsl(var(--foreground))', color: 'hsl(var(--background))' } : { borderColor: 'hsl(var(--border))' }, children: isSelected && _jsx(Check, { className: "h-3 w-3" }) }), _jsx("span", { className: "truncate text-left", children: val })] }, val));
152
- }), filteredValues.length === 0 && (_jsx("div", { className: "px-2 py-2 text-xs text-muted-foreground text-center", children: "No items found." }))] }), (tableFilters[colHeader] || []).length > 0 && (_jsx("div", { className: "px-2 pt-1 border-t", children: _jsx(Button, { variant: "ghost", size: "sm", className: "w-full text-xs", onClick: () => {
153
- const nextFilters = Object.assign({}, tableFilters);
154
- delete nextFilters[colHeader];
155
- setTableFilters(nextFilters);
156
- onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(nextFilters);
157
- }, children: "Clear Selections" }) }))] })] }, colHeader));
158
- }) })), _jsxs("div", { className: "w-full flex items-center gap-2 p-2 border border-dashed border-border rounded-lg bg-muted/20 min-h-[48px] transition-all hover:bg-muted/40 group shadow-sm", onDragOver: (e) => e.preventDefault(), onDrop: (e) => {
159
- e.preventDefault();
160
- const columnHeader = e.dataTransfer.getData("columnHeader");
161
- if (columnHeader && !groupedColumns.includes(columnHeader)) {
162
- handleToggleGroup(columnHeader);
163
- }
164
- }, children: [_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground text-xs px-2 select-none border-r pr-4 mr-2 border-border/50", children: [_jsx(GripVertical, { className: "w-4 h-4 opacity-40" }), _jsx("span", { className: "font-semibold uppercase tracking-wider opacity-70", children: "Grouping" })] }), _jsx("div", { className: "flex flex-wrap gap-2", children: groupedColumns.length === 0 ? (_jsx("div", { className: "flex items-center gap-2 text-muted-foreground/60 text-sm italic py-1", children: _jsx("span", { children: "Drag column headers here to group your data..." }) })) : (groupedColumns.map(col => (_jsxs(Badge, { variant: "secondary", className: "gap-2 pl-3 pr-1.5 h-8 text-xs font-semibold bg-background border shadow-sm animate-in fade-in zoom-in duration-200", children: [col, _jsx("button", { onClick: () => handleToggleGroup(col), className: "hover:bg-muted rounded-full p-0.5 transition-colors", children: _jsx(X, { className: "w-3.5 h-3.5" }) })] }, col)))) })] }), _jsxs("div", { className: "relative min-h-[300px] mt-2", children: [_jsx(Reload, { isLoading: isLoading !== null && isLoading !== void 0 ? isLoading : false, onReload: onReload || (() => window.location.reload()) }), _jsx("div", { className: `transition-all duration-300 ${isLoading ? 'opacity-50 pointer-events-none' : ''}`, children: viewMode === "list" ? (_jsx(DataTable, { data: data, columns: columns.filter(col => typeof col.header === "string" ? visibleColumns.includes(col.header) : true), keyExtractor: keyExtractor !== null && keyExtractor !== void 0 ? keyExtractor : (() => ""), onRowClick: onRowClick, groupedColumns: groupedColumns, onToggleGroup: handleToggleGroup })) : (_jsxs(_Fragment, { children: [gridComponent ? gridComponent(data) : (_jsx("div", { className: "p-12 text-center text-muted-foreground border border-border border-dashed rounded-md bg-muted/20", children: "Grid view not implemented for this component yet." })), viewMode === "grid" && hasMore && (_jsx("div", { ref: observerTarget, className: "flex justify-center p-6 w-full", children: _jsx("div", { className: "w-6 h-6 border-2 rounded-full animate-spin border-foreground border-t-transparent" }) }))] })) })] }), viewMode === "list" && (_jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-4 pt-4 border-t border-border mt-4", children: [_jsx(DataTablePageSize, {}), _jsx(DataTablePagination, { totalPages: totalPages !== null && totalPages !== void 0 ? totalPages : 0, currentPage: currentPage !== null && currentPage !== void 0 ? currentPage : 0 })] }))] }));
4
+ return (_jsx(DataTable, { data: data, columns: columns, extraTools: extraTools }));
165
5
  }
@@ -1,34 +1,93 @@
1
- export interface ColumnDef<T> {
2
- header: string | (() => React.ReactNode);
3
- accessorKey?: keyof T;
4
- cell?: (row: T) => React.ReactNode;
5
- }
6
- export interface DataTableProps<T> {
7
- data: T[];
8
- columns: ColumnDef<T>[];
9
- keyExtractor: (row: T) => string | number;
10
- onRowClick?: (row: T) => void;
11
- groupedColumns?: string[];
12
- onToggleGroup?: (columnHeader: string) => void;
13
- }
1
+ import type { ColumnDef, PaginationState } from "@tanstack/react-table";
2
+ import type { ActionMenuProps } from "../action-menu/type";
14
3
  export interface DataTableLayoutProps<T> {
15
4
  data: T[];
16
- columns: ColumnDef<T>[];
5
+ columns: ColumnsProps<T, unknown>[];
17
6
  extraTools?: ExtraPrams<T>;
18
7
  }
19
8
  export type ExtraPrams<T> = {
20
- keyExtractor: (row: T) => string | number;
21
- totalPages: number;
22
- currentPage: number;
23
- filterComponent?: React.ReactNode;
9
+ /** Total page count. When omitted, it's derived from `data.length / pageSize` (10/page default). */
10
+ totalPages?: number;
11
+ /**
12
+ * Server-side (pageable) pagination. When true, the table renders `data` as-is
13
+ * (already paged by your API) and emits `onPaginationChange` so the parent can
14
+ * fetch the next page. When false/undefined (default) the table receives the
15
+ * full `data` and paginates client-side — i.e. "call all data" mode.
16
+ */
17
+ manualPagination?: boolean;
18
+ /** Initial page index (0-based). Defaults to 0. */
19
+ pageIndex?: number;
20
+ /** Initial / current page size. Defaults to 10. */
21
+ pageSize?: number;
22
+ /** Fired whenever the page index or size changes — use it to fetch from your API. */
23
+ onPaginationChange?: (state: PaginationState) => void;
24
+ toggleViewMode?: boolean;
25
+ hiddenColumns?: string[];
24
26
  actionNode?: React.ReactNode;
25
- onRowClick?: (row: T) => void;
27
+ actionMenu?: TableActionMenuProps;
28
+ groupActionMenu?: TableActionMenuProps;
26
29
  gridComponent?: (data: T[]) => React.ReactNode;
27
30
  isLoading?: boolean;
28
31
  onReload?: () => void;
29
- themeColor?: string;
30
- onLoadMore?: () => void;
31
- hasMore?: boolean;
32
- onFilterChange?: (filters: Record<string, string[]>) => void;
33
- unfilteredData?: T[];
32
+ /** Enable default grouping. When true, the table is grouped by `groupedValue` on first render. */
33
+ grouping?: boolean;
34
+ /** Column id(s) to group by initially (used when `grouping` is true). */
35
+ groupedValue?: string[];
36
+ showFooter?: boolean;
37
+ footerLabel?: string;
38
+ /** Max height of the scrollable content (shared by list & grid view), e.g. "500px" or "60vh". */
39
+ tableHeight?: string;
40
+ /**
41
+ * Dynamic footer definition. Each entry is one footer row, so the footer can
42
+ * show multiple labels / summary rows. When provided (non-empty) it takes
43
+ * precedence over the column-level `footer` definitions used by `showFooter`.
44
+ */
45
+ footerRows?: FooterRowConfig<T>[];
46
+ fileName?: string;
47
+ };
48
+ /** Built-in single-column aggregations available to a footer cell. */
49
+ export type FooterAggregate = "sum" | "avg" | "min" | "max" | "count";
50
+ /** Arithmetic operations for combining several columns in a footer cell. */
51
+ export type FooterOperation = "add" | "subtract" | "multiply" | "divide";
52
+ /**
53
+ * Definition of a single footer cell. Use a plain string for a static label,
54
+ * or an object to aggregate one column / combine several columns arithmetically.
55
+ */
56
+ export type FooterCellConfig<T> = string | {
57
+ /** Aggregate a single column's numeric values. */
58
+ aggregate?: FooterAggregate;
59
+ /** Column key to aggregate (defaults to the column this cell sits under). */
60
+ column?: string;
61
+ /** Combine the sums of multiple columns with an arithmetic operation. */
62
+ operation?: FooterOperation;
63
+ /** Column keys used by `operation`, combined left-to-right. */
64
+ columns?: string[];
65
+ /** Decimal places for numeric output (defaults to locale formatting). */
66
+ decimals?: number;
67
+ /** Text rendered before the value. */
68
+ prefix?: string;
69
+ /** Text rendered after the value. */
70
+ suffix?: string;
71
+ /** Full custom renderer; receives the filtered row data. Overrides the above. */
72
+ render?: (rows: T[]) => React.ReactNode;
73
+ /** Extra class names applied to the footer cell. */
74
+ className?: string;
75
+ };
76
+ /** Definition of one footer row, with cells keyed by column id / accessorKey. */
77
+ export type FooterRowConfig<T> = {
78
+ /** Cell definitions keyed by column id / accessorKey. */
79
+ cells: Record<string, FooterCellConfig<T>>;
80
+ /** Extra class names applied to the footer row. */
81
+ className?: string;
82
+ };
83
+ export type ColumnsProps<TData, TValue = unknown> = ColumnDef<TData, TValue> & {
84
+ header: string | (() => React.ReactNode);
85
+ footer?: (row: TData) => React.ReactNode;
86
+ filterFns?: string | "multiSelect";
87
+ draggable?: boolean | undefined;
88
+ headerClassName?: string;
89
+ };
90
+ export type TableActionMenuProps = {
91
+ items: ActionMenuProps[];
92
+ extraArguments?: any[];
34
93
  };
@@ -1,8 +1 @@
1
- // export interface DataTableLayoutProps<T> {
2
- // data: T[];
3
- // columns: ColumnDef<T>[];
4
- // keyExtractor: (row: T) => string | number;
5
- // totalPages: number;
6
- // currentPage: number;
7
- ;
8
1
  export {};
@@ -1,2 +1,3 @@
1
1
  import { TabProps } from "./type";
2
- export declare function CustomTabs({ children, tabArray, pathName, tabListClass, tabListInnerClass, tabListButtonClass, tabContentClass, headerEndComponent, onTabChange, isSeperatePage, }: TabProps): import("react/jsx-runtime").JSX.Element;
2
+ import React from "react";
3
+ export declare function CustomTabs({ children, tabArray, pathName, tabListClass, tabListInnerClass, tabListButtonClass, tabContentClass, headerEndComponent, onTabChange, isSeperatePage, }: TabProps): React.JSX.Element;
@@ -1 +1 @@
1
- export declare function ThemeToggleBtn(): import("react/jsx-runtime").JSX.Element | null;
1
+ export declare function ThemeToggleBtn(): import("react").JSX.Element | null;
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  interface Props {
2
3
  title: string;
3
4
  value: number;
@@ -8,5 +9,5 @@ interface Props {
8
9
  valueClassName?: string;
9
10
  progressClassName?: string;
10
11
  }
11
- export declare function TitleProgress({ title, value, valueText, isPercent, className, titleClassName, valueClassName, progressClassName }: Props): import("react/jsx-runtime").JSX.Element;
12
+ export declare function TitleProgress({ title, value, valueText, isPercent, className, titleClassName, valueClassName, progressClassName }: Props): React.JSX.Element;
12
13
  export {};
@@ -2,4 +2,4 @@ import * as React from "react";
2
2
  export declare function TooltipComponent({ tooltipContent, children }: {
3
3
  tooltipContent: string | React.ReactNode;
4
4
  children: React.ReactNode;
5
- }): import("react/jsx-runtime").JSX.Element;
5
+ }): React.JSX.Element;
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  export interface FrameworkEntry {
2
3
  id: string;
3
4
  index: string;
@@ -27,5 +28,5 @@ interface FrameworkItemDropdownProps {
27
28
  searchPlaceholder?: string;
28
29
  className?: string;
29
30
  }
30
- export declare function FrameworkItemDropdown({ processedData, value, onChange, placeholder, searchPlaceholder, className, }: FrameworkItemDropdownProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function FrameworkItemDropdown({ processedData, value, onChange, placeholder, searchPlaceholder, className, }: FrameworkItemDropdownProps): React.JSX.Element;
31
32
  export {};
@@ -1 +1 @@
1
- export declare function UploadTab(): import("react/jsx-runtime").JSX.Element;
1
+ export declare function UploadTab(): import("react").JSX.Element;
@@ -1,2 +1,3 @@
1
+ import * as React from "react";
1
2
  import { WidgetsFunctionProps } from "./type";
2
- export declare function Widgets({ widgetData }: WidgetsFunctionProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function Widgets({ widgetData }: WidgetsFunctionProps): React.JSX.Element;
@@ -1 +1,2 @@
1
- export declare function WorkInProgress(): import("react/jsx-runtime").JSX.Element;
1
+ import React from "react";
2
+ export declare function WorkInProgress(): React.JSX.Element;
package/dist/index.d.ts CHANGED
@@ -59,7 +59,7 @@ export { getDataTableColumnTitle } from "./ikoncomponents/data-table/function";
59
59
  export { DataTable } from "./ikoncomponents/data-table";
60
60
  export type { DataTableProps, DTColumnsProps, DTExtraParamsProps, DTActionMenuProps, DataTableViewOptionsProps, DTToolBarProps, DataTableFilterProps, DataTableFacetedFilterProps, DataTablePaginationProps, DragDropHeaderProp, } from "./ikoncomponents/data-table/type";
61
61
  export { DataTableLayout } from "./ikoncomponents/table";
62
- export type { DataTableLayoutProps, ColumnDef } from "./ikoncomponents/table/type";
62
+ export type { DataTableLayoutProps, ExtraPrams, ColumnsProps } from "./ikoncomponents/table/type";
63
63
  export { Reload } from "./ikoncomponents/reload-component";
64
64
  export { EChart } from "./ikoncomponents/e-chart";
65
65
  export { FileInput } from "./ikoncomponents/file-input";
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
3
- declare function Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
- declare function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>): import("react/jsx-runtime").JSX.Element;
5
- declare function AccordionTrigger({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
6
- declare function AccordionContent({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
3
+ declare function Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>): React.JSX.Element;
4
+ declare function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>): React.JSX.Element;
5
+ declare function AccordionTrigger({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger>): React.JSX.Element;
6
+ declare function AccordionContent({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Content>): React.JSX.Element;
7
7
  export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };