@multicomma/arkcn 0.1.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 (237) hide show
  1. package/README.md +78 -0
  2. package/bin/arkcn.mjs +78 -0
  3. package/cli/commands.mjs +251 -0
  4. package/cli/project.mjs +168 -0
  5. package/cli/registry.mjs +50 -0
  6. package/cli/ui.mjs +46 -0
  7. package/mcp/server.mjs +149 -0
  8. package/package.json +201 -0
  9. package/registry/base.css +680 -0
  10. package/registry/index.json +1833 -0
  11. package/registry/items/accordion.json +18 -0
  12. package/registry/items/activity-feed.json +18 -0
  13. package/registry/items/alert-dialog.json +18 -0
  14. package/registry/items/alert.json +17 -0
  15. package/registry/items/angle-slider.json +17 -0
  16. package/registry/items/app-shell.json +28 -0
  17. package/registry/items/aspect-ratio.json +13 -0
  18. package/registry/items/attachment.json +19 -0
  19. package/registry/items/avatar.json +17 -0
  20. package/registry/items/badge.json +18 -0
  21. package/registry/items/breadcrumb.json +18 -0
  22. package/registry/items/bubble.json +18 -0
  23. package/registry/items/button-group.json +19 -0
  24. package/registry/items/button.json +18 -0
  25. package/registry/items/calendar.json +19 -0
  26. package/registry/items/canvas.json +24 -0
  27. package/registry/items/card.json +15 -0
  28. package/registry/items/carousel.json +19 -0
  29. package/registry/items/cascader.json +23 -0
  30. package/registry/items/chart.json +17 -0
  31. package/registry/items/chat.json +23 -0
  32. package/registry/items/checkbox.json +18 -0
  33. package/registry/items/clipboard.json +19 -0
  34. package/registry/items/collapsible.json +15 -0
  35. package/registry/items/color-picker.json +19 -0
  36. package/registry/items/combobox.json +20 -0
  37. package/registry/items/command.json +21 -0
  38. package/registry/items/comment-thread.json +25 -0
  39. package/registry/items/context-menu.json +18 -0
  40. package/registry/items/controllable.json +14 -0
  41. package/registry/items/data-grid.json +24 -0
  42. package/registry/items/data-table-adapter.json +14 -0
  43. package/registry/items/data-table.json +32 -0
  44. package/registry/items/date-input.json +17 -0
  45. package/registry/items/dialog.json +19 -0
  46. package/registry/items/direction.json +13 -0
  47. package/registry/items/drag-preview.json +16 -0
  48. package/registry/items/drawer.json +18 -0
  49. package/registry/items/dropdown-menu.json +18 -0
  50. package/registry/items/editable.json +17 -0
  51. package/registry/items/empty.json +17 -0
  52. package/registry/items/field.json +19 -0
  53. package/registry/items/file-upload.json +19 -0
  54. package/registry/items/floating-panel.json +19 -0
  55. package/registry/items/floating-toolbar.json +16 -0
  56. package/registry/items/form.json +14 -0
  57. package/registry/items/format.json +15 -0
  58. package/registry/items/gantt.json +22 -0
  59. package/registry/items/history.json +14 -0
  60. package/registry/items/hotkeys.json +18 -0
  61. package/registry/items/hover-card.json +17 -0
  62. package/registry/items/image-cropper.json +17 -0
  63. package/registry/items/input-group.json +20 -0
  64. package/registry/items/input-otp.json +18 -0
  65. package/registry/items/input.json +15 -0
  66. package/registry/items/item.json +19 -0
  67. package/registry/items/json-tree-view.json +17 -0
  68. package/registry/items/kanban.json +26 -0
  69. package/registry/items/kbd.json +15 -0
  70. package/registry/items/label.json +15 -0
  71. package/registry/items/live-region.json +16 -0
  72. package/registry/items/marker.json +18 -0
  73. package/registry/items/marquee.json +17 -0
  74. package/registry/items/menubar.json +19 -0
  75. package/registry/items/message.json +15 -0
  76. package/registry/items/navigation-menu.json +19 -0
  77. package/registry/items/node-graph.json +22 -0
  78. package/registry/items/number-input.json +18 -0
  79. package/registry/items/pagination.json +18 -0
  80. package/registry/items/password-input.json +18 -0
  81. package/registry/items/popconfirm.json +20 -0
  82. package/registry/items/popover.json +18 -0
  83. package/registry/items/progress.json +17 -0
  84. package/registry/items/qr-code.json +17 -0
  85. package/registry/items/query-builder.json +23 -0
  86. package/registry/items/radio-group.json +17 -0
  87. package/registry/items/rating-group.json +18 -0
  88. package/registry/items/resizable.json +17 -0
  89. package/registry/items/rich-text-editor.json +37 -0
  90. package/registry/items/row-layout.json +15 -0
  91. package/registry/items/scheduler.json +23 -0
  92. package/registry/items/scroll-area.json +17 -0
  93. package/registry/items/segment-group.json +17 -0
  94. package/registry/items/select.json +19 -0
  95. package/registry/items/separator.json +15 -0
  96. package/registry/items/sheet.json +19 -0
  97. package/registry/items/sidebar.json +27 -0
  98. package/registry/items/signature-pad.json +19 -0
  99. package/registry/items/skeleton.json +15 -0
  100. package/registry/items/slider.json +17 -0
  101. package/registry/items/sonner.json +17 -0
  102. package/registry/items/spinner.json +17 -0
  103. package/registry/items/steps.json +19 -0
  104. package/registry/items/swap.json +17 -0
  105. package/registry/items/switch.json +17 -0
  106. package/registry/items/table.json +16 -0
  107. package/registry/items/tabs.json +18 -0
  108. package/registry/items/tags-input.json +18 -0
  109. package/registry/items/textarea.json +15 -0
  110. package/registry/items/time.json +14 -0
  111. package/registry/items/timer.json +18 -0
  112. package/registry/items/toc.json +17 -0
  113. package/registry/items/toggle-group.json +19 -0
  114. package/registry/items/toggle.json +18 -0
  115. package/registry/items/tooltip.json +17 -0
  116. package/registry/items/tour.json +19 -0
  117. package/registry/items/transfer-list.json +24 -0
  118. package/registry/items/tree-select.json +24 -0
  119. package/registry/items/tree-view.json +18 -0
  120. package/registry/items/use-mobile.json +13 -0
  121. package/registry/items/utils.json +17 -0
  122. package/registry/items/virtual-list.json +16 -0
  123. package/src/components/ui/accordion.tsx +111 -0
  124. package/src/components/ui/activity-feed.tsx +228 -0
  125. package/src/components/ui/alert-dialog.tsx +204 -0
  126. package/src/components/ui/alert.tsx +55 -0
  127. package/src/components/ui/angle-slider.tsx +117 -0
  128. package/src/components/ui/app-shell.tsx +985 -0
  129. package/src/components/ui/aspect-ratio.tsx +35 -0
  130. package/src/components/ui/attachment.tsx +193 -0
  131. package/src/components/ui/avatar.tsx +94 -0
  132. package/src/components/ui/badge.tsx +45 -0
  133. package/src/components/ui/breadcrumb.tsx +93 -0
  134. package/src/components/ui/bubble.tsx +119 -0
  135. package/src/components/ui/button-group.tsx +79 -0
  136. package/src/components/ui/button.tsx +65 -0
  137. package/src/components/ui/calendar.tsx +172 -0
  138. package/src/components/ui/canvas.tsx +723 -0
  139. package/src/components/ui/card.tsx +69 -0
  140. package/src/components/ui/carousel.tsx +228 -0
  141. package/src/components/ui/cascader.tsx +754 -0
  142. package/src/components/ui/chart.tsx +303 -0
  143. package/src/components/ui/chat.tsx +544 -0
  144. package/src/components/ui/checkbox.tsx +94 -0
  145. package/src/components/ui/clipboard.tsx +94 -0
  146. package/src/components/ui/collapsible.tsx +32 -0
  147. package/src/components/ui/color-picker.tsx +441 -0
  148. package/src/components/ui/combobox.tsx +400 -0
  149. package/src/components/ui/command.tsx +292 -0
  150. package/src/components/ui/comment-thread.tsx +923 -0
  151. package/src/components/ui/context-menu.tsx +331 -0
  152. package/src/components/ui/data-grid.tsx +1227 -0
  153. package/src/components/ui/data-table.tsx +993 -0
  154. package/src/components/ui/date-input.tsx +103 -0
  155. package/src/components/ui/dialog.tsx +159 -0
  156. package/src/components/ui/direction.tsx +32 -0
  157. package/src/components/ui/drawer.tsx +200 -0
  158. package/src/components/ui/dropdown-menu.tsx +329 -0
  159. package/src/components/ui/editable.tsx +90 -0
  160. package/src/components/ui/empty.tsx +86 -0
  161. package/src/components/ui/field.tsx +218 -0
  162. package/src/components/ui/file-upload.tsx +204 -0
  163. package/src/components/ui/floating-panel.tsx +199 -0
  164. package/src/components/ui/floating-toolbar.tsx +79 -0
  165. package/src/components/ui/format.tsx +22 -0
  166. package/src/components/ui/gantt.tsx +950 -0
  167. package/src/components/ui/hotkeys.tsx +340 -0
  168. package/src/components/ui/hover-card.tsx +83 -0
  169. package/src/components/ui/image-cropper.tsx +100 -0
  170. package/src/components/ui/input-group.tsx +133 -0
  171. package/src/components/ui/input-otp.tsx +82 -0
  172. package/src/components/ui/input.tsx +18 -0
  173. package/src/components/ui/item.tsx +174 -0
  174. package/src/components/ui/json-tree-view.tsx +37 -0
  175. package/src/components/ui/kanban.tsx +884 -0
  176. package/src/components/ui/kbd.tsx +20 -0
  177. package/src/components/ui/label.tsx +30 -0
  178. package/src/components/ui/live-region.tsx +54 -0
  179. package/src/components/ui/marker.tsx +66 -0
  180. package/src/components/ui/marquee.tsx +61 -0
  181. package/src/components/ui/menubar.tsx +456 -0
  182. package/src/components/ui/message.tsx +74 -0
  183. package/src/components/ui/navigation-menu.tsx +202 -0
  184. package/src/components/ui/node-graph.tsx +1723 -0
  185. package/src/components/ui/number-input.tsx +148 -0
  186. package/src/components/ui/pagination.tsx +88 -0
  187. package/src/components/ui/password-input.tsx +104 -0
  188. package/src/components/ui/popconfirm.tsx +149 -0
  189. package/src/components/ui/popover.tsx +126 -0
  190. package/src/components/ui/progress.tsx +114 -0
  191. package/src/components/ui/qr-code.tsx +51 -0
  192. package/src/components/ui/query-builder.tsx +938 -0
  193. package/src/components/ui/radio-group.tsx +108 -0
  194. package/src/components/ui/rating-group.tsx +91 -0
  195. package/src/components/ui/resizable.tsx +41 -0
  196. package/src/components/ui/rich-text-editor.tsx +845 -0
  197. package/src/components/ui/scheduler.tsx +1164 -0
  198. package/src/components/ui/scroll-area.tsx +82 -0
  199. package/src/components/ui/segment-group.tsx +95 -0
  200. package/src/components/ui/select.tsx +354 -0
  201. package/src/components/ui/separator.tsx +32 -0
  202. package/src/components/ui/sheet.tsx +130 -0
  203. package/src/components/ui/sidebar.tsx +665 -0
  204. package/src/components/ui/signature-pad.tsx +112 -0
  205. package/src/components/ui/skeleton.tsx +7 -0
  206. package/src/components/ui/slider.tsx +183 -0
  207. package/src/components/ui/sonner.tsx +37 -0
  208. package/src/components/ui/spinner.tsx +16 -0
  209. package/src/components/ui/steps.tsx +152 -0
  210. package/src/components/ui/swap.tsx +33 -0
  211. package/src/components/ui/switch.tsx +83 -0
  212. package/src/components/ui/table.tsx +72 -0
  213. package/src/components/ui/tabs.tsx +100 -0
  214. package/src/components/ui/tags-input.tsx +153 -0
  215. package/src/components/ui/textarea.tsx +17 -0
  216. package/src/components/ui/timer.tsx +67 -0
  217. package/src/components/ui/toc.tsx +64 -0
  218. package/src/components/ui/toggle-group.tsx +89 -0
  219. package/src/components/ui/toggle.tsx +46 -0
  220. package/src/components/ui/tooltip.tsx +113 -0
  221. package/src/components/ui/tour.tsx +168 -0
  222. package/src/components/ui/transfer-list.tsx +700 -0
  223. package/src/components/ui/tree-select.tsx +638 -0
  224. package/src/components/ui/tree-view.tsx +217 -0
  225. package/src/components/ui/virtual-list.tsx +343 -0
  226. package/src/hooks/use-mobile.ts +19 -0
  227. package/src/lib/controllable.ts +31 -0
  228. package/src/lib/data-table-adapter.ts +67 -0
  229. package/src/lib/drag-preview.ts +39 -0
  230. package/src/lib/form.ts +39 -0
  231. package/src/lib/history.ts +55 -0
  232. package/src/lib/row-layout.ts +81 -0
  233. package/src/lib/table.ts +483 -0
  234. package/src/lib/time.ts +37 -0
  235. package/src/lib/utils.ts +6 -0
  236. package/src/styles/arkcn.css +764 -0
  237. package/src/styles/index.css +3 -0
