@rebasepro/ui 0.24.0 → 0.24.1-canary.gcb918fc

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 (241) hide show
  1. package/dist/components/Alert.d.ts +6 -0
  2. package/dist/components/Alert.es.js +82 -0
  3. package/dist/components/Alert.es.js.map +1 -0
  4. package/dist/components/Autocomplete.es.js +53 -0
  5. package/dist/components/Autocomplete.es.js.map +1 -0
  6. package/dist/components/Avatar.d.ts +3 -1
  7. package/dist/components/Avatar.es.js +37 -0
  8. package/dist/components/Avatar.es.js.map +1 -0
  9. package/dist/components/Badge.es.js +27 -0
  10. package/dist/components/Badge.es.js.map +1 -0
  11. package/dist/components/BooleanSwitch.es.js +75 -0
  12. package/dist/components/BooleanSwitch.es.js.map +1 -0
  13. package/dist/components/BooleanSwitchWithLabel.es.js +55 -0
  14. package/dist/components/BooleanSwitchWithLabel.es.js.map +1 -0
  15. package/dist/components/Button.es.js +58 -0
  16. package/dist/components/Button.es.js.map +1 -0
  17. package/dist/components/Card.es.js +26 -0
  18. package/dist/components/Card.es.js.map +1 -0
  19. package/dist/components/CenteredView.es.js +23 -0
  20. package/dist/components/CenteredView.es.js.map +1 -0
  21. package/dist/components/Checkbox.es.js +62 -0
  22. package/dist/components/Checkbox.es.js.map +1 -0
  23. package/dist/components/Chip.es.js +72 -0
  24. package/dist/components/Chip.es.js.map +1 -0
  25. package/dist/components/CircularProgress.es.js +28 -0
  26. package/dist/components/CircularProgress.es.js.map +1 -0
  27. package/dist/components/CircularProgressCenter.es.js +30 -0
  28. package/dist/components/CircularProgressCenter.es.js.map +1 -0
  29. package/dist/components/Collapse.es.js +57 -0
  30. package/dist/components/Collapse.es.js.map +1 -0
  31. package/dist/components/ColorPicker.es.js +89 -0
  32. package/dist/components/ColorPicker.es.js.map +1 -0
  33. package/dist/components/Container.es.js +31 -0
  34. package/dist/components/Container.es.js.map +1 -0
  35. package/dist/components/DateTimeField.d.ts +11 -1
  36. package/dist/components/DateTimeField.es.js +253 -0
  37. package/dist/components/DateTimeField.es.js.map +1 -0
  38. package/dist/components/DebouncedTextField.es.js +93 -0
  39. package/dist/components/DebouncedTextField.es.js.map +1 -0
  40. package/dist/components/Dialog.es.js +98 -0
  41. package/dist/components/Dialog.es.js.map +1 -0
  42. package/dist/components/DialogActions.es.js +15 -0
  43. package/dist/components/DialogActions.es.js.map +1 -0
  44. package/dist/components/DialogContent.es.js +18 -0
  45. package/dist/components/DialogContent.es.js.map +1 -0
  46. package/dist/components/DialogTitle.es.js +26 -0
  47. package/dist/components/DialogTitle.es.js.map +1 -0
  48. package/dist/components/ErrorBoundary.es.js +158 -0
  49. package/dist/components/ErrorBoundary.es.js.map +1 -0
  50. package/dist/components/ExpandablePanel.es.js +91 -0
  51. package/dist/components/ExpandablePanel.es.js.map +1 -0
  52. package/dist/components/FileUpload.es.js +58 -0
  53. package/dist/components/FileUpload.es.js.map +1 -0
  54. package/dist/components/FilterChip.es.js +31 -0
  55. package/dist/components/FilterChip.es.js.map +1 -0
  56. package/dist/components/IconButton.es.js +52 -0
  57. package/dist/components/IconButton.es.js.map +1 -0
  58. package/dist/components/InfoLabel.es.js +18 -0
  59. package/dist/components/InfoLabel.es.js.map +1 -0
  60. package/dist/components/InputLabel.es.js +27 -0
  61. package/dist/components/InputLabel.es.js.map +1 -0
  62. package/dist/components/Label.es.js +18 -0
  63. package/dist/components/Label.es.js.map +1 -0
  64. package/dist/components/LoadingButton.es.js +21 -0
  65. package/dist/components/LoadingButton.es.js.map +1 -0
  66. package/dist/components/Markdown.es.js +88 -0
  67. package/dist/components/Markdown.es.js.map +1 -0
  68. package/dist/components/Menu.es.js +46 -0
  69. package/dist/components/Menu.es.js.map +1 -0
  70. package/dist/components/Menubar.es.js +142 -0
  71. package/dist/components/Menubar.es.js.map +1 -0
  72. package/dist/components/MultiSelect.d.ts +1 -7
  73. package/dist/components/MultiSelect.es.js +271 -0
  74. package/dist/components/MultiSelect.es.js.map +1 -0
  75. package/dist/components/Paper.es.js +16 -0
  76. package/dist/components/Paper.es.js.map +1 -0
  77. package/dist/components/Popover.es.js +113 -0
  78. package/dist/components/Popover.es.js.map +1 -0
  79. package/dist/components/RadioGroup.es.js +30 -0
  80. package/dist/components/RadioGroup.es.js.map +1 -0
  81. package/dist/components/ResizablePanels.d.ts +3 -1
  82. package/dist/components/ResizablePanels.es.js +137 -0
  83. package/dist/components/ResizablePanels.es.js.map +1 -0
  84. package/dist/components/SearchBar.es.js +82 -0
  85. package/dist/components/SearchBar.es.js.map +1 -0
  86. package/dist/components/Select.d.ts +8 -1
  87. package/dist/components/Select.es.js +300 -0
  88. package/dist/components/Select.es.js.map +1 -0
  89. package/dist/components/Separator.es.js +20 -0
  90. package/dist/components/Separator.es.js.map +1 -0
  91. package/dist/components/Sheet.es.js +73 -0
  92. package/dist/components/Sheet.es.js.map +1 -0
  93. package/dist/components/Skeleton.es.js +33 -0
  94. package/dist/components/Skeleton.es.js.map +1 -0
  95. package/dist/components/Slider.es.js +56 -0
  96. package/dist/components/Slider.es.js.map +1 -0
  97. package/dist/components/Table.d.ts +18 -3
  98. package/dist/components/Table.es.js +69 -0
  99. package/dist/components/Table.es.js.map +1 -0
  100. package/dist/components/Tabs.es.js +101 -0
  101. package/dist/components/Tabs.es.js.map +1 -0
  102. package/dist/components/TextField.d.ts +0 -8
  103. package/dist/components/TextField.es.js +111 -0
  104. package/dist/components/TextField.es.js.map +1 -0
  105. package/dist/components/TextareaAutosize.es.js +187 -0
  106. package/dist/components/TextareaAutosize.es.js.map +1 -0
  107. package/dist/components/ToggleButtonGroup.d.ts +6 -1
  108. package/dist/components/ToggleButtonGroup.es.js +35 -0
  109. package/dist/components/ToggleButtonGroup.es.js.map +1 -0
  110. package/dist/components/Tooltip.d.ts +24 -0
  111. package/dist/components/Tooltip.es.js +165 -0
  112. package/dist/components/Tooltip.es.js.map +1 -0
  113. package/dist/components/Typography.es.js +85 -0
  114. package/dist/components/Typography.es.js.map +1 -0
  115. package/dist/components/VirtualTable/VirtualTable.es.js +516 -0
  116. package/dist/components/VirtualTable/VirtualTable.es.js.map +1 -0
  117. package/dist/components/VirtualTable/VirtualTableCell.d.ts +1 -1
  118. package/dist/components/VirtualTable/VirtualTableCell.es.js +40 -0
  119. package/dist/components/VirtualTable/VirtualTableCell.es.js.map +1 -0
  120. package/dist/components/VirtualTable/VirtualTableHeader.es.js +209 -0
  121. package/dist/components/VirtualTable/VirtualTableHeader.es.js.map +1 -0
  122. package/dist/components/VirtualTable/VirtualTableHeaderRow.es.js +166 -0
  123. package/dist/components/VirtualTable/VirtualTableHeaderRow.es.js.map +1 -0
  124. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -2
  125. package/dist/components/VirtualTable/VirtualTableRow.d.ts +6 -7
  126. package/dist/components/VirtualTable/VirtualTableRow.es.js +41 -0
  127. package/dist/components/VirtualTable/VirtualTableRow.es.js.map +1 -0
  128. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +2 -1
  129. package/dist/components/VirtualTable/fields/VirtualTableDateField.es.js +71 -0
  130. package/dist/components/VirtualTable/fields/VirtualTableDateField.es.js.map +1 -0
  131. package/dist/components/VirtualTable/fields/VirtualTableInput.es.js +73 -0
  132. package/dist/components/VirtualTable/fields/VirtualTableInput.es.js.map +1 -0
  133. package/dist/components/VirtualTable/fields/VirtualTableNumberInput.es.js +47 -0
  134. package/dist/components/VirtualTable/fields/VirtualTableNumberInput.es.js.map +1 -0
  135. package/dist/components/VirtualTable/fields/VirtualTableSelect.es.js +83 -0
  136. package/dist/components/VirtualTable/fields/VirtualTableSelect.es.js.map +1 -0
  137. package/dist/components/VirtualTable/fields/VirtualTableSwitch.es.js +22 -0
  138. package/dist/components/VirtualTable/fields/VirtualTableSwitch.es.js.map +1 -0
  139. package/dist/components/VirtualTable/selection/SelectionContext.es.js +23 -0
  140. package/dist/components/VirtualTable/selection/SelectionContext.es.js.map +1 -0
  141. package/dist/components/VirtualTable/selection/SelectionStore.es.js +43 -0
  142. package/dist/components/VirtualTable/selection/SelectionStore.es.js.map +1 -0
  143. package/dist/components/VirtualTable/types.d.ts +1 -1
  144. package/dist/components/common/SelectInputLabel.es.js +28 -0
  145. package/dist/components/common/SelectInputLabel.es.js.map +1 -0
  146. package/dist/components/index.es.js +64 -0
  147. package/dist/hooks/PortalContainerContext.es.js +40 -0
  148. package/dist/hooks/PortalContainerContext.es.js.map +1 -0
  149. package/dist/hooks/UiLabelsContext.d.ts +63 -0
  150. package/dist/hooks/UiLabelsContext.es.js +59 -0
  151. package/dist/hooks/UiLabelsContext.es.js.map +1 -0
  152. package/dist/hooks/useDebounceCallback.es.js +15 -0
  153. package/dist/hooks/useDebounceCallback.es.js.map +1 -0
  154. package/dist/hooks/useDebounceValue.es.js +19 -0
  155. package/dist/hooks/useDebounceValue.es.js.map +1 -0
  156. package/dist/hooks/useDebouncedCallback.es.js +36 -0
  157. package/dist/hooks/useDebouncedCallback.es.js.map +1 -0
  158. package/dist/hooks/useInjectStyles.es.js +27 -0
  159. package/dist/hooks/useInjectStyles.es.js.map +1 -0
  160. package/dist/hooks/useIsDarkMode.es.js +61 -0
  161. package/dist/hooks/useIsDarkMode.es.js.map +1 -0
  162. package/dist/hooks/useModalFocus.es.js +81 -0
  163. package/dist/hooks/useModalFocus.es.js.map +1 -0
  164. package/dist/hooks/useOutsideAlerter.es.js +41 -0
  165. package/dist/hooks/useOutsideAlerter.es.js.map +1 -0
  166. package/dist/hooks/useRestoreInterruptedFocus.es.js +61 -0
  167. package/dist/hooks/useRestoreInterruptedFocus.es.js.map +1 -0
  168. package/dist/icons/GitHubIcon.es.js +23 -0
  169. package/dist/icons/GitHubIcon.es.js.map +1 -0
  170. package/dist/icons/HandleIcon.es.js +60 -0
  171. package/dist/icons/HandleIcon.es.js.map +1 -0
  172. package/dist/icons/Icon.es.js +25 -0
  173. package/dist/icons/Icon.es.js.map +1 -0
  174. package/dist/icons/LucideIconByName.d.ts +12 -9
  175. package/dist/icons/LucideIconByName.es.js +83 -0
  176. package/dist/icons/LucideIconByName.es.js.map +1 -0
  177. package/dist/icons/cool_icon_keys.es.js +55 -0
  178. package/dist/icons/cool_icon_keys.es.js.map +1 -0
  179. package/dist/icons/icon_keys.es.js +1941 -0
  180. package/dist/icons/icon_keys.es.js.map +1 -0
  181. package/dist/icons/index.d.ts +4 -3
  182. package/dist/icons/index.es.js +8 -0
  183. package/dist/icons/lucide_icon_map.d.ts +12 -0
  184. package/dist/icons/lucide_icon_map.es.js +2 -0
  185. package/dist/index.d.ts +2 -0
  186. package/dist/index.es.js +87 -9563
  187. package/dist/styles.es.js +158 -0
  188. package/dist/styles.es.js.map +1 -0
  189. package/dist/util/chip_colors.es.js +290 -0
  190. package/dist/util/chip_colors.es.js.map +1 -0
  191. package/dist/util/cls.es.js +10 -0
  192. package/dist/util/cls.es.js.map +1 -0
  193. package/dist/util/debounce.es.js +22 -0
  194. package/dist/util/debounce.es.js.map +1 -0
  195. package/dist/util/hash.es.js +16 -0
  196. package/dist/util/hash.es.js.map +1 -0
  197. package/dist/util/keys.es.js +37 -0
  198. package/dist/util/keys.es.js.map +1 -0
  199. package/dist/util/lazy_chunk.es.js +96 -0
  200. package/dist/util/lazy_chunk.es.js.map +1 -0
  201. package/dist/views/CardView.d.ts +26 -2
  202. package/dist/views/CardView.es.js +435 -0
  203. package/dist/views/CardView.es.js.map +1 -0
  204. package/dist/views/CollectionView/CollectionCardView.es.js +179 -0
  205. package/dist/views/CollectionView/CollectionCardView.es.js.map +1 -0
  206. package/dist/views/CollectionView/CollectionKanbanView.es.js +172 -0
  207. package/dist/views/CollectionView/CollectionKanbanView.es.js.map +1 -0
  208. package/dist/views/CollectionView/CollectionListView.es.js +156 -0
  209. package/dist/views/CollectionView/CollectionListView.es.js.map +1 -0
  210. package/dist/views/CollectionView/CollectionTableView.es.js +149 -0
  211. package/dist/views/CollectionView/CollectionTableView.es.js.map +1 -0
  212. package/dist/views/CollectionView/CollectionView.es.js +197 -0
  213. package/dist/views/CollectionView/CollectionView.es.js.map +1 -0
  214. package/dist/views/CollectionView/CollectionViewToolbar.es.js +155 -0
  215. package/dist/views/CollectionView/CollectionViewToolbar.es.js.map +1 -0
  216. package/dist/views/CollectionView/DefaultCellRenderer.es.js +302 -0
  217. package/dist/views/CollectionView/DefaultCellRenderer.es.js.map +1 -0
  218. package/dist/views/CollectionView/resolveTitleProperty.es.js +56 -0
  219. package/dist/views/CollectionView/resolveTitleProperty.es.js.map +1 -0
  220. package/dist/views/CollectionView/utils.es.js +19 -0
  221. package/dist/views/CollectionView/utils.es.js.map +1 -0
  222. package/dist/views/Kanban/Board.es.js +237 -0
  223. package/dist/views/Kanban/Board.es.js.map +1 -0
  224. package/dist/views/Kanban/BoardColumn.es.js +81 -0
  225. package/dist/views/Kanban/BoardColumn.es.js.map +1 -0
  226. package/dist/views/Kanban/BoardColumnTitle.es.js +27 -0
  227. package/dist/views/Kanban/BoardColumnTitle.es.js.map +1 -0
  228. package/dist/views/Kanban/BoardSortableList.es.js +98 -0
  229. package/dist/views/Kanban/BoardSortableList.es.js.map +1 -0
  230. package/dist/views/Kanban/placement.es.js +27 -0
  231. package/dist/views/Kanban/placement.es.js.map +1 -0
  232. package/dist/views/KanbanView.es.js +11 -0
  233. package/dist/views/KanbanView.es.js.map +1 -0
  234. package/dist/views/ListView.d.ts +15 -2
  235. package/dist/views/ListView.es.js +245 -0
  236. package/dist/views/ListView.es.js.map +1 -0
  237. package/dist/views/useScrollParentRestoration.d.ts +8 -1
  238. package/dist/views/useScrollParentRestoration.es.js +75 -0
  239. package/dist/views/useScrollParentRestoration.es.js.map +1 -0
  240. package/package.json +2 -2
  241. package/dist/index.es.js.map +0 -1
