@rebasepro/ui 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +13 -0
  2. package/dist/components/VirtualTable/fields/VirtualTableInput.d.ts +10 -0
  3. package/dist/components/VirtualTable/fields/VirtualTableNumberInput.d.ts +9 -0
  4. package/dist/components/VirtualTable/fields/VirtualTableSelect.d.ts +17 -0
  5. package/dist/components/VirtualTable/fields/VirtualTableSwitch.d.ts +8 -0
  6. package/dist/components/VirtualTable/index.d.ts +7 -0
  7. package/dist/components/VirtualTable/selection/SelectionContext.d.ts +11 -0
  8. package/dist/components/VirtualTable/selection/SelectionStore.d.ts +14 -0
  9. package/dist/icons/index.d.ts +1 -1
  10. package/dist/index.d.ts +13 -3
  11. package/dist/index.es.js +2322 -23
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/styles.d.ts +1 -1
  14. package/dist/views/CardView.d.ts +32 -0
  15. package/dist/views/CollectionView/CollectionCardView.d.ts +30 -0
  16. package/dist/views/CollectionView/CollectionKanbanView.d.ts +31 -0
  17. package/dist/views/CollectionView/CollectionListView.d.ts +30 -0
  18. package/dist/views/CollectionView/CollectionTableView.d.ts +37 -0
  19. package/dist/views/CollectionView/CollectionView.d.ts +121 -0
  20. package/dist/views/CollectionView/CollectionViewToolbar.d.ts +31 -0
  21. package/dist/views/CollectionView/CollectionViewTypes.d.ts +106 -0
  22. package/dist/views/CollectionView/DefaultCellRenderer.d.ts +9 -0
  23. package/dist/views/CollectionView/index.d.ts +24 -0
  24. package/dist/views/CollectionView/utils.d.ts +5 -0
  25. package/dist/views/Kanban/Board.d.ts +3 -0
  26. package/dist/views/Kanban/BoardColumn.d.ts +20 -0
  27. package/dist/views/Kanban/BoardColumnTitle.d.ts +8 -0
  28. package/dist/views/Kanban/BoardSortableList.d.ts +14 -0
  29. package/dist/views/Kanban/board_types.d.ts +61 -0
  30. package/dist/views/Kanban/index.d.ts +5 -0
  31. package/dist/views/KanbanView.d.ts +24 -0
  32. package/dist/views/ListView.d.ts +40 -0
  33. package/dist/views/TableView.d.ts +6 -0
  34. package/dist/views/index.d.ts +5 -0
  35. package/package.json +1 -1
  36. package/src/components/Sheet.tsx +8 -4
  37. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +32 -0
  38. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +82 -0
  39. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +71 -0
  40. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +107 -0
  41. package/src/components/VirtualTable/fields/VirtualTableSwitch.tsx +28 -0
  42. package/src/components/VirtualTable/index.tsx +7 -0
  43. package/src/components/VirtualTable/selection/SelectionContext.tsx +36 -0
  44. package/src/components/VirtualTable/selection/SelectionStore.ts +54 -0
  45. package/src/icons/index.ts +3 -0
  46. package/src/index.ts +43 -3
  47. package/src/styles.ts +1 -1
  48. package/src/views/CardView.tsx +281 -0
  49. package/src/views/CollectionView/CollectionCardView.tsx +270 -0
  50. package/src/views/CollectionView/CollectionKanbanView.tsx +251 -0
  51. package/src/views/CollectionView/CollectionListView.tsx +245 -0
  52. package/src/views/CollectionView/CollectionTableView.tsx +229 -0
  53. package/src/views/CollectionView/CollectionView.tsx +388 -0
  54. package/src/views/CollectionView/CollectionViewToolbar.tsx +229 -0
  55. package/src/views/CollectionView/CollectionViewTypes.ts +137 -0
  56. package/src/views/CollectionView/DefaultCellRenderer.tsx +404 -0
  57. package/src/views/CollectionView/index.ts +44 -0
  58. package/src/views/CollectionView/utils.ts +14 -0
  59. package/src/views/Kanban/Board.tsx +421 -0
  60. package/src/views/Kanban/BoardColumn.tsx +135 -0
  61. package/src/views/Kanban/BoardColumnTitle.tsx +47 -0
  62. package/src/views/Kanban/BoardSortableList.tsx +170 -0
  63. package/src/views/Kanban/board_types.ts +70 -0
  64. package/src/views/Kanban/index.tsx +5 -0
  65. package/src/views/KanbanView.tsx +32 -0
  66. package/src/views/ListView.tsx +281 -0
  67. package/src/views/TableView.tsx +7 -0
  68. package/src/views/index.ts +5 -0
