@datum-cloud/datum-ui 0.2.1 → 0.3.0-alpha.ffa8392

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 (156) hide show
  1. package/dist/autocomplete/index.mjs +4 -4
  2. package/dist/{autocomplete-DZtI97HP.mjs → autocomplete-e33EmvBu.mjs} +3 -3
  3. package/dist/avatar-stack/index.mjs +2 -2
  4. package/dist/{avatar-stack-JCfBlPB9.mjs → avatar-stack-Ci0cnjxv.mjs} +1 -1
  5. package/dist/calendar-date-picker-BBAg78Lg.mjs +665 -0
  6. package/dist/checkbox/index.mjs +2 -1
  7. package/dist/checkbox-DB5_3E_l.mjs +22 -0
  8. package/dist/checkbox-DMC1Mhaw.mjs +17 -0
  9. package/dist/collapsible/index.mjs +1 -1
  10. package/dist/command/index.mjs +2 -2
  11. package/dist/{command-s0Yv3abE.mjs → command-DQlO6uTL.mjs} +1 -1
  12. package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts +2 -1
  13. package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts.map +1 -1
  14. package/dist/components/features/data-table/adapters/nuqs-adapter.d.ts +46 -0
  15. package/dist/components/features/data-table/adapters/nuqs-adapter.d.ts.map +1 -0
  16. package/dist/components/features/data-table/columns/selection-column.d.ts +6 -0
  17. package/dist/components/features/data-table/columns/selection-column.d.ts.map +1 -0
  18. package/dist/components/features/data-table/components/bulk-actions.d.ts +3 -0
  19. package/dist/components/features/data-table/components/bulk-actions.d.ts.map +1 -0
  20. package/dist/components/features/data-table/components/column-header.d.ts +3 -0
  21. package/dist/components/features/data-table/components/column-header.d.ts.map +1 -0
  22. package/dist/components/features/data-table/components/content.d.ts +3 -0
  23. package/dist/components/features/data-table/components/content.d.ts.map +1 -0
  24. package/dist/components/features/data-table/components/inline-content.d.ts +3 -0
  25. package/dist/components/features/data-table/components/inline-content.d.ts.map +1 -0
  26. package/dist/components/features/data-table/components/loading.d.ts +3 -0
  27. package/dist/components/features/data-table/components/loading.d.ts.map +1 -0
  28. package/dist/components/features/data-table/components/pagination.d.ts +3 -0
  29. package/dist/components/features/data-table/components/pagination.d.ts.map +1 -0
  30. package/dist/components/features/data-table/components/row-actions.d.ts +3 -0
  31. package/dist/components/features/data-table/components/row-actions.d.ts.map +1 -0
  32. package/dist/components/features/data-table/components/search.d.ts +3 -0
  33. package/dist/components/features/data-table/components/search.d.ts.map +1 -0
  34. package/dist/components/features/data-table/constants.d.ts +5 -0
  35. package/dist/components/features/data-table/constants.d.ts.map +1 -0
  36. package/dist/components/features/data-table/core/client-provider.d.ts +11 -0
  37. package/dist/components/features/data-table/core/client-provider.d.ts.map +1 -0
  38. package/dist/components/features/data-table/core/data-table-context.d.ts +10 -0
  39. package/dist/components/features/data-table/core/data-table-context.d.ts.map +1 -0
  40. package/dist/components/features/data-table/core/filter-engine.d.ts +16 -0
  41. package/dist/components/features/data-table/core/filter-engine.d.ts.map +1 -0
  42. package/dist/components/features/data-table/core/server-provider.d.ts +11 -0
  43. package/dist/components/features/data-table/core/server-provider.d.ts.map +1 -0
  44. package/dist/components/features/data-table/core/store.d.ts +3 -0
  45. package/dist/components/features/data-table/core/store.d.ts.map +1 -0
  46. package/dist/components/features/data-table/data-table.d.ts +29 -0
  47. package/dist/components/features/data-table/data-table.d.ts.map +1 -0
  48. package/dist/components/features/data-table/filters/checkbox-filter.d.ts +3 -0
  49. package/dist/components/features/data-table/filters/checkbox-filter.d.ts.map +1 -0
  50. package/dist/components/features/data-table/filters/date-picker-filter.d.ts +3 -0
  51. package/dist/components/features/data-table/filters/date-picker-filter.d.ts.map +1 -0
  52. package/dist/components/features/data-table/filters/select-filter.d.ts +3 -0
  53. package/dist/components/features/data-table/filters/select-filter.d.ts.map +1 -0
  54. package/dist/components/features/data-table/hooks/index.d.ts +4 -0
  55. package/dist/components/features/data-table/hooks/index.d.ts.map +1 -0
  56. package/dist/components/features/data-table/hooks/use-data-table-client.d.ts +20 -0
  57. package/dist/components/features/data-table/hooks/use-data-table-client.d.ts.map +1 -0
  58. package/dist/components/features/data-table/hooks/use-data-table-context.d.ts +2 -0
  59. package/dist/components/features/data-table/hooks/use-data-table-context.d.ts.map +1 -0
  60. package/dist/components/features/data-table/hooks/use-data-table-server.d.ts +30 -0
  61. package/dist/components/features/data-table/hooks/use-data-table-server.d.ts.map +1 -0
  62. package/dist/components/features/data-table/hooks/use-selectors.d.ts +81 -0
  63. package/dist/components/features/data-table/hooks/use-selectors.d.ts.map +1 -0
  64. package/dist/components/features/data-table/index.d.ts +11 -0
  65. package/dist/components/features/data-table/index.d.ts.map +1 -0
  66. package/dist/components/features/data-table/types.d.ts +305 -0
  67. package/dist/components/features/data-table/types.d.ts.map +1 -0
  68. package/dist/data-table/index.mjs +1477 -0
  69. package/dist/date-picker/index.mjs +5 -4
  70. package/dist/dialog/index.mjs +2 -2
  71. package/dist/{dialog-bnMMf9GD.mjs → dialog-B2EZJW-q.mjs} +2 -2
  72. package/dist/dropdown/index.mjs +1 -1
  73. package/dist/dropdown-menu-Xahj42Gr.mjs +87 -0
  74. package/dist/dropzone/index.mjs +1 -1
  75. package/dist/empty-content/index.mjs +1 -1
  76. package/dist/form/index.mjs +12 -12
  77. package/dist/grid/index.mjs +1 -1
  78. package/dist/hooks/index.mjs +2 -2
  79. package/dist/hover-card/index.mjs +1 -1
  80. package/dist/icons/index.mjs +1 -1
  81. package/dist/index.mjs +52 -48
  82. package/dist/input/index.mjs +2 -2
  83. package/dist/{input-fzXBheCN.mjs → input-D241oNEm.mjs} +1 -1
  84. package/dist/input-group/index.mjs +3 -3
  85. package/dist/{input-group-CPaFSTEV.mjs → input-group-uobp64zr.mjs} +2 -2
  86. package/dist/input-number/index.mjs +2 -2
  87. package/dist/{input-number-9o62JHRl.mjs → input-number-CEMgBk8-.mjs} +1 -1
  88. package/dist/input-with-addons/index.mjs +1 -1
  89. package/dist/label/index.mjs +2 -1
  90. package/dist/label-ClzLBWRT.mjs +16 -0
  91. package/dist/{label-_ste_Re3.mjs → label-byipFGok.mjs} +1 -12
  92. package/dist/loader-overlay/index.mjs +1 -1
  93. package/dist/map/index.mjs +8 -7
  94. package/dist/{map-WL6jhkSM.mjs → map-DupFPkJT.mjs} +6 -86
  95. package/dist/more-actions/index.mjs +2 -2
  96. package/dist/{more-actions-Ch1f6Mh3.mjs → more-actions-D6OyqZQS.mjs} +2 -2
  97. package/dist/page-title/index.mjs +1 -1
  98. package/dist/popover/index.mjs +1 -1
  99. package/dist/radio-group/index.mjs +1 -1
  100. package/dist/select/index.mjs +1 -1
  101. package/dist/{select-DVlEzD2W.mjs → select-BznmyqBr.mjs} +1 -1
  102. package/dist/sheet/index.mjs +2 -2
  103. package/dist/{sheet-BKiCwtNO.mjs → sheet-Bmayi68h.mjs} +2 -2
  104. package/dist/sidebar/index.mjs +6 -6
  105. package/dist/{sidebar-DfqezV8t.mjs → sidebar-D2zE7rPy.mjs} +5 -5
  106. package/dist/skeleton/index.mjs +1 -1
  107. package/dist/spinner/index.mjs +1 -1
  108. package/dist/stepper/index.mjs +1 -1
  109. package/dist/switch/index.mjs +1 -1
  110. package/dist/table/index.mjs +1 -1
  111. package/dist/tabs/index.mjs +1 -1
  112. package/dist/tag-input/index.mjs +2 -2
  113. package/dist/{tag-input-Di7SDNbK.mjs → tag-input-BI8IRBDH.mjs} +1 -1
  114. package/dist/task-queue/index.mjs +4 -4
  115. package/dist/{task-queue-dropdown-DW72ikDH.mjs → task-queue-dropdown-D6k067_W.mjs} +4 -4
  116. package/dist/textarea/index.mjs +2 -2
  117. package/dist/{textarea-CxE3YbC7.mjs → textarea-BZ85VFsJ.mjs} +1 -1
  118. package/dist/theme/index.mjs +1 -1
  119. package/dist/{to-api-format-C2xjQUcI.mjs → to-api-format-CXQ7knV4.mjs} +7 -662
  120. package/dist/toast/index.mjs +1 -1
  121. package/dist/tooltip/index.mjs +1 -1
  122. package/dist/typography/index.mjs +1 -1
  123. package/dist/{use-copy-to-clipboard-ki-WoTml.mjs → use-copy-to-clipboard-CC2hhyYI.mjs} +1 -1
  124. package/dist/{use-stepper-BaToCYMs.mjs → use-stepper-CU75TdjZ.mjs} +14 -14
  125. package/dist/{use-toast-mdn_CqRY.mjs → use-toast-BLBGnOC3.mjs} +1 -1
  126. package/dist/visually-hidden/index.mjs +1 -1
  127. package/package.json +15 -1
  128. package/dist/checkbox-LG1OKTpG.mjs +0 -34
  129. /package/dist/{close.icon-CMNMoXM_.mjs → close.icon-D2r5q3bj.mjs} +0 -0
  130. /package/dist/{col-lrLMZaTJ.mjs → col-Cg_2sTDA.mjs} +0 -0
  131. /package/dist/{collapsible-Bt9UYfv3.mjs → collapsible-Dw71o2um.mjs} +0 -0
  132. /package/dist/{dialog-DXBaT9gA.mjs → dialog-Bm4trnic.mjs} +0 -0
  133. /package/dist/{dropdown-DtSa_lqc.mjs → dropdown-DLZXinlT.mjs} +0 -0
  134. /package/dist/{dropzone-BkOnwrS4.mjs → dropzone-CGyjGnER.mjs} +0 -0
  135. /package/dist/{empty-content-BM9rzI13.mjs → empty-content-ByvwjHUs.mjs} +0 -0
  136. /package/dist/{hover-card-CUPfFUqE.mjs → hover-card-BNrHtWy6.mjs} +0 -0
  137. /package/dist/{input-DuyjEKEW.mjs → input-C-ZmsHkk.mjs} +0 -0
  138. /package/dist/{input-with-addons-BQn7KCTU.mjs → input-with-addons-DzuyGa6G.mjs} +0 -0
  139. /package/dist/{loader-overlay-DUaQSZQP.mjs → loader-overlay-CbxcjyHV.mjs} +0 -0
  140. /package/dist/{map-leaflet-imports-C4JYls8q.mjs → map-leaflet-imports-CgEyVRnp.mjs} +0 -0
  141. /package/dist/{page-title-BJuo81rT.mjs → page-title-CrYQ091u.mjs} +0 -0
  142. /package/dist/{popover-SQlKSz6L.mjs → popover-CYzXdp9q.mjs} +0 -0
  143. /package/dist/{radio-group-Oshv0b-U.mjs → radio-group-WZCIDQCH.mjs} +0 -0
  144. /package/dist/{sheet-CtnP6gTD.mjs → sheet-b9V9soz8.mjs} +0 -0
  145. /package/dist/{skeleton-vzbxA-DQ.mjs → skeleton-D3qW_KvG.mjs} +0 -0
  146. /package/dist/{spinner-BE7k2bAD.mjs → spinner-CKTGKv5n.mjs} +0 -0
  147. /package/dist/{stepper-SWB-u_nM.mjs → stepper-B07hPGG7.mjs} +0 -0
  148. /package/dist/{switch-Calk7Gyw.mjs → switch-CujyyOi6.mjs} +0 -0
  149. /package/dist/{table-CsXBcQLI.mjs → table-fZEvpdD-.mjs} +0 -0
  150. /package/dist/{tabs-D8n-dqnw.mjs → tabs-B7cW59gB.mjs} +0 -0
  151. /package/dist/{textarea-QYRcDEpK.mjs → textarea-BSkDKiej.mjs} +0 -0
  152. /package/dist/{theme.provider-CzCxEFFh.mjs → theme.provider-BG3cS9xe.mjs} +0 -0
  153. /package/dist/{tooltip-Dd3ActSS.mjs → tooltip-CbCWKEzu.mjs} +0 -0
  154. /package/dist/{typography-UA7ZZvgJ.mjs → typography-DdrxIJMd.mjs} +0 -0
  155. /package/dist/{use-debounce-B6wPrZV8.mjs → use-debounce-Dc95PFRX.mjs} +0 -0
  156. /package/dist/{visuallyhidden-aaTUk4Yo.mjs → visuallyhidden-CfBnXfvh.mjs} +0 -0