@@ -0,0 +1,516 @@
1
+ import { cls } from "../../util/cls.es.js";
2
+ import { useDebounceCallback } from "../../hooks/useDebounceCallback.es.js";
3
+ import { CenteredView } from "../CenteredView.es.js";
4
+ import { CircularProgress } from "../CircularProgress.es.js";
5
+ import { Typography } from "../Typography.es.js";
6
+ import { useUiLabels } from "../../hooks/UiLabelsContext.es.js";
7
+ import { VirtualTableHeaderRow } from "./VirtualTableHeaderRow.es.js";
8
+ import { VirtualTableRow } from "./VirtualTableRow.es.js";
9
+ import { VirtualTableCell } from "./VirtualTableCell.es.js";
10
+ import React, { createContext, forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import { deepEqual, shallowEqual } from "fast-equals";
13
+ import { FixedSizeList } from "react-window";
14
+ import useMeasure from "react-use-measure";
15
+ import { SortableContext, arrayMove, horizontalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
16
+ import { DndContext, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
17
+ //#region src/components/VirtualTable/VirtualTable.tsx
18
+ var VirtualListContext = createContext(null);
19
+ VirtualListContext.displayName = "VirtualListContext";
20
+ var innerElementType = forwardRef(({ children, ...rest }, ref) => {
21
+ return /* @__PURE__ */ jsx(VirtualListContext.Consumer, { children: (virtualTableProps) => {
22
+ const customView = virtualTableProps.customView;
23
+ const headerHeight = virtualTableProps.headerHeight ?? 48;
24
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
25
+ id: "virtual-table",
26
+ style: {
27
+ position: "relative",
28
+ height: "100%",
29
+ zIndex: 0
30
+ },
31
+ children: /* @__PURE__ */ jsxs("div", {
32
+ ref,
33
+ ...rest,
34
+ style: {
35
+ ...rest?.style,
36
+ height: (typeof rest?.style?.height === "number" ? rest.style.height : parseFloat(rest?.style?.height || "0")) + headerHeight,
37
+ minHeight: "100%",
38
+ position: "relative"
39
+ },
40
+ children: [/* @__PURE__ */ jsx("div", {
41
+ style: {
42
+ position: "sticky",
43
+ top: 0,
44
+ zIndex: 20
45
+ },
46
+ children: /* @__PURE__ */ jsx(VirtualTableHeaderRow, { ...virtualTableProps })
47
+ }), !customView && children]
48
+ })
49
+ }), customView && /* @__PURE__ */ jsx("div", {
50
+ style: {
51
+ position: "sticky",
52
+ top: virtualTableProps.headerHeight ?? 48,
53
+ flexGrow: 1,
54
+ height: `calc(100% - ${virtualTableProps.headerHeight ?? 48}px)`,
55
+ marginTop: `calc(${virtualTableProps.headerHeight ?? 48}px - 100vh)`,
56
+ left: 0
57
+ },
58
+ children: customView
59
+ })] });
60
+ } });
61
+ });
62
+ /**
63
+ * This is a Table component that allows displaying arbitrary data, not
64
+ * necessarily related to entities or properties. It is the component
65
+ * that powers the entity collections but has a generic API, so it
66
+ * can be reused.
67
+ *
68
+ * @group Components
69
+ */
70
+ var VirtualTableInner = React.memo(function VirtualTable({ data, onResetPagination, onEndReached, endOffset = 600, rowHeight = 54, headerHeight = 40, columns: columnsProp, onRowClick, onColumnResize, onColumnResizeEnd, filter: filterInput, checkFilterCombination, onFilterUpdate, sortBy, error, emptyComponent, onSortByUpdate, onScroll: onScrollProp, loading, cellRenderer, hoverRow, createFilterField, rowClassName, style, className, endAdornment, AddColumnComponent, initialScroll = 0, onColumnsOrderChange, extraData, onRowsRendered }) {
71
+ const sortIndex = useMemo(() => {
72
+ const index = /* @__PURE__ */ new Map();
73
+ (sortBy ?? []).forEach(([key, direction], position) => {
74
+ if (!index.has(key)) index.set(key, {
75
+ direction,
76
+ position
77
+ });
78
+ });
79
+ return index;
80
+ }, [sortBy]);
81
+ const columnsPropRef = useRef(columnsProp);
82
+ if (columnsPropRef.current !== columnsProp && !deepEqual(columnsPropRef.current, columnsProp)) columnsPropRef.current = columnsProp;
83
+ const stableColumnsProp = columnsPropRef.current;
84
+ const [columns, setColumns] = useState(stableColumnsProp);
85
+ const [adoptedColumnsProp, setAdoptedColumnsProp] = useState(stableColumnsProp);
86
+ if (adoptedColumnsProp !== stableColumnsProp) {
87
+ setAdoptedColumnsProp(stableColumnsProp);
88
+ setColumns(stableColumnsProp);
89
+ }
90
+ const tableRef = useRef(null);
91
+ const endReachCallbackThreshold = useRef(0);
92
+ const debouncedScroll = useDebounceCallback(onScrollProp, 200);
93
+ const [draggingColumnId, setDraggingColumnId] = useState(null);
94
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
95
+ const handleDragStart = useCallback((event) => {
96
+ setDraggingColumnId(event.active.id);
97
+ }, []);
98
+ const handleDragEnd = useCallback((event) => {
99
+ const { active, over } = event;
100
+ setDraggingColumnId(null);
101
+ if (over && active.id !== over.id && onColumnsOrderChange) {
102
+ const oldIndex = columns.findIndex((col) => col.key === active.id);
103
+ const newIndex = columns.findIndex((col) => col.key === over.id);
104
+ if (oldIndex !== -1 && newIndex !== -1) {
105
+ const newColumns = arrayMove(columns, oldIndex, newIndex);
106
+ setColumns(newColumns);
107
+ onColumnsOrderChange(newColumns);
108
+ }
109
+ }
110
+ }, [columns, onColumnsOrderChange]);
111
+ const handleDragCancel = useCallback(() => {
112
+ setDraggingColumnId(null);
113
+ }, []);
114
+ const pendingInitialScroll = useRef(initialScroll > 0 ? initialScroll : void 0);
115
+ useEffect(() => {
116
+ if (tableRef.current && initialScroll) {
117
+ const { scrollLeft } = tableRef.current;
118
+ tableRef.current.scrollTo(scrollLeft, initialScroll);
119
+ }
120
+ }, [tableRef, initialScroll]);
121
+ const [measureRef, bounds] = useMeasure({
122
+ polyfill: ResizeObserver,
123
+ scroll: true,
124
+ offsetSize: true
125
+ });
126
+ const onColumnResizeInternal = useCallback((params) => {
127
+ setColumns((prevColumns) => prevColumns.map((column) => column.key === params.column.key ? params.column : column));
128
+ }, []);
129
+ const onColumnResizeEndInternal = useCallback((params) => {
130
+ setColumns(columns.map((column) => column.key === params.column.key ? params.column : column));
131
+ if (onColumnResize) onColumnResize(params);
132
+ if (onColumnResizeEnd) onColumnResizeEnd(params);
133
+ }, [
134
+ columns,
135
+ onColumnResize,
136
+ onColumnResizeEnd
137
+ ]);
138
+ const filterRef = useRef(void 0);
139
+ useEffect(() => {
140
+ filterRef.current = filterInput;
141
+ }, [filterInput]);
142
+ const scrollToTop = useCallback(() => {
143
+ endReachCallbackThreshold.current = 0;
144
+ if (tableRef.current) tableRef.current.scrollTo(tableRef.current?.scrollLeft, 0);
145
+ }, []);
146
+ /**
147
+ * Click a header to sort by that column: ascending, descending, then
148
+ * off. Shift-click to keep the sort you already have and add this
149
+ * column under it — the same idiom spreadsheets use, and the only way
150
+ * to build "by role, newest first" out of two clicks.
151
+ *
152
+ * Shift cycles the column it lands on through the same three states, so
153
+ * a key added by mistake is removed by shift-clicking it twice more,
154
+ * without disturbing the keys around it.
155
+ */
156
+ const onColumnSort = useCallback((key, additive = false) => {
157
+ const current = sortIndex.get(key);
158
+ const next = current === void 0 ? "asc" : current.direction === "asc" ? "desc" : void 0;
159
+ const existing = sortBy ?? [];
160
+ let newSortBy;
161
+ if (!additive) newSortBy = next ? [[key, next]] : void 0;
162
+ else if (next === void 0) newSortBy = existing.filter(([existingKey]) => existingKey !== key);
163
+ else if (current === void 0) newSortBy = [...existing, [key, next]];
164
+ else newSortBy = existing.map((entry) => entry[0] === key ? [key, next] : entry);
165
+ if (newSortBy?.length === 0) newSortBy = void 0;
166
+ const filter = filterRef.current;
167
+ if (filter) {
168
+ if (checkFilterCombination && !checkFilterCombination(filter, newSortBy)) {
169
+ if (onFilterUpdate) onFilterUpdate(void 0);
170
+ }
171
+ }
172
+ if (onResetPagination) onResetPagination();
173
+ if (onSortByUpdate) onSortByUpdate(newSortBy);
174
+ scrollToTop();
175
+ }, [
176
+ checkFilterCombination,
177
+ onFilterUpdate,
178
+ onResetPagination,
179
+ onSortByUpdate,
180
+ scrollToTop,
181
+ sortBy,
182
+ sortIndex
183
+ ]);
184
+ const maxScroll = Math.max((data?.length ?? 0) * rowHeight - bounds.height, 0);
185
+ const onEndReachedInternal = useCallback((scrollOffset) => {
186
+ if (onEndReached && (data?.length ?? 0) > 0 && scrollOffset > endReachCallbackThreshold.current + endOffset) {
187
+ endReachCallbackThreshold.current = scrollOffset;
188
+ onEndReached();
189
+ }
190
+ }, [data?.length, onEndReached]);
191
+ const onScroll = useCallback(({ scrollDirection, scrollOffset, scrollUpdateWasRequested }) => {
192
+ if (scrollOffset > 0) pendingInitialScroll.current = void 0;
193
+ if (onScrollProp) debouncedScroll({
194
+ scrollDirection,
195
+ scrollOffset,
196
+ scrollUpdateWasRequested
197
+ });
198
+ if (!scrollUpdateWasRequested && scrollOffset >= maxScroll - endOffset) onEndReachedInternal(scrollOffset);
199
+ }, [maxScroll, onEndReachedInternal]);
200
+ const lastReportedRange = useRef(void 0);
201
+ const onItemsRendered = useCallback(({ visibleStartIndex, visibleStopIndex }) => {
202
+ if (!onRowsRendered) return;
203
+ const rows = data?.length ?? 0;
204
+ let start = visibleStartIndex;
205
+ let end = visibleStopIndex + 1;
206
+ const restoring = pendingInitialScroll.current;
207
+ if (restoring !== void 0 && visibleStartIndex === 0) {
208
+ start = Math.floor(restoring / rowHeight);
209
+ end = start + Math.max(1, Math.ceil(bounds.height / rowHeight));
210
+ }
211
+ start = Math.min(start, rows);
212
+ end = Math.min(end, rows);
213
+ const last = lastReportedRange.current;
214
+ if (last && last.start === start && last.end === end) return;
215
+ lastReportedRange.current = {
216
+ start,
217
+ end
218
+ };
219
+ onRowsRendered({
220
+ start,
221
+ end
222
+ });
223
+ }, [
224
+ onRowsRendered,
225
+ data?.length,
226
+ rowHeight,
227
+ bounds.height
228
+ ]);
229
+ const onFilterUpdateInternal = useCallback((column, filterForProperty) => {
230
+ endReachCallbackThreshold.current = 0;
231
+ const filter = filterRef.current;
232
+ let newFilterValue = filter ? { ...filter } : {};
233
+ if (!filterForProperty) delete newFilterValue[column.key];
234
+ else newFilterValue[column.key] = filterForProperty;
235
+ if (!(!checkFilterCombination || checkFilterCombination(newFilterValue, sortBy))) newFilterValue = filterForProperty ? { [column.key]: filterForProperty } : {};
236
+ if (onFilterUpdate) onFilterUpdate(newFilterValue);
237
+ }, [
238
+ checkFilterCombination,
239
+ onFilterUpdate,
240
+ sortBy
241
+ ]);
242
+ const labels = useUiLabels();
243
+ const empty = !loading && (data?.length ?? 0) === 0;
244
+ const customView = error && (data?.length ?? 0) === 0 ? /* @__PURE__ */ jsxs(CenteredView, {
245
+ maxWidth: "2xl",
246
+ className: "flex flex-col gap-2",
247
+ children: [/* @__PURE__ */ jsx(Typography, {
248
+ variant: "h6",
249
+ children: labels.error
250
+ }), error?.message && /* @__PURE__ */ jsx(SafeLinkRenderer, { text: error.message })]
251
+ }) : empty ? loading ? /* @__PURE__ */ jsx("div", {
252
+ className: "flex items-center justify-center py-12 px-8",
253
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" })
254
+ }) : /* @__PURE__ */ jsx("div", {
255
+ className: "flex flex-col overflow-auto items-center justify-center py-12 px-8",
256
+ children: emptyComponent
257
+ }) : void 0;
258
+ const virtualListController = useMemo(() => ({
259
+ data,
260
+ rowHeight,
261
+ headerHeight,
262
+ cellRenderer,
263
+ columns,
264
+ onRowClick,
265
+ customView,
266
+ onColumnResize: onColumnResizeInternal,
267
+ onColumnResizeEnd: onColumnResizeEndInternal,
268
+ filter: filterInput,
269
+ onColumnSort,
270
+ onFilterUpdate: onFilterUpdateInternal,
271
+ sortIndex,
272
+ hoverRow: hoverRow ?? false,
273
+ createFilterField,
274
+ rowClassName,
275
+ endAdornment,
276
+ AddColumnComponent,
277
+ onColumnsOrderChange: onColumnsOrderChange ? (newColumns) => {
278
+ setColumns(newColumns);
279
+ onColumnsOrderChange(newColumns);
280
+ } : void 0,
281
+ draggingColumnId,
282
+ extraData
283
+ }), [
284
+ data,
285
+ rowHeight,
286
+ cellRenderer,
287
+ columns,
288
+ onRowClick,
289
+ customView,
290
+ onColumnResizeInternal,
291
+ onColumnResizeEndInternal,
292
+ filterInput,
293
+ onColumnSort,
294
+ onFilterUpdateInternal,
295
+ sortIndex,
296
+ hoverRow,
297
+ createFilterField,
298
+ rowClassName,
299
+ endAdornment,
300
+ AddColumnComponent,
301
+ onColumnsOrderChange,
302
+ draggingColumnId,
303
+ extraData
304
+ ]);
305
+ const sortableColumnKeys = columns.filter((col) => !col.frozen).map((col) => col.key);
306
+ const tableContent = /* @__PURE__ */ jsx("div", {
307
+ ref: measureRef,
308
+ style,
309
+ className: cls("h-full w-full", className, draggingColumnId && "overflow-hidden"),
310
+ children: /* @__PURE__ */ jsx(VirtualListContext.Provider, {
311
+ value: virtualListController,
312
+ children: /* @__PURE__ */ jsx(MemoizedList, {
313
+ outerRef: tableRef,
314
+ width: bounds.width,
315
+ height: bounds.height,
316
+ itemCount: (data?.length ?? 0) + (endAdornment ? 1 : 0),
317
+ onScroll: draggingColumnId ? void 0 : onScroll,
318
+ onItemsRendered: onRowsRendered ? onItemsRendered : void 0,
319
+ itemSize: rowHeight
320
+ }, rowHeight)
321
+ })
322
+ });
323
+ if (onColumnsOrderChange) return /* @__PURE__ */ jsx(DndContext, {
324
+ sensors,
325
+ collisionDetection: closestCenter,
326
+ onDragStart: handleDragStart,
327
+ onDragEnd: handleDragEnd,
328
+ onDragCancel: handleDragCancel,
329
+ children: /* @__PURE__ */ jsx(SortableContext, {
330
+ items: sortableColumnKeys,
331
+ strategy: horizontalListSortingStrategy,
332
+ children: tableContent
333
+ })
334
+ });
335
+ return tableContent;
336
+ }, areVirtualTablePropsEqual);
337
+ /**
338
+ * Every prop by value except `data`, which is compared by reference.
339
+ *
340
+ * A realtime frame decodes into new row objects whether or not anything in
341
+ * them changed, so a deep compare of `data` walked every row the table held —
342
+ * 10,000 rows scrolled through cost ~22 ms per frame — to decide what only
343
+ * the rows on screen can show. A new array now re-renders the table, and each
344
+ * row on screen compares its own row by value (`areRowRendererPropsEqual`):
345
+ * the work is bounded by the window, not by how far the user scrolled.
346
+ */
347
+ function areVirtualTablePropsEqual(a, b) {
348
+ if (a.data !== b.data) return false;
349
+ return deepEqual({
350
+ ...a,
351
+ data: void 0
352
+ }, {
353
+ ...b,
354
+ data: void 0
355
+ });
356
+ }
357
+ /**
358
+ * `React.memo` is not generic-preserving: it takes the props type as its own
359
+ * type argument, so annotating the call with
360
+ * `VirtualTableProps<Record<string, unknown>>` pinned `T` at the boundary and
361
+ * discarded the `<T>` the inner function declares. The exported component was
362
+ * therefore not generic at all — every consumer got `Record<string, unknown>`,
363
+ * `columns` and `cellRenderer` were unrelated to `data`, and a caller writing
364
+ * `<VirtualTable<Post> …>` was told the component expects no type arguments.
365
+ *
366
+ * Re-asserting the call signature is the standard way to carry a type parameter
367
+ * across `memo`; it is the only cast here, and it restores the generic the
368
+ * implementation always had. Runtime behaviour is unchanged — this is the same
369
+ * memoized component under a type that describes it.
370
+ */
371
+ var VirtualTable = VirtualTableInner;
372
+ var SortableCellWrapper = ({ columnKey, width, isDragging, isDraggable, frozen, children }) => {
373
+ const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
374
+ id: columnKey,
375
+ disabled: !isDraggable || frozen
376
+ });
377
+ const { tabIndex: _tabIndex, ...attrsWithoutTabIndex } = attributes;
378
+ return /* @__PURE__ */ jsx("div", {
379
+ ref: setNodeRef,
380
+ style: {
381
+ transform: transform ? `translateX(${transform.x}px)` : void 0,
382
+ transition: isDragging ? void 0 : transition,
383
+ minWidth: width,
384
+ maxWidth: width,
385
+ width
386
+ },
387
+ className: cls("flex-shrink-0", frozen && "sticky left-0 z-10 bg-surface-card"),
388
+ ...attrsWithoutTabIndex,
389
+ children
390
+ });
391
+ };
392
+ /**
393
+ * One row and its cells, drawn again only when something it is drawn from
394
+ * changed.
395
+ *
396
+ * Every input is a prop and every prop is compared, so nothing a row shows can
397
+ * go stale behind its memo. The comparisons are by reference except for the
398
+ * row itself and `extraData`, which are compared by value: a realtime frame
399
+ * decodes into new, equal objects, and comparing only the rows on screen is
400
+ * what lets the table skip a deep compare of everything it holds.
401
+ *
402
+ * This replaced a deep compare of the row's `children` — every cell element,
403
+ * each carrying the full `columns` array — which cost ~400 column-object
404
+ * compares per row on every parent render.
405
+ */
406
+ var VirtualTableRowRenderer = React.memo(function VirtualTableRowRenderer({ rowData, index, style, onRowClick, columns, hoverRow, rowClassName, rowHeight, headerHeight, cellRenderer, draggingColumnId, columnsReorderable, includeAddColumn, extraData }) {
407
+ return /* @__PURE__ */ jsxs(VirtualTableRow, {
408
+ rowData,
409
+ rowIndex: index,
410
+ onRowClick,
411
+ columns,
412
+ hoverRow,
413
+ rowClassName,
414
+ style: {
415
+ ...style,
416
+ top: `calc(${style.top}px + ${headerHeight ?? 48}px)`
417
+ },
418
+ rowHeight,
419
+ children: [columns.map((column, columnIndex) => {
420
+ const cellData = rowData && rowData[column.key];
421
+ const isDragging = draggingColumnId === column.key;
422
+ const isDraggable = !column.frozen && columnsReorderable;
423
+ const cell = /* @__PURE__ */ jsx(VirtualTableCell, {
424
+ dataKey: column.key,
425
+ cellRenderer,
426
+ column,
427
+ columns,
428
+ rowData,
429
+ cellData,
430
+ rowIndex: index,
431
+ columnIndex,
432
+ extraData
433
+ });
434
+ return columnsReorderable ? /* @__PURE__ */ jsx(SortableCellWrapper, {
435
+ columnKey: column.key,
436
+ width: column.width,
437
+ isDragging,
438
+ isDraggable,
439
+ frozen: column.frozen,
440
+ children: cell
441
+ }, `cell_wrapper_${column.key}`) : /* @__PURE__ */ jsx("div", {
442
+ className: cls("flex-shrink-0 relative", column.frozen && "sticky left-0 z-10 bg-surface-card"),
443
+ style: {
444
+ minWidth: column.width,
445
+ maxWidth: column.width,
446
+ width: column.width
447
+ },
448
+ children: cell
449
+ }, `cell_wrapper_${column.key}`);
450
+ }), includeAddColumn && /* @__PURE__ */ jsx("div", { className: "w-20" })]
451
+ });
452
+ }, areRowRendererPropsEqual);
453
+ function areRowRendererPropsEqual(a, b) {
454
+ return a.index === b.index && a.columns === b.columns && a.cellRenderer === b.cellRenderer && a.onRowClick === b.onRowClick && a.rowClassName === b.rowClassName && a.hoverRow === b.hoverRow && a.rowHeight === b.rowHeight && a.headerHeight === b.headerHeight && a.draggingColumnId === b.draggingColumnId && a.columnsReorderable === b.columnsReorderable && a.includeAddColumn === b.includeAddColumn && shallowEqual(a.style, b.style) && deepEqual(a.extraData, b.extraData) && deepEqual(a.rowData, b.rowData);
455
+ }
456
+ function MemoizedList({ outerRef, width, height, itemCount, onScroll, onItemsRendered, itemSize }) {
457
+ return /* @__PURE__ */ jsx(FixedSizeList, {
458
+ outerRef,
459
+ innerElementType,
460
+ width,
461
+ height,
462
+ overscanCount: 4,
463
+ itemCount,
464
+ onScroll,
465
+ onItemsRendered,
466
+ itemSize,
467
+ children: useCallback(({ index, style }) => {
468
+ return /* @__PURE__ */ jsx(VirtualListContext.Consumer, { children: ({ onRowClick, data, columns, rowHeight = 54, headerHeight = 40, cellRenderer, hoverRow, rowClassName, endAdornment, draggingColumnId, onColumnsOrderChange, AddColumnComponent, extraData }) => {
469
+ if (endAdornment && index === (data ?? []).length) return /* @__PURE__ */ jsx("div", {
470
+ style: {
471
+ ...style,
472
+ height: "auto",
473
+ position: "sticky",
474
+ bottom: 0,
475
+ zIndex: 1
476
+ },
477
+ children: endAdornment
478
+ });
479
+ return /* @__PURE__ */ jsx(VirtualTableRowRenderer, {
480
+ rowData: data ? data[index] : void 0,
481
+ index,
482
+ style,
483
+ onRowClick,
484
+ columns,
485
+ hoverRow,
486
+ rowClassName,
487
+ rowHeight,
488
+ headerHeight,
489
+ cellRenderer,
490
+ draggingColumnId,
491
+ columnsReorderable: Boolean(onColumnsOrderChange),
492
+ includeAddColumn: Boolean(AddColumnComponent),
493
+ extraData
494
+ });
495
+ } });
496
+ }, [])
497
+ });
498
+ }
499
+ var SafeLinkRenderer = ({ text }) => {
500
+ const urlRegex = /https?:\/\/[^\s]+/g;
501
+ const urls = text.match(urlRegex) || [];
502
+ return /* @__PURE__ */ jsx("div", {
503
+ className: "break-all",
504
+ children: text.split(urlRegex).map((part, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [part, urls[i] && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("a", {
505
+ href: urls[i],
506
+ className: "underline",
507
+ target: "_blank",
508
+ rel: "noopener noreferrer",
509
+ children: "Link"
510
+ }), /* @__PURE__ */ jsx("br", {})] })] }, i))
511
+ });
512
+ };
513
+ //#endregion
514
+ export { VirtualTable };
515
+
516
+ //# sourceMappingURL=VirtualTable.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualTable.es.js","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.tsx"],"sourcesContent":["\n\nimport React, { createContext, forwardRef, RefObject, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { deepEqual as equal, shallowEqual } from \"fast-equals\"\n\nimport { FixedSizeList as List } from \"react-window\";\nimport useMeasure from \"react-use-measure\";\n\nimport { CircularProgress } from \"../CircularProgress\";\nimport {\n OnVirtualTableColumnResizeParams,\n VirtualTableColumn,\n VirtualTableFilterValues,\n VirtualTableProps,\n VirtualTableSortKey,\n VirtualTableWhereFilterOp\n} from \"./VirtualTableProps\";\n\nimport { VirtualTableContextProps } from \"./types\";\nimport { VirtualTableHeaderRow } from \"./VirtualTableHeaderRow\";\nimport { VirtualTableRow } from \"./VirtualTableRow\";\nimport { VirtualTableCell } from \"./VirtualTableCell\";\nimport { CenteredView } from \"../CenteredView\";\nimport { Typography } from \"../Typography\";\nimport { cls } from \"../../util/cls\";\nimport { useDebounceCallback } from \"../../hooks/useDebounceCallback\";\nimport { useUiLabels } from \"../../hooks/UiLabelsContext\";\nimport {\n closestCenter,\n DndContext,\n DragEndEvent,\n DragStartEvent,\n PointerSensor,\n useSensor,\n useSensors\n} from \"@dnd-kit/core\";\nimport { arrayMove, horizontalListSortingStrategy, SortableContext, useSortable } from \"@dnd-kit/sortable\";\n\n\nconst VirtualListContext = createContext<VirtualTableContextProps<Record<string, unknown>>>(null! as VirtualTableContextProps<Record<string, unknown>>);\nVirtualListContext.displayName = \"VirtualListContext\";\n\ntype InnerElementProps = {\n children: React.ReactNode,\n style: React.CSSProperties\n};\n\n// eslint-disable-next-line react/display-name\nconst innerElementType = forwardRef<HTMLDivElement, InnerElementProps>(({\n children,\n ...rest\n}: InnerElementProps, ref) => {\n\n return (\n <VirtualListContext.Consumer>\n {(virtualTableProps) => {\n const customView = virtualTableProps.customView;\n const headerHeight = virtualTableProps.headerHeight ?? 48;\n return (\n <>\n <div\n id={\"virtual-table\"}\n style={{\n position: \"relative\",\n height: \"100%\",\n zIndex: 0\n }}>\n <div\n ref={ref}\n {...rest}\n style={{\n ...rest?.style,\n height: (typeof rest?.style?.height === \"number\" ? rest.style.height : parseFloat((rest?.style?.height as string) || \"0\")) + headerHeight,\n minHeight: \"100%\",\n position: \"relative\"\n }}>\n <div style={{ position: \"sticky\",\ntop: 0,\nzIndex: 20 }}>\n <VirtualTableHeaderRow {...virtualTableProps}/>\n </div>\n {!customView && children}\n </div>\n\n </div>\n\n {customView && <div style={{\n position: \"sticky\",\n top: virtualTableProps.headerHeight ?? 48,\n flexGrow: 1,\n height: `calc(100% - ${virtualTableProps.headerHeight ?? 48}px)`,\n marginTop: `calc(${(virtualTableProps.headerHeight ?? 48)}px - 100vh)`,\n left: 0\n }}>{customView}</div>}\n\n </>\n );\n }}\n </VirtualListContext.Consumer>\n );\n})\n ;\n\n/**\n * This is a Table component that allows displaying arbitrary data, not\n * necessarily related to entities or properties. It is the component\n * that powers the entity collections but has a generic API, so it\n * can be reused.\n *\n * @group Components\n */\nconst VirtualTableInner = React.memo<VirtualTableProps<Record<string, unknown>>>(\n function VirtualTable<T extends object>({\n data,\n onResetPagination,\n onEndReached,\n endOffset = 600,\n rowHeight = 54,\n headerHeight = 40,\n columns: columnsProp,\n onRowClick,\n onColumnResize,\n onColumnResizeEnd,\n filter: filterInput,\n checkFilterCombination,\n onFilterUpdate,\n sortBy,\n error,\n emptyComponent,\n onSortByUpdate,\n onScroll: onScrollProp,\n loading,\n cellRenderer,\n hoverRow,\n createFilterField,\n rowClassName,\n style,\n className,\n endAdornment,\n AddColumnComponent,\n initialScroll = 0,\n onColumnsOrderChange,\n extraData,\n onRowsRendered\n }: VirtualTableProps<T>) {\n\n // Where each sorted column sits in the order, so a header can show both\n // which way it runs and how much it counts: `roles ↑1, created_at ↓2`\n // reads as \"by role, newest first within each role\". Without the rank a\n // multi-key sort shows two arrows and no way to tell which one wins.\n const sortIndex = useMemo(() => {\n const index = new Map<string, { direction: \"asc\" | \"desc\"; position: number }>();\n (sortBy ?? []).forEach(([key, direction], position) => {\n if (!index.has(key)) index.set(key, { direction,\nposition });\n });\n return index;\n }, [sortBy]);\n\n // Held by value: a caller that rebuilds equal column objects on each\n // render must not hand every cell a new `columns` array, which is one\n // of the things a cell is drawn from (see `areCellPropsEqual`).\n const columnsPropRef = useRef(columnsProp);\n if (columnsPropRef.current !== columnsProp && !equal(columnsPropRef.current, columnsProp)) {\n columnsPropRef.current = columnsProp;\n }\n const stableColumnsProp = columnsPropRef.current;\n\n // The columns as drawn: the prop, or what a resize or a drag has made\n // of it since. Adopted during render when the prop changes rather than\n // in an effect, which drew every changed column a second time — first\n // with the old columns, then again, a commit later, with the new ones.\n const [columns, setColumns] = useState(stableColumnsProp);\n const [adoptedColumnsProp, setAdoptedColumnsProp] = useState(stableColumnsProp);\n if (adoptedColumnsProp !== stableColumnsProp) {\n setAdoptedColumnsProp(stableColumnsProp);\n setColumns(stableColumnsProp);\n }\n\n const tableRef = useRef<HTMLDivElement>(null);\n const endReachCallbackThreshold = useRef<number>(0);\n\n const debouncedScroll = useDebounceCallback(onScrollProp, 200);\n\n // Drag and drop state\n const [draggingColumnId, setDraggingColumnId] = useState<string | null>(null);\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5\n }\n })\n );\n\n const handleDragStart = useCallback((event: DragStartEvent) => {\n setDraggingColumnId(event.active.id as string);\n }, []);\n\n const handleDragEnd = useCallback((event: DragEndEvent) => {\n const {\n active,\n over\n } = event;\n setDraggingColumnId(null);\n\n if (over && active.id !== over.id && onColumnsOrderChange) {\n const oldIndex = columns.findIndex((col) => col.key === active.id);\n const newIndex = columns.findIndex((col) => col.key === over.id);\n\n if (oldIndex !== -1 && newIndex !== -1) {\n const newColumns = arrayMove(columns, oldIndex, newIndex);\n setColumns(newColumns);\n onColumnsOrderChange(newColumns);\n }\n }\n }, [columns, onColumnsOrderChange]);\n\n const handleDragCancel = useCallback(() => {\n setDraggingColumnId(null);\n }, []);\n\n // The offset this table opened at, until it has scrolled there: the\n // list first draws its top rows, and reporting them would have the\n // rows above a restored position read for nothing.\n const pendingInitialScroll = useRef(initialScroll > 0 ? initialScroll : undefined);\n\n // Set initial scroll position\n useEffect(() => {\n if (tableRef.current && initialScroll) {\n const { scrollLeft } = tableRef.current;\n tableRef.current.scrollTo(scrollLeft, initialScroll);\n }\n }, [tableRef, initialScroll]);\n\n // Removed redundant ResizeObserver to prevent performance issues and UI flickering.\n\n const [measureRef, bounds] = useMeasure({\n polyfill: ResizeObserver,\n scroll: true,\n // This is important for handling zooming in react-flow\n offsetSize: true\n });\n\n const onColumnResizeInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {\n setColumns(prevColumns =>\n prevColumns.map((column) =>\n column.key === params.column.key ? params.column : column\n )\n );\n }, []);\n\n const onColumnResizeEndInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {\n setColumns(columns.map((column) => column.key === params.column.key ? params.column : column));\n if (onColumnResize) {\n onColumnResize(params);\n }\n if (onColumnResizeEnd) {\n onColumnResizeEnd(params);\n }\n }, [columns, onColumnResize, onColumnResizeEnd]);\n\n // saving the current filter as a ref as a workaround for header closure\n const filterRef = useRef<VirtualTableFilterValues<string> | undefined>(undefined);\n\n useEffect(() => {\n filterRef.current = filterInput;\n }, [filterInput]);\n\n const scrollToTop = useCallback(() => {\n endReachCallbackThreshold.current = 0;\n if (tableRef.current) {\n tableRef.current.scrollTo(tableRef.current?.scrollLeft, 0);\n }\n }, []);\n\n /**\n * Click a header to sort by that column: ascending, descending, then\n * off. Shift-click to keep the sort you already have and add this\n * column under it — the same idiom spreadsheets use, and the only way\n * to build \"by role, newest first\" out of two clicks.\n *\n * Shift cycles the column it lands on through the same three states, so\n * a key added by mistake is removed by shift-clicking it twice more,\n * without disturbing the keys around it.\n */\n const onColumnSort = useCallback((key: string, additive = false) => {\n\n const current = sortIndex.get(key);\n const next: \"asc\" | \"desc\" | undefined = current === undefined\n ? \"asc\"\n : current.direction === \"asc\" ? \"desc\" : undefined;\n\n const existing = sortBy ?? [];\n let newSortBy: VirtualTableSortKey[] | undefined;\n if (!additive) {\n newSortBy = next ? [[key, next]] : undefined;\n } else if (next === undefined) {\n newSortBy = existing.filter(([existingKey]) => existingKey !== key);\n } else if (current === undefined) {\n newSortBy = [...existing, [key, next]];\n } else {\n newSortBy = existing.map((entry) => entry[0] === key ? [key, next] as VirtualTableSortKey : entry);\n }\n if (newSortBy?.length === 0) newSortBy = undefined;\n\n const filter = filterRef.current;\n if (filter) {\n if (checkFilterCombination && !checkFilterCombination(filter, newSortBy)) {\n if (onFilterUpdate)\n onFilterUpdate(undefined);\n }\n }\n\n if (onResetPagination) {\n onResetPagination();\n }\n\n if (onSortByUpdate) {\n onSortByUpdate(newSortBy);\n }\n\n scrollToTop();\n }, [checkFilterCombination, onFilterUpdate, onResetPagination, onSortByUpdate, scrollToTop, sortBy, sortIndex]);\n\n const maxScroll = Math.max((data?.length ?? 0) * rowHeight - bounds.height, 0);\n\n const onEndReachedInternal = useCallback((scrollOffset: number) => {\n if (onEndReached && (data?.length ?? 0) > 0 && scrollOffset > endReachCallbackThreshold.current + endOffset) {\n endReachCallbackThreshold.current = scrollOffset;\n onEndReached();\n }\n }, [data?.length, onEndReached]);\n\n const onScroll = useCallback(({\n scrollDirection,\n scrollOffset,\n scrollUpdateWasRequested\n }: {\n scrollDirection: \"forward\" | \"backward\",\n scrollOffset: number,\n scrollUpdateWasRequested: boolean;\n }) => {\n if (scrollOffset > 0) pendingInitialScroll.current = undefined;\n if (onScrollProp) {\n debouncedScroll({\n scrollDirection,\n scrollOffset,\n scrollUpdateWasRequested\n })\n }\n if (!scrollUpdateWasRequested && (scrollOffset >= maxScroll - endOffset))\n onEndReachedInternal(scrollOffset);\n }, [maxScroll, onEndReachedInternal]);\n\n const lastReportedRange = useRef<{ start: number; end: number } | undefined>(undefined);\n const onItemsRendered = useCallback(({\n visibleStartIndex,\n visibleStopIndex\n }: { visibleStartIndex: number; visibleStopIndex: number }) => {\n if (!onRowsRendered) return;\n const rows = data?.length ?? 0;\n let start = visibleStartIndex;\n let end = visibleStopIndex + 1;\n const restoring = pendingInitialScroll.current;\n if (restoring !== undefined && visibleStartIndex === 0) {\n start = Math.floor(restoring / rowHeight);\n end = start + Math.max(1, Math.ceil(bounds.height / rowHeight));\n }\n // The end adornment's slot is not a row.\n start = Math.min(start, rows);\n end = Math.min(end, rows);\n const last = lastReportedRange.current;\n if (last && last.start === start && last.end === end) return;\n lastReportedRange.current = { start, end };\n onRowsRendered({ start, end });\n }, [onRowsRendered, data?.length, rowHeight, bounds.height]);\n\n const onFilterUpdateInternal = useCallback((column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, unknown]) => {\n\n endReachCallbackThreshold.current = 0;\n const filter = filterRef.current;\n let newFilterValue: VirtualTableFilterValues<string> = filter ? { ...filter } : {};\n\n if (!filterForProperty) {\n delete newFilterValue[column.key];\n } else {\n newFilterValue[column.key] = filterForProperty;\n }\n const isNewFilterCombinationValid = !checkFilterCombination || checkFilterCombination(newFilterValue, sortBy);\n if (!isNewFilterCombinationValid) {\n newFilterValue = filterForProperty ? { [column.key]: filterForProperty } as VirtualTableFilterValues<Extract<keyof T, string>> : {};\n }\n\n if (onFilterUpdate) onFilterUpdate(newFilterValue);\n }, [checkFilterCombination, onFilterUpdate, sortBy]);\n\n const labels = useUiLabels();\n const empty = !loading && (data?.length ?? 0) === 0;\n const customView = (error && (data?.length ?? 0) === 0)\n ? <CenteredView maxWidth={\"2xl\"}\n className=\"flex flex-col gap-2\">\n\n <Typography variant={\"h6\"}>\n {labels.error}\n </Typography>\n\n {error?.message && <SafeLinkRenderer text={error.message}/>}\n\n </CenteredView>\n : (empty\n ? (loading\n ? <div className=\"flex items-center justify-center py-12 px-8\">\n <CircularProgress size=\"small\"/>\n </div>\n : <div\n className=\"flex flex-col overflow-auto items-center justify-center py-12 px-8\">\n {emptyComponent}\n </div>)\n : undefined);\n\n const virtualListController = useMemo(() => ({\n data,\n rowHeight: rowHeight,\n headerHeight: headerHeight,\n cellRenderer,\n columns,\n onRowClick,\n customView,\n onColumnResize: onColumnResizeInternal,\n onColumnResizeEnd: onColumnResizeEndInternal,\n // The prop, not `filterRef`: the ref is brought up to date by an\n // effect, after this render has read it, so the header showed the\n // filter from before — until something else redrew it.\n filter: filterInput,\n onColumnSort,\n onFilterUpdate: onFilterUpdateInternal,\n sortIndex,\n hoverRow: hoverRow ?? false,\n createFilterField,\n rowClassName,\n endAdornment,\n AddColumnComponent,\n onColumnsOrderChange: onColumnsOrderChange ? (newColumns: VirtualTableColumn[]) => {\n setColumns(newColumns);\n onColumnsOrderChange(newColumns);\n } : undefined,\n draggingColumnId,\n extraData\n }), [data, rowHeight, cellRenderer, columns, onRowClick, customView, onColumnResizeInternal, onColumnResizeEndInternal, filterInput, onColumnSort, onFilterUpdateInternal, sortIndex, hoverRow, createFilterField, rowClassName, endAdornment, AddColumnComponent, onColumnsOrderChange, draggingColumnId, extraData]);\n\n // Get sortable column keys (excluding frozen columns)\n const sortableColumnKeys = columns\n .filter(col => !col.frozen)\n .map(col => col.key);\n\n const tableContent = (\n <div\n ref={measureRef}\n style={style}\n className={cls(\n \"h-full w-full\",\n className,\n draggingColumnId && \"overflow-hidden\"\n )}>\n {/* SAFETY: T extends Record<string, any> is structurally assignable to Record<string, unknown> */}\n <VirtualListContext.Provider\n value={virtualListController as VirtualTableContextProps<Record<string, unknown>>}>\n\n <MemoizedList\n outerRef={tableRef}\n key={rowHeight}\n width={bounds.width}\n height={bounds.height}\n itemCount={(data?.length ?? 0) + (endAdornment ? 1 : 0)}\n onScroll={draggingColumnId ? undefined : onScroll}\n onItemsRendered={onRowsRendered ? onItemsRendered : undefined}\n itemSize={rowHeight}/>\n\n </VirtualListContext.Provider>\n </div>\n );\n\n // Wrap with DndContext if column reorder is enabled\n if (onColumnsOrderChange) {\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n >\n <SortableContext\n items={sortableColumnKeys}\n strategy={horizontalListSortingStrategy}\n >\n {tableContent}\n </SortableContext>\n </DndContext>\n );\n }\n\n return tableContent;\n },\n areVirtualTablePropsEqual\n);\n\n/**\n * Every prop by value except `data`, which is compared by reference.\n *\n * A realtime frame decodes into new row objects whether or not anything in\n * them changed, so a deep compare of `data` walked every row the table held —\n * 10,000 rows scrolled through cost ~22 ms per frame — to decide what only\n * the rows on screen can show. A new array now re-renders the table, and each\n * row on screen compares its own row by value (`areRowRendererPropsEqual`):\n * the work is bounded by the window, not by how far the user scrolled.\n */\nfunction areVirtualTablePropsEqual(\n a: VirtualTableProps<Record<string, unknown>>,\n b: VirtualTableProps<Record<string, unknown>>\n): boolean {\n if (a.data !== b.data) return false;\n return equal({ ...a, data: undefined }, { ...b, data: undefined });\n}\n\n/**\n * `React.memo` is not generic-preserving: it takes the props type as its own\n * type argument, so annotating the call with\n * `VirtualTableProps<Record<string, unknown>>` pinned `T` at the boundary and\n * discarded the `<T>` the inner function declares. The exported component was\n * therefore not generic at all — every consumer got `Record<string, unknown>`,\n * `columns` and `cellRenderer` were unrelated to `data`, and a caller writing\n * `<VirtualTable<Post> …>` was told the component expects no type arguments.\n *\n * Re-asserting the call signature is the standard way to carry a type parameter\n * across `memo`; it is the only cast here, and it restores the generic the\n * implementation always had. Runtime behaviour is unchanged — this is the same\n * memoized component under a type that describes it.\n */\nexport const VirtualTable = VirtualTableInner as <T extends object>(\n props: VirtualTableProps<T>\n) => React.ReactElement | null;\n// Wrapper that applies sortable transforms to cells\nconst SortableCellWrapper = ({\n columnKey,\n width,\n isDragging,\n isDraggable,\n frozen,\n children\n}: {\n columnKey: string;\n width: number;\n isDragging: boolean;\n isDraggable: boolean;\n frozen?: boolean;\n children: React.ReactNode;\n}) => {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition\n } = useSortable({\n id: columnKey,\n disabled: !isDraggable || frozen\n });\n\n // Remove tabIndex from attributes to avoid capturing focus before cell content\n const { tabIndex: _tabIndex, ...attrsWithoutTabIndex } = attributes;\n\n const style = {\n // Only use translate, ignore any scale transforms\n transform: transform ? `translateX(${transform.x}px)` : undefined,\n // Don't transition the dragged item - only other items should animate\n transition: isDragging ? undefined : transition,\n minWidth: width,\n maxWidth: width,\n width: width\n };\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={cls(\n \"flex-shrink-0\",\n frozen && \"sticky left-0 z-10 bg-surface-card\"\n )}\n {...attrsWithoutTabIndex}\n >\n {children}\n </div>\n );\n};\n\ntype VirtualTableRowRendererProps = {\n rowData: Record<string, unknown> | undefined;\n index: number;\n style: React.CSSProperties;\n onRowClick?: VirtualTableContextProps<Record<string, unknown>>[\"onRowClick\"];\n columns: VirtualTableColumn[];\n hoverRow: boolean;\n rowClassName?: (rowData: Record<string, unknown>) => string | undefined;\n rowHeight: number;\n headerHeight: number;\n cellRenderer: VirtualTableContextProps<Record<string, unknown>>[\"cellRenderer\"];\n draggingColumnId?: string | null;\n columnsReorderable: boolean;\n includeAddColumn: boolean;\n extraData?: unknown;\n};\n\n/**\n * One row and its cells, drawn again only when something it is drawn from\n * changed.\n *\n * Every input is a prop and every prop is compared, so nothing a row shows can\n * go stale behind its memo. The comparisons are by reference except for the\n * row itself and `extraData`, which are compared by value: a realtime frame\n * decodes into new, equal objects, and comparing only the rows on screen is\n * what lets the table skip a deep compare of everything it holds.\n *\n * This replaced a deep compare of the row's `children` — every cell element,\n * each carrying the full `columns` array — which cost ~400 column-object\n * compares per row on every parent render.\n */\nconst VirtualTableRowRenderer = React.memo(function VirtualTableRowRenderer({\n rowData,\n index,\n style,\n onRowClick,\n columns,\n hoverRow,\n rowClassName,\n rowHeight,\n headerHeight,\n cellRenderer,\n draggingColumnId,\n columnsReorderable,\n includeAddColumn,\n extraData\n}: VirtualTableRowRendererProps) {\n return (\n <VirtualTableRow\n rowData={rowData}\n rowIndex={index}\n onRowClick={onRowClick}\n columns={columns}\n hoverRow={hoverRow}\n rowClassName={rowClassName}\n style={{\n ...style,\n top: `calc(${style.top}px + ${headerHeight ?? 48}px)`\n }}\n rowHeight={rowHeight}>\n\n {columns.map((column: VirtualTableColumn, columnIndex: number) => {\n // The one place the row is read by key, and the one\n // cast for it. `T` is constrained to `object`\n // rather than `Record<string, unknown>` because an\n // `interface` — `Entity`, every consumer's row type\n // — has no implicit index signature and so does not\n // satisfy the latter. Constraining it there did not\n // make this read safe; it pushed an\n // `as unknown as Record<string, unknown>` onto every\n // caller, on the data going in AND on each callback\n // coming back out, which is four of them in\n // `SelectableTable` alone.\n const cellData = rowData && (rowData as Record<string, unknown>)[column.key];\n const isDragging = draggingColumnId === column.key;\n const isDraggable = !column.frozen && columnsReorderable;\n\n const cell = <VirtualTableCell\n dataKey={column.key}\n // @ts-expect-error -- React.memo<VirtualTableProps<any>> erases the generic T, so cellRenderer's parameter type widens to `any` losing structural compatibility with VirtualTableCell<T>. The types are structurally correct at runtime.\n cellRenderer={cellRenderer}\n column={column}\n columns={columns}\n rowData={rowData}\n cellData={cellData}\n rowIndex={index}\n columnIndex={columnIndex}\n extraData={extraData}/>;\n\n return columnsReorderable ? (\n <SortableCellWrapper\n key={`cell_wrapper_${column.key}`}\n columnKey={column.key}\n width={column.width}\n isDragging={isDragging}\n isDraggable={isDraggable}\n frozen={column.frozen}\n >\n {cell}\n </SortableCellWrapper>\n ) : (\n <div\n key={`cell_wrapper_${column.key}`}\n className={cls(\n \"flex-shrink-0 relative\",\n column.frozen && \"sticky left-0 z-10 bg-surface-card\"\n )}\n style={{\n minWidth: column.width,\n maxWidth: column.width,\n width: column.width\n }}\n >\n {cell}\n </div>\n );\n })}\n\n {includeAddColumn && <div className={\"w-20\"}/>}\n\n </VirtualTableRow>\n );\n}, areRowRendererPropsEqual);\n\nfunction areRowRendererPropsEqual(a: VirtualTableRowRendererProps, b: VirtualTableRowRendererProps): boolean {\n return a.index === b.index &&\n a.columns === b.columns &&\n a.cellRenderer === b.cellRenderer &&\n a.onRowClick === b.onRowClick &&\n a.rowClassName === b.rowClassName &&\n a.hoverRow === b.hoverRow &&\n a.rowHeight === b.rowHeight &&\n a.headerHeight === b.headerHeight &&\n a.draggingColumnId === b.draggingColumnId &&\n a.columnsReorderable === b.columnsReorderable &&\n a.includeAddColumn === b.includeAddColumn &&\n shallowEqual(a.style, b.style) &&\n equal(a.extraData, b.extraData) &&\n equal(a.rowData, b.rowData);\n}\n\nfunction MemoizedList({\n outerRef,\n width,\n height,\n itemCount,\n onScroll,\n onItemsRendered,\n itemSize\n}: {\n outerRef: RefObject<HTMLDivElement | null>;\n width: number;\n height: number;\n itemCount: number;\n onScroll?: (params: {\n scrollDirection: \"forward\" | \"backward\",\n scrollOffset: number,\n scrollUpdateWasRequested: boolean;\n }) => void;\n onItemsRendered?: (params: { visibleStartIndex: number; visibleStopIndex: number }) => void;\n itemSize: number;\n}) {\n\n const Row = useCallback(({\n index,\n style\n }: { index: number; style: React.CSSProperties }) => {\n return <VirtualListContext.Consumer>\n {({\n onRowClick,\n data,\n columns,\n rowHeight = 54,\n headerHeight = 40,\n cellRenderer,\n hoverRow,\n rowClassName,\n endAdornment,\n draggingColumnId,\n onColumnsOrderChange,\n AddColumnComponent,\n extraData\n }) => {\n\n if (endAdornment && index === (data ?? []).length) {\n return <div style={{\n ...style,\n height: \"auto\",\n position: \"sticky\",\n bottom: 0,\n zIndex: 1\n }}>\n {endAdornment}\n </div>;\n }\n\n return <VirtualTableRowRenderer\n rowData={data ? data[index] : undefined}\n index={index}\n style={style}\n onRowClick={onRowClick}\n columns={columns}\n hoverRow={hoverRow}\n rowClassName={rowClassName}\n rowHeight={rowHeight}\n headerHeight={headerHeight}\n cellRenderer={cellRenderer}\n draggingColumnId={draggingColumnId}\n columnsReorderable={Boolean(onColumnsOrderChange)}\n // Read here rather than from this function's closure: the\n // component is created once, and a closure would keep the\n // first value for the life of the list.\n includeAddColumn={Boolean(AddColumnComponent)}\n extraData={extraData}/>;\n }}\n </VirtualListContext.Consumer>;\n }, []);\n\n return <List\n outerRef={outerRef}\n innerElementType={innerElementType}\n width={width}\n height={height}\n overscanCount={4}\n itemCount={itemCount}\n onScroll={onScroll}\n onItemsRendered={onItemsRendered}\n itemSize={itemSize}>\n {Row}\n </List>;\n}\n\nconst SafeLinkRenderer: React.FC<{\n text: string;\n}> = ({ text }) => {\n const urlRegex = /https?:\\/\\/[^\\s]+/g;\n const urls = text.match(urlRegex) || [];\n const parts = text.split(urlRegex);\n\n return (\n <div className={\"break-all\"}>\n {parts.map((part, i) => (\n <React.Fragment key={i}>\n {part}\n {urls[i] && (\n <>\n <a href={urls[i]} className=\"underline\" target=\"_blank\" rel=\"noopener noreferrer\">Link</a>\n <br/>\n </>\n )}\n </React.Fragment>\n ))}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ type VirtualTableCellProps<T> = {
4
4
  dataKey: string;