@@ -0,0 +1,170 @@
1
+ import React, { memo, useEffect, useMemo, useRef } from "react";
2
+ import { useDroppable } from "@dnd-kit/core";
3
+ import { useSortable, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
4
+ import { CSS } from "@dnd-kit/utilities";
5
+ import { CircularProgress } from "../../components";
6
+ import { cls } from "../../util";
7
+ import { BoardItem, BoardItemViewProps } from "./board_types";
8
+
9
+ interface BoardSortableListProps<T> {
10
+ columnId: string;
11
+ items: BoardItem<T>[];
12
+ ItemComponent: React.ComponentType<BoardItemViewProps<T>>;
13
+ isDragging: boolean;
14
+ isDragOverColumn: boolean;
15
+ loading?: boolean;
16
+ hasMore?: boolean;
17
+ onLoadMore?: () => void;
18
+ }
19
+
20
+ export function BoardSortableList<T>({
21
+ columnId,
22
+ items,
23
+ ItemComponent,
24
+ isDragging,
25
+ isDragOverColumn,
26
+ loading = false,
27
+ hasMore = false,
28
+ onLoadMore
29
+ }: BoardSortableListProps<T>) {
30
+ const {
31
+ setNodeRef
32
+ } = useDroppable({
33
+ id: columnId,
34
+ data: { type: "ITEM-LIST" }
35
+ });
36
+
37
+ const sentinelRef = useRef<HTMLDivElement>(null);
38
+ const isLoadingRef = useRef(loading);
39
+ isLoadingRef.current = loading;
40
+ const lastLoadTimeRef = useRef(0);
41
+
42
+ useEffect(() => {
43
+ if (!sentinelRef.current || !hasMore || !onLoadMore) return;
44
+
45
+ const sentinel = sentinelRef.current;
46
+
47
+ const observer = new IntersectionObserver(
48
+ (entries) => {
49
+ const now = Date.now();
50
+ if (
51
+ entries[0].isIntersecting &&
52
+ hasMore &&
53
+ !isLoadingRef.current &&
54
+ now - lastLoadTimeRef.current > 500
55
+ ) {
56
+ lastLoadTimeRef.current = now;
57
+ onLoadMore();
58
+ }
59
+ },
60
+ { threshold: 0.1 }
61
+ );
62
+
63
+ observer.observe(sentinel);
64
+
65
+ const rect = sentinel.getBoundingClientRect();
66
+ const containerRect = sentinel.parentElement?.getBoundingClientRect();
67
+ if (containerRect && rect.top < containerRect.bottom && rect.bottom > containerRect.top) {
68
+ const now = Date.now();
69
+ if (hasMore && !isLoadingRef.current && now - lastLoadTimeRef.current > 500) {
70
+ lastLoadTimeRef.current = now;
71
+ onLoadMore();
72
+ }
73
+ }
74
+
75
+ return () => observer.disconnect();
76
+ }, [hasMore, onLoadMore]);
77
+
78
+ const containerClassName = useMemo(() => cls(
79
+ "flex flex-col p-2 transition-opacity duration-100 transition-bg ease-linear w-full overflow-y-auto no-scrollbar flex-1 rounded-md",
80
+ isDragging && isDragOverColumn
81
+ ? "bg-surface-accent-200 dark:bg-surface-900"
82
+ : isDragging
83
+ ? "bg-surface-50 dark:bg-surface-900 hover:bg-surface-accent-100 dark:hover:bg-surface-800"
84
+ : "bg-surface-50 dark:bg-surface-900"
85
+ ), [isDragging, isDragOverColumn]);
86
+
87
+ return (
88
+ <div
89
+ ref={setNodeRef}
90
+ className={containerClassName}
91
+ style={{ minHeight: 80 }}
92
+ >
93
+ <SortableContext
94
+ items={items.map(i => i.id)}
95
+ strategy={verticalListSortingStrategy}
96
+ >
97
+ {items.length === 0 && !loading ? (
98
+ <div className="flex-1 flex items-center justify-center">
99
+ <span className="text-xs text-surface-400 dark:text-surface-500">
100
+ No items
101
+ </span>
102
+ </div>
103
+ ) : (
104
+ <>
105
+ {items.map((item, index) => (
106
+ <SortableItem
107
+ key={item.id}
108
+ item={item}
109
+ index={index}
110
+ columnId={columnId}
111
+ ItemComponent={ItemComponent}
112
+ />
113
+ ))}
114
+ {(loading || hasMore) && (
115
+ <div ref={sentinelRef} className="flex items-center justify-center py-2 min-h-6">
116
+ {loading && <CircularProgress size="smallest"/>}
117
+ </div>
118
+ )}
119
+ </>
120
+ )}
121
+ </SortableContext>
122
+ </div>
123
+ );
124
+ }
125
+
126
+ interface SortableItemProps<T> {
127
+ item: BoardItem<T>;
128
+ index: number;
129
+ columnId: string;
130
+ ItemComponent: React.ComponentType<BoardItemViewProps<T>>;
131
+ }
132
+
133
+ const SortableItem = memo(function SortableItem<T>({
134
+ item,
135
+ index,
136
+ columnId,
137
+ ItemComponent
138
+ }: SortableItemProps<T>) {
139
+ const {
140
+ setNodeRef,
141
+ attributes,
142
+ listeners,
143
+ isDragging: isItemBeingDragged,
144
+ transform,
145
+ transition
146
+ } = useSortable({
147
+ id: item.id,
148
+ data: {
149
+ type: "ITEM",
150
+ columnId
151
+ }
152
+ });
153
+
154
+ const sortableStyle = useMemo(() => ({
155
+ transform: CSS.Transform.toString(transform),
156
+ transition,
157
+ zIndex: isItemBeingDragged ? 2 : 1,
158
+ opacity: isItemBeingDragged ? 0 : 1
159
+ }), [transform, transition, isItemBeingDragged]);
160
+
161
+ return (
162
+ <div ref={setNodeRef} style={sortableStyle} {...attributes} {...listeners}>
163
+ <ItemComponent
164
+ item={item}
165
+ isDragging={isItemBeingDragged}
166
+ index={index}
167
+ />
168
+ </div>
169
+ );
170
+ }) as <T>(props: SortableItemProps<T>) => React.ReactElement;
@@ -0,0 +1,70 @@
1
+ import { CSSProperties } from "react";
2
+
3
+ export type ChipColorKey = "primary" | "secondary" | "success" | "warning" | "error" | "info" | "neutral" | string;
4
+ export type ChipColorScheme = "filled" | "outlined" | "tinted" | string;
5
+
6
+ /**
7
+ * Item wrapper for elements in the Board component
8
+ */
9
+ export interface BoardItem<T = any> {
10
+ id: string;
11
+ data: T;
12
+ }
13
+
14
+ /**
15
+ * Map of column keys to arrays of board items
16
+ */
17
+ export interface BoardItemMap<T = any> {
18
+ [columnKey: string]: BoardItem<T>[];
19
+ }
20
+
21
+ /**
22
+ * Props passed to custom item render components
23
+ */
24
+ export interface BoardItemViewProps<T = any> {
25
+ item: BoardItem<T>;
26
+ isDragging: boolean;
27
+ isClone?: boolean;
28
+ isGroupedOver?: boolean;
29
+ style?: CSSProperties;
30
+ index?: number;
31
+ }
32
+
33
+ /**
34
+ * Per-column loading state
35
+ */
36
+ export interface ColumnLoadingState {
37
+ [columnKey: string]: {
38
+ loading: boolean;
39
+ hasMore: boolean;
40
+ itemCount: number;
41
+ totalCount?: number;
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Props for the Board component
47
+ */
48
+ export interface BoardProps<T, COLUMN extends string> {
49
+ data: BoardItem<T>[];
50
+ columns: COLUMN[];
51
+ columnLabels?: Record<COLUMN, string>;
52
+ columnColors?: Record<COLUMN, any>;
53
+ className?: string;
54
+ assignColumn: (item: BoardItem<T>) => COLUMN;
55
+ allowColumnReorder?: boolean;
56
+ onColumnReorder?: (columns: COLUMN[]) => void;
57
+ onItemsReorder?: (
58
+ items: BoardItem<T>[],
59
+ moveInfo?: {
60
+ itemId: string;
61
+ sourceColumn: COLUMN;
62
+ targetColumn: COLUMN;
63
+ }
64
+ ) => void;
65
+ ItemComponent: React.ComponentType<BoardItemViewProps<T>>;
66
+ columnLoadingState?: ColumnLoadingState;
67
+ onLoadMoreColumn?: (column: COLUMN) => void;
68
+ onAddItemToColumn?: (column: COLUMN) => void;
69
+ AddColumnComponent?: React.ReactNode;
70
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./board_types";
2
+ export * from "./BoardColumnTitle";
3
+ export * from "./BoardSortableList";
4
+ export * from "./BoardColumn";
5
+ export * from "./Board";
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import { Board } from "./Kanban/Board";
3
+ import { BoardItem, BoardItemViewProps, ColumnLoadingState } from "./Kanban/board_types";
4
+
5
+ export type KanbanViewProps<T, COLUMN extends string> = {
6
+ columns: COLUMN[];
7
+ columnLabels?: Record<COLUMN, string>;
8
+ columnColors?: Record<COLUMN, any>;
9
+ className?: string;
10
+ assignColumn: (item: BoardItem<T>) => COLUMN;
11
+ allowColumnReorder?: boolean;
12
+ onColumnReorder?: (columns: COLUMN[]) => void;
13
+ onItemsReorder?: (
14
+ items: BoardItem<T>[],
15
+ moveInfo?: {
16
+ itemId: string;
17
+ sourceColumn: COLUMN;
18
+ targetColumn: COLUMN;
19
+ }
20
+ ) => void;
21
+ ItemComponent: React.ComponentType<BoardItemViewProps<T>>;
22
+ columnLoadingState?: ColumnLoadingState;
23
+ onLoadMoreColumn?: (column: COLUMN) => void;
24
+ onAddItemToColumn?: (column: COLUMN) => void;
25
+ AddColumnComponent?: React.ReactNode;
26
+ data: BoardItem<T>[];
27
+ };
28
+
29
+ export function KanbanView<T, COLUMN extends string>(props: KanbanViewProps<T, COLUMN>) {
30
+ return <Board {...props} />;
31
+ }
32
+ export type { BoardItem, BoardItemViewProps, ColumnLoadingState };
@@ -0,0 +1,281 @@
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import {
3
+ CircularProgress,
4
+ Typography
5
+ } from "../components";
6
+ import { cls } from "../util";
7
+
8
+ export type CollectionSize = "xs" | "s" | "m" | "l" | "xl";
9
+
10
+ export type ListViewColumnDef<T> = {
11
+ key: string;
12
+ label: string;
13
+ align?: "left" | "center" | "right";
14
+ width?: string;
15
+ renderCell: (item: T) => React.ReactNode;
16
+ isTitle?: boolean;
17
+ };
18
+
19
+ export type ListViewProps<T> = {
20
+ data: T[];
21
+ dataLoading?: boolean;
22
+ noMoreToLoad?: boolean;
23
+ dataLoadingError?: Error;
24
+ itemCount?: number;
25
+ setItemCount?: (itemCount: number) => void;
26
+ pageSize?: number;
27
+ paginationEnabled?: boolean;
28
+
29
+ onItemClick?: (item: T) => void;
30
+ selectedIds?: Set<string | number>;
31
+ highlightedIds?: Set<string | number>;
32
+ selectionEnabled?: boolean;
33
+ onSelectionChange?: (item: T, selected: boolean) => void;
34
+ emptyComponent?: React.ReactNode;
35
+
36
+ size?: CollectionSize;
37
+ selectedEntityId?: string | number;
38
+
39
+ renderRow: (params: {
40
+ item: T;
41
+ index: number;
42
+ style: React.CSSProperties;
43
+ className: string;
44
+ selected: boolean;
45
+ highlighted: boolean;
46
+ isLast: boolean;
47
+ onClick: (e: React.MouseEvent) => void;
48
+ onSelectionChange: (selected: boolean) => void;
49
+ }) => React.ReactNode;
50
+ };
51
+
52
+ function getEstimatedRowHeight(size: CollectionSize): number {
53
+ switch (size) {
54
+ case "xs": return 44;
55
+ case "s": return 52;
56
+ case "m": return 64;
57
+ case "l": return 76;
58
+ case "xl": return 88;
59
+ default: return 64;
60
+ }
61
+ }
62
+
63
+ const OVERSCAN_COUNT = 8;
64
+ const LOAD_MORE_THRESHOLD = 400;
65
+
66
+ function getScrollParent(element: HTMLElement | null): HTMLElement | null {
67
+ let parent = element?.parentElement ?? null;
68
+ while (parent) {
69
+ const style = getComputedStyle(parent);
70
+ if (
71
+ style.overflowY === "auto" || style.overflowY === "scroll" ||
72
+ style.overflow === "auto" || style.overflow === "scroll"
73
+ ) {
74
+ return parent;
75
+ }
76
+ parent = parent.parentElement;
77
+ }
78
+ return document.documentElement;
79
+ }
80
+
81
+ export function ListView<T>({
82
+ data,
83
+ dataLoading = false,
84
+ noMoreToLoad = false,
85
+ dataLoadingError,
86
+ itemCount,
87
+ setItemCount,
88
+ pageSize = 50,
89
+ paginationEnabled = true,
90
+
91
+ onItemClick,
92
+ selectedIds,
93
+ highlightedIds,
94
+ selectionEnabled = true,
95
+ onSelectionChange,
96
+ emptyComponent,
97
+
98
+ size = "m",
99
+ selectedEntityId,
100
+ renderRow
101
+ }: ListViewProps<T>) {
102
+ const containerRef = useRef<HTMLDivElement>(null);
103
+ const isLoadingMore = useRef(false);
104
+
105
+ // Reset loading gate when loading stops
106
+ useEffect(() => {
107
+ if (!dataLoading) isLoadingMore.current = false;
108
+ }, [dataLoading]);
109
+
110
+ // Virtualization scroll states
111
+ const estimatedRowHeight = getEstimatedRowHeight(size);
112
+ const [effectiveScrollTop, setEffectiveScrollTop] = useState(0);
113
+ const [viewportHeight, setViewportHeight] = useState(800);
114
+
115
+ const paginationStateRef = useRef({ paginationEnabled, noMoreToLoad, itemCount, pageSize });
116
+ useEffect(() => {
117
+ paginationStateRef.current = { paginationEnabled, noMoreToLoad, itemCount, pageSize };
118
+ }, [paginationEnabled, noMoreToLoad, itemCount, pageSize]);
119
+
120
+ useEffect(() => {
121
+ const el = containerRef.current;
122
+ if (!el) return;
123
+ const scrollEl = getScrollParent(el);
124
+ if (!scrollEl) return;
125
+
126
+ let rafId: number | null = null;
127
+
128
+ const update = () => {
129
+ rafId = null;
130
+ const scrollRect = scrollEl.getBoundingClientRect();
131
+ const listRect = el.getBoundingClientRect();
132
+
133
+ const listTopRelative = listRect.top - scrollRect.top;
134
+ setEffectiveScrollTop(Math.max(0, -listTopRelative));
135
+ setViewportHeight(scrollRect.height);
136
+
137
+ const { paginationEnabled: pe, noMoreToLoad: nm, itemCount: ic, pageSize: ps } = paginationStateRef.current;
138
+ if (
139
+ pe &&
140
+ !nm &&
141
+ !isLoadingMore.current &&
142
+ scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight < LOAD_MORE_THRESHOLD
143
+ ) {
144
+ isLoadingMore.current = true;
145
+ setItemCount?.((ic ?? ps) + ps);
146
+ }
147
+ };
148
+
149
+ const onScroll = () => {
150
+ if (rafId === null) rafId = requestAnimationFrame(update);
151
+ };
152
+
153
+ scrollEl.addEventListener("scroll", onScroll, { passive: true });
154
+ const ro = new ResizeObserver(() => update());
155
+ ro.observe(scrollEl);
156
+ update();
157
+
158
+ return () => {
159
+ scrollEl.removeEventListener("scroll", onScroll);
160
+ ro.disconnect();
161
+ if (rafId !== null) cancelAnimationFrame(rafId);
162
+ };
163
+ }, [setItemCount]);
164
+
165
+ const totalHeight = data.length * estimatedRowHeight;
166
+ const startIndex = Math.max(0, Math.floor(effectiveScrollTop / estimatedRowHeight) - OVERSCAN_COUNT);
167
+ const endIndex = Math.min(
168
+ data.length,
169
+ Math.ceil((effectiveScrollTop + viewportHeight) / estimatedRowHeight) + OVERSCAN_COUNT
170
+ );
171
+ const visibleData = data.slice(startIndex, endIndex);
172
+ const offsetY = startIndex * estimatedRowHeight;
173
+
174
+ const footerHeight = dataLoading ? 48 : (!dataLoading && noMoreToLoad && data.length > 0) ? 32 : 0;
175
+
176
+ const isInitialLoading = dataLoading && data.length === 0;
177
+ const isEmpty = !dataLoading && data.length === 0 && !dataLoadingError;
178
+
179
+ const getItemId = useCallback((item: T): string | number => {
180
+ if (item && typeof item === "object" && "id" in item) {
181
+ const id = (item as Record<"id", unknown>).id;
182
+ return typeof id === "number" ? id : String(id);
183
+ }
184
+ return String(item);
185
+ }, []);
186
+
187
+ const borderMixinClass = "border-surface-200 dark:border-surface-800";
188
+
189
+ return (
190
+ <div
191
+ ref={containerRef}
192
+ className={cls(
193
+ "w-full",
194
+ selectedEntityId === undefined && `rounded-lg overflow-hidden border ${borderMixinClass}`
195
+ )}
196
+ >
197
+ {dataLoadingError && data.length === 0 ? (
198
+ <div className="flex items-center justify-center p-8">
199
+ <Typography className="text-red-500">
200
+ Error loading data: {dataLoadingError.message}
201
+ </Typography>
202
+ </div>
203
+ ) : isInitialLoading ? (
204
+ <div className="flex items-center justify-center py-12 px-8">
205
+ <CircularProgress size="small" />
206
+ </div>
207
+ ) : isEmpty ? (
208
+ <div className="w-full flex items-center justify-center py-12 px-8">
209
+ {emptyComponent ?? (
210
+ <Typography variant="label" color="secondary">
211
+ No entries found
212
+ </Typography>
213
+ )}
214
+ </div>
215
+ ) : (
216
+ <div style={{ height: totalHeight + footerHeight, position: "relative" }}>
217
+ <div style={{ position: "absolute", top: offsetY, left: 0, right: 0 }}>
218
+ {visibleData.map((item, i) => {
219
+ const actualIndex = startIndex + i;
220
+ const isLast = actualIndex === data.length - 1;
221
+ const id = getItemId(item);
222
+ const selected = selectedIds?.has(id) ?? false;
223
+ const highlighted = highlightedIds?.has(id) ?? false;
224
+
225
+ const handleClick = (e: React.MouseEvent) => {
226
+ if ((e.metaKey || e.ctrlKey) && selectionEnabled) {
227
+ e.preventDefault();
228
+ onSelectionChange?.(item, !selected);
229
+ return;
230
+ }
231
+ onItemClick?.(item);
232
+ };
233
+
234
+ const handleSelectionChange = (val: boolean) => {
235
+ onSelectionChange?.(item, val);
236
+ };
237
+
238
+ return (
239
+ <React.Fragment key={id || actualIndex}>
240
+ {renderRow({
241
+ item,
242
+ index: actualIndex,
243
+ style: { height: estimatedRowHeight },
244
+ className: cls(
245
+ !isLast && "border-b",
246
+ !isLast && borderMixinClass
247
+ ),
248
+ selected,
249
+ highlighted,
250
+ isLast,
251
+ onClick: handleClick,
252
+ onSelectionChange: handleSelectionChange
253
+ })}
254
+ </React.Fragment>
255
+ );
256
+ })}
257
+ </div>
258
+
259
+ {dataLoading && (
260
+ <div
261
+ className="flex items-center justify-center py-3"
262
+ style={{ position: "absolute", top: totalHeight, left: 0, right: 0 }}
263
+ >
264
+ <CircularProgress size="small" />
265
+ </div>
266
+ )}
267
+ {!dataLoading && noMoreToLoad && data.length > 0 && (
268
+ <div
269
+ className="flex items-center justify-center py-2 dark:bg-surface-900"
270
+ style={{ position: "absolute", top: totalHeight, left: 0, right: 0 }}
271
+ >
272
+ <Typography variant="caption" color="secondary">
273
+ All {data.length} entries loaded
274
+ </Typography>
275
+ </div>
276
+ )}
277
+ </div>
278
+ )}
279
+ </div>
280
+ );
281
+ }
@@ -0,0 +1,7 @@
1
+ export { VirtualTable as TableView } from "../components/VirtualTable/VirtualTable";
2
+ export type { VirtualTableProps as TableViewProps } from "../components/VirtualTable/VirtualTableProps";
3
+
4
+ export type OnColumnResizeParams = {
5
+ width: number;
6
+ key: string;
7
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./ListView";
2
+ export * from "./CardView";
3
+ export * from "./KanbanView";
4
+ export * from "./TableView";
5
+ export * from "./CollectionView";