@ayasofyazilim/ui 0.0.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 (236) hide show
  1. package/__mocks__/canvas.ts +8 -0
  2. package/components.json +21 -0
  3. package/eslint.config.js +4 -0
  4. package/jest-environment.js +37 -0
  5. package/jest.config.ts +47 -0
  6. package/jest.setup.ts +69 -0
  7. package/package.json +124 -0
  8. package/postcss.config.mjs +6 -0
  9. package/src/aria/index.tsx +1 -0
  10. package/src/aria/number-field.tsx +41 -0
  11. package/src/components/.gitkeep +0 -0
  12. package/src/components/accordion.tsx +66 -0
  13. package/src/components/alert-dialog.tsx +157 -0
  14. package/src/components/alert.tsx +70 -0
  15. package/src/components/aspect-ratio.tsx +11 -0
  16. package/src/components/avatar.tsx +53 -0
  17. package/src/components/badge.tsx +67 -0
  18. package/src/components/breadcrumb.tsx +109 -0
  19. package/src/components/button-group.tsx +83 -0
  20. package/src/components/button.tsx +68 -0
  21. package/src/components/calendar.tsx +219 -0
  22. package/src/components/card.tsx +92 -0
  23. package/src/components/carousel.tsx +241 -0
  24. package/src/components/chart.tsx +363 -0
  25. package/src/components/checkbox.tsx +32 -0
  26. package/src/components/collapsible.tsx +33 -0
  27. package/src/components/command.tsx +184 -0
  28. package/src/components/context-menu.tsx +252 -0
  29. package/src/components/dialog.tsx +144 -0
  30. package/src/components/drawer.tsx +135 -0
  31. package/src/components/dropdown-menu.tsx +258 -0
  32. package/src/components/empty.tsx +100 -0
  33. package/src/components/field.tsx +248 -0
  34. package/src/components/form.tsx +169 -0
  35. package/src/components/hover-card.tsx +44 -0
  36. package/src/components/input-group.tsx +170 -0
  37. package/src/components/input-otp.tsx +77 -0
  38. package/src/components/input.tsx +21 -0
  39. package/src/components/item.tsx +193 -0
  40. package/src/components/kbd.tsx +28 -0
  41. package/src/components/label.tsx +24 -0
  42. package/src/components/menubar.tsx +276 -0
  43. package/src/components/navigation-menu.tsx +168 -0
  44. package/src/components/pagination.tsx +130 -0
  45. package/src/components/popover.tsx +88 -0
  46. package/src/components/progress.tsx +31 -0
  47. package/src/components/radio-group.tsx +45 -0
  48. package/src/components/resizable.tsx +56 -0
  49. package/src/components/scroll-area.tsx +58 -0
  50. package/src/components/select.tsx +189 -0
  51. package/src/components/separator.tsx +28 -0
  52. package/src/components/sheet.tsx +140 -0
  53. package/src/components/sidebar.tsx +862 -0
  54. package/src/components/skeleton.tsx +13 -0
  55. package/src/components/slider.tsx +63 -0
  56. package/src/components/sonner.tsx +40 -0
  57. package/src/components/spinner.tsx +16 -0
  58. package/src/components/stepper.tsx +291 -0
  59. package/src/components/switch.tsx +31 -0
  60. package/src/components/table.tsx +133 -0
  61. package/src/components/tabs.tsx +66 -0
  62. package/src/components/textarea.tsx +18 -0
  63. package/src/components/toggle-group.tsx +83 -0
  64. package/src/components/toggle.tsx +47 -0
  65. package/src/components/tooltip.tsx +66 -0
  66. package/src/custom/action-button.tsx +48 -0
  67. package/src/custom/async-select.tsx +287 -0
  68. package/src/custom/awesome-not-found.tsx +116 -0
  69. package/src/custom/charts/area-chart.tsx +147 -0
  70. package/src/custom/charts/bar-chart.tsx +233 -0
  71. package/src/custom/charts/chart-card.tsx +103 -0
  72. package/src/custom/charts/index.tsx +16 -0
  73. package/src/custom/charts/pie-chart.tsx +168 -0
  74. package/src/custom/charts/radar-chart.tsx +126 -0
  75. package/src/custom/checkbox-tree.tsx +100 -0
  76. package/src/custom/combobox.tsx +296 -0
  77. package/src/custom/confirm-dialog.tsx +102 -0
  78. package/src/custom/country-selector.tsx +204 -0
  79. package/src/custom/date-picker/calendar-rac.tsx +109 -0
  80. package/src/custom/date-picker/datefield-rac.tsx +84 -0
  81. package/src/custom/date-picker/index.tsx +273 -0
  82. package/src/custom/date-picker/types/index.ts +4 -0
  83. package/src/custom/date-picker/utils/index.ts +42 -0
  84. package/src/custom/date-picker-old.tsx +50 -0
  85. package/src/custom/date-tooltip.tsx +98 -0
  86. package/src/custom/document-scanner/consts.ts +5 -0
  87. package/src/custom/document-scanner/corner-adjustment/action-buttons.tsx +33 -0
  88. package/src/custom/document-scanner/corner-adjustment/corner-handle.tsx +43 -0
  89. package/src/custom/document-scanner/corner-adjustment/hooks/use-corner-drag.ts +85 -0
  90. package/src/custom/document-scanner/corner-adjustment/index.tsx +125 -0
  91. package/src/custom/document-scanner/corner-adjustment/types.ts +53 -0
  92. package/src/custom/document-scanner/corner-adjustment/utils/clip-path.ts +22 -0
  93. package/src/custom/document-scanner/corner-adjustment/zoom-magnifier.tsx +115 -0
  94. package/src/custom/document-scanner/hooks/use-document-capture.ts +81 -0
  95. package/src/custom/document-scanner/hooks/use-document-scanner.ts +80 -0
  96. package/src/custom/document-scanner/hooks/use-perspective-crop.ts +38 -0
  97. package/src/custom/document-scanner/index.tsx +255 -0
  98. package/src/custom/document-scanner/lib.ts +407 -0
  99. package/src/custom/document-scanner/types.ts +205 -0
  100. package/src/custom/document-scanner/utils/perspective-correction.ts +139 -0
  101. package/src/custom/document-viewer/controllers.tsx +98 -0
  102. package/src/custom/document-viewer/index.tsx +43 -0
  103. package/src/custom/document-viewer/renderers/image.tsx +37 -0
  104. package/src/custom/document-viewer/renderers/index.tsx +2 -0
  105. package/src/custom/document-viewer/renderers/pdf.tsx +105 -0
  106. package/src/custom/email-input/domains.json +159 -0
  107. package/src/custom/email-input/email.tsx +229 -0
  108. package/src/custom/email-input/index.tsx +4 -0
  109. package/src/custom/email-input/types.ts +104 -0
  110. package/src/custom/file-uploader.tsx +541 -0
  111. package/src/custom/filter-component/fields/async-select.tsx +33 -0
  112. package/src/custom/filter-component/fields/date.tsx +60 -0
  113. package/src/custom/filter-component/fields/multi-select.tsx +30 -0
  114. package/src/custom/filter-component/index.tsx +217 -0
  115. package/src/custom/image-canvas.tsx +260 -0
  116. package/src/custom/json-editor.tsx +22 -0
  117. package/src/custom/master-data-grid/components/dialogs/column-settings-dialog.tsx +100 -0
  118. package/src/custom/master-data-grid/components/dialogs/index.ts +1 -0
  119. package/src/custom/master-data-grid/components/filters/client-filter.tsx +368 -0
  120. package/src/custom/master-data-grid/components/filters/filter-input.tsx +256 -0
  121. package/src/custom/master-data-grid/components/filters/index.ts +3 -0
  122. package/src/custom/master-data-grid/components/filters/inline-column-filter.tsx +233 -0
  123. package/src/custom/master-data-grid/components/filters/multi-filter-dialog.tsx +90 -0
  124. package/src/custom/master-data-grid/components/filters/server-filter.tsx +255 -0
  125. package/src/custom/master-data-grid/components/master-data-grid.tsx +472 -0
  126. package/src/custom/master-data-grid/components/pagination/index.ts +1 -0
  127. package/src/custom/master-data-grid/components/pagination/pagination.tsx +178 -0
  128. package/src/custom/master-data-grid/components/table/cell-renderer.tsx +634 -0
  129. package/src/custom/master-data-grid/components/table/header-cell.tsx +162 -0
  130. package/src/custom/master-data-grid/components/table/index.ts +4 -0
  131. package/src/custom/master-data-grid/components/table/table-body-renderer.tsx +113 -0
  132. package/src/custom/master-data-grid/components/table/virtual-body.tsx +138 -0
  133. package/src/custom/master-data-grid/components/toolbar/index.ts +1 -0
  134. package/src/custom/master-data-grid/components/toolbar/toolbar.tsx +314 -0
  135. package/src/custom/master-data-grid/hooks/index.ts +3 -0
  136. package/src/custom/master-data-grid/hooks/use-columns.tsx +332 -0
  137. package/src/custom/master-data-grid/hooks/use-editing.ts +106 -0
  138. package/src/custom/master-data-grid/hooks/use-table-state-reducer.ts +157 -0
  139. package/src/custom/master-data-grid/hooks/use-table-state.ts +31 -0
  140. package/src/custom/master-data-grid/index.ts +16 -0
  141. package/src/custom/master-data-grid/types.ts +466 -0
  142. package/src/custom/master-data-grid/utils/column-generator.tsx +306 -0
  143. package/src/custom/master-data-grid/utils/export-utils.ts +67 -0
  144. package/src/custom/master-data-grid/utils/filter-fns.ts +290 -0
  145. package/src/custom/master-data-grid/utils/index.ts +8 -0
  146. package/src/custom/master-data-grid/utils/pinning-utils.ts +88 -0
  147. package/src/custom/master-data-grid/utils/translation-utils.ts +42 -0
  148. package/src/custom/multi-select.tsx +432 -0
  149. package/src/custom/password-input.tsx +194 -0
  150. package/src/custom/phone-input.tsx +172 -0
  151. package/src/custom/schema-form/custom/index.tsx +1 -0
  152. package/src/custom/schema-form/custom/label.tsx +53 -0
  153. package/src/custom/schema-form/fields/base-input-field.tsx +82 -0
  154. package/src/custom/schema-form/fields/field.tsx +67 -0
  155. package/src/custom/schema-form/fields/index.tsx +5 -0
  156. package/src/custom/schema-form/fields/object.tsx +12 -0
  157. package/src/custom/schema-form/fields/table-array/array-field-item.tsx +90 -0
  158. package/src/custom/schema-form/fields/table-array/array-field-template.tsx +115 -0
  159. package/src/custom/schema-form/index.tsx +259 -0
  160. package/src/custom/schema-form/templates/description.tsx +20 -0
  161. package/src/custom/schema-form/templates/index.tsx +2 -0
  162. package/src/custom/schema-form/templates/submit.tsx +32 -0
  163. package/src/custom/schema-form/types.ts +64 -0
  164. package/src/custom/schema-form/utils/index.ts +4 -0
  165. package/src/custom/schema-form/utils/schema-dependency.ts +655 -0
  166. package/src/custom/schema-form/utils/schemas.ts +289 -0
  167. package/src/custom/schema-form/utils/validation.ts +23 -0
  168. package/src/custom/schema-form/widgets/boolean.tsx +77 -0
  169. package/src/custom/schema-form/widgets/combobox.tsx +274 -0
  170. package/src/custom/schema-form/widgets/date.tsx +59 -0
  171. package/src/custom/schema-form/widgets/email.tsx +34 -0
  172. package/src/custom/schema-form/widgets/index.tsx +10 -0
  173. package/src/custom/schema-form/widgets/password.tsx +40 -0
  174. package/src/custom/schema-form/widgets/phone.tsx +40 -0
  175. package/src/custom/schema-form/widgets/select.tsx +105 -0
  176. package/src/custom/schema-form/widgets/selectable.tsx +25 -0
  177. package/src/custom/schema-form/widgets/string-array.tsx +296 -0
  178. package/src/custom/schema-form/widgets/url.tsx +56 -0
  179. package/src/custom/section-layout-v2.tsx +212 -0
  180. package/src/custom/select-tabs.tsx +109 -0
  181. package/src/custom/selectable.tsx +316 -0
  182. package/src/custom/stepper.tsx +236 -0
  183. package/src/custom/tab-layout.tsx +213 -0
  184. package/src/custom/tanstack-table/fields/index.tsx +12 -0
  185. package/src/custom/tanstack-table/fields/tanstack-table-action-dialogs.tsx +89 -0
  186. package/src/custom/tanstack-table/fields/tanstack-table-column-header.tsx +66 -0
  187. package/src/custom/tanstack-table/fields/tanstack-table-filter-date.tsx +180 -0
  188. package/src/custom/tanstack-table/fields/tanstack-table-filter-faceted.tsx +158 -0
  189. package/src/custom/tanstack-table/fields/tanstack-table-filter-text.tsx +76 -0
  190. package/src/custom/tanstack-table/fields/tanstack-table-pagination.tsx +136 -0
  191. package/src/custom/tanstack-table/fields/tanstack-table-plain-table.tsx +142 -0
  192. package/src/custom/tanstack-table/fields/tanstack-table-row-actions-confirmation.tsx +77 -0
  193. package/src/custom/tanstack-table/fields/tanstack-table-row-actions-custom-dialog.tsx +87 -0
  194. package/src/custom/tanstack-table/fields/tanstack-table-row-actions.tsx +151 -0
  195. package/src/custom/tanstack-table/fields/tanstack-table-table-actions-custom-dialog.tsx +88 -0
  196. package/src/custom/tanstack-table/fields/tanstack-table-table-actions-schemaform-dialog.tsx +47 -0
  197. package/src/custom/tanstack-table/fields/tanstack-table-toolbar.tsx +143 -0
  198. package/src/custom/tanstack-table/fields/tanstack-table-view-options.tsx +171 -0
  199. package/src/custom/tanstack-table/index.tsx +244 -0
  200. package/src/custom/tanstack-table/types/index.ts +328 -0
  201. package/src/custom/tanstack-table/utils/cell-with-actions.tsx +21 -0
  202. package/src/custom/tanstack-table/utils/column-names.ts +26 -0
  203. package/src/custom/tanstack-table/utils/columns-by-row-data.tsx +312 -0
  204. package/src/custom/tanstack-table/utils/editable-columns-by-row-data.tsx +219 -0
  205. package/src/custom/tanstack-table/utils/faceted-boolean-options.tsx +22 -0
  206. package/src/custom/tanstack-table/utils/index.tsx +10 -0
  207. package/src/custom/tanstack-table/utils/pinning-styles.ts +57 -0
  208. package/src/custom/tanstack-table/utils/table.tsx +83 -0
  209. package/src/custom/tanstack-table/utils/test-conditions.ts +17 -0
  210. package/src/custom/timeline.tsx +208 -0
  211. package/src/custom/tree.tsx +200 -0
  212. package/src/custom/tscanify/browser.ts +66 -0
  213. package/src/custom/tscanify/index.ts +51 -0
  214. package/src/custom/tscanify/tscanify-browser.ts +522 -0
  215. package/src/custom/tscanify/tscanify.ts +262 -0
  216. package/src/custom/tscanify/types.ts +22 -0
  217. package/src/custom/webcam.tsx +737 -0
  218. package/src/hooks/.gitkeep +0 -0
  219. package/src/hooks/use-callback-ref.ts +27 -0
  220. package/src/hooks/use-controllable-state.ts +67 -0
  221. package/src/hooks/use-debounce.ts +19 -0
  222. package/src/hooks/use-is-visible.ts +23 -0
  223. package/src/hooks/use-media-query.ts +21 -0
  224. package/src/hooks/use-mobile.ts +21 -0
  225. package/src/hooks/use-on-window-resize.ts +15 -0
  226. package/src/hooks/use-scroll.tsx +22 -0
  227. package/src/lib/utils.ts +61 -0
  228. package/src/lib/zod.ts +2 -0
  229. package/src/styles/core.css +57 -0
  230. package/src/styles/globals.css +130 -0
  231. package/src/test/email-input.test.tsx +217 -0
  232. package/src/test/password-input.test.tsx +92 -0
  233. package/src/test/select-tabs.test.tsx +302 -0
  234. package/src/test/selectable.test.tsx +1093 -0
  235. package/tsconfig.json +13 -0
  236. package/tsconfig.lint.json +8 -0