@@ -0,0 +1,993 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ type ColumnDef,
6
+ type ColumnFiltersState,
7
+ type PaginationState,
8
+ type Row,
9
+ type RowSelectionState,
10
+ type SortingState,
11
+ type TableOptions,
12
+ type VisibilityState,
13
+ useTable,
14
+ } from "@/lib/table"
15
+ import {
16
+ type DataTableColumn,
17
+ type DataTableInstance,
18
+ type DataTableRow as DataTableRowInstance,
19
+ } from "@/lib/data-table-adapter"
20
+ import {
21
+ ArrowDownIcon,
22
+ ArrowUpIcon,
23
+ CheckIcon,
24
+ ChevronLeftIcon,
25
+ ChevronRightIcon,
26
+ ChevronsLeftIcon,
27
+ ChevronsRightIcon,
28
+ ChevronsUpDownIcon,
29
+ EllipsisIcon,
30
+ EyeOffIcon,
31
+ PlusCircleIcon,
32
+ Settings2Icon,
33
+ XIcon,
34
+ } from "lucide-react"
35
+ import { cn } from "@/lib/utils"
36
+ import { LiveRegion, useLiveRegion } from "@/components/ui/live-region"
37
+
38
+ import { Badge } from "@/components/ui/badge"
39
+ import { Button } from "@/components/ui/button"
40
+ import { Checkbox } from "@/components/ui/checkbox"
41
+ import {
42
+ Command,
43
+ CommandEmpty,
44
+ CommandGroup,
45
+ CommandInput,
46
+ CommandItem,
47
+ CommandList,
48
+ CommandSeparator,
49
+ useFilter,
50
+ useListCollection,
51
+ } from "@/components/ui/command"
52
+ import {
53
+ DropdownMenu,
54
+ DropdownMenuCheckboxItem,
55
+ DropdownMenuContent,
56
+ DropdownMenuGroup,
57
+ DropdownMenuItem,
58
+ DropdownMenuLabel,
59
+ DropdownMenuSeparator,
60
+ DropdownMenuTrigger,
61
+ } from "@/components/ui/dropdown-menu"
62
+ import { Input } from "@/components/ui/input"
63
+ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
64
+ import {
65
+ Select,
66
+ SelectContent,
67
+ SelectControl,
68
+ SelectItem,
69
+ SelectTrigger,
70
+ SelectValue,
71
+ createListCollection,
72
+ } from "@/components/ui/select"
73
+ import { FloatingToolbar } from "@/components/ui/floating-toolbar"
74
+ import { Separator } from "@/components/ui/separator"
75
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
76
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
77
+
78
+ /* -------------------------------------------------------------------------- */
79
+ /* Hook */
80
+ /* -------------------------------------------------------------------------- */
81
+
82
+ /**
83
+ * The built-in adapter: the dependency-free engine from `@/lib/table`. Its
84
+ * instance satisfies `DataTableInstance`, so it can be passed to `<DataTable>`
85
+ * directly. Any other object implementing `DataTableInstance` works the same way.
86
+ */
87
+ function useDataTable<TData>(options: TableOptions<TData>) {
88
+ return useTable<TData>(options)
89
+ }
90
+
91
+ /* -------------------------------------------------------------------------- */
92
+ /* Context */
93
+ /* -------------------------------------------------------------------------- */
94
+
95
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
+ const DataTableContext = React.createContext<DataTableInstance<any> | null>(null)
97
+
98
+ function useDataTableContext<TData>(explicit?: DataTableInstance<TData>): DataTableInstance<TData> {
99
+ const fromContext = React.useContext(DataTableContext)
100
+ const table = explicit ?? fromContext
101
+ if (!table) {
102
+ throw new Error("Data table parts must be rendered inside <DataTable> or receive a `table` prop.")
103
+ }
104
+ return table
105
+ }
106
+
107
+ function DataTable<TData>({
108
+ table,
109
+ className,
110
+ ...props
111
+ }: React.ComponentProps<"div"> & { table: DataTableInstance<TData> }) {
112
+ return (
113
+ <DataTableContext.Provider value={table}>
114
+ <div data-slot="data-table" className={cn("flex flex-1 flex-col gap-4", className)} {...props} />
115
+ </DataTableContext.Provider>
116
+ )
117
+ }
118
+
119
+ /* -------------------------------------------------------------------------- */
120
+ /* Toolbar */
121
+ /* -------------------------------------------------------------------------- */
122
+
123
+ function DataTableToolbar({ className, ...props }: React.ComponentProps<"div">) {
124
+ return (
125
+ <div
126
+ data-slot="data-table-toolbar"
127
+ className={cn("flex items-center justify-between gap-2", className)}
128
+ {...props}
129
+ />
130
+ )
131
+ }
132
+
133
+ function DataTableToolbarGroup({ className, ...props }: React.ComponentProps<"div">) {
134
+ return (
135
+ <div
136
+ data-slot="data-table-toolbar-group"
137
+ className={cn("flex flex-1 flex-col-reverse items-start gap-2 sm:flex-row sm:items-center", className)}
138
+ {...props}
139
+ />
140
+ )
141
+ }
142
+
143
+ function DataTableSearch<TData>({
144
+ table: tableProp,
145
+ columnId,
146
+ className,
147
+ ...props
148
+ }: Omit<React.ComponentProps<typeof Input>, "value" | "onChange"> & {
149
+ table?: DataTableInstance<TData>
150
+ /** Filter a single column instead of the global filter. */
151
+ columnId?: string
152
+ }) {
153
+ const table = useDataTableContext(tableProp)
154
+ const column = columnId ? table.getColumn(columnId) : undefined
155
+ const value = columnId
156
+ ? ((column?.getFilterValue() as string) ?? "")
157
+ : ((table.getState().globalFilter as string) ?? "")
158
+ return (
159
+ <Input
160
+ data-slot="data-table-search"
161
+ value={value}
162
+ onChange={(event) =>
163
+ columnId ? column?.setFilterValue(event.target.value) : table.setGlobalFilter(event.target.value)
164
+ }
165
+ className={cn("h-8 w-37.5 lg:w-62.5", className)}
166
+ {...props}
167
+ />
168
+ )
169
+ }
170
+
171
+ function DataTableResetFilters<TData>({
172
+ table: tableProp,
173
+ className,
174
+ children,
175
+ asChild,
176
+ ...props
177
+ }: React.ComponentProps<typeof Button> & { table?: DataTableInstance<TData> }) {
178
+ const table = useDataTableContext(tableProp)
179
+ const isFiltered = table.getState().columnFilters.length > 0 || !!table.getState().globalFilter
180
+ if (!isFiltered) return null
181
+ return (
182
+ <Button
183
+ data-slot="data-table-reset-filters"
184
+ variant="ghost"
185
+ size="sm"
186
+ asChild={asChild}
187
+ onClick={() => {
188
+ table.resetColumnFilters()
189
+ table.setGlobalFilter("")
190
+ }}
191
+ className={cn("h-8 px-2 lg:px-3", className)}
192
+ {...props}
193
+ >
194
+ {asChild
195
+ ? children
196
+ : (children ?? (
197
+ <>
198
+ Reset
199
+ <XIcon />
200
+ </>
201
+ ))}
202
+ </Button>
203
+ )
204
+ }
205
+
206
+ /* -------------------------------------------------------------------------- */
207
+ /* Faceted filter */
208
+ /* -------------------------------------------------------------------------- */
209
+
210
+ type FacetOption = {
211
+ label: string
212
+ value: string
213
+ icon?: React.ComponentType<{ className?: string }>
214
+ }
215
+
216
+ function DataTableFacetedFilter<TData, TValue>({
217
+ table: tableProp,
218
+ columnId,
219
+ column: columnProp,
220
+ title,
221
+ options,
222
+ }: {
223
+ table?: DataTableInstance<TData>
224
+ columnId?: string
225
+ column?: DataTableColumn<TData, TValue>
226
+ title?: string
227
+ options: FacetOption[]
228
+ }) {
229
+ const table = useDataTableContext(tableProp)
230
+ const column = columnProp ?? (columnId ? table.getColumn(columnId) : undefined)
231
+ const facets = column?.getFacetedUniqueValues()
232
+ const selectedValues = new Set((column?.getFilterValue() as string[]) ?? [])
233
+
234
+ const { contains } = useFilter({ sensitivity: "base" })
235
+ const { collection, filter } = useListCollection<FacetOption>({
236
+ initialItems: options,
237
+ itemToString: (item) => item.label,
238
+ itemToValue: (item) => item.value,
239
+ filter: contains,
240
+ })
241
+
242
+ const toggle = (value: string) => {
243
+ const next = new Set(selectedValues)
244
+ if (next.has(value)) next.delete(value)
245
+ else next.add(value)
246
+ const values = Array.from(next)
247
+ column?.setFilterValue(values.length ? values : undefined)
248
+ }
249
+
250
+ return (
251
+ <Popover positioning={{ placement: "bottom-start" }}>
252
+ <PopoverTrigger asChild>
253
+ <Button data-slot="data-table-faceted-filter-trigger" variant="outline" size="sm" className="h-8 border-dashed">
254
+ <PlusCircleIcon />
255
+ {title}
256
+ {selectedValues.size > 0 && (
257
+ <>
258
+ <Separator orientation="vertical" className="mx-1 h-4" />
259
+ <Badge variant="secondary" className="rounded-sm px-1 font-normal lg:hidden">
260
+ {selectedValues.size}
261
+ </Badge>
262
+ <div className="hidden gap-1 lg:flex">
263
+ {selectedValues.size > 2 ? (
264
+ <Badge variant="secondary" className="rounded-sm px-1 font-normal">
265
+ {selectedValues.size} selected
266
+ </Badge>
267
+ ) : (
268
+ options
269
+ .filter((option) => selectedValues.has(option.value))
270
+ .map((option) => (
271
+ <Badge key={option.value} variant="secondary" className="rounded-sm px-1 font-normal">
272
+ {option.label}
273
+ </Badge>
274
+ ))
275
+ )}
276
+ </div>
277
+ </>
278
+ )}
279
+ </Button>
280
+ </PopoverTrigger>
281
+ <PopoverContent data-slot="data-table-faceted-filter-content" className="w-50 p-0">
282
+ <Command collection={collection} value={[]} onSelect={({ value }) => toggle(value)}>
283
+ <CommandInput placeholder={title} onValueChange={filter} />
284
+ <CommandList>
285
+ <CommandEmpty>No results found.</CommandEmpty>
286
+ <CommandGroup>
287
+ {collection.items.map((option) => {
288
+ const isSelected = selectedValues.has(option.value)
289
+ return (
290
+ <CommandItem
291
+ key={option.value}
292
+ item={option}
293
+ className="**:data-[slot=command-item-indicator]:hidden"
294
+ >
295
+ <div
296
+ className={cn(
297
+ "flex size-4 items-center justify-center rounded-sm border border-primary",
298
+ isSelected ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"
299
+ )}
300
+ >
301
+ <CheckIcon className="size-3.5" />
302
+ </div>
303
+ {option.icon && <option.icon className="size-4 text-muted-foreground" />}
304
+ <span>{option.label}</span>
305
+ {facets?.get(option.value) ? (
306
+ <span className="ml-auto flex size-4 items-center justify-center font-mono text-xs">
307
+ {facets.get(option.value)}
308
+ </span>
309
+ ) : null}
310
+ </CommandItem>
311
+ )
312
+ })}
313
+ </CommandGroup>
314
+ {selectedValues.size > 0 && (
315
+ <>
316
+ <CommandSeparator />
317
+ <CommandGroup>
318
+ <CommandItem
319
+ item={{ label: "Clear filters", value: "__clear__" }}
320
+ onSelect={() => column?.setFilterValue(undefined)}
321
+ className="justify-center text-center **:data-[slot=command-item-indicator]:hidden"
322
+ >
323
+ Clear filters
324
+ </CommandItem>
325
+ </CommandGroup>
326
+ </>
327
+ )}
328
+ </CommandList>
329
+ </Command>
330
+ </PopoverContent>
331
+ </Popover>
332
+ )
333
+ }
334
+
335
+ /* -------------------------------------------------------------------------- */
336
+ /* View options */
337
+ /* -------------------------------------------------------------------------- */
338
+
339
+ function DataTableViewOptions<TData>({
340
+ table: tableProp,
341
+ className,
342
+ children,
343
+ }: {
344
+ table?: DataTableInstance<TData>
345
+ className?: string
346
+ children?: React.ReactNode
347
+ }) {
348
+ const table = useDataTableContext(tableProp)
349
+ return (
350
+ <DropdownMenu positioning={{ placement: "bottom-end" }}>
351
+ <DropdownMenuTrigger asChild>
352
+ <Button
353
+ data-slot="data-table-view-options-trigger"
354
+ variant="outline"
355
+ size="sm"
356
+ className={cn("ml-auto hidden h-8 lg:flex", className)}
357
+ >
358
+ <Settings2Icon />
359
+ {children ?? "View"}
360
+ </Button>
361
+ </DropdownMenuTrigger>
362
+ <DropdownMenuContent data-slot="data-table-view-options-content" className="w-37.5">
363
+ <DropdownMenuGroup>
364
+ <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
365
+ <DropdownMenuSeparator />
366
+ {table
367
+ .getAllColumns()
368
+ .filter((column) => typeof column.accessorFn !== "undefined" && column.getCanHide())
369
+ .map((column) => (
370
+ <DropdownMenuCheckboxItem
371
+ key={column.id}
372
+ value={column.id}
373
+ className="capitalize"
374
+ checked={column.getIsVisible()}
375
+ onCheckedChange={(value) => column.toggleVisibility(!!value)}
376
+ closeOnSelect={false}
377
+ >
378
+ {column.label ?? column.id}
379
+ </DropdownMenuCheckboxItem>
380
+ ))}
381
+ </DropdownMenuGroup>
382
+ </DropdownMenuContent>
383
+ </DropdownMenu>
384
+ )
385
+ }
386
+
387
+ /* -------------------------------------------------------------------------- */
388
+ /* Column header */
389
+ /* -------------------------------------------------------------------------- */
390
+
391
+ /**
392
+ * A header cell bound to a column id. Sortable columns get the sort/hide menu
393
+ * with `children` as the title; hidden columns render nothing.
394
+ */
395
+ function DataTableHead<TData>({
396
+ column: columnId,
397
+ table: tableProp,
398
+ className,
399
+ children,
400
+ ...props
401
+ }: React.ComponentProps<typeof TableHead> & { column?: string; table?: DataTableInstance<TData> }) {
402
+ const table = useDataTableContext(tableProp)
403
+ const column = columnId ? table.getColumn(columnId) : undefined
404
+ if (column && !column.getIsVisible()) return null
405
+ if (!column?.getCanSort()) {
406
+ return (
407
+ <TableHead data-slot="data-table-head" data-column={columnId} className={className} {...props}>
408
+ {children}
409
+ </TableHead>
410
+ )
411
+ }
412
+ const sorted = column.getIsSorted()
413
+ return (
414
+ <TableHead data-slot="data-table-head" data-column={columnId} className={className} {...props}>
415
+ <DropdownMenu positioning={{ placement: "bottom-start" }}>
416
+ <DropdownMenuTrigger asChild>
417
+ <Button variant="ghost" size="sm" className="-ml-2.5 h-8 data-open:bg-accent">
418
+ <span>{children}</span>
419
+ {sorted === "desc" ? <ArrowDownIcon /> : sorted === "asc" ? <ArrowUpIcon /> : <ChevronsUpDownIcon />}
420
+ </Button>
421
+ </DropdownMenuTrigger>
422
+ <DropdownMenuContent>
423
+ <DropdownMenuItem value="asc" onSelect={() => column.toggleSorting(false)}>
424
+ <ArrowUpIcon className="text-muted-foreground/70" />
425
+ Asc
426
+ </DropdownMenuItem>
427
+ <DropdownMenuItem value="desc" onSelect={() => column.toggleSorting(true)}>
428
+ <ArrowDownIcon className="text-muted-foreground/70" />
429
+ Desc
430
+ </DropdownMenuItem>
431
+ {column.getCanHide() && (
432
+ <>
433
+ <DropdownMenuSeparator />
434
+ <DropdownMenuItem value="hide" onSelect={() => column.toggleVisibility(false)}>
435
+ <EyeOffIcon className="text-muted-foreground/70" />
436
+ Hide
437
+ </DropdownMenuItem>
438
+ </>
439
+ )}
440
+ </DropdownMenuContent>
441
+ </DropdownMenu>
442
+ </TableHead>
443
+ )
444
+ }
445
+
446
+ /* -------------------------------------------------------------------------- */
447
+ /* Selection cells */
448
+ /* -------------------------------------------------------------------------- */
449
+
450
+ function DataTableSelectAll<TData>({
451
+ table,
452
+ className,
453
+ ...props
454
+ }: Omit<React.ComponentProps<typeof Checkbox>, "checked" | "onCheckedChange"> & {
455
+ table: DataTableInstance<TData>
456
+ }) {
457
+ return (
458
+ <Checkbox
459
+ data-slot="data-table-select-all"
460
+ checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate")}
461
+ onCheckedChange={({ checked }) => table.toggleAllPageRowsSelected(checked === true)}
462
+ aria-label="Select all"
463
+ className={cn("translate-y-0.5", className)}
464
+ {...props}
465
+ />
466
+ )
467
+ }
468
+
469
+ function DataTableSelectRow<TData>({
470
+ row,
471
+ className,
472
+ ...props
473
+ }: Omit<React.ComponentProps<typeof Checkbox>, "checked" | "onCheckedChange"> & {
474
+ row: DataTableRowInstance<TData>
475
+ }) {
476
+ return (
477
+ <Checkbox
478
+ data-slot="data-table-select-row"
479
+ checked={row.getIsSelected()}
480
+ onCheckedChange={({ checked }) => row.toggleSelected(checked === true)}
481
+ aria-label="Select row"
482
+ className={cn("translate-y-0.5", className)}
483
+ {...props}
484
+ />
485
+ )
486
+ }
487
+
488
+ /* -------------------------------------------------------------------------- */
489
+ /* Row actions */
490
+ /* -------------------------------------------------------------------------- */
491
+
492
+ function DataTableRowActions({
493
+ children,
494
+ className,
495
+ trigger,
496
+ ...props
497
+ }: React.ComponentProps<typeof DropdownMenu> & {
498
+ className?: string
499
+ /** Replace the default ellipsis button with your own element. */
500
+ trigger?: React.ReactElement
501
+ }) {
502
+ return (
503
+ <DropdownMenu positioning={{ placement: "bottom-end" }} {...props}>
504
+ <DropdownMenuTrigger asChild>
505
+ {trigger ?? (
506
+ <Button
507
+ data-slot="data-table-row-actions-trigger"
508
+ variant="ghost"
509
+ size="icon"
510
+ className={cn("size-8 data-open:bg-muted", className)}
511
+ >
512
+ <EllipsisIcon />
513
+ <span className="sr-only">Open menu</span>
514
+ </Button>
515
+ )}
516
+ </DropdownMenuTrigger>
517
+ <DropdownMenuContent data-slot="data-table-row-actions-content" className="w-40">
518
+ {children}
519
+ </DropdownMenuContent>
520
+ </DropdownMenu>
521
+ )
522
+ }
523
+
524
+ /* -------------------------------------------------------------------------- */
525
+ /* Table rendering */
526
+ /* -------------------------------------------------------------------------- */
527
+
528
+ function DataTableContainer({ className, ...props }: React.ComponentProps<"div">) {
529
+ return (
530
+ <div data-slot="data-table-container" className={cn("overflow-hidden rounded-md border", className)} {...props} />
531
+ )
532
+ }
533
+
534
+ /** The header row. Put `DataTableHead` cells inside, one per column, in display order. */
535
+ function DataTableHeader({ className, children, ...props }: React.ComponentProps<typeof TableHeader>) {
536
+ return (
537
+ <TableHeader data-slot="data-table-header" className={className} {...props}>
538
+ <TableRow>{children}</TableRow>
539
+ </TableHeader>
540
+ )
541
+ }
542
+
543
+ /** A body row bound to a row instance; carries the selected state. */
544
+ function DataTableRow<TData>({
545
+ row,
546
+ className,
547
+ ...props
548
+ }: React.ComponentProps<typeof TableRow> & { row: DataTableRowInstance<TData> }) {
549
+ return (
550
+ <TableRow
551
+ data-slot="data-table-row"
552
+ data-state={row.getIsSelected() ? "selected" : undefined}
553
+ className={cn("group/row", className)}
554
+ {...props}
555
+ />
556
+ )
557
+ }
558
+
559
+ /** A body cell bound to a column id; hidden columns render nothing. */
560
+ function DataTableCell<TData>({
561
+ column: columnId,
562
+ table: tableProp,
563
+ className,
564
+ ...props
565
+ }: React.ComponentProps<typeof TableCell> & { column?: string; table?: DataTableInstance<TData> }) {
566
+ const table = useDataTableContext(tableProp)
567
+ const column = columnId ? table.getColumn(columnId) : undefined
568
+ if (column && !column.getIsVisible()) return null
569
+ return <TableCell data-slot="data-table-cell" data-column={columnId} className={className} {...props} />
570
+ }
571
+
572
+ /**
573
+ * Renders the current page of rows. `children` receives each row and returns
574
+ * its cells (wrap them in `DataTableRow`, or return a fragment of cells to get
575
+ * a default row). Shows `empty` when there are no rows.
576
+ */
577
+ function DataTableBody<TData>({
578
+ table: tableProp,
579
+ empty = "No results.",
580
+ children,
581
+ ...props
582
+ }: Omit<React.ComponentProps<typeof TableBody>, "children"> & {
583
+ table?: DataTableInstance<TData>
584
+ empty?: React.ReactNode
585
+ children: (row: DataTableRowInstance<TData>) => React.ReactNode
586
+ }) {
587
+ const table = useDataTableContext(tableProp)
588
+ const rows = table.getRowModel().rows
589
+ return (
590
+ <TableBody data-slot="data-table-body" {...props}>
591
+ {rows.length ? (
592
+ rows.map((row) => {
593
+ const content = children(row)
594
+ return React.isValidElement(content) && content.type === DataTableRow ? (
595
+ <React.Fragment key={row.id}>{content}</React.Fragment>
596
+ ) : (
597
+ <DataTableRow key={row.id} row={row}>
598
+ {content}
599
+ </DataTableRow>
600
+ )
601
+ })
602
+ ) : (
603
+ <DataTableEmpty table={table}>{empty}</DataTableEmpty>
604
+ )}
605
+ </TableBody>
606
+ )
607
+ }
608
+
609
+ /** A single full-width row for the empty state; spans the visible columns. */
610
+ function DataTableEmpty<TData>({
611
+ table: tableProp,
612
+ colSpan,
613
+ className,
614
+ ...props
615
+ }: React.ComponentProps<typeof TableCell> & { table?: DataTableInstance<TData>; colSpan?: number }) {
616
+ const table = useDataTableContext(tableProp)
617
+ const span = colSpan ?? Math.max(1, table.getAllColumns().filter((c) => c.getIsVisible()).length)
618
+ return (
619
+ <TableRow data-slot="data-table-empty">
620
+ <TableCell colSpan={span} className={cn("h-24 text-center", className)} {...props} />
621
+ </TableRow>
622
+ )
623
+ }
624
+
625
+ /** The scrolling, bordered table. Compose `DataTableHeader` and `DataTableBody` inside. */
626
+ function DataTableTable({ className, ...props }: React.ComponentProps<typeof Table>) {
627
+ return (
628
+ <DataTableContainer>
629
+ <Table data-slot="data-table-table" className={cn("min-w-xl", className)} {...props} />
630
+ </DataTableContainer>
631
+ )
632
+ }
633
+
634
+ /* -------------------------------------------------------------------------- */
635
+ /* Pagination */
636
+ /* -------------------------------------------------------------------------- */
637
+
638
+ function getPageNumbers(currentPage: number, totalPages: number) {
639
+ const maxVisiblePages = 5
640
+ const range: Array<number | "..."> = []
641
+ if (totalPages <= maxVisiblePages) {
642
+ for (let i = 1; i <= totalPages; i++) range.push(i)
643
+ } else {
644
+ range.push(1)
645
+ if (currentPage <= 3) {
646
+ for (let i = 2; i <= 4; i++) range.push(i)
647
+ range.push("...", totalPages)
648
+ } else if (currentPage >= totalPages - 2) {
649
+ range.push("...")
650
+ for (let i = totalPages - 3; i <= totalPages; i++) range.push(i)
651
+ } else {
652
+ range.push("...")
653
+ for (let i = currentPage - 1; i <= currentPage + 1; i++) range.push(i)
654
+ range.push("...", totalPages)
655
+ }
656
+ }
657
+ return range
658
+ }
659
+
660
+ function DataTablePagination({ className, ...props }: React.ComponentProps<"div">) {
661
+ return (
662
+ <div
663
+ data-slot="data-table-pagination"
664
+ className={cn("flex flex-col-reverse items-center justify-between gap-4 px-2 md:flex-row", className)}
665
+ {...props}
666
+ />
667
+ )
668
+ }
669
+
670
+ const defaultPageSizes = [10, 20, 30, 40, 50]
671
+
672
+ function DataTablePageSize<TData>({
673
+ table: tableProp,
674
+ pageSizes = defaultPageSizes,
675
+ className,
676
+ children,
677
+ }: {
678
+ table?: DataTableInstance<TData>
679
+ pageSizes?: number[]
680
+ className?: string
681
+ children?: React.ReactNode
682
+ }) {
683
+ const table = useDataTableContext(tableProp)
684
+ const collection = React.useMemo(() => createListCollection({ items: pageSizes.map(String) }), [pageSizes])
685
+ const pageSize = table.getState().pagination.pageSize
686
+ return (
687
+ <div data-slot="data-table-page-size" className={cn("flex items-center gap-2", className)}>
688
+ <Select
689
+ collection={collection}
690
+ value={[String(pageSize)]}
691
+ onValueChange={({ value }) => table.setPageSize(Number(value[0]))}
692
+ positioning={{ placement: "top", sameWidth: true }}
693
+ >
694
+ <SelectControl>
695
+ <SelectTrigger className="h-8 w-17.5">
696
+ <SelectValue placeholder={String(pageSize)} />
697
+ </SelectTrigger>
698
+ </SelectControl>
699
+ <SelectContent className="min-w-0">
700
+ {collection.items.map((size) => (
701
+ <SelectItem key={size} item={size}>
702
+ {size}
703
+ </SelectItem>
704
+ ))}
705
+ </SelectContent>
706
+ </Select>
707
+ <p className="hidden text-sm font-medium sm:block">{children ?? "Rows per page"}</p>
708
+ </div>
709
+ )
710
+ }
711
+
712
+ function DataTablePageInfo<TData>({
713
+ table: tableProp,
714
+ className,
715
+ ...props
716
+ }: React.ComponentProps<"div"> & { table?: DataTableInstance<TData> }) {
717
+ const table = useDataTableContext(tableProp)
718
+ const currentPage = table.getState().pagination.pageIndex + 1
719
+ const totalPages = Math.max(table.getPageCount(), 1)
720
+ return (
721
+ <div
722
+ data-slot="data-table-page-info"
723
+ className={cn("flex w-25 items-center justify-center text-sm font-medium", className)}
724
+ {...props}
725
+ >
726
+ Page {currentPage} of {totalPages}
727
+ </div>
728
+ )
729
+ }
730
+
731
+ function DataTablePageNav<TData>({
732
+ table: tableProp,
733
+ className,
734
+ showEdges = true,
735
+ ...props
736
+ }: React.ComponentProps<"div"> & {
737
+ table?: DataTableInstance<TData>
738
+ /** Show the first and last page buttons. */
739
+ showEdges?: boolean
740
+ }) {
741
+ const table = useDataTableContext(tableProp)
742
+ const currentPage = table.getState().pagination.pageIndex + 1
743
+ const totalPages = table.getPageCount()
744
+ const pageNumbers = getPageNumbers(currentPage, totalPages)
745
+ return (
746
+ <div data-slot="data-table-page-nav" className={cn("flex items-center gap-2", className)} {...props}>
747
+ {showEdges && (
748
+ <Button
749
+ variant="outline"
750
+ size="icon"
751
+ className="hidden size-8 md:inline-flex"
752
+ onClick={() => table.setPageIndex(0)}
753
+ disabled={!table.getCanPreviousPage()}
754
+ >
755
+ <span className="sr-only">Go to first page</span>
756
+ <ChevronsLeftIcon />
757
+ </Button>
758
+ )}
759
+ <Button
760
+ variant="outline"
761
+ size="icon"
762
+ className="size-8"
763
+ onClick={() => table.previousPage()}
764
+ disabled={!table.getCanPreviousPage()}
765
+ >
766
+ <span className="sr-only">Go to previous page</span>
767
+ <ChevronLeftIcon />
768
+ </Button>
769
+ {pageNumbers.map((pageNumber, index) =>
770
+ pageNumber === "..." ? (
771
+ <span key={`ellipsis-${index}`} className="px-1 text-sm text-muted-foreground">
772
+ ...
773
+ </span>
774
+ ) : (
775
+ <Button
776
+ key={pageNumber}
777
+ variant={currentPage === pageNumber ? "default" : "outline"}
778
+ size="sm"
779
+ className="h-8 min-w-8 px-2"
780
+ onClick={() => table.setPageIndex(pageNumber - 1)}
781
+ aria-current={currentPage === pageNumber ? "page" : undefined}
782
+ >
783
+ <span className="sr-only">Go to page </span>
784
+ {pageNumber}
785
+ </Button>
786
+ )
787
+ )}
788
+ <Button
789
+ variant="outline"
790
+ size="icon"
791
+ className="size-8"
792
+ onClick={() => table.nextPage()}
793
+ disabled={!table.getCanNextPage()}
794
+ >
795
+ <span className="sr-only">Go to next page</span>
796
+ <ChevronRightIcon />
797
+ </Button>
798
+ {showEdges && (
799
+ <Button
800
+ variant="outline"
801
+ size="icon"
802
+ className="hidden size-8 md:inline-flex"
803
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
804
+ disabled={!table.getCanNextPage()}
805
+ >
806
+ <span className="sr-only">Go to last page</span>
807
+ <ChevronsRightIcon />
808
+ </Button>
809
+ )}
810
+ </div>
811
+ )
812
+ }
813
+
814
+ /* -------------------------------------------------------------------------- */
815
+ /* Bulk actions */
816
+ /* -------------------------------------------------------------------------- */
817
+
818
+ function DataTableBulkActions<TData>({
819
+ table: tableProp,
820
+ entityName = "row",
821
+ className,
822
+ children,
823
+ ...props
824
+ }: React.ComponentProps<"div"> & {
825
+ table?: DataTableInstance<TData>
826
+ entityName?: string
827
+ }) {
828
+ const table = useDataTableContext(tableProp)
829
+ const selectedCount = table.getFilteredSelectedRowModel().rows.length
830
+ const { message: announcement, announce } = useLiveRegion({ clearAfter: 3000 })
831
+ const plural = selectedCount > 1 ? "s" : ""
832
+
833
+ React.useEffect(() => {
834
+ if (selectedCount === 0) return
835
+ announce(`${selectedCount} ${entityName}${plural} selected. Bulk actions toolbar is available.`)
836
+ }, [selectedCount, entityName, plural, announce])
837
+
838
+ return (
839
+ <>
840
+ <LiveRegion data-slot="data-table-live-region" message={announcement} />
841
+ <FloatingToolbar
842
+ open={selectedCount > 0}
843
+ data-slot="data-table-bulk-actions"
844
+ aria-label={`Bulk actions for ${selectedCount} selected ${entityName}${plural}`}
845
+ onEscape={() => table.resetRowSelection()}
846
+ className={className}
847
+ {...props}
848
+ >
849
+ <DataTableBulkActionsClear table={table} />
850
+ <Separator orientation="vertical" className="h-5" aria-hidden />
851
+ <DataTableBulkActionsCount table={table} entityName={entityName} />
852
+ <Separator orientation="vertical" className="h-5" aria-hidden />
853
+ {children}
854
+ </FloatingToolbar>
855
+ </>
856
+ )
857
+ }
858
+
859
+ function DataTableBulkActionsClear<TData>({
860
+ table: tableProp,
861
+ className,
862
+ asChild,
863
+ children,
864
+ ...props
865
+ }: React.ComponentProps<typeof Button> & { table?: DataTableInstance<TData> }) {
866
+ const table = useDataTableContext(tableProp)
867
+ return (
868
+ <Tooltip>
869
+ <TooltipTrigger asChild>
870
+ <Button
871
+ data-slot="data-table-bulk-actions-clear"
872
+ variant="outline"
873
+ size="icon"
874
+ asChild={asChild}
875
+ onClick={() => table.resetRowSelection()}
876
+ className={cn("size-6 rounded-full", className)}
877
+ aria-label="Clear selection"
878
+ {...props}
879
+ >
880
+ {asChild ? children : (children ?? <XIcon />)}
881
+ </Button>
882
+ </TooltipTrigger>
883
+ <TooltipContent>Clear selection (Escape)</TooltipContent>
884
+ </Tooltip>
885
+ )
886
+ }
887
+
888
+ function DataTableBulkActionsCount<TData>({
889
+ table: tableProp,
890
+ entityName = "row",
891
+ className,
892
+ ...props
893
+ }: React.ComponentProps<"div"> & {
894
+ table?: DataTableInstance<TData>
895
+ entityName?: string
896
+ }) {
897
+ const table = useDataTableContext(tableProp)
898
+ const count = table.getFilteredSelectedRowModel().rows.length
899
+ return (
900
+ <div
901
+ data-slot="data-table-bulk-actions-count"
902
+ className={cn("flex items-center gap-1 text-sm", className)}
903
+ {...props}
904
+ >
905
+ <Badge className="min-w-8 justify-center rounded-lg" aria-label={`${count} selected`}>
906
+ {count}
907
+ </Badge>{" "}
908
+ <span className="hidden sm:inline">
909
+ {entityName}
910
+ {count > 1 ? "s" : ""}
911
+ </span>{" "}
912
+ selected
913
+ </div>
914
+ )
915
+ }
916
+
917
+ function DataTableBulkActionTrigger({
918
+ label,
919
+ className,
920
+ children,
921
+ asChild,
922
+ ...props
923
+ }: React.ComponentProps<typeof Button> & { label: string }) {
924
+ return (
925
+ <Tooltip>
926
+ <TooltipTrigger asChild>
927
+ <Button
928
+ data-slot="data-table-bulk-action-trigger"
929
+ variant="outline"
930
+ size="icon"
931
+ asChild={asChild}
932
+ className={cn("size-8", className)}
933
+ aria-label={label}
934
+ {...props}
935
+ >
936
+ {asChild ? (
937
+ children
938
+ ) : (
939
+ <>
940
+ {children}
941
+ <span className="sr-only">{label}</span>
942
+ </>
943
+ )}
944
+ </Button>
945
+ </TooltipTrigger>
946
+ <TooltipContent>{label}</TooltipContent>
947
+ </Tooltip>
948
+ )
949
+ }
950
+
951
+ export {
952
+ DataTable,
953
+ DataTableBody,
954
+ DataTableBulkActionTrigger,
955
+ DataTableBulkActions,
956
+ DataTableBulkActionsClear,
957
+ DataTableBulkActionsCount,
958
+ DataTableCell,
959
+ DataTableHead,
960
+ DataTableContainer,
961
+ DataTableEmpty,
962
+ DataTableFacetedFilter,
963
+ DataTableHeader,
964
+ DataTablePageInfo,
965
+ DataTablePageNav,
966
+ DataTablePageSize,
967
+ DataTablePagination,
968
+ DataTableResetFilters,
969
+ DataTableRow,
970
+ DataTableRowActions,
971
+ DataTableSearch,
972
+ DataTableSelectAll,
973
+ DataTableSelectRow,
974
+ DataTableTable,
975
+ DataTableToolbar,
976
+ DataTableToolbarGroup,
977
+ DataTableViewOptions,
978
+ getPageNumbers,
979
+ useDataTable,
980
+ useDataTableContext,
981
+ type ColumnDef,
982
+ type ColumnFiltersState,
983
+ type FacetOption,
984
+ type PaginationState,
985
+ type Row,
986
+ type RowSelectionState,
987
+ type SortingState,
988
+ type DataTableColumn,
989
+ type DataTableInstance,
990
+ type DataTableRowInstance,
991
+ type TableOptions,
992
+ type VisibilityState,
993
+ }