5
5
  column: VirtualTableColumn;
6
6
  columns: VirtualTableColumn[];
7
- rowData: T;
7
+ rowData: T | undefined;
8
8
  cellData: unknown;
9
9
  rowIndex: number;
10
10
  columnIndex: number;
@@ -0,0 +1,40 @@
1
+ import React from "react";
2
+ import { deepEqual } from "fast-equals";
3
+ //#region src/components/VirtualTable/VirtualTableCell.tsx
4
+ var VirtualTableCell = React.memo(function VirtualTableCell(props) {
5
+ return props.rowData !== null ? props.cellRenderer({
6
+ cellData: props.cellData,
7
+ rowData: props.rowData,
8
+ rowIndex: props.rowIndex,
9
+ isScrolling: false,
10
+ column: props.column,
11
+ columns: props.columns,
12
+ columnIndex: props.columnIndex,
13
+ width: props.column.width,
14
+ sortableNodeRef: props.sortableNodeRef,
15
+ sortableStyle: props.sortableStyle,
16
+ sortableAttributes: props.sortableAttributes,
17
+ isDragging: props.isDragging,
18
+ isDraggable: props.isDraggable,
19
+ frozen: props.frozen,
20
+ extraData: props.extraData
21
+ }) : null;
22
+ }, areCellPropsEqual);
23
+ /**
24
+ * Every prop the cell hands `cellRenderer` is compared, and so is
25
+ * `cellRenderer` itself: a cell that kept the renderer it was first given kept
26
+ * every value that renderer closed over — inline editing switched off, a
27
+ * permission revoked, a new row-actions builder — until its row changed.
28
+ *
29
+ * Values that a parent rebuilds on each render (the row, its cell value, the
30
+ * column, `extraData`) are compared by value; `deepEqual` returns at once for
31
+ * the same reference. Functions and `columns` are compared by reference —
32
+ * `VirtualTable` holds `columns` by value already.
33
+ */
34
+ function areCellPropsEqual(a, b) {
35
+ return a.cellRenderer === b.cellRenderer && a.columns === b.columns && a.dataKey === b.dataKey && a.rowIndex === b.rowIndex && a.columnIndex === b.columnIndex && a.isDragging === b.isDragging && a.isDraggable === b.isDraggable && a.frozen === b.frozen && a.sortableNodeRef === b.sortableNodeRef && a.sortableStyle === b.sortableStyle && a.sortableAttributes === b.sortableAttributes && deepEqual(a.column, b.column) && deepEqual(a.cellData, b.cellData) && deepEqual(a.extraData, b.extraData) && deepEqual(a.rowData, b.rowData);
36
+ }
37
+ //#endregion
38
+ export { VirtualTableCell };
39
+
40
+ //# sourceMappingURL=VirtualTableCell.es.js.map