@@ -0,0 +1,162 @@
1
+ "use no memo";
2
+ import type { Column, Header } from "@tanstack/react-table";
3
+ import {
4
+ ArrowDown,
5
+ ArrowUp,
6
+ ChevronDown,
7
+ EyeOff,
8
+ FilterIcon,
9
+ PinIcon,
10
+ PinOffIcon,
11
+ Undo2,
12
+ } from "lucide-react";
13
+ import { Button } from "../../../../components/button";
14
+ import {
15
+ DropdownMenu,
16
+ DropdownMenuContent,
17
+ DropdownMenuGroup,
18
+ DropdownMenuItem,
19
+ DropdownMenuLabel,
20
+ DropdownMenuSeparator,
21
+ DropdownMenuTrigger,
22
+ } from "../../../../components/dropdown-menu";
23
+ import { getTranslations } from "../../utils/translation-utils";
24
+ import { InlineColumnFilter } from "../filters";
25
+ import { MasterDataGridResources } from "../../types";
26
+
27
+ interface HeaderCellProps<TData> {
28
+ column: Column<TData>;
29
+ header?: Header<TData, unknown>;
30
+ label: string;
31
+ t?: MasterDataGridResources;
32
+ }
33
+ export function HeaderCell<TData>({
34
+ column,
35
+ header,
36
+ label,
37
+ t,
38
+ }: HeaderCellProps<TData>) {
39
+ const isSorted = column.getIsSorted();
40
+ const isPinned = column.getIsPinned();
41
+
42
+ const hasAnyAction =
43
+ column.getCanSort() ||
44
+ column.getCanPin() ||
45
+ column.getCanFilter() ||
46
+ column.getCanResize() ||
47
+ column.getCanHide();
48
+
49
+ if (!hasAnyAction) {
50
+ return (
51
+ <div className="flex items-center size-full">
52
+ <span className="font-semibold truncate">{label}</span>
53
+ </div>
54
+ );
55
+ }
56
+
57
+ return (
58
+ <div className="flex items-center size-full relative">
59
+ <DropdownMenu>
60
+ <DropdownMenuTrigger asChild>
61
+ <Button
62
+ variant="ghost"
63
+ className="data-[state=open]:bg-accent w-full rounded-none"
64
+ >
65
+ <span className="font-semibold mr-auto truncate">{label}</span>
66
+ {isSorted === "asc" ? (
67
+ <ArrowUp className="ml-2 h-4 w-4" />
68
+ ) : isSorted === "desc" ? (
69
+ <ArrowDown className="ml-2 h-4 w-4" />
70
+ ) : (
71
+ <ChevronDown className="ml-2 h-4 w-4" />
72
+ )}
73
+ </Button>
74
+ </DropdownMenuTrigger>
75
+ <DropdownMenuContent align="start">
76
+ {column.getCanSort() && (
77
+ <>
78
+ <DropdownMenuItem onClick={() => column.toggleSorting(false)}>
79
+ <ArrowUp className="mr-2 h-4 w-4" />
80
+ {getTranslations("column.sortAsc", t)}
81
+ </DropdownMenuItem>
82
+ <DropdownMenuItem onClick={() => column.toggleSorting(true)}>
83
+ <ArrowDown className="mr-2 h-4 w-4" />
84
+ {getTranslations("column.sortDesc", t)}
85
+ </DropdownMenuItem>
86
+ <DropdownMenuSeparator />
87
+ </>
88
+ )}
89
+
90
+ {column.getCanPin() && (
91
+ <>
92
+ <DropdownMenuItem onClick={() => column.pin("left")}>
93
+ <PinIcon className="mr-2 h-4 w-4" />
94
+ {getTranslations("column.pinLeft", t)}
95
+ </DropdownMenuItem>
96
+ <DropdownMenuItem onClick={() => column.pin("right")}>
97
+ <PinIcon className="mr-2 h-4 w-4" />
98
+ {getTranslations("column.pinRight", t)}
99
+ </DropdownMenuItem>
100
+ {isPinned && (
101
+ <DropdownMenuItem onClick={() => column.pin(false)}>
102
+ <PinOffIcon className="mr-2 h-4 w-4" />
103
+ {getTranslations("column.unpin", t)}
104
+ </DropdownMenuItem>
105
+ )}
106
+ <DropdownMenuSeparator />
107
+ </>
108
+ )}
109
+
110
+ {column.getCanFilter() && (
111
+ <DropdownMenuGroup>
112
+ <DropdownMenuLabel className="flex items-center gap-4 font-normal">
113
+ <FilterIcon className="h-4 w-4 text-muted-foreground" />
114
+ {getTranslations("column.filter", t)}
115
+ </DropdownMenuLabel>
116
+ <DropdownMenuItem className="p-0" asChild>
117
+ <InlineColumnFilter column={column} t={t} />
118
+ </DropdownMenuItem>
119
+ </DropdownMenuGroup>
120
+ )}
121
+
122
+ {header &&
123
+ column.getCanResize() &&
124
+ column.getSize() !== column.columnDef.size && (
125
+ <>
126
+ <DropdownMenuSeparator />
127
+ <DropdownMenuItem onClick={() => header.column.resetSize()}>
128
+ <Undo2 className="mr-2 h-4 w-4" />
129
+ {getTranslations("column.resetSize", t)}
130
+ </DropdownMenuItem>
131
+ </>
132
+ )}
133
+
134
+ {column.getCanHide() && (
135
+ <>
136
+ <DropdownMenuSeparator />
137
+ <DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
138
+ <EyeOff className="mr-2 h-4 w-4" />
139
+ {getTranslations("column.hide", t)}
140
+ </DropdownMenuItem>
141
+ </>
142
+ )}
143
+ </DropdownMenuContent>
144
+ </DropdownMenu>
145
+
146
+ {header && column.getCanResize() && (
147
+ <div
148
+ onMouseDown={header.getResizeHandler()}
149
+ onTouchStart={header.getResizeHandler()}
150
+ className={`absolute right-0 top-0 h-full w-1 cursor-col-resize select-none touch-none hover:bg-primary transition-opacity ${
151
+ column.getIsResizing()
152
+ ? "bg-primary opacity-100"
153
+ : "opacity-0 hover:opacity-50"
154
+ }`}
155
+ style={{
156
+ transform: column.getIsResizing() ? "translateX(0)" : undefined,
157
+ }}
158
+ />
159
+ )}
160
+ </div>
161
+ );
162
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./cell-renderer";
2
+ export * from "./table-body-renderer";
3
+ export * from "./virtual-body";
4
+ export * from "./header-cell";
@@ -0,0 +1,113 @@
1
+ "use no memo";
2
+ import type { Row, Table as TanStackTable } from "@tanstack/react-table";
3
+ import { flexRender } from "@tanstack/react-table";
4
+ import React from "react";
5
+ import { TableBody, TableCell, TableRow } from "../../../../components/table";
6
+ import { cn } from "../../../../lib/utils";
7
+ import {
8
+ getPinningCellClassNames,
9
+ getPinningCellStyles,
10
+ } from "../../utils/pinning-utils";
11
+
12
+ interface TableBodyRendererProps<TData> {
13
+ table: TanStackTable<TData>;
14
+ rows: Row<TData>[];
15
+ rowClassName?: string | ((row: TData) => string);
16
+ cellClassName?: string | ((cell: { row: TData; columnId: string }) => string);
17
+ editingRows?: Record<string, Record<string, unknown>>;
18
+ getRowId?: (row: TData, index: number) => string;
19
+ editingEnabled?: boolean;
20
+ emptyMessage?: string;
21
+ expansionEnabled?: boolean;
22
+ expansionRenderContent?: (row: TData) => React.ReactNode;
23
+ bodyClassName?: string;
24
+ }
25
+
26
+ export function TableBodyRenderer<TData>({
27
+ table,
28
+ rows,
29
+ rowClassName,
30
+ cellClassName,
31
+ editingRows,
32
+ getRowId,
33
+ editingEnabled,
34
+ emptyMessage,
35
+ expansionEnabled,
36
+ expansionRenderContent,
37
+ bodyClassName,
38
+ }: TableBodyRendererProps<TData>) {
39
+ return (
40
+ <TableBody className={bodyClassName}>
41
+ {rows.length ? (
42
+ rows.map((row) => (
43
+ <React.Fragment key={row.id}>
44
+ <TableRow
45
+ data-state={row.getIsSelected() && "selected"}
46
+ className={cn(
47
+ typeof rowClassName === "function"
48
+ ? rowClassName(row.original)
49
+ : rowClassName,
50
+ "group"
51
+ )}
52
+ >
53
+ {row.getVisibleCells().map((cell) => {
54
+ const cellClass =
55
+ typeof cellClassName === "function"
56
+ ? cellClassName({
57
+ row: row.original,
58
+ columnId: cell.column.id,
59
+ })
60
+ : cellClassName;
61
+
62
+ const rowId = getRowId
63
+ ? getRowId(row.original, row.index)
64
+ : String(row.index);
65
+ const isEditing = editingRows?.[rowId] !== undefined;
66
+
67
+ return (
68
+ <TableCell
69
+ key={cell.id}
70
+ style={getPinningCellStyles(cell)}
71
+ className={cn(
72
+ cellClass,
73
+ "last:border-0! first:border-0! group-last:border-b-0! py-0 h-9 has-[div>input]:px-0 has-[div>button]:px-0",
74
+ getPinningCellClassNames(cell),
75
+ isEditing && "py-0",
76
+ editingEnabled && "border",
77
+ editingEnabled &&
78
+ !isEditing &&
79
+ "hover:border-muted-foreground/40"
80
+ )}
81
+ >
82
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
83
+ </TableCell>
84
+ );
85
+ })}
86
+ </TableRow>
87
+ {row.getIsExpanded() &&
88
+ expansionEnabled &&
89
+ expansionRenderContent && (
90
+ <TableRow>
91
+ <TableCell
92
+ className="has-[.pp-0]:p-0"
93
+ colSpan={row.getVisibleCells().length}
94
+ >
95
+ {expansionRenderContent(row.original)}
96
+ </TableCell>
97
+ </TableRow>
98
+ )}
99
+ </React.Fragment>
100
+ ))
101
+ ) : (
102
+ <TableRow>
103
+ <TableCell
104
+ colSpan={table.getAllColumns().length}
105
+ className="h-24 text-center"
106
+ >
107
+ {emptyMessage || "No results."}
108
+ </TableCell>
109
+ </TableRow>
110
+ )}
111
+ </TableBody>
112
+ );
113
+ }
@@ -0,0 +1,138 @@
1
+ "use no memo";
2
+ import type { Row } from "@tanstack/react-table";
3
+ import { flexRender } from "@tanstack/react-table";
4
+ import { useVirtualizer } from "@tanstack/react-virtual";
5
+ import React, { useRef } from "react";
6
+ import { TableBody, TableCell, TableRow } from "../../../../components/table";
7
+ import { cn } from "../../../../lib/utils";
8
+ import {
9
+ getPinningCellClassNames,
10
+ getPinningCellStyles,
11
+ } from "../../utils/pinning-utils";
12
+
13
+ interface VirtualBodyProps<TData> {
14
+ rows: Row<TData>[];
15
+ estimateSize?: number;
16
+ overscan?: number;
17
+ rowClassName?: string | ((row: TData) => string);
18
+ cellClassName?: string | ((cell: { row: TData; columnId: string }) => string);
19
+ editingRows?: Record<string, Record<string, unknown>>;
20
+ getRowId?: (row: TData, index: number) => string;
21
+ editingEnabled?: boolean;
22
+ expansionEnabled?: boolean;
23
+ expansionRenderContent?: (row: TData) => React.ReactNode;
24
+ }
25
+
26
+ export function VirtualBody<TData>({
27
+ rows,
28
+ estimateSize = 53,
29
+ overscan = 10,
30
+ rowClassName,
31
+ cellClassName,
32
+ editingRows,
33
+ getRowId,
34
+ editingEnabled,
35
+ expansionEnabled,
36
+ expansionRenderContent,
37
+ }: VirtualBodyProps<TData>) {
38
+ const tableContainerRef = useRef<HTMLTableSectionElement>(null);
39
+
40
+ const rowVirtualizer = useVirtualizer({
41
+ count: rows.length,
42
+ getScrollElement: () => {
43
+ return tableContainerRef.current?.closest(
44
+ ".overflow-auto"
45
+ ) as HTMLElement | null;
46
+ },
47
+ estimateSize: () => estimateSize,
48
+ overscan,
49
+ });
50
+
51
+ const virtualRows = rowVirtualizer.getVirtualItems();
52
+ const totalSize = rowVirtualizer.getTotalSize();
53
+
54
+ const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start || 0 : 0;
55
+ const paddingBottom =
56
+ virtualRows.length > 0
57
+ ? totalSize - (virtualRows[virtualRows.length - 1]?.end || 0)
58
+ : 0;
59
+
60
+ return (
61
+ <TableBody ref={tableContainerRef}>
62
+ {paddingTop > 0 && (
63
+ <tr>
64
+ <td style={{ height: `${paddingTop}px` }} />
65
+ </tr>
66
+ )}
67
+
68
+ {virtualRows.map((virtualRow) => {
69
+ const row = rows[virtualRow.index];
70
+ if (!row) return null;
71
+
72
+ const rowClass =
73
+ typeof rowClassName === "function"
74
+ ? rowClassName(row.original)
75
+ : rowClassName;
76
+
77
+ return (
78
+ <React.Fragment key={row.id}>
79
+ <TableRow
80
+ data-state={row.getIsSelected() && "selected"}
81
+ className={cn(rowClass, "group")}
82
+ >
83
+ {row.getVisibleCells().map((cell) => {
84
+ const cellClass =
85
+ typeof cellClassName === "function"
86
+ ? cellClassName({
87
+ row: row.original,
88
+ columnId: cell.column.id,
89
+ })
90
+ : cellClassName;
91
+
92
+ const rowId = getRowId
93
+ ? getRowId(row.original, row.index)
94
+ : String(row.index);
95
+ const isEditing = editingRows?.[rowId] !== undefined;
96
+
97
+ return (
98
+ <TableCell
99
+ key={cell.id}
100
+ style={getPinningCellStyles(cell)}
101
+ className={cn(
102
+ cellClass,
103
+ isEditing && "py-0",
104
+ getPinningCellClassNames(cell),
105
+ "border-b border-r",
106
+ editingEnabled &&
107
+ "border border-dashed border-muted-foreground/20",
108
+ editingEnabled &&
109
+ !isEditing &&
110
+ "hover:border-muted-foreground/40"
111
+ )}
112
+ >
113
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
114
+ </TableCell>
115
+ );
116
+ })}
117
+ </TableRow>
118
+ {row.getIsExpanded() &&
119
+ expansionEnabled &&
120
+ expansionRenderContent && (
121
+ <TableRow>
122
+ <TableCell colSpan={row.getVisibleCells().length}>
123
+ {expansionRenderContent(row.original)}
124
+ </TableCell>
125
+ </TableRow>
126
+ )}
127
+ </React.Fragment>
128
+ );
129
+ })}
130
+
131
+ {paddingBottom > 0 && (
132
+ <tr>
133
+ <td style={{ height: `${paddingBottom}px` }} />
134
+ </tr>
135
+ )}
136
+ </TableBody>
137
+ );
138
+ }
@@ -0,0 +1 @@
1
+ export { Toolbar } from "./toolbar";