@@ -0,0 +1,1477 @@
1
+ import { t as cn } from "../utils-Bfgoe-Gm.mjs";
2
+ import { t as Button } from "../button-AzpnV-WB.mjs";
3
+ import { t as Checkbox } from "../checkbox-DB5_3E_l.mjs";
4
+ import "../dialog-Bm4trnic.mjs";
5
+ import { a as CommandInput, i as CommandGroup, o as CommandItem, r as CommandEmpty, s as CommandList, t as Command } from "../command-DQlO6uTL.mjs";
6
+ import { t as Input } from "../input-C-ZmsHkk.mjs";
7
+ import { t as Label } from "../label-ClzLBWRT.mjs";
8
+ import { i as DropdownMenuItem, l as DropdownMenuTrigger, r as DropdownMenuContent, t as DropdownMenu } from "../dropdown-menu-Xahj42Gr.mjs";
9
+ import { i as PopoverTrigger, r as PopoverContent, t as Popover } from "../popover-CYzXdp9q.mjs";
10
+ import { d as Select, f as SelectContent, h as SelectValue, m as SelectTrigger, p as SelectItem } from "../select-BznmyqBr.mjs";
11
+ import { t as Skeleton } from "../skeleton-D3qW_KvG.mjs";
12
+ import { c as TableRow, i as TableCell, n as TableBody, o as TableHead, s as TableHeader, t as Table } from "../table-fZEvpdD-.mjs";
13
+ import { t as CalendarDatePicker } from "../calendar-date-picker-BBAg78Lg.mjs";
14
+ import { cva } from "class-variance-authority";
15
+ import { ArrowDown, ArrowUp, ArrowUpDown, Check, ChevronDown, ChevronLeft, ChevronRight, MoreHorizontal, X } from "lucide-react";
16
+ import { createContext, use, useCallback, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ import { parseAsInteger, parseAsString, useQueryStates } from "nuqs";
19
+ import { flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
20
+
21
+ //#region src/components/features/data-table/constants.ts
22
+ const DEFAULT_PAGE_SIZE = 20;
23
+ const DEFAULT_PAGE_SIZES = [
24
+ 10,
25
+ 20,
26
+ 30,
27
+ 50
28
+ ];
29
+ const DEFAULT_DEBOUNCE_MS = 300;
30
+ const DEFAULT_LOADING_ROWS = 5;
31
+
32
+ //#endregion
33
+ //#region src/components/features/data-table/adapters/nuqs-adapter.ts
34
+ /**
35
+ * Serialize SortingState to URL-friendly string.
36
+ * Format: "name" (asc), "-name" (desc), comma-separated for multi-sort.
37
+ * Example: "-department,name" → [{id:"department",desc:true},{id:"name",desc:false}]
38
+ */
39
+ function serializeSorting(sorting) {
40
+ if (sorting.length === 0) return "";
41
+ return sorting.map((s) => s.desc ? `-${s.id}` : s.id).join(",");
42
+ }
43
+ /**
44
+ * Parse URL sort string back to SortingState.
45
+ */
46
+ function parseSorting(value) {
47
+ if (!value) return [];
48
+ return value.split(",").filter(Boolean).map((part) => {
49
+ if (part.startsWith("-")) return {
50
+ id: part.slice(1),
51
+ desc: true
52
+ };
53
+ return {
54
+ id: part,
55
+ desc: false
56
+ };
57
+ });
58
+ }
59
+ const coreSearchParams = {
60
+ sort: parseAsString.withDefault(""),
61
+ q: parseAsString.withDefault(""),
62
+ page: parseAsInteger.withDefault(0),
63
+ size: parseAsInteger.withDefault(DEFAULT_PAGE_SIZE)
64
+ };
65
+ /**
66
+ * Hook that creates a StateAdapter backed by nuqs URL query state.
67
+ *
68
+ * URL format:
69
+ * - `?sort=name` (asc) or `?sort=-name` (desc), comma-separated for multi-sort
70
+ * - `?q=search` for search text
71
+ * - `?page=0&size=20` for pagination
72
+ * - Custom filter keys as declared in options
73
+ *
74
+ * Requires `nuqs` to be installed in the consumer app.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * const stateAdapter = useNuqsAdapter({
79
+ * filters: {
80
+ * status: parseAsString.withDefault(''),
81
+ * department: parseAsArrayOf(parseAsString).withDefault([]),
82
+ * },
83
+ * })
84
+ * const tableState = useDataTableClient({ data, columns, stateAdapter })
85
+ * ```
86
+ */
87
+ function useNuqsAdapter(options = {}) {
88
+ const { filters: filterParsers } = options;
89
+ const [coreState, setCoreState] = useQueryStates(coreSearchParams);
90
+ const hasFilters = filterParsers != null && Object.keys(filterParsers).length > 0;
91
+ const [filterState, setFilterState] = useQueryStates(hasFilters ? filterParsers : { _dt: parseAsString.withDefault("") });
92
+ return useMemo(() => ({
93
+ read: () => ({
94
+ sorting: parseSorting(coreState.sort),
95
+ search: coreState.q,
96
+ pageIndex: coreState.page,
97
+ pageSize: coreState.size,
98
+ ...hasFilters ? { filters: filterState } : {}
99
+ }),
100
+ write: (state) => {
101
+ setCoreState({
102
+ sort: serializeSorting(state.sorting),
103
+ q: state.search,
104
+ page: state.pageIndex ?? 0,
105
+ size: state.pageSize ?? DEFAULT_PAGE_SIZE
106
+ });
107
+ if (hasFilters && filterParsers) {
108
+ const update = {};
109
+ for (const key of Object.keys(filterParsers)) update[key] = state.filters?.[key] ?? null;
110
+ setFilterState(update);
111
+ }
112
+ }
113
+ }), [
114
+ coreState,
115
+ filterState,
116
+ hasFilters,
117
+ setCoreState,
118
+ setFilterState,
119
+ filterParsers
120
+ ]);
121
+ }
122
+
123
+ //#endregion
124
+ //#region src/components/features/data-table/columns/selection-column.tsx
125
+ const SELECTION_COLUMN_ID = "select";
126
+ function createSelectionColumn(options = {}) {
127
+ const { className, headerClassName, renderHeader, renderCell } = options;
128
+ return {
129
+ id: SELECTION_COLUMN_ID,
130
+ size: 40,
131
+ enableSorting: false,
132
+ enableHiding: false,
133
+ header: renderHeader ?? (({ table }) => /* @__PURE__ */ jsx(Checkbox, {
134
+ checked: table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected() && "indeterminate",
135
+ onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value),
136
+ "aria-label": "Select all",
137
+ className: headerClassName
138
+ })),
139
+ cell: renderCell ?? (({ row }) => /* @__PURE__ */ jsx(Checkbox, {
140
+ checked: row.getIsSelected(),
141
+ onCheckedChange: (value) => row.toggleSelected(!!value),
142
+ "aria-label": "Select row",
143
+ className
144
+ }))
145
+ };
146
+ }
147
+ function hasSelectionColumn(columns) {
148
+ return columns.some((col) => "id" in col && col.id === SELECTION_COLUMN_ID);
149
+ }
150
+ function withSelectionColumn(columns, options = {}) {
151
+ if (hasSelectionColumn(columns)) return columns;
152
+ return [createSelectionColumn(options), ...columns];
153
+ }
154
+
155
+ //#endregion
156
+ //#region src/components/features/data-table/core/filter-engine.ts
157
+ const FILTER_STRATEGIES = {
158
+ "checkbox": (cellValue, filterValue) => {
159
+ if (filterValue == null) return true;
160
+ if (Array.isArray(filterValue) && filterValue.length === 0) return true;
161
+ if (!Array.isArray(filterValue)) return cellValue === filterValue;
162
+ if (Array.isArray(cellValue)) return cellValue.some((v) => filterValue.includes(v));
163
+ return filterValue.includes(cellValue);
164
+ },
165
+ "select": (cellValue, filterValue) => {
166
+ if (filterValue == null || filterValue === "") return true;
167
+ return cellValue === filterValue;
168
+ },
169
+ "date-gte": (cellValue, filterValue) => {
170
+ if (!filterValue) return true;
171
+ const cell = new Date(cellValue);
172
+ const filter = new Date(filterValue);
173
+ if (Number.isNaN(cell.getTime()) || Number.isNaN(filter.getTime())) return true;
174
+ return cell >= filter;
175
+ },
176
+ "date-lte": (cellValue, filterValue) => {
177
+ if (!filterValue) return true;
178
+ const cell = new Date(cellValue);
179
+ const filter = new Date(filterValue);
180
+ if (Number.isNaN(cell.getTime()) || Number.isNaN(filter.getTime())) return true;
181
+ return cell <= filter;
182
+ }
183
+ };
184
+ function resolveStrategy(strategy) {
185
+ if (!strategy) return void 0;
186
+ if (typeof strategy === "function") return strategy;
187
+ return FILTER_STRATEGIES[strategy];
188
+ }
189
+ function applyFilters(data, filters, search, registeredFilters, customFilterFns, searchConfig) {
190
+ const hasFilters = Object.keys(filters).length > 0;
191
+ const hasSearch = search.length > 0;
192
+ if (!hasFilters && !hasSearch) return data;
193
+ return data.filter((row) => {
194
+ if (hasFilters) for (const [column, value] of Object.entries(filters)) {
195
+ const fn = customFilterFns[column] ?? resolveStrategy(registeredFilters.get(column));
196
+ if (!fn) {
197
+ console.warn(`[DataTable] No filter strategy registered for column "${column}". Filter ignored.`);
198
+ continue;
199
+ }
200
+ const cellValue = row[column];
201
+ if (!fn(cellValue, value)) return false;
202
+ }
203
+ if (hasSearch) {
204
+ const query = search.toLowerCase();
205
+ if (searchConfig.searchFn) return searchConfig.searchFn(row, search);
206
+ if (searchConfig.searchableColumns && searchConfig.searchableColumns.length > 0) return searchConfig.searchableColumns.some((col) => {
207
+ const cellValue = row[col];
208
+ return cellValue != null && String(cellValue).toLowerCase().includes(query);
209
+ });
210
+ return Object.values(row).some((val) => {
211
+ if (val == null) return false;
212
+ return String(val).toLowerCase().includes(query);
213
+ });
214
+ }
215
+ return true;
216
+ });
217
+ }
218
+
219
+ //#endregion
220
+ //#region src/components/features/data-table/core/store.ts
221
+ function createDataTableStore(options) {
222
+ const registeredFilters = /* @__PURE__ */ new Map();
223
+ const listeners = /* @__PURE__ */ new Set();
224
+ function computeFilteredData(s) {
225
+ if (s.mode === "server") return s.data;
226
+ return applyFilters(s.data, s.filters, s.search, registeredFilters, options.filterFns ?? {}, {
227
+ searchFn: options.searchFn,
228
+ searchableColumns: options.searchableColumns
229
+ });
230
+ }
231
+ let state = {
232
+ data: options.data,
233
+ filteredData: options.data,
234
+ sorting: options.defaultSort ?? [],
235
+ filters: options.defaultFilters ?? {},
236
+ search: "",
237
+ rowSelection: {},
238
+ pageIndex: 0,
239
+ pageSize: options.pageSize ?? DEFAULT_PAGE_SIZE,
240
+ mode: options.mode,
241
+ isLoading: false,
242
+ error: null,
243
+ inlineContents: []
244
+ };
245
+ if (options.defaultFilters && Object.keys(options.defaultFilters).length > 0) state = {
246
+ ...state,
247
+ filteredData: computeFilteredData(state)
248
+ };
249
+ function notify() {
250
+ for (const listener of listeners) listener();
251
+ }
252
+ function setState(next) {
253
+ state = next;
254
+ notify();
255
+ }
256
+ return {
257
+ getSnapshot: () => state,
258
+ subscribe: (listener) => {
259
+ listeners.add(listener);
260
+ return () => listeners.delete(listener);
261
+ },
262
+ setData: (data) => {
263
+ const next = {
264
+ ...state,
265
+ data,
266
+ pageIndex: 0,
267
+ rowSelection: {}
268
+ };
269
+ setState({
270
+ ...next,
271
+ filteredData: computeFilteredData(next)
272
+ });
273
+ },
274
+ setServerData: (data) => {
275
+ setState({
276
+ ...state,
277
+ data,
278
+ filteredData: data
279
+ });
280
+ },
281
+ setTable: (_t) => {},
282
+ setSorting: (sorting) => {
283
+ setState({
284
+ ...state,
285
+ sorting,
286
+ rowSelection: {}
287
+ });
288
+ },
289
+ setFilter: (key, value) => {
290
+ const next = {
291
+ ...state,
292
+ filters: {
293
+ ...state.filters,
294
+ [key]: value
295
+ },
296
+ rowSelection: {},
297
+ pageIndex: 0
298
+ };
299
+ setState({
300
+ ...next,
301
+ filteredData: computeFilteredData(next)
302
+ });
303
+ },
304
+ clearFilter: (key) => {
305
+ const filters = Object.fromEntries(Object.entries(state.filters).filter(([k]) => k !== key));
306
+ const next = {
307
+ ...state,
308
+ filters,
309
+ rowSelection: {},
310
+ pageIndex: 0
311
+ };
312
+ setState({
313
+ ...next,
314
+ filteredData: computeFilteredData(next)
315
+ });
316
+ },
317
+ clearAllFilters: () => {
318
+ const next = {
319
+ ...state,
320
+ filters: {},
321
+ rowSelection: {},
322
+ pageIndex: 0
323
+ };
324
+ setState({
325
+ ...next,
326
+ filteredData: computeFilteredData(next)
327
+ });
328
+ },
329
+ setSearch: (search) => {
330
+ const next = {
331
+ ...state,
332
+ search,
333
+ rowSelection: {},
334
+ pageIndex: 0
335
+ };
336
+ setState({
337
+ ...next,
338
+ filteredData: computeFilteredData(next)
339
+ });
340
+ },
341
+ clearSearch: () => {
342
+ const next = {
343
+ ...state,
344
+ search: "",
345
+ rowSelection: {},
346
+ pageIndex: 0
347
+ };
348
+ setState({
349
+ ...next,
350
+ filteredData: computeFilteredData(next)
351
+ });
352
+ },
353
+ setRowSelection: (rowSelection) => {
354
+ setState({
355
+ ...state,
356
+ rowSelection
357
+ });
358
+ },
359
+ setPageIndex: (pageIndex) => {
360
+ setState({
361
+ ...state,
362
+ pageIndex,
363
+ rowSelection: {}
364
+ });
365
+ },
366
+ setPageSize: (pageSize) => {
367
+ setState({
368
+ ...state,
369
+ pageSize,
370
+ pageIndex: 0,
371
+ rowSelection: {}
372
+ });
373
+ },
374
+ setLoading: (isLoading) => {
375
+ setState({
376
+ ...state,
377
+ isLoading
378
+ });
379
+ },
380
+ setError: (error) => {
381
+ setState({
382
+ ...state,
383
+ error
384
+ });
385
+ },
386
+ registerFilter: (column, strategy) => {
387
+ registeredFilters.set(column, strategy);
388
+ const filteredData = computeFilteredData(state);
389
+ setState({
390
+ ...state,
391
+ filteredData
392
+ });
393
+ },
394
+ unregisterFilter: (column) => {
395
+ registeredFilters.delete(column);
396
+ if (column in state.filters) {
397
+ const filteredData = computeFilteredData(state);
398
+ setState({
399
+ ...state,
400
+ filteredData
401
+ });
402
+ }
403
+ },
404
+ registerInlineContent: (entry) => {
405
+ const existing = state.inlineContents.findIndex((e) => e.id === entry.id);
406
+ const inlineContents = existing >= 0 ? state.inlineContents.map((e, i) => i === existing ? entry : e) : [...state.inlineContents, entry];
407
+ setState({
408
+ ...state,
409
+ inlineContents
410
+ });
411
+ },
412
+ unregisterInlineContent: (id) => {
413
+ const inlineContents = state.inlineContents.filter((e) => e.id !== id);
414
+ setState({
415
+ ...state,
416
+ inlineContents
417
+ });
418
+ }
419
+ };
420
+ }
421
+
422
+ //#endregion
423
+ //#region src/components/features/data-table/core/data-table-context.tsx
424
+ const DataTableStoreContext = createContext(null);
425
+ const TableInstanceContext = createContext(null);
426
+ const DataTableContext = createContext(null);
427
+ function useDataTableStore() {
428
+ const store = use(DataTableStoreContext);
429
+ if (!store) throw new Error("useDataTableStore must be used within a <DataTable.Client> or <DataTable.Server> provider");
430
+ return store;
431
+ }
432
+ function useTableInstance() {
433
+ const table = use(TableInstanceContext);
434
+ if (!table) throw new Error("useTableInstance must be used within a <DataTable.Client> or <DataTable.Server> provider");
435
+ return table;
436
+ }
437
+
438
+ //#endregion
439
+ //#region src/components/features/data-table/hooks/use-selectors.ts
440
+ function shallowEqual(a, b) {
441
+ const keysA = Object.keys(a);
442
+ const keysB = Object.keys(b);
443
+ if (keysA.length !== keysB.length) return false;
444
+ for (const key of keysA) {
445
+ const va = a[key];
446
+ const vb = b[key];
447
+ if (va === vb) continue;
448
+ if (Array.isArray(va) && Array.isArray(vb)) {
449
+ if (va.length !== vb.length) return false;
450
+ for (let i = 0; i < va.length; i++) if (va[i] !== vb[i]) return false;
451
+ continue;
452
+ }
453
+ return false;
454
+ }
455
+ return true;
456
+ }
457
+ function useSliceSelector(selector) {
458
+ const store = useDataTableStore();
459
+ const cachedRef = useRef(null);
460
+ const getSnapshot = useCallback(() => {
461
+ const next = selector(store.getSnapshot());
462
+ if (cachedRef.current && shallowEqual(cachedRef.current, next)) return cachedRef.current;
463
+ cachedRef.current = next;
464
+ return next;
465
+ }, [store, selector]);
466
+ return useSyncExternalStore(store.subscribe, getSnapshot);
467
+ }
468
+ function useDataTableFilters() {
469
+ const store = useDataTableStore();
470
+ return useSliceSelector(useCallback((state) => ({
471
+ filters: state.filters,
472
+ setFilter: store.setFilter,
473
+ clearFilter: store.clearFilter,
474
+ clearAllFilters: store.clearAllFilters,
475
+ registerFilter: store.registerFilter,
476
+ unregisterFilter: store.unregisterFilter
477
+ }), [store]));
478
+ }
479
+ function useDataTableSearch() {
480
+ const store = useDataTableStore();
481
+ return useSliceSelector(useCallback((state) => ({
482
+ search: state.search,
483
+ setSearch: store.setSearch,
484
+ clearSearch: store.clearSearch
485
+ }), [store]));
486
+ }
487
+ function useDataTableSorting() {
488
+ const store = useDataTableStore();
489
+ return useSliceSelector(useCallback((state) => ({
490
+ sorting: state.sorting,
491
+ setSorting: store.setSorting
492
+ }), [store]));
493
+ }
494
+ function useDataTableSelection() {
495
+ const store = useDataTableStore();
496
+ const table = useTableInstance();
497
+ return useSliceSelector(useCallback((state) => ({
498
+ rowSelection: state.rowSelection,
499
+ setRowSelection: store.setRowSelection,
500
+ selectedRows: table.getFilteredSelectedRowModel().rows.map((r) => r.original)
501
+ }), [store, table]));
502
+ }
503
+ function useDataTablePagination() {
504
+ const store = useDataTableStore();
505
+ const table = useTableInstance();
506
+ const nextPage = useCallback(() => table.nextPage(), [table]);
507
+ const prevPage = useCallback(() => table.previousPage(), [table]);
508
+ return useSliceSelector(useCallback((state) => ({
509
+ canNextPage: table.getCanNextPage(),
510
+ canPrevPage: table.getCanPreviousPage(),
511
+ nextPage,
512
+ prevPage,
513
+ pageIndex: state.pageIndex,
514
+ pageCount: table.getPageCount(),
515
+ setPageIndex: store.setPageIndex,
516
+ pageSize: state.pageSize,
517
+ setPageSize: store.setPageSize,
518
+ totalRows: state.filteredData.length
519
+ }), [
520
+ store,
521
+ table,
522
+ nextPage,
523
+ prevPage
524
+ ]));
525
+ }
526
+ function useDataTableRows() {
527
+ const table = useTableInstance();
528
+ return useSliceSelector(useCallback((_state) => ({
529
+ rows: table.getRowModel().rows,
530
+ headerGroups: table.getHeaderGroups(),
531
+ totalColumns: table.getAllColumns().length
532
+ }), [table]));
533
+ }
534
+ function useDataTableLoading() {
535
+ return useSliceSelector(useCallback((state) => ({
536
+ isLoading: state.isLoading,
537
+ error: state.error
538
+ }), []));
539
+ }
540
+ function useDataTableInlineContents() {
541
+ const store = useDataTableStore();
542
+ return useSliceSelector(useCallback((state) => ({
543
+ inlineContents: state.inlineContents,
544
+ registerInlineContent: store.registerInlineContent,
545
+ unregisterInlineContent: store.unregisterInlineContent
546
+ }), [store]));
547
+ }
548
+ function useDataTableContext() {
549
+ const store = useDataTableStore();
550
+ const table = useTableInstance();
551
+ const state = useSyncExternalStore(store.subscribe, store.getSnapshot);
552
+ return {
553
+ table,
554
+ mode: state.mode,
555
+ sorting: state.sorting,
556
+ filters: state.filters,
557
+ search: state.search,
558
+ rowSelection: state.rowSelection,
559
+ isLoading: state.isLoading,
560
+ setSorting: store.setSorting,
561
+ setFilter: store.setFilter,
562
+ clearFilter: store.clearFilter,
563
+ clearAllFilters: store.clearAllFilters,
564
+ setSearch: store.setSearch,
565
+ clearSearch: store.clearSearch,
566
+ setRowSelection: store.setRowSelection,
567
+ pagination: {
568
+ canNextPage: table.getCanNextPage(),
569
+ canPrevPage: table.getCanPreviousPage(),
570
+ nextPage: () => table.nextPage(),
571
+ prevPage: () => table.previousPage(),
572
+ pageIndex: state.pageIndex,
573
+ pageCount: table.getPageCount(),
574
+ setPageIndex: store.setPageIndex,
575
+ pageSize: state.pageSize,
576
+ setPageSize: store.setPageSize
577
+ },
578
+ inlineContents: state.inlineContents,
579
+ registerInlineContent: store.registerInlineContent,
580
+ unregisterInlineContent: store.unregisterInlineContent
581
+ };
582
+ }
583
+
584
+ //#endregion
585
+ //#region src/components/features/data-table/components/bulk-actions.tsx
586
+ function DataTableBulkActions({ children, className }) {
587
+ const { selectedRows } = useDataTableSelection();
588
+ if (selectedRows.length === 0) return null;
589
+ return /* @__PURE__ */ jsx("div", {
590
+ "data-slot": "dt-bulk-actions",
591
+ className,
592
+ children: children(selectedRows)
593
+ });
594
+ }
595
+
596
+ //#endregion
597
+ //#region src/components/features/data-table/components/column-header.tsx
598
+ function DataTableColumnHeader({ column, title, className }) {
599
+ if (!column.getCanSort()) return /* @__PURE__ */ jsx("div", {
600
+ className: cn(className),
601
+ "data-slot": "dt-column-header",
602
+ children: title
603
+ });
604
+ const sorted = column.getIsSorted();
605
+ return /* @__PURE__ */ jsx("div", {
606
+ className: cn("flex items-center gap-2", className),
607
+ "data-slot": "dt-column-header",
608
+ children: /* @__PURE__ */ jsxs("button", {
609
+ type: "button",
610
+ className: "flex items-center gap-1 hover:text-foreground -ml-3 h-8 px-3 cursor-pointer",
611
+ onClick: column.getToggleSortingHandler(),
612
+ children: [/* @__PURE__ */ jsx("span", { children: title }), sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "size-4" }) : sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-4" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "size-4" })]
613
+ })
614
+ });
615
+ }
616
+
617
+ //#endregion
618
+ //#region src/components/features/data-table/components/content.tsx
619
+ function resolveClassName(value, item) {
620
+ if (typeof value === "function") return value(item);
621
+ return value;
622
+ }
623
+ function renderInlineContentRow(entry, colSpan, rows) {
624
+ return /* @__PURE__ */ jsx(TableRow, {
625
+ "data-slot": "dt-inline-content",
626
+ "data-position": entry.position,
627
+ className: cn("transition-all duration-200", entry.className),
628
+ children: /* @__PURE__ */ jsx(TableCell, {
629
+ colSpan,
630
+ children: entry.render({
631
+ onClose: entry.onClose,
632
+ rowData: entry.position === "row" ? rows.find((r) => r.id === entry.rowId)?.original ?? null : null
633
+ })
634
+ })
635
+ }, entry.id);
636
+ }
637
+ function DataTableContent({ emptyMessage, className, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName }) {
638
+ const { rows, headerGroups, totalColumns } = useDataTableRows();
639
+ const { inlineContents } = useDataTableInlineContents();
640
+ const openInlineContents = useMemo(() => inlineContents.filter((e) => e.open), [inlineContents]);
641
+ const colSpan = totalColumns;
642
+ return /* @__PURE__ */ jsx("div", {
643
+ className: cn("datum-ui-data-table", className),
644
+ "data-slot": "dt",
645
+ style: { overflowX: "auto" },
646
+ children: /* @__PURE__ */ jsxs(Table, {
647
+ className: cn(tableClassName),
648
+ "data-slot": "dt-table",
649
+ children: [/* @__PURE__ */ jsx(TableHeader, {
650
+ className: cn(headerClassName),
651
+ "data-slot": "dt-header",
652
+ children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx(TableRow, {
653
+ className: cn(headerRowClassName),
654
+ "data-slot": "dt-header-row",
655
+ children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx(TableHead, {
656
+ className: cn(headerCellClassName),
657
+ "data-slot": "dt-header-cell",
658
+ children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())
659
+ }, header.id))
660
+ }, headerGroup.id))
661
+ }), /* @__PURE__ */ jsxs(TableBody, {
662
+ className: cn(bodyClassName),
663
+ "data-slot": "dt-body",
664
+ children: [openInlineContents.filter((e) => e.position === "top").map((entry) => renderInlineContentRow(entry, colSpan, rows)), rows.length > 0 ? rows.map((row) => {
665
+ const rowEntry = openInlineContents.find((e) => e.position === "row" && e.rowId === row.id);
666
+ if (rowEntry) return renderInlineContentRow(rowEntry, colSpan, rows);
667
+ return /* @__PURE__ */ jsx(TableRow, {
668
+ className: cn(resolveClassName(rowClassName, row)),
669
+ style: { transitionProperty: "none" },
670
+ "data-slot": "dt-row",
671
+ "data-state": row.getIsSelected() ? "selected" : void 0,
672
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, {
673
+ className: cn(resolveClassName(cellClassName, cell)),
674
+ "data-slot": "dt-cell",
675
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
676
+ }, cell.id))
677
+ }, row.id);
678
+ }) : /* @__PURE__ */ jsx(TableRow, {
679
+ "data-slot": "dt-row",
680
+ children: /* @__PURE__ */ jsx(TableCell, {
681
+ colSpan,
682
+ className: "h-24 text-center",
683
+ "data-slot": "dt-empty",
684
+ children: emptyMessage ?? "No results."
685
+ })
686
+ })]
687
+ })]
688
+ })
689
+ });
690
+ }
691
+
692
+ //#endregion
693
+ //#region src/components/features/data-table/components/inline-content.tsx
694
+ function DataTableInlineContent({ position, rowId, open, onClose, className, children }) {
695
+ const id = useId();
696
+ const { registerInlineContent, unregisterInlineContent } = useDataTableInlineContents();
697
+ const initialRender = useRef(true);
698
+ useEffect(() => {
699
+ registerInlineContent({
700
+ id,
701
+ position,
702
+ rowId,
703
+ open,
704
+ onClose,
705
+ className,
706
+ render: children
707
+ });
708
+ return () => {
709
+ unregisterInlineContent(id);
710
+ };
711
+ }, [
712
+ id,
713
+ registerInlineContent,
714
+ unregisterInlineContent
715
+ ]);
716
+ useEffect(() => {
717
+ if (initialRender.current) {
718
+ initialRender.current = false;
719
+ return;
720
+ }
721
+ registerInlineContent({
722
+ id,
723
+ position,
724
+ rowId,
725
+ open,
726
+ onClose,
727
+ className,
728
+ render: children
729
+ });
730
+ }, [
731
+ id,
732
+ position,
733
+ rowId,
734
+ open,
735
+ onClose,
736
+ className,
737
+ children,
738
+ registerInlineContent
739
+ ]);
740
+ return null;
741
+ }
742
+
743
+ //#endregion
744
+ //#region src/components/features/data-table/components/loading.tsx
745
+ function DataTableLoading({ rows = DEFAULT_LOADING_ROWS, columns = 4, className }) {
746
+ return /* @__PURE__ */ jsx("div", {
747
+ className,
748
+ "data-slot": "dt-loading",
749
+ children: /* @__PURE__ */ jsxs("div", {
750
+ className: "rounded-md border",
751
+ children: [/* @__PURE__ */ jsx("div", {
752
+ className: "border-b",
753
+ children: /* @__PURE__ */ jsx("div", {
754
+ className: "flex gap-4 p-4",
755
+ children: Array.from({ length: columns }, (_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-4 flex-1" }, i))
756
+ })
757
+ }), Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ jsx("div", {
758
+ className: "flex gap-4 border-b p-4 last:border-b-0",
759
+ children: Array.from({ length: columns }, (_, colIndex) => /* @__PURE__ */ jsx(Skeleton, { className: "h-4 flex-1" }, colIndex))
760
+ }, rowIndex))]
761
+ })
762
+ });
763
+ }
764
+
765
+ //#endregion
766
+ //#region src/components/features/data-table/components/pagination.tsx
767
+ /**
768
+ * Generates page numbers with ellipsis for large page counts.
769
+ * Shows up to 7 items: first, last, current +/- 1 neighbor, and ellipsis gaps.
770
+ */
771
+ function getPageNumbers(currentPage, totalPages) {
772
+ if (totalPages <= 7) return Array.from({ length: totalPages }, (_, i) => i + 1);
773
+ const pages = [1];
774
+ const current = currentPage + 1;
775
+ if (current <= 4) {
776
+ for (let i = 2; i <= 5; i++) pages.push(i);
777
+ pages.push("...");
778
+ pages.push(totalPages);
779
+ } else if (current >= totalPages - 3) {
780
+ pages.push("...");
781
+ for (let i = totalPages - 4; i <= totalPages; i++) pages.push(i);
782
+ } else {
783
+ pages.push("...");
784
+ for (let i = current - 1; i <= current + 1; i++) pages.push(i);
785
+ pages.push("...");
786
+ pages.push(totalPages);
787
+ }
788
+ return pages;
789
+ }
790
+ function DataTablePagination({ pageSizes = DEFAULT_PAGE_SIZES, className }) {
791
+ const { canNextPage, canPrevPage, nextPage, prevPage, pageIndex, pageCount, setPageIndex, pageSize, setPageSize, totalRows } = useDataTablePagination();
792
+ const isClientMode = pageCount > 0;
793
+ const startRow = pageIndex * pageSize + 1;
794
+ const endRow = Math.min((pageIndex + 1) * pageSize, totalRows);
795
+ const pageNumbers = useMemo(() => getPageNumbers(pageIndex, pageCount), [pageIndex, pageCount]);
796
+ return /* @__PURE__ */ jsxs("div", {
797
+ className: cn("flex flex-col-reverse items-center justify-between gap-4 px-2 py-4 sm:flex-row", className),
798
+ "data-slot": "dt-pagination",
799
+ children: [/* @__PURE__ */ jsxs("div", {
800
+ className: "flex items-center gap-4",
801
+ children: [isClientMode && totalRows > 0 && /* @__PURE__ */ jsxs("span", {
802
+ className: "text-sm text-muted-foreground whitespace-nowrap",
803
+ children: [
804
+ "Showing",
805
+ " ",
806
+ startRow,
807
+ " ",
808
+ "to",
809
+ " ",
810
+ endRow,
811
+ " ",
812
+ "of",
813
+ " ",
814
+ totalRows,
815
+ " ",
816
+ "rows"
817
+ ]
818
+ }), /* @__PURE__ */ jsxs("div", {
819
+ className: "flex items-center gap-2",
820
+ children: [/* @__PURE__ */ jsx("span", {
821
+ className: "text-sm text-muted-foreground whitespace-nowrap",
822
+ children: "Rows per page"
823
+ }), /* @__PURE__ */ jsxs(Select, {
824
+ value: String(pageSize),
825
+ onValueChange: (value) => setPageSize(Number(value)),
826
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
827
+ className: "h-8 w-[70px]",
828
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: String(pageSize) })
829
+ }), /* @__PURE__ */ jsx(SelectContent, {
830
+ side: "top",
831
+ children: pageSizes.map((size) => /* @__PURE__ */ jsx(SelectItem, {
832
+ value: String(size),
833
+ children: size
834
+ }, size))
835
+ })]
836
+ })]
837
+ })]
838
+ }), /* @__PURE__ */ jsxs("div", {
839
+ className: "flex items-center gap-1",
840
+ children: [
841
+ /* @__PURE__ */ jsx(Button, {
842
+ variant: "outline",
843
+ size: "icon",
844
+ className: "size-8",
845
+ onClick: prevPage,
846
+ disabled: !canPrevPage,
847
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" })
848
+ }),
849
+ isClientMode && pageCount > 1 ? pageNumbers.map((page, index) => {
850
+ if (page === "...") return /* @__PURE__ */ jsx("span", {
851
+ className: "px-2 text-sm text-muted-foreground",
852
+ children: "..."
853
+ }, `ellipsis-${index}`);
854
+ const isActive = page === pageIndex + 1;
855
+ return /* @__PURE__ */ jsx(Button, {
856
+ variant: isActive ? "default" : "outline",
857
+ size: "sm",
858
+ className: cn("h-8 min-w-8 px-2", isActive && "font-semibold"),
859
+ onClick: () => setPageIndex(page - 1),
860
+ disabled: isActive,
861
+ children: page
862
+ }, page);
863
+ }) : !isClientMode && /* @__PURE__ */ jsxs("span", {
864
+ className: "px-2 text-sm text-muted-foreground",
865
+ children: [
866
+ "Page",
867
+ " ",
868
+ pageIndex + 1
869
+ ]
870
+ }),
871
+ /* @__PURE__ */ jsx(Button, {
872
+ variant: "outline",
873
+ size: "icon",
874
+ className: "size-8",
875
+ onClick: nextPage,
876
+ disabled: !canNextPage,
877
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
878
+ })
879
+ ]
880
+ })]
881
+ });
882
+ }
883
+
884
+ //#endregion
885
+ //#region src/components/features/data-table/components/row-actions.tsx
886
+ function DataTableRowActions({ row, actions, isLoading = false, className }) {
887
+ const data = row.original;
888
+ const visibleActions = actions.filter((action) => {
889
+ if (action.hidden === void 0) return true;
890
+ return typeof action.hidden === "function" ? !action.hidden(data) : !action.hidden;
891
+ });
892
+ if (visibleActions.length === 0) return null;
893
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
894
+ asChild: true,
895
+ children: /* @__PURE__ */ jsxs(Button, {
896
+ variant: "ghost",
897
+ size: "sm",
898
+ className,
899
+ disabled: isLoading,
900
+ "data-slot": "dt-row-actions",
901
+ children: [/* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
902
+ className: "sr-only",
903
+ children: "Open menu"
904
+ })]
905
+ })
906
+ }), /* @__PURE__ */ jsx(DropdownMenuContent, {
907
+ align: "end",
908
+ children: visibleActions.map((action) => {
909
+ return /* @__PURE__ */ jsxs(DropdownMenuItem, {
910
+ disabled: typeof action.disabled === "function" ? action.disabled(data) : action.disabled ?? false,
911
+ onClick: () => action.onClick(data),
912
+ className: action.variant === "destructive" ? "text-destructive" : void 0,
913
+ children: [action.icon && /* @__PURE__ */ jsx(action.icon, { className: "mr-2 size-4" }), action.label]
914
+ }, action.label);
915
+ })
916
+ })] });
917
+ }
918
+
919
+ //#endregion
920
+ //#region src/components/features/data-table/components/search.tsx
921
+ function DataTableSearch({ placeholder = "Search...", debounceMs = DEFAULT_DEBOUNCE_MS, className }) {
922
+ const { search, setSearch } = useDataTableSearch();
923
+ const [inputValue, setInputValue] = useState(search);
924
+ useEffect(() => {
925
+ setInputValue(search);
926
+ }, [search]);
927
+ useEffect(() => {
928
+ const timer = setTimeout(() => {
929
+ if (inputValue !== search) setSearch(inputValue);
930
+ }, debounceMs);
931
+ return () => clearTimeout(timer);
932
+ }, [
933
+ inputValue,
934
+ debounceMs,
935
+ search,
936
+ setSearch
937
+ ]);
938
+ return /* @__PURE__ */ jsx(Input, {
939
+ placeholder,
940
+ value: inputValue,
941
+ onChange: (e) => setInputValue(e.target.value),
942
+ className,
943
+ "data-slot": "dt-search"
944
+ });
945
+ }
946
+
947
+ //#endregion
948
+ //#region src/components/features/data-table/core/client-provider.tsx
949
+ function ClientProvider({ store, table, className, children }) {
950
+ return /* @__PURE__ */ jsx(DataTableStoreContext, {
951
+ value: store,
952
+ children: /* @__PURE__ */ jsx(TableInstanceContext, {
953
+ value: table,
954
+ children: /* @__PURE__ */ jsx("div", {
955
+ className,
956
+ children
957
+ })
958
+ })
959
+ });
960
+ }
961
+
962
+ //#endregion
963
+ //#region src/components/features/data-table/core/server-provider.tsx
964
+ function ServerProvider({ store, table, className, children }) {
965
+ return /* @__PURE__ */ jsx(DataTableStoreContext, {
966
+ value: store,
967
+ children: /* @__PURE__ */ jsx(TableInstanceContext, {
968
+ value: table,
969
+ children: /* @__PURE__ */ jsx("div", {
970
+ className,
971
+ children
972
+ })
973
+ })
974
+ });
975
+ }
976
+
977
+ //#endregion
978
+ //#region ../shadcn/ui/badge.tsx
979
+ /**
980
+ * Vanilla shadcn/ui Badge Component
981
+ * Pure shadcn badge without Datum customizations
982
+ * For Datum-specific variants (sunglow, butter), import from @/modules/datum-ui
983
+ */
984
+ const badgeVariants = cva("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2", {
985
+ variants: { variant: {
986
+ default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
987
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
988
+ destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
989
+ outline: "text-foreground"
990
+ } },
991
+ defaultVariants: { variant: "default" }
992
+ });
993
+ function Badge({ className, variant, ...props }) {
994
+ return /* @__PURE__ */ jsx("div", {
995
+ className: cn(badgeVariants({ variant }), className),
996
+ ...props
997
+ });
998
+ }
999
+
1000
+ //#endregion
1001
+ //#region src/components/features/data-table/filters/checkbox-filter.tsx
1002
+ const MAX_VISIBLE_BADGES = 2;
1003
+ function CheckboxFilter({ column, label, options, className, checkboxPopoverClassName }) {
1004
+ const { filters, setFilter, clearFilter, registerFilter, unregisterFilter } = useDataTableFilters();
1005
+ const [open, setOpen] = useState(false);
1006
+ useEffect(() => {
1007
+ registerFilter(column, "checkbox");
1008
+ return () => unregisterFilter(column);
1009
+ }, [
1010
+ column,
1011
+ registerFilter,
1012
+ unregisterFilter
1013
+ ]);
1014
+ const selectedValues = filters[column] ?? [];
1015
+ const updateValues = (newValues) => {
1016
+ if (newValues.length > 0) setFilter(column, newValues);
1017
+ else clearFilter(column);
1018
+ };
1019
+ const handleToggle = (optionValue, checked) => {
1020
+ updateValues(checked ? [...selectedValues, optionValue] : selectedValues.filter((v) => v !== optionValue));
1021
+ };
1022
+ const removeValue = (optionValue) => {
1023
+ updateValues(selectedValues.filter((v) => v !== optionValue));
1024
+ };
1025
+ const visibleBadges = selectedValues.slice(0, MAX_VISIBLE_BADGES);
1026
+ const remainingCount = selectedValues.length - MAX_VISIBLE_BADGES;
1027
+ return /* @__PURE__ */ jsxs(Popover, {
1028
+ open,
1029
+ onOpenChange: setOpen,
1030
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
1031
+ asChild: true,
1032
+ children: /* @__PURE__ */ jsxs(Button, {
1033
+ variant: "outline",
1034
+ className: cn("justify-between gap-1", className),
1035
+ "data-slot": "dt-filter",
1036
+ "data-testid": "dt-filter-trigger",
1037
+ children: [selectedValues.length > 0 ? /* @__PURE__ */ jsxs("div", {
1038
+ className: "flex items-center gap-1 flex-wrap",
1039
+ children: [visibleBadges.map((val) => {
1040
+ const opt = options.find((o) => o.value === val);
1041
+ return /* @__PURE__ */ jsxs(Badge, {
1042
+ variant: "secondary",
1043
+ className: "text-xs px-1.5 py-0",
1044
+ children: [opt?.label ?? val, /* @__PURE__ */ jsx("span", {
1045
+ role: "button",
1046
+ tabIndex: 0,
1047
+ "aria-label": `Remove ${opt?.label ?? val}`,
1048
+ className: "ml-1 rounded-sm hover:bg-muted",
1049
+ onClick: (e) => {
1050
+ e.stopPropagation();
1051
+ removeValue(val);
1052
+ },
1053
+ onKeyDown: (e) => {
1054
+ if (e.key === "Enter" || e.key === " ") {
1055
+ e.preventDefault();
1056
+ removeValue(val);
1057
+ }
1058
+ },
1059
+ children: /* @__PURE__ */ jsx(X, { className: "size-3" })
1060
+ })]
1061
+ }, val);
1062
+ }), remainingCount > 0 && /* @__PURE__ */ jsxs("span", {
1063
+ className: "text-xs text-muted-foreground",
1064
+ children: [
1065
+ "+",
1066
+ remainingCount,
1067
+ " ",
1068
+ "more"
1069
+ ]
1070
+ })]
1071
+ }) : /* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 opacity-50 ml-auto shrink-0" })]
1072
+ })
1073
+ }), /* @__PURE__ */ jsxs(PopoverContent, {
1074
+ className: cn("popover-content-width-full p-0", checkboxPopoverClassName),
1075
+ align: "start",
1076
+ children: [/* @__PURE__ */ jsxs("div", {
1077
+ className: "flex items-center justify-between p-2 border-b",
1078
+ children: [/* @__PURE__ */ jsx("span", {
1079
+ className: "text-sm font-medium",
1080
+ children: label
1081
+ }), selectedValues.length > 0 && /* @__PURE__ */ jsx(Button, {
1082
+ variant: "ghost",
1083
+ size: "sm",
1084
+ className: "h-auto p-1 text-xs",
1085
+ onClick: () => clearFilter(column),
1086
+ children: "Clear"
1087
+ })]
1088
+ }), /* @__PURE__ */ jsx("div", {
1089
+ className: "max-h-48 overflow-y-auto p-2",
1090
+ children: /* @__PURE__ */ jsx("div", {
1091
+ className: "flex flex-col gap-2",
1092
+ children: options.map((option) => /* @__PURE__ */ jsxs("div", {
1093
+ className: "flex items-center gap-2",
1094
+ children: [/* @__PURE__ */ jsx(Checkbox, {
1095
+ id: `${column}-${option.value}`,
1096
+ checked: selectedValues.includes(option.value),
1097
+ onCheckedChange: (checked) => handleToggle(option.value, checked === true)
1098
+ }), /* @__PURE__ */ jsx(Label, {
1099
+ htmlFor: `${column}-${option.value}`,
1100
+ className: "text-sm font-normal cursor-pointer",
1101
+ children: option.label
1102
+ })]
1103
+ }, option.value))
1104
+ })
1105
+ })]
1106
+ })]
1107
+ });
1108
+ }
1109
+
1110
+ //#endregion
1111
+ //#region src/components/features/data-table/filters/date-picker-filter.tsx
1112
+ function DatePickerFilter({ column, label, className, datePickerPopoverClassName, disableFuture, disablePast, minDate, maxDate }) {
1113
+ const { filters, setFilter, clearFilter, registerFilter, unregisterFilter } = useDataTableFilters();
1114
+ const rawValue = filters[column];
1115
+ useEffect(() => {
1116
+ registerFilter(column, "date-gte");
1117
+ return () => unregisterFilter(column);
1118
+ }, [
1119
+ column,
1120
+ registerFilter,
1121
+ unregisterFilter
1122
+ ]);
1123
+ const dateRange = useMemo(() => {
1124
+ const date = rawValue ? new Date(rawValue) : void 0;
1125
+ return {
1126
+ from: date,
1127
+ to: date
1128
+ };
1129
+ }, [rawValue]);
1130
+ return /* @__PURE__ */ jsx("div", {
1131
+ "data-slot": "dt-filter",
1132
+ children: /* @__PURE__ */ jsx(CalendarDatePicker, {
1133
+ date: dateRange,
1134
+ numberOfMonths: 1,
1135
+ closeOnSelect: true,
1136
+ placeholder: label,
1137
+ triggerClassName: className,
1138
+ variant: "outline",
1139
+ disableFuture,
1140
+ disablePast,
1141
+ minDate,
1142
+ maxDate,
1143
+ popoverClassName: datePickerPopoverClassName,
1144
+ onDateSelect: (range) => {
1145
+ if (range?.from) setFilter(column, range.from.toISOString());
1146
+ else clearFilter(column);
1147
+ }
1148
+ })
1149
+ });
1150
+ }
1151
+
1152
+ //#endregion
1153
+ //#region src/components/features/data-table/filters/select-filter.tsx
1154
+ function SelectFilter({ column, label, options, placeholder, searchable = true, className, selectPopoverClassName }) {
1155
+ const { filters, setFilter, clearFilter, registerFilter, unregisterFilter } = useDataTableFilters();
1156
+ const [open, setOpen] = useState(false);
1157
+ const value = filters[column];
1158
+ useEffect(() => {
1159
+ registerFilter(column, "select");
1160
+ return () => unregisterFilter(column);
1161
+ }, [
1162
+ column,
1163
+ registerFilter,
1164
+ unregisterFilter
1165
+ ]);
1166
+ const selectedOption = options.find((o) => o.value === value);
1167
+ return /* @__PURE__ */ jsxs(Popover, {
1168
+ open,
1169
+ onOpenChange: setOpen,
1170
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
1171
+ asChild: true,
1172
+ children: /* @__PURE__ */ jsxs(Button, {
1173
+ variant: "outline",
1174
+ role: "combobox",
1175
+ "aria-expanded": open,
1176
+ className: cn("justify-between", className),
1177
+ "data-slot": "dt-filter",
1178
+ "data-testid": "dt-filter-trigger",
1179
+ children: [/* @__PURE__ */ jsx("span", {
1180
+ className: "truncate",
1181
+ children: selectedOption ? selectedOption.label : placeholder ?? label
1182
+ }), /* @__PURE__ */ jsxs("div", {
1183
+ className: "ml-2 flex items-center gap-1",
1184
+ children: [value && /* @__PURE__ */ jsx("span", {
1185
+ role: "button",
1186
+ "aria-label": `Clear ${label} filter`,
1187
+ className: "rounded-sm opacity-70 hover:opacity-100",
1188
+ onClick: (e) => {
1189
+ e.stopPropagation();
1190
+ clearFilter(column);
1191
+ },
1192
+ onKeyDown: (e) => {
1193
+ if (e.key === "Enter" || e.key === " ") {
1194
+ e.preventDefault();
1195
+ e.stopPropagation();
1196
+ clearFilter(column);
1197
+ }
1198
+ },
1199
+ tabIndex: 0,
1200
+ children: /* @__PURE__ */ jsx(X, { className: "size-3" })
1201
+ }), /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 opacity-50" })]
1202
+ })]
1203
+ })
1204
+ }), /* @__PURE__ */ jsx(PopoverContent, {
1205
+ className: cn("popover-content-width-full p-0", selectPopoverClassName),
1206
+ align: "start",
1207
+ children: /* @__PURE__ */ jsxs(Command, { children: [searchable && /* @__PURE__ */ jsx(CommandInput, { placeholder: `Search ${label.toLowerCase()}...` }), /* @__PURE__ */ jsxs(CommandList, { children: [/* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }), /* @__PURE__ */ jsx(CommandGroup, { children: options.map((option) => /* @__PURE__ */ jsxs(CommandItem, {
1208
+ value: option.value,
1209
+ onSelect: () => {
1210
+ setFilter(column, option.value);
1211
+ setOpen(false);
1212
+ },
1213
+ children: [/* @__PURE__ */ jsx(Check, { className: cn("mr-2 size-4", value === option.value ? "opacity-100" : "opacity-0") }), option.label]
1214
+ }, option.value)) })] })] })
1215
+ })]
1216
+ });
1217
+ }
1218
+
1219
+ //#endregion
1220
+ //#region src/components/features/data-table/data-table.tsx
1221
+ const DataTable = {
1222
+ Client: ClientProvider,
1223
+ Server: ServerProvider,
1224
+ Content: DataTableContent,
1225
+ InlineContent: DataTableInlineContent,
1226
+ ColumnHeader: DataTableColumnHeader,
1227
+ Pagination: DataTablePagination,
1228
+ Search: DataTableSearch,
1229
+ RowActions: DataTableRowActions,
1230
+ BulkActions: DataTableBulkActions,
1231
+ Loading: DataTableLoading,
1232
+ SelectFilter,
1233
+ CheckboxFilter,
1234
+ DatePickerFilter
1235
+ };
1236
+
1237
+ //#endregion
1238
+ //#region src/components/features/data-table/hooks/use-data-table-client.ts
1239
+ function useDataTableClient(options) {
1240
+ const { data, columns, pageSize, getRowId, enableRowSelection = false, defaultSort, defaultFilters, searchableColumns, searchFn, filterFns, stateAdapter } = options;
1241
+ const store = useMemo(() => createDataTableStore({
1242
+ data,
1243
+ mode: "client",
1244
+ defaultSort,
1245
+ defaultFilters,
1246
+ pageSize,
1247
+ searchableColumns,
1248
+ searchFn,
1249
+ filterFns
1250
+ }), []);
1251
+ const isInitialRender = useRef(true);
1252
+ useEffect(() => {
1253
+ if (isInitialRender.current) {
1254
+ isInitialRender.current = false;
1255
+ return;
1256
+ }
1257
+ store.setData(data);
1258
+ }, [data, store]);
1259
+ const resolvedColumns = useMemo(() => enableRowSelection ? withSelectionColumn(columns, typeof enableRowSelection === "object" ? enableRowSelection : {}) : columns, [columns, enableRowSelection]);
1260
+ const { filteredData, sorting, rowSelection, pageIndex, pageSize: storePageSize, filters, search } = useSyncExternalStore(store.subscribe, store.getSnapshot);
1261
+ const table = useReactTable({
1262
+ data: filteredData,
1263
+ columns: resolvedColumns,
1264
+ state: {
1265
+ sorting,
1266
+ rowSelection,
1267
+ pagination: {
1268
+ pageIndex,
1269
+ pageSize: storePageSize
1270
+ }
1271
+ },
1272
+ onSortingChange: (updater) => {
1273
+ const next = typeof updater === "function" ? updater(sorting) : updater;
1274
+ store.setSorting(next);
1275
+ },
1276
+ onRowSelectionChange: (updater) => {
1277
+ const next = typeof updater === "function" ? updater(rowSelection) : updater;
1278
+ store.setRowSelection(next);
1279
+ },
1280
+ onPaginationChange: (updater) => {
1281
+ const next = typeof updater === "function" ? updater({
1282
+ pageIndex,
1283
+ pageSize: storePageSize
1284
+ }) : updater;
1285
+ store.setPageIndex(next.pageIndex);
1286
+ store.setPageSize(next.pageSize);
1287
+ },
1288
+ getCoreRowModel: getCoreRowModel(),
1289
+ getSortedRowModel: getSortedRowModel(),
1290
+ getPaginationRowModel: getPaginationRowModel(),
1291
+ getRowId,
1292
+ enableRowSelection: !!enableRowSelection
1293
+ });
1294
+ const hydratedRef = useRef(false);
1295
+ useEffect(() => {
1296
+ if (stateAdapter && !hydratedRef.current) {
1297
+ hydratedRef.current = true;
1298
+ const persisted = stateAdapter.read();
1299
+ if (persisted.sorting && persisted.sorting.length > 0) store.setSorting(persisted.sorting);
1300
+ if (persisted.filters) {
1301
+ for (const [key, value] of Object.entries(persisted.filters)) if (value != null) store.setFilter(key, value);
1302
+ }
1303
+ if (persisted.search) store.setSearch(persisted.search);
1304
+ if (persisted.pageIndex != null && persisted.pageIndex > 0) store.setPageIndex(persisted.pageIndex);
1305
+ if (persisted.pageSize != null) store.setPageSize(persisted.pageSize);
1306
+ }
1307
+ }, []);
1308
+ const isFirstWrite = useRef(true);
1309
+ useEffect(() => {
1310
+ if (!stateAdapter) return;
1311
+ if (isFirstWrite.current) {
1312
+ isFirstWrite.current = false;
1313
+ return;
1314
+ }
1315
+ stateAdapter.write({
1316
+ sorting,
1317
+ filters,
1318
+ search,
1319
+ pageIndex,
1320
+ pageSize: storePageSize
1321
+ });
1322
+ }, [
1323
+ sorting,
1324
+ filters,
1325
+ search,
1326
+ pageIndex,
1327
+ storePageSize,
1328
+ stateAdapter
1329
+ ]);
1330
+ return {
1331
+ store,
1332
+ table
1333
+ };
1334
+ }
1335
+
1336
+ //#endregion
1337
+ //#region src/components/features/data-table/hooks/use-data-table-server.ts
1338
+ function useDataTableServer(options) {
1339
+ const { columns, fetchFn, transform, limit = 20, getRowId, enableRowSelection = false, defaultSort, defaultFilters, stateAdapter } = options;
1340
+ const fetchRef = useRef(fetchFn);
1341
+ const transformRef = useRef(transform);
1342
+ useEffect(() => {
1343
+ fetchRef.current = fetchFn;
1344
+ }, [fetchFn]);
1345
+ useEffect(() => {
1346
+ transformRef.current = transform;
1347
+ }, [transform]);
1348
+ const cursorMapRef = useRef(/* @__PURE__ */ new Map());
1349
+ const [hasNextPage, setHasNextPage] = useState(false);
1350
+ const store = useMemo(() => createDataTableStore({
1351
+ data: [],
1352
+ mode: "server",
1353
+ defaultSort,
1354
+ defaultFilters,
1355
+ pageSize: limit
1356
+ }), []);
1357
+ const { sorting, filters, search, rowSelection, pageSize, pageIndex } = useSyncExternalStore(store.subscribe, store.getSnapshot);
1358
+ useEffect(() => {
1359
+ let cancelled = false;
1360
+ store.setLoading(true);
1361
+ const cursor = cursorMapRef.current.get(pageIndex);
1362
+ fetchRef.current({
1363
+ sorting,
1364
+ filters,
1365
+ search,
1366
+ cursor,
1367
+ limit: pageSize
1368
+ }).then((response) => {
1369
+ if (cancelled) return;
1370
+ const result = transformRef.current(response);
1371
+ store.setServerData(result.data);
1372
+ store.setError(null);
1373
+ if (result.nextCursor) cursorMapRef.current.set(pageIndex + 1, result.nextCursor);
1374
+ setHasNextPage(result.hasNextPage);
1375
+ }).catch((error) => {
1376
+ if (cancelled) return;
1377
+ store.setServerData([]);
1378
+ store.setError(error instanceof Error ? error : new Error(String(error)));
1379
+ setHasNextPage(false);
1380
+ }).finally(() => {
1381
+ if (!cancelled) store.setLoading(false);
1382
+ });
1383
+ return () => {
1384
+ cancelled = true;
1385
+ };
1386
+ }, [
1387
+ sorting,
1388
+ filters,
1389
+ search,
1390
+ pageSize,
1391
+ pageIndex,
1392
+ store
1393
+ ]);
1394
+ const prevQueryRef = useRef({
1395
+ sorting,
1396
+ filters,
1397
+ search,
1398
+ pageSize
1399
+ });
1400
+ useEffect(() => {
1401
+ const prev = prevQueryRef.current;
1402
+ if (prev.sorting !== sorting || prev.filters !== filters || prev.search !== search || prev.pageSize !== pageSize) {
1403
+ cursorMapRef.current = /* @__PURE__ */ new Map();
1404
+ store.setPageIndex(0);
1405
+ setHasNextPage(false);
1406
+ }
1407
+ prevQueryRef.current = {
1408
+ sorting,
1409
+ filters,
1410
+ search,
1411
+ pageSize
1412
+ };
1413
+ }, [
1414
+ sorting,
1415
+ filters,
1416
+ search,
1417
+ pageSize,
1418
+ store
1419
+ ]);
1420
+ const resolvedColumns = useMemo(() => enableRowSelection ? withSelectionColumn(columns, typeof enableRowSelection === "object" ? enableRowSelection : {}) : columns, [columns, enableRowSelection]);
1421
+ const table = useReactTable({
1422
+ data: store.getSnapshot().data,
1423
+ columns: resolvedColumns,
1424
+ state: {
1425
+ sorting,
1426
+ rowSelection,
1427
+ pagination: {
1428
+ pageIndex,
1429
+ pageSize
1430
+ }
1431
+ },
1432
+ manualPagination: true,
1433
+ manualSorting: true,
1434
+ manualFiltering: true,
1435
+ pageCount: hasNextPage ? pageIndex + 2 : pageIndex + 1,
1436
+ getCoreRowModel: getCoreRowModel(),
1437
+ getRowId,
1438
+ enableRowSelection: !!enableRowSelection,
1439
+ onSortingChange: (updater) => {
1440
+ const next = typeof updater === "function" ? updater(sorting) : updater;
1441
+ store.setSorting(next);
1442
+ },
1443
+ onRowSelectionChange: (updater) => {
1444
+ const next = typeof updater === "function" ? updater(rowSelection) : updater;
1445
+ store.setRowSelection(next);
1446
+ },
1447
+ onPaginationChange: (updater) => {
1448
+ const next = typeof updater === "function" ? updater({
1449
+ pageIndex,
1450
+ pageSize
1451
+ }) : updater;
1452
+ if (next.pageIndex !== pageIndex) store.setPageIndex(next.pageIndex);
1453
+ if (next.pageSize !== pageSize) store.setPageSize(next.pageSize);
1454
+ }
1455
+ });
1456
+ useEffect(() => {
1457
+ if (stateAdapter) stateAdapter.write({
1458
+ sorting,
1459
+ filters,
1460
+ search,
1461
+ pageSize
1462
+ });
1463
+ }, [
1464
+ sorting,
1465
+ filters,
1466
+ search,
1467
+ pageSize,
1468
+ stateAdapter
1469
+ ]);
1470
+ return {
1471
+ store,
1472
+ table
1473
+ };
1474
+ }
1475
+
1476
+ //#endregion
1477
+ export { DEFAULT_DEBOUNCE_MS, DEFAULT_LOADING_ROWS, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZES, DataTable, createDataTableStore, createSelectionColumn, useDataTableClient, useDataTableContext, useDataTableFilters, useDataTableInlineContents, useDataTableLoading, useDataTablePagination, useDataTableRows, useDataTableSearch, useDataTableSelection, useDataTableServer, useDataTableSorting, useNuqsAdapter };