@vuu-ui/vuu-table 0.6.25-debug → 0.6.26-debug

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.
package/esm/index.js CHANGED
@@ -2,823 +2,671 @@
2
2
  import { ContextMenuProvider } from "@vuu-ui/vuu-popups";
3
3
  import { Button, useIdMemo } from "@salt-ds/core";
4
4
 
5
- // src/ColumnBasedTable.tsx
6
- import { metadataKeys as metadataKeys4 } from "@vuu-ui/vuu-utils";
7
- import { useCallback as useCallback8 } from "react";
8
- import cx6 from "classnames";
9
-
10
- // src/TableRow.tsx
11
- import {
12
- isGroupColumn,
13
- isJsonColumn,
14
- isJsonGroup,
15
- metadataKeys as metadataKeys3,
16
- notHidden
17
- } from "@vuu-ui/vuu-utils";
18
- import cx2 from "classnames";
19
- import { memo as memo2, useCallback as useCallback3 } from "react";
20
-
21
- // src/TableCell.tsx
22
- import { getColumnPinStyle, metadataKeys } from "@vuu-ui/vuu-utils";
23
- import { EditableLabel } from "@heswell/salt-lab";
24
- import cx from "classnames";
25
- import { memo, useCallback, useRef, useState } from "react";
26
- import { jsx } from "react/jsx-runtime";
27
- var { KEY } = metadataKeys;
28
- var TableCell = memo(
29
- ({ className: classNameProp, column, onClick, row }) => {
30
- const labelFieldRef = useRef(null);
31
- const {
32
- align,
33
- CellRenderer,
34
- key,
35
- pin,
36
- editable,
37
- resizing,
38
- valueFormatter
39
- } = column;
40
- const [editing, setEditing] = useState(false);
41
- const value = valueFormatter(row[key]);
42
- const [editableValue, setEditableValue] = useState(value);
43
- const handleTitleMouseDown = () => {
44
- var _a;
45
- (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
46
- };
47
- const handleTitleKeyDown = (evt) => {
48
- if (evt.key === "Enter") {
49
- setEditing(true);
50
- }
51
- };
52
- const handleClick = useCallback(() => {
53
- onClick == null ? void 0 : onClick(column);
54
- }, [column, onClick]);
55
- const handleEnterEditMode = () => {
56
- setEditing(true);
57
- };
58
- const handleExitEditMode = (originalValue = "", finalValue = "", allowDeactivation = true, editCancelled = false) => {
59
- var _a;
60
- setEditing(false);
61
- if (editCancelled) {
62
- setEditableValue(originalValue);
63
- } else if (finalValue !== originalValue) {
64
- setEditableValue(finalValue);
65
- }
66
- if (allowDeactivation === false) {
67
- (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
68
- }
69
- };
70
- const className = cx(classNameProp, {
71
- vuuAlignRight: align === "right",
72
- vuuPinFloating: pin === "floating",
73
- vuuPinLeft: pin === "left",
74
- vuuPinRight: pin === "right",
75
- "vuuTableCell-resizing": resizing
76
- }) || void 0;
77
- const pinnedStyle = getColumnPinStyle(column);
78
- return editable ? /* @__PURE__ */ jsx(
79
- "td",
80
- {
81
- className,
82
- "data-editable": true,
83
- style: pinnedStyle,
84
- onKeyDown: handleTitleKeyDown,
85
- children: /* @__PURE__ */ jsx(
86
- EditableLabel,
87
- {
88
- editing,
89
- value: editableValue,
90
- onChange: setEditableValue,
91
- onMouseDownCapture: handleTitleMouseDown,
92
- onEnterEditMode: handleEnterEditMode,
93
- onExitEditMode: handleExitEditMode,
94
- onKeyDown: handleTitleKeyDown,
95
- ref: labelFieldRef,
96
- tabIndex: 0
97
- },
98
- "title"
99
- )
100
- }
101
- ) : /* @__PURE__ */ jsx("td", { className, style: pinnedStyle, onClick: handleClick, children: CellRenderer ? /* @__PURE__ */ jsx(CellRenderer, { column, row }) : value });
102
- },
103
- cellValuesAreEqual
104
- );
105
- TableCell.displayName = "TableCell";
106
- function cellValuesAreEqual(prev, next) {
107
- return prev.column === next.column && prev.onClick === next.onClick && prev.row[KEY] === next.row[KEY] && prev.row[prev.column.key] === next.row[next.column.key];
108
- }
109
-
110
- // src/TableGroupCell.tsx
111
- import { metadataKeys as metadataKeys2 } from "@vuu-ui/vuu-utils";
112
- import { useCallback as useCallback2 } from "react";
113
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
114
- var { DEPTH, IS_LEAF } = metadataKeys2;
115
- var getGroupValueAndOffset = (columns, row) => {
116
- const { [DEPTH]: depth, [IS_LEAF]: isLeaf } = row;
117
- if (isLeaf || depth > columns.length) {
118
- return [null, depth === null ? 0 : depth - 1];
119
- } else if (depth === 0) {
120
- return ["$root", 0];
121
- } else {
122
- const { key, valueFormatter } = columns[depth - 1];
123
- const value = valueFormatter(row[key]);
124
- return [value, depth - 1];
5
+ // src/context-menu/buildContextMenuDescriptors.ts
6
+ import { isNumericColumn } from "@vuu-ui/vuu-utils";
7
+ var buildContextMenuDescriptors = (dataSource) => (location, options) => {
8
+ const descriptors = [];
9
+ if (dataSource === void 0) {
10
+ return descriptors;
11
+ }
12
+ if (location === "header") {
13
+ descriptors.push(
14
+ ...buildSortMenuItems(options, dataSource)
15
+ );
16
+ descriptors.push(
17
+ ...buildGroupMenuItems(options, dataSource)
18
+ );
19
+ descriptors.push(
20
+ ...buildAggregationMenuItems(options, dataSource)
21
+ );
22
+ descriptors.push(...buildColumnDisplayMenuItems(options));
23
+ } else if (location === "filter") {
24
+ const { column, filter } = options;
25
+ const colIsOnlyFilter = (filter == null ? void 0 : filter.column) === (column == null ? void 0 : column.name);
26
+ descriptors.push({
27
+ label: "Edit filter",
28
+ action: "filter-edit",
29
+ options
30
+ });
31
+ descriptors.push({
32
+ label: "Remove filter",
33
+ action: "filter-remove-column",
34
+ options
35
+ });
36
+ if (column && !colIsOnlyFilter) {
37
+ descriptors.push({
38
+ label: `Remove all filters`,
39
+ action: "remove-filters",
40
+ options
41
+ });
42
+ }
125
43
  }
44
+ return descriptors;
126
45
  };
127
- var TableGroupCell = ({ column, onClick, row }) => {
128
- const { columns } = column;
129
- const [value, offset] = getGroupValueAndOffset(columns, row);
130
- const handleClick = useCallback2(() => {
131
- onClick == null ? void 0 : onClick(column);
132
- }, [column, onClick]);
133
- const style = {
134
- left: column.pin == "left" ? column.pinnedOffset : void 0
135
- };
136
- const isLeaf = row[IS_LEAF];
137
- const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ jsx2("span", { className: "vuuTableGroupCell-spacer" }, i));
138
- return /* @__PURE__ */ jsxs(
139
- "td",
140
- {
141
- className: "vuuTableGroupCell vuuPinLeft",
142
- onClick: isLeaf ? void 0 : handleClick,
143
- style,
46
+ function buildSortMenuItems(options, { sort: { sortDefs } }) {
47
+ const { column } = options;
48
+ const menuItems = [];
49
+ if (column === void 0) {
50
+ return menuItems;
51
+ }
52
+ const hasSort = sortDefs.length > 0;
53
+ if (column.sorted === "A") {
54
+ menuItems.push({
55
+ label: "Reverse Sort (DSC)",
56
+ action: "sort-dsc",
57
+ options
58
+ });
59
+ } else if (column.sorted === "D") {
60
+ menuItems.push({
61
+ label: "Reverse Sort (ASC)",
62
+ action: "sort-asc",
63
+ options
64
+ });
65
+ } else if (typeof column.sorted === "number") {
66
+ if (column.sorted > 0) {
67
+ menuItems.push({
68
+ label: "Reverse Sort (DSC)",
69
+ action: "sort-add-dsc",
70
+ options
71
+ });
72
+ } else {
73
+ menuItems.push({
74
+ label: "Reverse Sort (ASC)",
75
+ action: "sort-add-asc",
76
+ options
77
+ });
78
+ }
79
+ if (hasSort && Math.abs(column.sorted) < sortDefs.length) {
80
+ menuItems.push({
81
+ label: "Remove from sort",
82
+ action: "sort-remove",
83
+ options
84
+ });
85
+ }
86
+ menuItems.push({
87
+ label: "New Sort",
144
88
  children: [
145
- spacers,
146
- isLeaf ? null : /* @__PURE__ */ jsx2("span", { className: "vuuTableGroupCell-toggle", "data-icon": "triangle-right" }),
147
- /* @__PURE__ */ jsx2("span", { children: value })
89
+ { label: "Ascending", action: "sort-asc", options },
90
+ { label: "Descending", action: "sort-dsc", options }
148
91
  ]
149
- }
150
- );
151
- };
152
-
153
- // src/TableRow.tsx
154
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
155
- var { IDX, IS_EXPANDED, SELECTED } = metadataKeys3;
156
- var classBase = "vuuTableRow";
157
- var TableRow = memo2(function Row({
158
- columns,
159
- height,
160
- index,
161
- onClick,
162
- onToggleGroup,
163
- virtualColSpan = 0,
164
- row
165
- }) {
166
- const {
167
- [IDX]: rowIndex,
168
- [IS_EXPANDED]: isExpanded,
169
- [SELECTED]: isSelected
170
- } = row;
171
- const className = cx2(classBase, {
172
- [`${classBase}-even`]: rowIndex % 2 === 0,
173
- [`${classBase}-expanded`]: isExpanded,
174
- [`${classBase}-preSelected`]: isSelected === 2
175
- });
176
- const offset = rowIndex - index;
177
- const handleRowClick = useCallback3(
178
- (evt) => {
179
- const rangeSelect = evt.shiftKey;
180
- const keepExistingSelection = evt.ctrlKey || evt.metaKey;
181
- onClick == null ? void 0 : onClick(row, rangeSelect, keepExistingSelection);
182
- },
183
- [onClick, row]
184
- );
185
- const handleGroupCellClick = useCallback3(
186
- (column) => {
187
- if (isGroupColumn(column) || isJsonGroup(column, row)) {
188
- onToggleGroup == null ? void 0 : onToggleGroup(row, column);
189
- }
190
- },
191
- [onToggleGroup, row]
192
- );
193
- return /* @__PURE__ */ jsxs2(
194
- "tr",
195
- {
196
- "aria-selected": isSelected === 1 ? true : void 0,
197
- "aria-rowindex": rowIndex,
198
- className,
199
- onClick: handleRowClick,
200
- style: {
201
- transform: `translate(0px, ${offset * height}px)`
202
- },
92
+ });
93
+ } else if (hasSort) {
94
+ menuItems.push({
95
+ label: "Add to sort",
203
96
  children: [
204
- virtualColSpan > 0 ? /* @__PURE__ */ jsx3("td", { colSpan: virtualColSpan }) : null,
205
- columns.filter(notHidden).map((column) => {
206
- const isGroup = isGroupColumn(column);
207
- const isJsonCell = isJsonColumn(column);
208
- const Cell = isGroup ? TableGroupCell : TableCell;
209
- return /* @__PURE__ */ jsx3(
210
- Cell,
211
- {
212
- column,
213
- onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
214
- row
215
- },
216
- column.name
217
- );
218
- })
97
+ { label: "Ascending", action: "sort-add-asc", options },
98
+ { label: "Descending", action: "sort-add-dsc", options }
99
+ ]
100
+ });
101
+ menuItems.push({
102
+ label: "New Sort",
103
+ children: [
104
+ { label: "Ascending", action: "sort-asc", options },
105
+ { label: "Descending", action: "sort-dsc", options }
219
106
  ]
107
+ });
108
+ } else {
109
+ menuItems.push({
110
+ label: "Sort",
111
+ children: [
112
+ { label: "Ascending", action: "sort-asc", options },
113
+ { label: "Descending", action: "sort-dsc", options }
114
+ ]
115
+ });
116
+ }
117
+ return menuItems;
118
+ }
119
+ function buildAggregationMenuItems(options, dataSource) {
120
+ const { column } = options;
121
+ if (column === void 0 || dataSource.groupBy.length === 0) {
122
+ return [];
123
+ }
124
+ const { name, label = name } = column;
125
+ return [
126
+ {
127
+ label: `Aggregate ${label}`,
128
+ children: [{ label: "Count", action: "agg-count", options }].concat(
129
+ isNumericColumn(column) ? [
130
+ { label: "Sum", action: "agg-sum", options },
131
+ { label: "Avg", action: "agg-avg", options },
132
+ { label: "High", action: "agg-high", options },
133
+ { label: "Low", action: "agg-low", options }
134
+ ] : []
135
+ )
220
136
  }
221
- );
137
+ ];
138
+ }
139
+ var pinColumn = (options, pinLocation) => ({
140
+ label: `Pin ${pinLocation}`,
141
+ action: `column-pin-${pinLocation}`,
142
+ options
222
143
  });
223
-
224
- // src/TableHeaderCell.tsx
225
- import cx5 from "classnames";
226
- import { useCallback as useCallback7, useRef as useRef4 } from "react";
227
-
228
- // src/ColumnResizer.tsx
229
- import { useCallback as useCallback4, useRef as useRef2 } from "react";
230
- import { jsx as jsx4 } from "react/jsx-runtime";
231
- var NOOP = () => void 0;
232
- var baseClass = "vuuColumnResizer";
233
- var ColumnResizer = ({
234
- onDrag,
235
- onDragEnd = NOOP,
236
- onDragStart = NOOP
237
- }) => {
238
- const position = useRef2(0);
239
- const onMouseMove = useCallback4(
240
- (e) => {
241
- if (e.stopPropagation) {
242
- e.stopPropagation();
243
- }
244
- if (e.preventDefault) {
245
- e.preventDefault();
246
- }
247
- const x = Math.round(e.clientX);
248
- const moveBy = x - position.current;
249
- position.current = x;
250
- if (moveBy !== 0) {
251
- onDrag(e, moveBy);
252
- }
253
- },
254
- [onDrag]
255
- );
256
- const onMouseUp = useCallback4(
257
- (e) => {
258
- window.removeEventListener("mouseup", onMouseUp);
259
- window.removeEventListener("mousemove", onMouseMove);
260
- onDragEnd(e);
144
+ var pinLeft = (options) => pinColumn(options, "left");
145
+ var pinFloating = (options) => pinColumn(options, "floating");
146
+ var pinRight = (options) => pinColumn(options, "right");
147
+ function buildColumnDisplayMenuItems(options) {
148
+ const { column } = options;
149
+ if (column === void 0) {
150
+ return [];
151
+ }
152
+ const { pin } = column;
153
+ const menuItems = [
154
+ {
155
+ label: `Hide column`,
156
+ action: "column-hide",
157
+ options
261
158
  },
262
- [onDragEnd, onMouseMove]
263
- );
264
- const handleMouseDown = useCallback4(
265
- (e) => {
266
- onDragStart(e);
267
- position.current = Math.round(e.clientX);
268
- window.addEventListener("mouseup", onMouseUp);
269
- window.addEventListener("mousemove", onMouseMove);
270
- if (e.stopPropagation) {
271
- e.stopPropagation();
159
+ {
160
+ label: `Remove column`,
161
+ action: "column-remove",
162
+ options
163
+ }
164
+ ];
165
+ if (pin === void 0) {
166
+ menuItems.push({
167
+ label: `Pin column`,
168
+ children: [pinLeft(options), pinFloating(options), pinRight(options)]
169
+ });
170
+ } else if (pin === "left") {
171
+ menuItems.push(
172
+ { label: "Unpin column", action: "column-unpin", options },
173
+ {
174
+ label: `Pin column`,
175
+ children: [pinFloating(options), pinRight(options)]
272
176
  }
273
- if (e.preventDefault) {
274
- e.preventDefault();
177
+ );
178
+ } else if (pin === "right") {
179
+ menuItems.push(
180
+ { label: "Unpin column", action: "column-unpin", options },
181
+ {
182
+ label: `Pin column`,
183
+ children: [pinLeft(options), pinFloating(options)]
275
184
  }
276
- },
277
- [onDragStart, onMouseMove, onMouseUp]
278
- );
279
- return /* @__PURE__ */ jsx4("div", { className: baseClass, onMouseDown: handleMouseDown });
280
- };
185
+ );
186
+ } else if (pin === "floating") {
187
+ menuItems.push(
188
+ { label: "Unpin column", action: "column-unpin", options },
189
+ {
190
+ label: `Pin column`,
191
+ children: [pinLeft(options), pinRight(options)]
192
+ }
193
+ );
194
+ }
195
+ return menuItems;
196
+ }
197
+ function buildGroupMenuItems(options, { groupBy }) {
198
+ const { column } = options;
199
+ const menuItems = [];
200
+ if (column === void 0) {
201
+ return menuItems;
202
+ }
203
+ const { name, label = name } = column;
204
+ if (groupBy.length === 0) {
205
+ menuItems.push({
206
+ label: `Group by ${label}`,
207
+ action: "group",
208
+ options
209
+ });
210
+ } else {
211
+ menuItems.push({
212
+ label: `Add ${label} to group by`,
213
+ action: "group-add",
214
+ options
215
+ });
216
+ }
217
+ return menuItems;
218
+ }
281
219
 
282
- // src/SortIndicator.tsx
283
- import cx3 from "classnames";
284
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
285
- var classBase2 = "vuuSortIndicator";
286
- var SortIndicator = ({ sorted }) => {
287
- if (!sorted) {
288
- return null;
220
+ // src/context-menu/useContextMenu.ts
221
+ import { removeColumnFromFilter } from "@vuu-ui/vuu-filters";
222
+ import {
223
+ addGroupColumn,
224
+ addSortColumn,
225
+ AggregationType,
226
+ setAggregations,
227
+ setSortColumn
228
+ } from "@vuu-ui/vuu-utils";
229
+ var removeFilterColumn = (dataSourceFilter, column) => {
230
+ if (dataSourceFilter.filterStruct && column) {
231
+ const [filterStruct, filter] = removeColumnFromFilter(
232
+ column,
233
+ dataSourceFilter.filterStruct
234
+ );
235
+ return {
236
+ filter,
237
+ filterStruct
238
+ };
239
+ } else {
240
+ return dataSourceFilter;
289
241
  }
290
- const direction = typeof sorted === "number" ? sorted < 0 ? "dsc" : "asc" : sorted === "A" ? "asc" : "dsc";
291
- return typeof sorted === "number" ? /* @__PURE__ */ jsxs3("div", { className: cx3(classBase2, "multi-col", direction), children: [
292
- /* @__PURE__ */ jsx5("span", { "data-icon": `sorted-${direction}` }),
293
- /* @__PURE__ */ jsx5("span", { className: "vuuSortPosition", children: Math.abs(sorted) })
294
- ] }) : /* @__PURE__ */ jsx5("div", { className: cx3(classBase2, "single-col"), children: /* @__PURE__ */ jsx5("span", { "data-icon": `sorted-${direction}` }) });
295
242
  };
296
-
297
- // src/useTableColumnResize.tsx
298
- import { useCallback as useCallback5, useRef as useRef3 } from "react";
299
- var useTableColumnResize = ({
300
- column,
301
- onResize,
302
- rootRef
243
+ var { Average, Count, High, Low, Sum } = AggregationType;
244
+ var useContextMenu = ({
245
+ dataSource,
246
+ onPersistentColumnOperation
303
247
  }) => {
304
- const widthRef = useRef3(0);
305
- const isResizing = useRef3(false);
306
- const { name } = column;
307
- const handleResizeStart = useCallback5(() => {
308
- if (onResize && rootRef.current) {
309
- const { width } = rootRef.current.getBoundingClientRect();
310
- widthRef.current = Math.round(width);
311
- isResizing.current = true;
312
- onResize == null ? void 0 : onResize("begin", name);
313
- }
314
- }, [name, onResize, rootRef]);
315
- const handleResize = useCallback5(
316
- (_evt, moveBy) => {
317
- if (rootRef.current) {
318
- if (onResize) {
319
- const { width } = rootRef.current.getBoundingClientRect();
320
- const newWidth = Math.round(width) + moveBy;
321
- if (newWidth !== widthRef.current && newWidth > 0) {
322
- onResize("resize", name, newWidth);
323
- widthRef.current = newWidth;
324
- }
325
- }
248
+ const handleContextMenuAction = (type, options) => {
249
+ const gridOptions = options;
250
+ if (gridOptions.column && dataSource) {
251
+ const { column } = gridOptions;
252
+ switch (type) {
253
+ case "sort-asc":
254
+ return dataSource.sort = setSortColumn(dataSource.sort, column, "A"), true;
255
+ case "sort-dsc":
256
+ return dataSource.sort = setSortColumn(dataSource.sort, column, "D"), true;
257
+ case "sort-add-asc":
258
+ return dataSource.sort = addSortColumn(dataSource.sort, column, "A"), true;
259
+ case "sort-add-dsc":
260
+ return dataSource.sort = addSortColumn(dataSource.sort, column, "D"), true;
261
+ case "group":
262
+ return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
263
+ case "group-add":
264
+ return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
265
+ case "column-hide":
266
+ return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
267
+ case "column-remove":
268
+ return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
269
+ case "filter-remove-column":
270
+ return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
271
+ case "remove-filters":
272
+ return dataSource.filter = { filter: "" }, true;
273
+ case "agg-avg":
274
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Average), true;
275
+ case "agg-high":
276
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, High), true;
277
+ case "agg-low":
278
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Low), true;
279
+ case "agg-count":
280
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Count), true;
281
+ case "agg-sum":
282
+ return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Sum), true;
283
+ case "column-pin-floating":
284
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
285
+ case "column-pin-left":
286
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
287
+ case "column-pin-right":
288
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
289
+ case "column-unpin":
290
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
291
+ default:
326
292
  }
327
- },
328
- [name, onResize, rootRef]
329
- );
330
- const handleResizeEnd = useCallback5(() => {
331
- if (onResize) {
332
- onResize("end", name, widthRef.current);
333
- setTimeout(() => {
334
- isResizing.current = false;
335
- }, 100);
336
293
  }
337
- }, [name, onResize]);
338
- return {
339
- isResizing: isResizing.current,
340
- onDrag: handleResize,
341
- onDragStart: handleResizeStart,
342
- onDragEnd: handleResizeEnd
294
+ return false;
343
295
  };
296
+ return handleContextMenuAction;
344
297
  };
345
298
 
346
- // src/TableHeaderCell.tsx
347
- import { useContextMenu as useContextMenu2 } from "@vuu-ui/vuu-popups";
299
+ // src/RowBasedTable.tsx
300
+ import {
301
+ buildColumnMap,
302
+ getColumnStyle as getColumnStyle3,
303
+ isGroupColumn as isGroupColumn2,
304
+ metadataKeys as metadataKeys4,
305
+ notHidden as notHidden2,
306
+ visibleColumnAtIndex
307
+ } from "@vuu-ui/vuu-utils";
308
+ import { useCallback as useCallback8, useMemo } from "react";
348
309
 
349
- // src/filter-indicator.tsx
350
- import { useContextMenu } from "@vuu-ui/vuu-popups";
351
- import cx4 from "classnames";
352
- import { useCallback as useCallback6 } from "react";
353
- import { jsx as jsx6 } from "react/jsx-runtime";
354
- var FilterIndicator = ({ column, filter }) => {
355
- const showContextMenu = useContextMenu();
356
- const handleClick = useCallback6(
357
- (evt) => {
358
- evt.stopPropagation();
359
- showContextMenu(evt, "filter", { column, filter });
360
- },
361
- [column, filter, showContextMenu]
362
- );
363
- if (!column.filter) {
364
- return null;
365
- }
366
- return /* @__PURE__ */ jsx6(
367
- "div",
368
- {
369
- className: cx4("vuuFilterIndicator"),
370
- "data-icon": "filter",
371
- onClick: handleClick
372
- }
373
- );
374
- };
310
+ // src/TableRow.tsx
311
+ import {
312
+ isGroupColumn,
313
+ isJsonColumn,
314
+ isJsonGroup,
315
+ metadataKeys as metadataKeys3,
316
+ notHidden
317
+ } from "@vuu-ui/vuu-utils";
318
+ import cx2 from "classnames";
319
+ import { memo as memo2, useCallback as useCallback3 } from "react";
375
320
 
376
- // src/TableHeaderCell.tsx
377
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
378
- var classBase3 = "vuuTable-headerCell";
379
- var TableHeaderCell = ({
380
- column,
381
- className: classNameProp,
382
- onClick,
383
- onDragStart,
384
- onResize,
385
- ...props
386
- }) => {
387
- const rootRef = useRef4(null);
388
- const { isResizing, ...resizeProps } = useTableColumnResize({
321
+ // src/TableCell.tsx
322
+ import { getColumnStyle, metadataKeys } from "@vuu-ui/vuu-utils";
323
+ import { EditableLabel } from "@heswell/salt-lab";
324
+ import cx from "classnames";
325
+ import { memo, useCallback, useRef, useState } from "react";
326
+ import { jsx } from "react/jsx-runtime";
327
+ var { KEY } = metadataKeys;
328
+ var TableCell = memo(
329
+ ({
330
+ className: classNameProp,
389
331
  column,
390
- onResize,
391
- rootRef
392
- });
393
- const showContextMenu = useContextMenu2();
394
- const dragTimerRef = useRef4(null);
395
- const handleContextMenu = (e) => {
396
- showContextMenu(e, "header", { column });
397
- };
398
- const handleClick = useCallback7(
399
- (evt) => !isResizing && (onClick == null ? void 0 : onClick(evt)),
400
- [isResizing, onClick]
401
- );
402
- const handleMouseDown = useCallback7(
403
- (evt) => {
404
- dragTimerRef.current = window.setTimeout(() => {
405
- onDragStart == null ? void 0 : onDragStart(evt);
406
- dragTimerRef.current = null;
407
- }, 250);
408
- },
409
- [onDragStart]
410
- );
411
- const handleMouseUp = useCallback7(() => {
412
- if (dragTimerRef.current !== null) {
413
- window.clearTimeout(dragTimerRef.current);
414
- dragTimerRef.current = null;
415
- }
416
- }, []);
417
- const className = cx5(classBase3, classNameProp, {
418
- vuuPinFloating: column.pin === "floating",
419
- vuuPinLeft: column.pin === "left",
420
- vuuPinRight: column.pin === "right",
421
- vuuEndPin: column.endPin,
422
- [`${classBase3}-resizing`]: column.resizing,
423
- [`${classBase3}-right`]: column.align === "right"
424
- });
425
- return /* @__PURE__ */ jsx7(
426
- "th",
427
- {
428
- className,
429
- ...props,
430
- onClick: handleClick,
431
- onContextMenu: handleContextMenu,
432
- onMouseDown: handleMouseDown,
433
- onMouseUp: handleMouseUp,
434
- ref: rootRef,
435
- children: /* @__PURE__ */ jsxs4("div", { className: `${classBase3}-inner`, children: [
436
- /* @__PURE__ */ jsx7(FilterIndicator, { column }),
437
- /* @__PURE__ */ jsx7("div", { className: `${classBase3}-label`, children: column.label }),
438
- /* @__PURE__ */ jsx7(SortIndicator, { sorted: column.sorted }),
439
- column.resizeable !== false ? /* @__PURE__ */ jsx7(ColumnResizer, { ...resizeProps }) : null
440
- ] })
441
- }
442
- );
443
- };
444
-
445
- // src/ColumnBasedTable.tsx
446
- import { Fragment, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
447
- var classBase4 = "vuuTable";
448
- var { RENDER_IDX } = metadataKeys4;
449
- var ColumnBasedTable = ({
450
- columns,
451
- data,
452
- headerHeight,
453
- onHeaderCellDragEnd,
454
- rowHeight
455
- }) => {
456
- const handleDragEnd = useCallback8(() => {
457
- onHeaderCellDragEnd == null ? void 0 : onHeaderCellDragEnd();
458
- }, [onHeaderCellDragEnd]);
459
- console.log(`ColumnBasedTable render`);
460
- return /* @__PURE__ */ jsx8(Fragment, { children: columns.map((column, i) => /* @__PURE__ */ jsx8(
461
- "table",
462
- {
463
- className: cx6(`${classBase4}-table`, `${classBase4}-columnBased`, {
464
- vuuPinLeft: column.pin === "left"
465
- }),
466
- "data-idx": i,
467
- id: `col-${i}`,
468
- style: {
469
- width: column.width,
470
- left: column.pinnedOffset,
471
- "--vuuTableHeaderHeight": `${headerHeight}px`,
472
- "--row-height": `${rowHeight}px`
473
- },
474
- children: /* @__PURE__ */ jsxs5("tbody", { children: [
475
- /* @__PURE__ */ jsx8("tr", { children: /* @__PURE__ */ jsx8(
476
- TableHeaderCell,
477
- {
478
- column,
479
- "data-idx": i,
480
- onDragEnd: handleDragEnd
481
- },
482
- i
483
- ) }, "header"),
484
- data.map((row, j) => /* @__PURE__ */ jsx8(
485
- TableRow,
332
+ columnMap,
333
+ onClick,
334
+ row
335
+ }) => {
336
+ const labelFieldRef = useRef(null);
337
+ const {
338
+ align,
339
+ CellRenderer,
340
+ key,
341
+ pin,
342
+ editable,
343
+ resizing,
344
+ valueFormatter
345
+ } = column;
346
+ const [editing, setEditing] = useState(false);
347
+ const value = valueFormatter(row[key]);
348
+ const [editableValue, setEditableValue] = useState(value);
349
+ const handleTitleMouseDown = () => {
350
+ var _a;
351
+ (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
352
+ };
353
+ const handleTitleKeyDown = (evt) => {
354
+ if (evt.key === "Enter") {
355
+ setEditing(true);
356
+ }
357
+ };
358
+ const handleClick = useCallback(() => {
359
+ onClick == null ? void 0 : onClick(column);
360
+ }, [column, onClick]);
361
+ const handleEnterEditMode = () => {
362
+ setEditing(true);
363
+ };
364
+ const handleExitEditMode = (originalValue = "", finalValue = "", allowDeactivation = true, editCancelled = false) => {
365
+ var _a;
366
+ setEditing(false);
367
+ if (editCancelled) {
368
+ setEditableValue(originalValue);
369
+ } else if (finalValue !== originalValue) {
370
+ setEditableValue(finalValue);
371
+ }
372
+ if (allowDeactivation === false) {
373
+ (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
374
+ }
375
+ };
376
+ const className = cx(classNameProp, {
377
+ vuuAlignRight: align === "right",
378
+ vuuPinFloating: pin === "floating",
379
+ vuuPinLeft: pin === "left",
380
+ vuuPinRight: pin === "right",
381
+ "vuuTableCell-resizing": resizing
382
+ }) || void 0;
383
+ const style = getColumnStyle(column);
384
+ return editable ? /* @__PURE__ */ jsx(
385
+ "div",
386
+ {
387
+ className,
388
+ "data-editable": true,
389
+ role: "cell",
390
+ style,
391
+ onKeyDown: handleTitleKeyDown,
392
+ children: /* @__PURE__ */ jsx(
393
+ EditableLabel,
486
394
  {
487
- columns: [column],
488
- height: rowHeight,
489
- index: j,
490
- row
395
+ editing,
396
+ value: editableValue,
397
+ onChange: setEditableValue,
398
+ onMouseDownCapture: handleTitleMouseDown,
399
+ onEnterEditMode: handleEnterEditMode,
400
+ onExitEditMode: handleExitEditMode,
401
+ onKeyDown: handleTitleKeyDown,
402
+ ref: labelFieldRef,
403
+ tabIndex: 0
491
404
  },
492
- row[RENDER_IDX]
493
- )),
494
- /* @__PURE__ */ jsx8("tr", { className: "vuuTable-filler" })
495
- ] })
496
- },
497
- column.name
498
- )) });
499
- };
500
-
501
- // src/context-menu/buildContextMenuDescriptors.ts
502
- import { isNumericColumn } from "@vuu-ui/vuu-utils";
503
- var buildContextMenuDescriptors = (dataSource) => (location, options) => {
504
- const descriptors = [];
505
- if (dataSource === void 0) {
506
- return descriptors;
507
- }
508
- if (location === "header") {
509
- descriptors.push(
510
- ...buildSortMenuItems(options, dataSource)
511
- );
512
- descriptors.push(
513
- ...buildGroupMenuItems(options, dataSource)
514
- );
515
- descriptors.push(
516
- ...buildAggregationMenuItems(options, dataSource)
405
+ "title"
406
+ )
407
+ }
408
+ ) : /* @__PURE__ */ jsx(
409
+ "div",
410
+ {
411
+ className,
412
+ role: "cell",
413
+ style,
414
+ onClick: handleClick,
415
+ children: CellRenderer ? /* @__PURE__ */ jsx(CellRenderer, { column, columnMap, row }) : value
416
+ }
517
417
  );
518
- descriptors.push(...buildColumnDisplayMenuItems(options));
519
- } else if (location === "filter") {
520
- const { column, filter } = options;
521
- const colIsOnlyFilter = (filter == null ? void 0 : filter.column) === (column == null ? void 0 : column.name);
522
- descriptors.push({
523
- label: "Edit filter",
524
- action: "filter-edit",
525
- options
526
- });
527
- descriptors.push({
528
- label: "Remove filter",
529
- action: "filter-remove-column",
530
- options
531
- });
532
- if (column && !colIsOnlyFilter) {
533
- descriptors.push({
534
- label: `Remove all filters`,
535
- action: "remove-filters",
536
- options
537
- });
538
- }
418
+ },
419
+ cellValuesAreEqual
420
+ );
421
+ TableCell.displayName = "TableCell";
422
+ function cellValuesAreEqual(prev, next) {
423
+ return prev.column === next.column && prev.onClick === next.onClick && prev.row[KEY] === next.row[KEY] && prev.row[prev.column.key] === next.row[next.column.key];
424
+ }
425
+
426
+ // src/TableGroupCell.tsx
427
+ import { getColumnStyle as getColumnStyle2, metadataKeys as metadataKeys2 } from "@vuu-ui/vuu-utils";
428
+ import { useCallback as useCallback2 } from "react";
429
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
430
+ var { DEPTH, IS_LEAF } = metadataKeys2;
431
+ var getGroupValueAndOffset = (columns, row) => {
432
+ const { [DEPTH]: depth, [IS_LEAF]: isLeaf } = row;
433
+ if (isLeaf || depth > columns.length) {
434
+ return [null, depth === null ? 0 : depth - 1];
435
+ } else if (depth === 0) {
436
+ return ["$root", 0];
437
+ } else {
438
+ const { key, valueFormatter } = columns[depth - 1];
439
+ const value = valueFormatter(row[key]);
440
+ return [value, depth - 1];
539
441
  }
540
- return descriptors;
541
442
  };
542
- function buildSortMenuItems(options, { sort: { sortDefs } }) {
543
- const { column } = options;
544
- const menuItems = [];
545
- if (column === void 0) {
546
- return menuItems;
547
- }
548
- const hasSort = sortDefs.length > 0;
549
- if (column.sorted === "A") {
550
- menuItems.push({
551
- label: "Reverse Sort (DSC)",
552
- action: "sort-dsc",
553
- options
554
- });
555
- } else if (column.sorted === "D") {
556
- menuItems.push({
557
- label: "Reverse Sort (ASC)",
558
- action: "sort-asc",
559
- options
560
- });
561
- } else if (typeof column.sorted === "number") {
562
- if (column.sorted > 0) {
563
- menuItems.push({
564
- label: "Reverse Sort (DSC)",
565
- action: "sort-add-dsc",
566
- options
567
- });
568
- } else {
569
- menuItems.push({
570
- label: "Reverse Sort (ASC)",
571
- action: "sort-add-asc",
572
- options
573
- });
574
- }
575
- if (hasSort && Math.abs(column.sorted) < sortDefs.length) {
576
- menuItems.push({
577
- label: "Remove from sort",
578
- action: "sort-remove",
579
- options
580
- });
581
- }
582
- menuItems.push({
583
- label: "New Sort",
584
- children: [
585
- { label: "Ascending", action: "sort-asc", options },
586
- { label: "Descending", action: "sort-dsc", options }
587
- ]
588
- });
589
- } else if (hasSort) {
590
- menuItems.push({
591
- label: "Add to sort",
592
- children: [
593
- { label: "Ascending", action: "sort-add-asc", options },
594
- { label: "Descending", action: "sort-add-dsc", options }
595
- ]
596
- });
597
- menuItems.push({
598
- label: "New Sort",
599
- children: [
600
- { label: "Ascending", action: "sort-asc", options },
601
- { label: "Descending", action: "sort-dsc", options }
602
- ]
603
- });
604
- } else {
605
- menuItems.push({
606
- label: "Sort",
443
+ var TableGroupCell = ({ column, onClick, row }) => {
444
+ const { columns } = column;
445
+ const [value, offset] = getGroupValueAndOffset(columns, row);
446
+ const handleClick = useCallback2(() => {
447
+ onClick == null ? void 0 : onClick(column);
448
+ }, [column, onClick]);
449
+ const style = getColumnStyle2(column);
450
+ const isLeaf = row[IS_LEAF];
451
+ const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ jsx2("span", { className: "vuuTableGroupCell-spacer" }, i));
452
+ return /* @__PURE__ */ jsxs(
453
+ "div",
454
+ {
455
+ className: "vuuTableGroupCell vuuPinLeft",
456
+ onClick: isLeaf ? void 0 : handleClick,
457
+ role: "cell",
458
+ style,
607
459
  children: [
608
- { label: "Ascending", action: "sort-asc", options },
609
- { label: "Descending", action: "sort-dsc", options }
460
+ spacers,
461
+ isLeaf ? null : /* @__PURE__ */ jsx2("span", { className: "vuuTableGroupCell-toggle", "data-icon": "triangle-right" }),
462
+ /* @__PURE__ */ jsx2("span", { children: value })
610
463
  ]
611
- });
612
- }
613
- return menuItems;
614
- }
615
- function buildAggregationMenuItems(options, dataSource) {
616
- const { column } = options;
617
- if (column === void 0 || dataSource.groupBy.length === 0) {
618
- return [];
619
- }
620
- const { name, label = name } = column;
621
- return [
622
- {
623
- label: `Aggregate ${label}`,
624
- children: [{ label: "Count", action: "agg-count", options }].concat(
625
- isNumericColumn(column) ? [
626
- { label: "Sum", action: "agg-sum", options },
627
- { label: "Avg", action: "agg-avg", options },
628
- { label: "High", action: "agg-high", options },
629
- { label: "Low", action: "agg-low", options }
630
- ] : []
631
- )
632
464
  }
633
- ];
634
- }
635
- var pinColumn = (options, pinLocation) => ({
636
- label: `Pin ${pinLocation}`,
637
- action: `column-pin-${pinLocation}`,
638
- options
639
- });
640
- var pinLeft = (options) => pinColumn(options, "left");
641
- var pinFloating = (options) => pinColumn(options, "floating");
642
- var pinRight = (options) => pinColumn(options, "right");
643
- function buildColumnDisplayMenuItems(options) {
644
- const { column } = options;
645
- if (column === void 0) {
646
- return [];
647
- }
648
- const { pin } = column;
649
- const menuItems = [
650
- {
651
- label: `Hide column`,
652
- action: "column-hide",
653
- options
465
+ );
466
+ };
467
+
468
+ // src/TableRow.tsx
469
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
470
+ var { IDX, IS_EXPANDED, SELECTED } = metadataKeys3;
471
+ var classBase = "vuuTableRow";
472
+ var TableRow = memo2(function Row({
473
+ columnMap,
474
+ columns,
475
+ offset,
476
+ onClick,
477
+ onToggleGroup,
478
+ virtualColSpan = 0,
479
+ row
480
+ }) {
481
+ const {
482
+ [IDX]: rowIndex,
483
+ [IS_EXPANDED]: isExpanded,
484
+ [SELECTED]: isSelected
485
+ } = row;
486
+ const className = cx2(classBase, {
487
+ [`${classBase}-even`]: rowIndex % 2 === 0,
488
+ [`${classBase}-expanded`]: isExpanded,
489
+ [`${classBase}-preSelected`]: isSelected === 2
490
+ });
491
+ const handleRowClick = useCallback3(
492
+ (evt) => {
493
+ const rangeSelect = evt.shiftKey;
494
+ const keepExistingSelection = evt.ctrlKey || evt.metaKey;
495
+ onClick == null ? void 0 : onClick(row, rangeSelect, keepExistingSelection);
496
+ },
497
+ [onClick, row]
498
+ );
499
+ const handleGroupCellClick = useCallback3(
500
+ (column) => {
501
+ if (isGroupColumn(column) || isJsonGroup(column, row)) {
502
+ onToggleGroup == null ? void 0 : onToggleGroup(row, column);
503
+ }
654
504
  },
505
+ [onToggleGroup, row]
506
+ );
507
+ return /* @__PURE__ */ jsxs2(
508
+ "div",
655
509
  {
656
- label: `Remove column`,
657
- action: "column-remove",
658
- options
510
+ "aria-selected": isSelected === 1 ? true : void 0,
511
+ "aria-rowindex": rowIndex,
512
+ className,
513
+ onClick: handleRowClick,
514
+ role: "row",
515
+ style: {
516
+ transform: `translate3d(0px, ${offset}px, 0px)`
517
+ },
518
+ children: [
519
+ virtualColSpan > 0 ? /* @__PURE__ */ jsx3("div", { role: "cell", style: { width: virtualColSpan } }) : null,
520
+ columns.filter(notHidden).map((column) => {
521
+ const isGroup = isGroupColumn(column);
522
+ const isJsonCell = isJsonColumn(column);
523
+ const Cell = isGroup ? TableGroupCell : TableCell;
524
+ return /* @__PURE__ */ jsx3(
525
+ Cell,
526
+ {
527
+ column,
528
+ columnMap,
529
+ onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
530
+ row
531
+ },
532
+ column.name
533
+ );
534
+ })
535
+ ]
659
536
  }
660
- ];
661
- if (pin === void 0) {
662
- menuItems.push({
663
- label: `Pin column`,
664
- children: [pinLeft(options), pinFloating(options), pinRight(options)]
665
- });
666
- } else if (pin === "left") {
667
- menuItems.push(
668
- { label: "Unpin column", action: "column-unpin", options },
669
- {
670
- label: `Pin column`,
671
- children: [pinFloating(options), pinRight(options)]
537
+ );
538
+ });
539
+
540
+ // src/TableGroupHeaderCell.tsx
541
+ import cx3 from "classnames";
542
+ import { useRef as useRef4 } from "react";
543
+
544
+ // src/ColumnResizer.tsx
545
+ import { useCallback as useCallback4, useRef as useRef2 } from "react";
546
+ import { jsx as jsx4 } from "react/jsx-runtime";
547
+ var NOOP = () => void 0;
548
+ var baseClass = "vuuColumnResizer";
549
+ var ColumnResizer = ({
550
+ onDrag,
551
+ onDragEnd = NOOP,
552
+ onDragStart = NOOP
553
+ }) => {
554
+ const position = useRef2(0);
555
+ const onMouseMove = useCallback4(
556
+ (e) => {
557
+ if (e.stopPropagation) {
558
+ e.stopPropagation();
672
559
  }
673
- );
674
- } else if (pin === "right") {
675
- menuItems.push(
676
- { label: "Unpin column", action: "column-unpin", options },
677
- {
678
- label: `Pin column`,
679
- children: [pinLeft(options), pinFloating(options)]
560
+ if (e.preventDefault) {
561
+ e.preventDefault();
680
562
  }
681
- );
682
- } else if (pin === "floating") {
683
- menuItems.push(
684
- { label: "Unpin column", action: "column-unpin", options },
685
- {
686
- label: `Pin column`,
687
- children: [pinLeft(options), pinRight(options)]
563
+ const x = Math.round(e.clientX);
564
+ const moveBy = x - position.current;
565
+ position.current = x;
566
+ if (moveBy !== 0) {
567
+ onDrag(e, moveBy);
688
568
  }
689
- );
690
- }
691
- return menuItems;
692
- }
693
- function buildGroupMenuItems(options, { groupBy }) {
694
- const { column } = options;
695
- const menuItems = [];
696
- if (column === void 0) {
697
- return menuItems;
698
- }
699
- const { name, label = name } = column;
700
- if (groupBy.length === 0) {
701
- menuItems.push({
702
- label: `Group by ${label}`,
703
- action: "group",
704
- options
705
- });
706
- } else {
707
- menuItems.push({
708
- label: `Add ${label} to group by`,
709
- action: "group-add",
710
- options
711
- });
712
- }
713
- return menuItems;
714
- }
715
-
716
- // src/context-menu/useContextMenu.ts
717
- import { removeColumnFromFilter } from "@vuu-ui/vuu-filters";
718
- import {
719
- addGroupColumn,
720
- addSortColumn,
721
- AggregationType,
722
- setAggregations,
723
- setSortColumn
724
- } from "@vuu-ui/vuu-utils";
725
- var removeFilterColumn = (dataSourceFilter, column) => {
726
- if (dataSourceFilter.filterStruct && column) {
727
- const [filterStruct, filter] = removeColumnFromFilter(
728
- column,
729
- dataSourceFilter.filterStruct
730
- );
731
- return {
732
- filter,
733
- filterStruct
734
- };
735
- } else {
736
- return dataSourceFilter;
737
- }
569
+ },
570
+ [onDrag]
571
+ );
572
+ const onMouseUp = useCallback4(
573
+ (e) => {
574
+ window.removeEventListener("mouseup", onMouseUp);
575
+ window.removeEventListener("mousemove", onMouseMove);
576
+ onDragEnd(e);
577
+ },
578
+ [onDragEnd, onMouseMove]
579
+ );
580
+ const handleMouseDown = useCallback4(
581
+ (e) => {
582
+ onDragStart(e);
583
+ position.current = Math.round(e.clientX);
584
+ window.addEventListener("mouseup", onMouseUp);
585
+ window.addEventListener("mousemove", onMouseMove);
586
+ if (e.stopPropagation) {
587
+ e.stopPropagation();
588
+ }
589
+ if (e.preventDefault) {
590
+ e.preventDefault();
591
+ }
592
+ },
593
+ [onDragStart, onMouseMove, onMouseUp]
594
+ );
595
+ return /* @__PURE__ */ jsx4("div", { className: baseClass, "data-align": "end", onMouseDown: handleMouseDown });
738
596
  };
739
- var { Average, Count, High, Low, Sum } = AggregationType;
740
- var useContextMenu3 = ({
741
- dataSource,
742
- onPersistentColumnOperation
597
+
598
+ // src/useTableColumnResize.tsx
599
+ import { useCallback as useCallback5, useRef as useRef3 } from "react";
600
+ var useTableColumnResize = ({
601
+ column,
602
+ onResize,
603
+ rootRef
743
604
  }) => {
744
- const handleContextMenuAction = (type, options) => {
745
- const gridOptions = options;
746
- if (gridOptions.column && dataSource) {
747
- const { column } = gridOptions;
748
- switch (type) {
749
- case "sort-asc":
750
- return dataSource.sort = setSortColumn(dataSource.sort, column, "A"), true;
751
- case "sort-dsc":
752
- return dataSource.sort = setSortColumn(dataSource.sort, column, "D"), true;
753
- case "sort-add-asc":
754
- return dataSource.sort = addSortColumn(dataSource.sort, column, "A"), true;
755
- case "sort-add-dsc":
756
- return dataSource.sort = addSortColumn(dataSource.sort, column, "D"), true;
757
- case "group":
758
- return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
759
- case "group-add":
760
- return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
761
- case "column-hide":
762
- return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
763
- case "column-remove":
764
- return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
765
- case "filter-remove-column":
766
- return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
767
- case "remove-filters":
768
- return dataSource.filter = { filter: "" }, true;
769
- case "agg-avg":
770
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Average), true;
771
- case "agg-high":
772
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, High), true;
773
- case "agg-low":
774
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Low), true;
775
- case "agg-count":
776
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Count), true;
777
- case "agg-sum":
778
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Sum), true;
779
- case "column-pin-floating":
780
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
781
- case "column-pin-left":
782
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
783
- case "column-pin-right":
784
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
785
- case "column-unpin":
786
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
787
- default:
605
+ const widthRef = useRef3(0);
606
+ const isResizing = useRef3(false);
607
+ const { name } = column;
608
+ const handleResizeStart = useCallback5(() => {
609
+ if (onResize && rootRef.current) {
610
+ const { width } = rootRef.current.getBoundingClientRect();
611
+ widthRef.current = Math.round(width);
612
+ isResizing.current = true;
613
+ onResize == null ? void 0 : onResize("begin", name);
614
+ }
615
+ }, [name, onResize, rootRef]);
616
+ const handleResize = useCallback5(
617
+ (_evt, moveBy) => {
618
+ if (rootRef.current) {
619
+ if (onResize) {
620
+ const { width } = rootRef.current.getBoundingClientRect();
621
+ const newWidth = Math.round(width) + moveBy;
622
+ if (newWidth !== widthRef.current && newWidth > 0) {
623
+ onResize("resize", name, newWidth);
624
+ widthRef.current = newWidth;
625
+ }
626
+ }
788
627
  }
628
+ },
629
+ [name, onResize, rootRef]
630
+ );
631
+ const handleResizeEnd = useCallback5(() => {
632
+ if (onResize) {
633
+ onResize("end", name, widthRef.current);
634
+ setTimeout(() => {
635
+ isResizing.current = false;
636
+ }, 100);
789
637
  }
790
- return false;
638
+ }, [name, onResize]);
639
+ return {
640
+ isResizing: isResizing.current,
641
+ onDrag: handleResize,
642
+ onDragStart: handleResizeStart,
643
+ onDragEnd: handleResizeEnd
791
644
  };
792
- return handleContextMenuAction;
793
645
  };
794
646
 
795
- // src/RowBasedTable.tsx
796
- import {
797
- getColumnPinStyle as getColumnPinStyle2,
798
- isGroupColumn as isGroupColumn2,
799
- metadataKeys as metadataKeys5,
800
- notHidden as notHidden2,
801
- visibleColumnAtIndex
802
- } from "@vuu-ui/vuu-utils";
803
- import { useCallback as useCallback9, useMemo } from "react";
804
-
805
647
  // src/TableGroupHeaderCell.tsx
806
- import cx7 from "classnames";
807
- import { useRef as useRef5 } from "react";
808
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
809
- var classBase5 = "vuuTable-groupHeaderCell";
648
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
649
+ var classBase2 = "vuuTable-groupHeaderCell";
650
+ var RemoveButton = ({
651
+ column,
652
+ onClick,
653
+ ...htmlAttributes
654
+ }) => {
655
+ return /* @__PURE__ */ jsx5(
656
+ "span",
657
+ {
658
+ ...htmlAttributes,
659
+ className: `${classBase2}-close`,
660
+ "data-icon": "close-circle",
661
+ onClick: () => onClick == null ? void 0 : onClick(column)
662
+ }
663
+ );
664
+ };
810
665
  var ColHeader = (props) => {
811
- const { column, className, onRemoveColumn } = props;
812
- return /* @__PURE__ */ jsxs6("div", { className: cx7(`${classBase5}-col`, className), role: "columnheader", children: [
813
- /* @__PURE__ */ jsx9("span", { className: `${classBase5}-label`, children: column.name }),
814
- /* @__PURE__ */ jsx9(
815
- "span",
816
- {
817
- className: `${classBase5}-close`,
818
- "data-icon": "close-circle",
819
- onClick: () => onRemoveColumn == null ? void 0 : onRemoveColumn(column)
820
- }
821
- )
666
+ const { children, column, className } = props;
667
+ return /* @__PURE__ */ jsxs3("div", { className: cx3(`${classBase2}-col`, className), role: "columnheader", children: [
668
+ /* @__PURE__ */ jsx5("span", { className: `${classBase2}-label`, children: column.name }),
669
+ children
822
670
  ] });
823
671
  };
824
672
  var TableGroupHeaderCell = ({
@@ -828,40 +676,153 @@ var TableGroupHeaderCell = ({
828
676
  onResize,
829
677
  ...props
830
678
  }) => {
831
- const rootRef = useRef5(null);
679
+ const rootRef = useRef4(null);
832
680
  const { isResizing, ...resizeProps } = useTableColumnResize({
833
681
  column: groupColumn,
834
682
  onResize,
835
683
  rootRef
836
684
  });
837
- const className = cx7(classBase5, classNameProp, {
685
+ const className = cx3(classBase2, classNameProp, {
838
686
  vuuPinLeft: groupColumn.pin === "left",
839
- [`${classBase5}-right`]: groupColumn.align === "right",
840
- [`${classBase5}-resizing`]: groupColumn.resizing,
841
- [`${classBase5}-pending`]: groupColumn.groupConfirmed === false
687
+ [`${classBase2}-right`]: groupColumn.align === "right",
688
+ [`${classBase2}-resizing`]: groupColumn.resizing,
689
+ [`${classBase2}-pending`]: groupColumn.groupConfirmed === false
842
690
  });
843
691
  const { columns } = groupColumn;
844
- return /* @__PURE__ */ jsx9("th", { className, ref: rootRef, ...props, children: /* @__PURE__ */ jsxs6("div", { className: `${classBase5}-inner`, children: [
845
- columns.map((column) => /* @__PURE__ */ jsx9(
846
- ColHeader,
847
- {
848
- column,
849
- onRemoveColumn
850
- },
851
- column.key
852
- )),
853
- groupColumn.resizeable !== false ? /* @__PURE__ */ jsx9(ColumnResizer, { ...resizeProps }) : null
692
+ return /* @__PURE__ */ jsx5("div", { className, ref: rootRef, ...props, children: /* @__PURE__ */ jsxs3("div", { className: `${classBase2}-inner`, children: [
693
+ columns.map((column) => /* @__PURE__ */ jsx5(ColHeader, { column, children: columns.length > 1 ? /* @__PURE__ */ jsx5(RemoveButton, { column, onClick: onRemoveColumn }) : null }, column.key)),
694
+ /* @__PURE__ */ jsx5(RemoveButton, { "data-align": "end", onClick: onRemoveColumn }),
695
+ groupColumn.resizeable !== false ? /* @__PURE__ */ jsx5(ColumnResizer, { ...resizeProps }) : null
854
696
  ] }) });
855
697
  };
856
698
 
699
+ // src/TableHeaderCell.tsx
700
+ import cx6 from "classnames";
701
+ import { useCallback as useCallback7, useRef as useRef5 } from "react";
702
+
703
+ // src/SortIndicator.tsx
704
+ import cx4 from "classnames";
705
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
706
+ var classBase3 = "vuuSortIndicator";
707
+ var SortIndicator = ({ sorted }) => {
708
+ if (!sorted) {
709
+ return null;
710
+ }
711
+ const direction = typeof sorted === "number" ? sorted < 0 ? "dsc" : "asc" : sorted === "A" ? "asc" : "dsc";
712
+ return typeof sorted === "number" ? /* @__PURE__ */ jsxs4("div", { className: cx4(classBase3, "multi-col", direction), children: [
713
+ /* @__PURE__ */ jsx6("span", { "data-icon": `sorted-${direction}` }),
714
+ /* @__PURE__ */ jsx6("span", { className: "vuuSortPosition", children: Math.abs(sorted) })
715
+ ] }) : /* @__PURE__ */ jsx6("div", { className: cx4(classBase3, "single-col"), children: /* @__PURE__ */ jsx6("span", { "data-icon": `sorted-${direction}` }) });
716
+ };
717
+
718
+ // src/TableHeaderCell.tsx
719
+ import { useContextMenu as useContextMenu3 } from "@vuu-ui/vuu-popups";
720
+
721
+ // src/filter-indicator.tsx
722
+ import { useContextMenu as useContextMenu2 } from "@vuu-ui/vuu-popups";
723
+ import cx5 from "classnames";
724
+ import { useCallback as useCallback6 } from "react";
725
+ import { jsx as jsx7 } from "react/jsx-runtime";
726
+ var FilterIndicator = ({ column, filter }) => {
727
+ const showContextMenu = useContextMenu2();
728
+ const handleClick = useCallback6(
729
+ (evt) => {
730
+ evt.stopPropagation();
731
+ showContextMenu(evt, "filter", { column, filter });
732
+ },
733
+ [column, filter, showContextMenu]
734
+ );
735
+ if (!column.filter) {
736
+ return null;
737
+ }
738
+ return /* @__PURE__ */ jsx7(
739
+ "div",
740
+ {
741
+ className: cx5("vuuFilterIndicator"),
742
+ "data-icon": "filter",
743
+ onClick: handleClick
744
+ }
745
+ );
746
+ };
747
+
748
+ // src/TableHeaderCell.tsx
749
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
750
+ var classBase4 = "vuuTable-headerCell";
751
+ var TableHeaderCell = ({
752
+ column,
753
+ className: classNameProp,
754
+ onClick,
755
+ onDragStart,
756
+ onResize,
757
+ ...props
758
+ }) => {
759
+ const rootRef = useRef5(null);
760
+ const { isResizing, ...resizeProps } = useTableColumnResize({
761
+ column,
762
+ onResize,
763
+ rootRef
764
+ });
765
+ const showContextMenu = useContextMenu3();
766
+ const dragTimerRef = useRef5(null);
767
+ const handleContextMenu = (e) => {
768
+ showContextMenu(e, "header", { column });
769
+ };
770
+ const handleClick = useCallback7(
771
+ (evt) => !isResizing && (onClick == null ? void 0 : onClick(evt)),
772
+ [isResizing, onClick]
773
+ );
774
+ const handleMouseDown = useCallback7(
775
+ (evt) => {
776
+ dragTimerRef.current = window.setTimeout(() => {
777
+ onDragStart == null ? void 0 : onDragStart(evt);
778
+ dragTimerRef.current = null;
779
+ }, 500);
780
+ },
781
+ [onDragStart]
782
+ );
783
+ const handleMouseUp = useCallback7(() => {
784
+ if (dragTimerRef.current !== null) {
785
+ window.clearTimeout(dragTimerRef.current);
786
+ dragTimerRef.current = null;
787
+ }
788
+ }, []);
789
+ const className = cx6(classBase4, classNameProp, {
790
+ vuuPinFloating: column.pin === "floating",
791
+ vuuPinLeft: column.pin === "left",
792
+ vuuPinRight: column.pin === "right",
793
+ vuuEndPin: column.endPin,
794
+ [`${classBase4}-resizing`]: column.resizing,
795
+ [`${classBase4}-right`]: column.align === "right"
796
+ });
797
+ return /* @__PURE__ */ jsx8(
798
+ "div",
799
+ {
800
+ className,
801
+ ...props,
802
+ onClick: handleClick,
803
+ onContextMenu: handleContextMenu,
804
+ onMouseDown: handleMouseDown,
805
+ onMouseUp: handleMouseUp,
806
+ ref: rootRef,
807
+ children: /* @__PURE__ */ jsxs5("div", { className: `${classBase4}-inner`, children: [
808
+ /* @__PURE__ */ jsx8(FilterIndicator, { column }),
809
+ /* @__PURE__ */ jsx8("div", { className: `${classBase4}-label`, children: column.label }),
810
+ /* @__PURE__ */ jsx8(SortIndicator, { sorted: column.sorted }),
811
+ column.resizeable !== false ? /* @__PURE__ */ jsx8(ColumnResizer, { ...resizeProps }) : null
812
+ ] })
813
+ }
814
+ );
815
+ };
816
+
857
817
  // src/RowBasedTable.tsx
858
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
859
- var classBase6 = "vuuTable";
860
- var { RENDER_IDX: RENDER_IDX2 } = metadataKeys5;
818
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
819
+ var classBase5 = "vuuTable";
820
+ var { RENDER_IDX } = metadataKeys4;
861
821
  var RowBasedTable = ({
862
822
  columns,
863
823
  columnsWithinViewport,
864
824
  data,
825
+ getRowOffset,
865
826
  headings,
866
827
  onColumnResize,
867
828
  onHeaderCellDragStart,
@@ -870,11 +831,11 @@ var RowBasedTable = ({
870
831
  onRowClick,
871
832
  onSort,
872
833
  onToggleGroup,
834
+ tableId,
873
835
  virtualColSpan = 0,
874
- rowCount,
875
- rowHeight
836
+ rowCount
876
837
  }) => {
877
- const handleDragStart = useCallback9(
838
+ const handleDragStart = useCallback8(
878
839
  (evt) => {
879
840
  onHeaderCellDragStart == null ? void 0 : onHeaderCellDragStart(evt);
880
841
  },
@@ -883,7 +844,8 @@ var RowBasedTable = ({
883
844
  const visibleColumns = useMemo(() => {
884
845
  return columns.filter(notHidden2);
885
846
  }, [columns]);
886
- const handleHeaderClick = useCallback9(
847
+ const columnMap = useMemo(() => buildColumnMap(columns), [columns]);
848
+ const handleHeaderClick = useCallback8(
887
849
  (evt) => {
888
850
  var _a;
889
851
  const targetElement = evt.target;
@@ -897,70 +859,77 @@ var RowBasedTable = ({
897
859
  },
898
860
  [columns, onSort]
899
861
  );
900
- return /* @__PURE__ */ jsxs7("table", { "aria-rowcount": rowCount, className: `${classBase6}-table`, children: [
901
- /* @__PURE__ */ jsx10("colgroup", { children: visibleColumns.map((column, i) => /* @__PURE__ */ jsx10("col", { width: `${column.width}px` }, i)) }),
902
- /* @__PURE__ */ jsxs7("thead", { children: [
903
- headings.map((colHeaders, i) => /* @__PURE__ */ jsx10("tr", { className: "vuuTable-heading", children: colHeaders.map(({ label, span }, j) => /* @__PURE__ */ jsx10("th", { colSpan: span, className: "vuuTable-headingCell", children: label }, j)) }, i)),
904
- /* @__PURE__ */ jsx10("tr", { children: visibleColumns.map((column, i) => {
905
- const style = getColumnPinStyle2(column);
906
- return isGroupColumn2(column) ? /* @__PURE__ */ jsx10(
862
+ return /* @__PURE__ */ jsxs6("div", { "aria-rowcount": rowCount, className: `${classBase5}-table`, role: "table", children: [
863
+ /* @__PURE__ */ jsxs6("div", { className: `${classBase5}-headers`, role: "rowGroup", children: [
864
+ headings.map((colHeaders, i) => /* @__PURE__ */ jsx9("div", { className: "vuuTable-heading", children: colHeaders.map(({ label, width }, j) => /* @__PURE__ */ jsx9("div", { className: "vuuTable-headingCell", style: { width }, children: label }, j)) }, i)),
865
+ /* @__PURE__ */ jsx9("div", { role: "row", children: visibleColumns.map((column, i) => {
866
+ const style = getColumnStyle3(column);
867
+ return isGroupColumn2(column) ? /* @__PURE__ */ jsx9(
907
868
  TableGroupHeaderCell,
908
869
  {
909
870
  column,
910
871
  "data-idx": i,
911
872
  onRemoveColumn: onRemoveColumnFromGroupBy,
912
873
  onResize: onColumnResize,
874
+ role: "columnHeader",
913
875
  style
914
876
  },
915
877
  i
916
- ) : /* @__PURE__ */ jsx10(
878
+ ) : /* @__PURE__ */ jsx9(
917
879
  TableHeaderCell,
918
880
  {
919
881
  column,
920
882
  "data-idx": i,
883
+ id: `${tableId}-${i}`,
921
884
  onClick: handleHeaderClick,
922
885
  onDragStart: handleDragStart,
923
886
  onResize: onColumnResize,
887
+ role: "columnHeader",
924
888
  style
925
889
  },
926
890
  i
927
891
  );
928
892
  }) })
929
893
  ] }),
930
- /* @__PURE__ */ jsxs7("tbody", { onContextMenu, children: [
931
- data == null ? void 0 : data.map((row, i) => /* @__PURE__ */ jsx10(
932
- TableRow,
933
- {
934
- columns: columnsWithinViewport,
935
- height: rowHeight,
936
- index: i,
937
- onClick: onRowClick,
938
- virtualColSpan,
939
- onToggleGroup,
940
- row
941
- },
942
- row[RENDER_IDX2]
943
- )),
944
- /* @__PURE__ */ jsx10("tr", { className: `${classBase6}-filler` })
945
- ] })
894
+ /* @__PURE__ */ jsx9(
895
+ "div",
896
+ {
897
+ className: `${classBase5}-body`,
898
+ onContextMenu,
899
+ role: "rowGroup",
900
+ children: data == null ? void 0 : data.map((row) => /* @__PURE__ */ jsx9(
901
+ TableRow,
902
+ {
903
+ columnMap,
904
+ columns: columnsWithinViewport,
905
+ offset: getRowOffset(row),
906
+ onClick: onRowClick,
907
+ virtualColSpan,
908
+ onToggleGroup,
909
+ row
910
+ },
911
+ row[RENDER_IDX]
912
+ ))
913
+ }
914
+ )
946
915
  ] });
947
916
  };
948
917
 
949
- // src/useDataTable.ts
918
+ // src/useTable.ts
950
919
  import { useContextMenu as usePopupContextMenu } from "@vuu-ui/vuu-popups";
951
920
  import {
952
921
  applySort,
953
- buildColumnMap,
922
+ buildColumnMap as buildColumnMap2,
954
923
  isJsonGroup as isJsonGroup2,
955
- metadataKeys as metadataKeys9,
924
+ metadataKeys as metadataKeys8,
956
925
  moveItem as moveItem2
957
926
  } from "@vuu-ui/vuu-utils";
958
927
  import {
959
928
  useCallback as useCallback18,
960
929
  useEffect as useEffect5,
961
930
  useMemo as useMemo6,
962
- useRef as useRef14,
963
- useState as useState6
931
+ useRef as useRef15,
932
+ useState as useState5
964
933
  } from "react";
965
934
 
966
935
  // src/useDataSource.ts
@@ -968,9 +937,9 @@ import {
968
937
  isVuuFeatureAction,
969
938
  isVuuFeatureInvocation
970
939
  } from "@vuu-ui/vuu-data";
971
- import { getFullRange, metadataKeys as metadataKeys6, WindowRange } from "@vuu-ui/vuu-utils";
972
- import { useCallback as useCallback10, useEffect, useMemo as useMemo2, useRef as useRef6, useState as useState2 } from "react";
973
- var { SELECTED: SELECTED2 } = metadataKeys6;
940
+ import { getFullRange, metadataKeys as metadataKeys5, WindowRange } from "@vuu-ui/vuu-utils";
941
+ import { useCallback as useCallback9, useEffect, useMemo as useMemo2, useRef as useRef6, useState as useState2 } from "react";
942
+ var { SELECTED: SELECTED2 } = metadataKeys5;
974
943
  function useDataSource({
975
944
  dataSource,
976
945
  onConfigChange,
@@ -993,7 +962,7 @@ function useDataSource({
993
962
  // eslint-disable-next-line react-hooks/exhaustive-deps
994
963
  []
995
964
  );
996
- const setData = useCallback10(
965
+ const setData = useCallback9(
997
966
  (updates) => {
998
967
  for (const row of updates) {
999
968
  dataWindow.add(row);
@@ -1003,7 +972,7 @@ function useDataSource({
1003
972
  },
1004
973
  [dataWindow]
1005
974
  );
1006
- const datasourceMessageHandler = useCallback10(
975
+ const datasourceMessageHandler = useCallback9(
1007
976
  (message) => {
1008
977
  if (message.type === "subscribed") {
1009
978
  onSubscribed == null ? void 0 : onSubscribed(message);
@@ -1045,7 +1014,7 @@ function useDataSource({
1045
1014
  },
1046
1015
  []
1047
1016
  );
1048
- const refreshIfUpdated = useCallback10(() => {
1017
+ const refreshIfUpdated = useCallback9(() => {
1049
1018
  if (isMounted.current) {
1050
1019
  if (hasUpdated.current) {
1051
1020
  forceUpdate({});
@@ -1057,27 +1026,27 @@ function useDataSource({
1057
1026
  useEffect(() => {
1058
1027
  rafHandle.current = requestAnimationFrame(refreshIfUpdated);
1059
1028
  }, [refreshIfUpdated]);
1060
- const adjustRange = useCallback10(
1029
+ const adjustRange = useCallback9(
1061
1030
  (rowCount) => {
1062
1031
  const { from } = dataSource.range;
1063
1032
  const rowRange = { from, to: from + rowCount };
1064
1033
  const fullRange = getFullRange(rowRange, renderBufferSize);
1034
+ dataWindow.setRange(fullRange);
1065
1035
  dataSource.range = rangeRef.current = fullRange;
1066
1036
  dataSource.emit("range", rowRange);
1067
- dataWindow.setRange(fullRange);
1068
1037
  },
1069
1038
  [dataSource, dataWindow, renderBufferSize]
1070
1039
  );
1071
- const setRange = useCallback10(
1040
+ const setRange = useCallback9(
1072
1041
  (range2) => {
1073
1042
  const fullRange = getFullRange(range2, renderBufferSize);
1074
- dataSource.range = rangeRef.current = fullRange;
1075
1043
  dataWindow.setRange(fullRange);
1044
+ dataSource.range = rangeRef.current = fullRange;
1076
1045
  dataSource.emit("range", range2);
1077
1046
  },
1078
1047
  [dataSource, dataWindow, renderBufferSize]
1079
1048
  );
1080
- const getSelectedRows = useCallback10(() => {
1049
+ const getSelectedRows = useCallback9(() => {
1081
1050
  return dataWindow.getSelectedRows();
1082
1051
  }, [dataWindow]);
1083
1052
  useEffect(() => {
@@ -1136,7 +1105,7 @@ var MovingWindow = class {
1136
1105
  setRange({ from, to }) {
1137
1106
  if (from !== this.range.from || to !== this.range.to) {
1138
1107
  const [overlapFrom, overlapTo] = this.range.overlap(from, to);
1139
- const newData = new Array(to - from);
1108
+ const newData = new Array(Math.max(0, to - from));
1140
1109
  for (let i = overlapFrom; i < overlapTo; i++) {
1141
1110
  const data = this.getAtIndex(i);
1142
1111
  if (data) {
@@ -1156,84 +1125,61 @@ var MovingWindow = class {
1156
1125
 
1157
1126
  // src/useDraggableColumn.ts
1158
1127
  import { useDragDrop } from "@heswell/salt-lab";
1159
- import {
1160
- useCallback as useCallback11,
1161
- useLayoutEffect,
1162
- useRef as useRef7,
1163
- useState as useState3
1164
- } from "react";
1165
- var useDraggableColumn = ({
1166
- onDrop,
1167
- tableContainerRef,
1168
- tableLayout: tableLayoutProp
1169
- }) => {
1170
- const [tableLayout, setTableLayout] = useState3(tableLayoutProp);
1128
+ import { useCallback as useCallback10, useRef as useRef7 } from "react";
1129
+ var useDraggableColumn = ({ onDrop }) => {
1171
1130
  const mousePosRef = useRef7();
1172
- const handleDropSettle = useCallback11(() => {
1131
+ const containerRef = useRef7(null);
1132
+ const handleDropSettle = useCallback10(() => {
1173
1133
  console.log(`handleDropSettle`);
1174
1134
  mousePosRef.current = void 0;
1175
- setTableLayout("row");
1135
+ containerRef.current = null;
1176
1136
  }, []);
1177
1137
  const { draggable, draggedItemIndex, onMouseDown } = useDragDrop({
1138
+ // allowDragDrop: "drop-indicator",
1178
1139
  allowDragDrop: true,
1179
- draggableClassName: "table-column",
1140
+ draggableClassName: "vuuTable-headerCell",
1180
1141
  orientation: "horizontal",
1181
- containerRef: tableContainerRef,
1182
- itemQuery: ".vuuTable-table",
1142
+ containerRef,
1143
+ itemQuery: ".vuuTable-headerCell",
1183
1144
  onDrop,
1184
1145
  onDropSettle: handleDropSettle
1185
1146
  });
1186
- const handleHeaderCellDragStart = useCallback11((evt) => {
1187
- const { clientX, clientY } = evt;
1188
- console.log(
1189
- `useDraggableColumn handleHeaderCellDragStart means mouseDown fired on a column in RowBasedTable`
1190
- );
1191
- const sourceElement = evt.target;
1192
- const thElement = sourceElement.closest(".vuuTable-headerCell");
1193
- const {
1194
- dataset: { idx = "-1" }
1195
- } = thElement;
1196
- mousePosRef.current = {
1197
- clientX,
1198
- clientY,
1199
- idx
1200
- };
1201
- setTableLayout("column");
1202
- }, []);
1203
- useLayoutEffect(() => {
1204
- var _a;
1205
- if (tableLayout === "column" && mousePosRef.current && !draggable) {
1206
- const { clientX, clientY, idx } = mousePosRef.current;
1207
- const target = (_a = tableContainerRef.current) == null ? void 0 : _a.querySelector(
1208
- `.vuuTable-table[data-idx="${idx}"]`
1147
+ const onHeaderCellDragStart = useCallback10(
1148
+ (evt) => {
1149
+ const { clientX, clientY } = evt;
1150
+ console.log(
1151
+ `useDraggableColumn handleHeaderCellDragStart means mouseDown fired on a column in RowBasedTable`
1209
1152
  );
1210
- if (target) {
1211
- const evt = {
1212
- persist: () => void 0,
1213
- nativeEvent: {
1214
- clientX,
1215
- clientY,
1216
- target
1217
- }
1218
- };
1219
- onMouseDown == null ? void 0 : onMouseDown(evt);
1220
- }
1221
- }
1222
- }, [draggable, onMouseDown, tableContainerRef, tableLayout]);
1153
+ const sourceElement = evt.target;
1154
+ const columnHeaderCell = sourceElement.closest(".vuuTable-headerCell");
1155
+ containerRef.current = columnHeaderCell == null ? void 0 : columnHeaderCell.closest(
1156
+ "[role='row']"
1157
+ );
1158
+ const {
1159
+ dataset: { idx = "-1" }
1160
+ } = columnHeaderCell;
1161
+ mousePosRef.current = {
1162
+ clientX,
1163
+ clientY,
1164
+ idx
1165
+ };
1166
+ onMouseDown == null ? void 0 : onMouseDown(evt);
1167
+ },
1168
+ [onMouseDown]
1169
+ );
1223
1170
  return {
1224
1171
  draggable,
1225
1172
  draggedItemIndex,
1226
- tableLayout,
1227
- onHeaderCellDragStart: tableLayout === "row" ? handleHeaderCellDragStart : void 0
1173
+ onHeaderCellDragStart
1228
1174
  };
1229
1175
  };
1230
1176
 
1231
1177
  // src/useKeyboardNavigation.ts
1232
1178
  import { withinRange } from "@vuu-ui/vuu-utils";
1233
1179
  import {
1234
- useCallback as useCallback12,
1180
+ useCallback as useCallback11,
1235
1181
  useEffect as useEffect2,
1236
- useLayoutEffect as useLayoutEffect2,
1182
+ useLayoutEffect,
1237
1183
  useMemo as useMemo3,
1238
1184
  useRef as useRef8
1239
1185
  } from "react";
@@ -1297,8 +1243,8 @@ var isNavigationKey = (key) => {
1297
1243
  };
1298
1244
 
1299
1245
  // src/useKeyboardNavigation.ts
1300
- var headerCellQuery = (colIdx) => `thead th:nth-child(${colIdx + 1})`;
1301
- var dataCellQuery = (rowIdx, colIdx) => `tbody > tr[aria-rowindex='${rowIdx}'] > td:nth-child(${colIdx + 1})`;
1246
+ var headerCellQuery = (colIdx) => `.vuuTable-headers .vuuTable-headerCell:nth-child(${colIdx + 1})`;
1247
+ var dataCellQuery = (rowIdx, colIdx) => `.vuuTable-body > [aria-rowindex='${rowIdx}'] > [role='cell']:nth-child(${colIdx + 1})`;
1302
1248
  var NULL_CELL_POS = [-1, -1];
1303
1249
  function nextCellPos(key, [rowIdx, colIdx], columnCount, rowCount) {
1304
1250
  if (key === ArrowUp) {
@@ -1344,7 +1290,7 @@ var useKeyboardNavigation = ({
1344
1290
  const focusedCellPos = useRef8([-1, -1]);
1345
1291
  const focusableCell = useRef8();
1346
1292
  const activeCellPos = useRef8([-1, 0]);
1347
- const getTableCell = useCallback12(
1293
+ const getTableCell = useCallback11(
1348
1294
  ([rowIdx, colIdx]) => {
1349
1295
  var _a2;
1350
1296
  const cssQuery = rowIdx === -1 ? headerCellQuery(colIdx) : dataCellQuery(rowIdx, colIdx);
@@ -1354,14 +1300,16 @@ var useKeyboardNavigation = ({
1354
1300
  },
1355
1301
  [containerRef]
1356
1302
  );
1357
- const getFocusedCell = (element) => element == null ? void 0 : element.closest("th,td");
1303
+ const getFocusedCell = (element) => element == null ? void 0 : element.closest(
1304
+ "[role='columnHeader'],[role='cell']"
1305
+ );
1358
1306
  const getTableCellPos = (tableCell) => {
1359
1307
  var _a2, _b;
1360
- if (tableCell.tagName === "TH") {
1308
+ if (tableCell.role === "columnHeader") {
1361
1309
  const colIdx = parseInt((_a2 = tableCell.dataset.idx) != null ? _a2 : "-1", 10);
1362
1310
  return [-1, colIdx];
1363
1311
  } else {
1364
- const focusedRow = tableCell.closest("tr");
1312
+ const focusedRow = tableCell.closest("[role='row']");
1365
1313
  if (focusedRow) {
1366
1314
  const rowIdx = parseInt((_b = focusedRow.ariaRowIndex) != null ? _b : "-1", 10);
1367
1315
  const colIdx = Array.from(focusedRow.childNodes).indexOf(tableCell);
@@ -1370,7 +1318,7 @@ var useKeyboardNavigation = ({
1370
1318
  }
1371
1319
  return NULL_CELL_POS;
1372
1320
  };
1373
- const focusCell = useCallback12(
1321
+ const focusCell = useCallback11(
1374
1322
  (cellPos) => {
1375
1323
  var _a2;
1376
1324
  if (containerRef.current) {
@@ -1392,7 +1340,7 @@ var useKeyboardNavigation = ({
1392
1340
  // be often whilst scrolling - store range in a a ref ?
1393
1341
  [containerRef, getTableCell, requestScroll, viewportRange]
1394
1342
  );
1395
- const setActiveCell = useCallback12(
1343
+ const setActiveCell = useCallback11(
1396
1344
  (rowIdx, colIdx, fromKeyboard = false) => {
1397
1345
  const pos = [rowIdx, colIdx];
1398
1346
  activeCellPos.current = pos;
@@ -1403,12 +1351,12 @@ var useKeyboardNavigation = ({
1403
1351
  },
1404
1352
  [focusCell]
1405
1353
  );
1406
- const virtualizeActiveCell = useCallback12(() => {
1354
+ const virtualizeActiveCell = useCallback11(() => {
1407
1355
  var _a2;
1408
1356
  (_a2 = focusableCell.current) == null ? void 0 : _a2.setAttribute("tabindex", "");
1409
1357
  focusableCell.current = void 0;
1410
1358
  }, []);
1411
- const nextPageItemIdx = useCallback12(
1359
+ const nextPageItemIdx = useCallback11(
1412
1360
  async (key, cellPos) => {
1413
1361
  switch (key) {
1414
1362
  case PageDown:
@@ -1428,7 +1376,7 @@ var useKeyboardNavigation = ({
1428
1376
  },
1429
1377
  [requestScroll]
1430
1378
  );
1431
- const handleFocus = useCallback12(() => {
1379
+ const handleFocus = useCallback11(() => {
1432
1380
  var _a2;
1433
1381
  if (disableHighlightOnFocus !== true) {
1434
1382
  if ((_a2 = containerRef.current) == null ? void 0 : _a2.contains(document.activeElement)) {
@@ -1439,7 +1387,7 @@ var useKeyboardNavigation = ({
1439
1387
  }
1440
1388
  }
1441
1389
  }, [disableHighlightOnFocus, containerRef]);
1442
- const navigateChildItems = useCallback12(
1390
+ const navigateChildItems = useCallback11(
1443
1391
  async (key) => {
1444
1392
  const [nextRowIdx, nextColIdx] = isPagingKey(key) ? await nextPageItemIdx(key, activeCellPos.current) : nextCellPos(key, activeCellPos.current, columnCount, rowCount);
1445
1393
  const [rowIdx, colIdx] = activeCellPos.current;
@@ -1449,7 +1397,7 @@ var useKeyboardNavigation = ({
1449
1397
  },
1450
1398
  [columnCount, nextPageItemIdx, rowCount, setActiveCell]
1451
1399
  );
1452
- const handleKeyDown = useCallback12(
1400
+ const handleKeyDown = useCallback11(
1453
1401
  (e) => {
1454
1402
  if (data.length > 0 && isNavigationKey(e.key)) {
1455
1403
  e.preventDefault();
@@ -1459,7 +1407,7 @@ var useKeyboardNavigation = ({
1459
1407
  },
1460
1408
  [data, navigateChildItems]
1461
1409
  );
1462
- const handleClick = useCallback12(
1410
+ const handleClick = useCallback11(
1463
1411
  // Might not be a cell e.g the Settings button
1464
1412
  (evt) => {
1465
1413
  const target = evt.target;
@@ -1478,7 +1426,7 @@ var useKeyboardNavigation = ({
1478
1426
  onKeyDown: handleKeyDown
1479
1427
  };
1480
1428
  }, [handleClick, handleFocus, handleKeyDown]);
1481
- useLayoutEffect2(() => {
1429
+ useLayoutEffect(() => {
1482
1430
  const { current: cellPos } = activeCellPos;
1483
1431
  const withinViewport = cellPos[0] >= viewportFirstRow && cellPos[0] <= viewportLastRow;
1484
1432
  if (focusableCell.current && !withinViewport) {
@@ -1504,10 +1452,10 @@ var useKeyboardNavigation = ({
1504
1452
  };
1505
1453
 
1506
1454
  // src/useMeasuredContainer.ts
1507
- import { useCallback as useCallback14, useRef as useRef10, useState as useState4 } from "react";
1455
+ import { useCallback as useCallback13, useRef as useRef10, useState as useState3 } from "react";
1508
1456
 
1509
1457
  // src/useResizeObserver.ts
1510
- import { useCallback as useCallback13, useEffect as useEffect3, useRef as useRef9 } from "react";
1458
+ import { useCallback as useCallback12, useEffect as useEffect3, useRef as useRef9 } from "react";
1511
1459
  var observedMap = /* @__PURE__ */ new Map();
1512
1460
  var getTargetSize = (element, size, dimension) => {
1513
1461
  switch (dimension) {
@@ -1559,7 +1507,7 @@ var resizeObserver = new ResizeObserver((entries) => {
1559
1507
  });
1560
1508
  function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false) {
1561
1509
  const dimensionsRef = useRef9(dimensions);
1562
- const measure = useCallback13((target) => {
1510
+ const measure = useCallback12((target) => {
1563
1511
  const { width, height } = target.getBoundingClientRect();
1564
1512
  const { clientWidth: contentWidth, clientHeight: contentHeight } = target;
1565
1513
  return dimensionsRef.current.reduce(
@@ -1633,14 +1581,15 @@ var useMeasuredContainer = ({
1633
1581
  width
1634
1582
  }) => {
1635
1583
  const containerRef = useRef10(null);
1636
- const [size, setSize] = useState4({
1584
+ const [size, setSize] = useState3({
1637
1585
  outer: {
1638
1586
  height: height != null ? height : "100%",
1639
1587
  width: width != null ? width : "100%"
1640
1588
  }
1641
1589
  });
1642
- const onResize = useCallback14(
1590
+ const onResize = useCallback13(
1643
1591
  ({ clientWidth, clientHeight }) => {
1592
+ console.log(`Resize ${clientHeight}`);
1644
1593
  setSize((currentSize) => {
1645
1594
  const { inner, outer } = currentSize;
1646
1595
  return isNumber(clientHeight) && isNumber(clientWidth) && (clientWidth !== (inner == null ? void 0 : inner.width) || clientHeight !== (inner == null ? void 0 : inner.height)) ? {
@@ -1663,9 +1612,9 @@ var useMeasuredContainer = ({
1663
1612
  };
1664
1613
 
1665
1614
  // src/useSelection.ts
1666
- import { deselectItem, metadataKeys as metadataKeys7, selectItem } from "@vuu-ui/vuu-utils";
1667
- import { useCallback as useCallback15, useRef as useRef11 } from "react";
1668
- var { IDX: IDX2, SELECTED: SELECTED3 } = metadataKeys7;
1615
+ import { deselectItem, metadataKeys as metadataKeys6, selectItem } from "@vuu-ui/vuu-utils";
1616
+ import { useCallback as useCallback14, useRef as useRef11 } from "react";
1617
+ var { IDX: IDX2, SELECTED: SELECTED3 } = metadataKeys6;
1669
1618
  var NO_SELECTION = [];
1670
1619
  var useSelection = ({
1671
1620
  selectionModel,
@@ -1674,7 +1623,7 @@ var useSelection = ({
1674
1623
  selectionModel === "extended" || selectionModel === "checkbox";
1675
1624
  const lastActiveRef = useRef11(-1);
1676
1625
  const selectedRef = useRef11(NO_SELECTION);
1677
- const handleSelectionChange = useCallback15(
1626
+ const handleSelectionChange = useCallback14(
1678
1627
  (row, rangeSelect, keepExistingSelection) => {
1679
1628
  const { [IDX2]: idx, [SELECTED3]: isSelected } = row;
1680
1629
  const { current: active } = lastActiveRef;
@@ -1715,14 +1664,14 @@ import {
1715
1664
  isPinned,
1716
1665
  isTypeDescriptor,
1717
1666
  logger,
1718
- metadataKeys as metadataKeys8,
1667
+ metadataKeys as metadataKeys7,
1719
1668
  sortPinnedColumns,
1720
1669
  stripFilterFromColumns
1721
1670
  } from "@vuu-ui/vuu-utils";
1722
1671
  import { useReducer } from "react";
1723
1672
  var { info } = logger("useTableModel");
1724
1673
  var DEFAULT_COLUMN_WIDTH = 100;
1725
- var KEY_OFFSET = metadataKeys8.count;
1674
+ var KEY_OFFSET = metadataKeys7.count;
1726
1675
  var columnWithoutDataType = ({ serverDataType }) => serverDataType === void 0;
1727
1676
  var getCellRendererForColumn = (column) => {
1728
1677
  var _a;
@@ -2015,78 +1964,52 @@ function replaceColumn(state, column) {
2015
1964
  }
2016
1965
 
2017
1966
  // src/useTableScroll.ts
2018
- import { useCallback as useCallback16, useRef as useRef12 } from "react";
1967
+ import { useCallback as useCallback15, useRef as useRef12 } from "react";
2019
1968
  var getPctScroll = (container) => {
2020
1969
  const { scrollLeft, scrollTop } = container;
2021
1970
  const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2022
1971
  const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);
2023
1972
  const pctScrollTop = scrollTop / (scrollHeight - clientHeight);
2024
- return [pctScrollLeft, pctScrollTop, scrollLeft, scrollTop];
1973
+ return [pctScrollLeft, pctScrollTop];
2025
1974
  };
2026
1975
  var getMaxScroll = (container) => {
2027
1976
  const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2028
1977
  return [scrollWidth - clientWidth, scrollHeight - clientHeight];
2029
1978
  };
1979
+ var useCallbackRef = ({
1980
+ onAttach,
1981
+ onDetach
1982
+ }) => {
1983
+ const ref = useRef12(null);
1984
+ const callbackRef = useCallback15(
1985
+ (el) => {
1986
+ if (el) {
1987
+ ref.current = el;
1988
+ onAttach == null ? void 0 : onAttach(el);
1989
+ } else if (ref.current) {
1990
+ const { current: originalRef } = ref;
1991
+ ref.current = el;
1992
+ onDetach == null ? void 0 : onDetach(originalRef);
1993
+ }
1994
+ },
1995
+ [onAttach, onDetach]
1996
+ );
1997
+ return callbackRef;
1998
+ };
2030
1999
  var useTableScroll = ({
2031
2000
  onHorizontalScroll,
2032
2001
  onVerticalScroll,
2033
2002
  viewport
2034
2003
  }) => {
2004
+ const contentContainerScrolledRef = useRef12(false);
2035
2005
  const scrollPosRef = useRef12({ scrollTop: 0, scrollLeft: 0 });
2036
2006
  const scrollbarContainerRef = useRef12(null);
2037
2007
  const contentContainerRef = useRef12(null);
2038
- const tableContainerRef = useRef12(null);
2039
- const contentContainerScrolledRef = useRef12(false);
2040
2008
  const {
2041
2009
  maxScrollContainerScrollHorizontal: maxScrollLeft,
2042
2010
  maxScrollContainerScrollVertical: maxScrollTop
2043
2011
  } = viewport;
2044
- const scrollTable = useCallback16(
2045
- (scrollLeft, scrollTop) => {
2046
- const { current: tableContainer } = tableContainerRef;
2047
- if (tableContainer) {
2048
- tableContainer.scrollTo({
2049
- top: scrollTop,
2050
- left: scrollLeft,
2051
- behavior: "auto"
2052
- });
2053
- }
2054
- },
2055
- [tableContainerRef]
2056
- );
2057
- const handleTableContainerScroll = useCallback16(() => {
2058
- const { current: tableContainer } = tableContainerRef;
2059
- if (tableContainer) {
2060
- const { current: scrollPos } = scrollPosRef;
2061
- const { scrollLeft, scrollTop } = tableContainer;
2062
- if (scrollPos.scrollTop !== scrollTop) {
2063
- scrollPos.scrollTop = scrollTop;
2064
- onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop);
2065
- }
2066
- if (scrollPos.scrollLeft !== scrollLeft) {
2067
- scrollPos.scrollLeft = scrollLeft;
2068
- onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2069
- }
2070
- }
2071
- }, [onHorizontalScroll, onVerticalScroll]);
2072
- const handleContentContainerScroll = useCallback16(() => {
2073
- const { current: rootContainer } = contentContainerRef;
2074
- const { current: scrollContainer } = scrollbarContainerRef;
2075
- if (rootContainer && scrollContainer) {
2076
- const [pctScrollLeft, pctScrollTop, scrollLeft, scrollTop] = getPctScroll(rootContainer);
2077
- contentContainerScrolledRef.current = true;
2078
- scrollContainer.scrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2079
- scrollContainer.scrollTop = Math.round(pctScrollTop * maxScrollTop);
2080
- scrollTable(scrollLeft, scrollTop);
2081
- }
2082
- }, [
2083
- maxScrollLeft,
2084
- maxScrollTop,
2085
- contentContainerRef,
2086
- scrollbarContainerRef,
2087
- scrollTable
2088
- ]);
2089
- const handleScrollbarContainerScroll = useCallback16(() => {
2012
+ const handleScrollbarContainerScroll = useCallback15(() => {
2090
2013
  const { current: contentContainer } = contentContainerRef;
2091
2014
  const { current: scrollbarContainer } = scrollbarContainerRef;
2092
2015
  const { current: contentContainerScrolled } = contentContainerScrolledRef;
@@ -2102,12 +2025,71 @@ var useTableScroll = ({
2102
2025
  top: rootScrollTop,
2103
2026
  behavior: "auto"
2104
2027
  });
2105
- scrollTable(rootScrollLeft, rootScrollTop);
2106
2028
  }
2107
- }, [contentContainerRef, scrollbarContainerRef, scrollTable]);
2108
- const requestScroll = useCallback16(
2029
+ }, []);
2030
+ const handleContentContainerScroll = useCallback15(() => {
2031
+ const { current: contentContainer } = contentContainerRef;
2032
+ const { current: scrollbarContainer } = scrollbarContainerRef;
2033
+ const { current: scrollPos } = scrollPosRef;
2034
+ if (contentContainer && scrollbarContainer) {
2035
+ const { scrollLeft, scrollTop } = contentContainer;
2036
+ const [pctScrollLeft, pctScrollTop] = getPctScroll(contentContainer);
2037
+ contentContainerScrolledRef.current = true;
2038
+ scrollbarContainer.scrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2039
+ scrollbarContainer.scrollTop = Math.round(pctScrollTop * maxScrollTop);
2040
+ if (scrollPos.scrollTop !== scrollTop) {
2041
+ scrollPos.scrollTop = scrollTop;
2042
+ onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop, pctScrollTop);
2043
+ }
2044
+ if (scrollPos.scrollLeft !== scrollLeft) {
2045
+ scrollPos.scrollLeft = scrollLeft;
2046
+ onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2047
+ }
2048
+ }
2049
+ }, [maxScrollLeft, maxScrollTop, onHorizontalScroll, onVerticalScroll]);
2050
+ const handleAttachScrollbarContainer = useCallback15(
2051
+ (el) => {
2052
+ scrollbarContainerRef.current = el;
2053
+ el.addEventListener("scroll", handleScrollbarContainerScroll, {
2054
+ passive: true
2055
+ });
2056
+ },
2057
+ [handleScrollbarContainerScroll]
2058
+ );
2059
+ const handleDetachScrollbarContainer = useCallback15(
2060
+ (el) => {
2061
+ scrollbarContainerRef.current = null;
2062
+ el.removeEventListener("scroll", handleScrollbarContainerScroll);
2063
+ },
2064
+ [handleScrollbarContainerScroll]
2065
+ );
2066
+ const handleAttachContentContainer = useCallback15(
2067
+ (el) => {
2068
+ contentContainerRef.current = el;
2069
+ el.addEventListener("scroll", handleContentContainerScroll, {
2070
+ passive: true
2071
+ });
2072
+ },
2073
+ [handleContentContainerScroll]
2074
+ );
2075
+ const handleDetachContentContainer = useCallback15(
2076
+ (el) => {
2077
+ contentContainerRef.current = null;
2078
+ el.removeEventListener("scroll", handleContentContainerScroll);
2079
+ },
2080
+ [handleContentContainerScroll]
2081
+ );
2082
+ const contentContainerCallbackRef = useCallbackRef({
2083
+ onAttach: handleAttachContentContainer,
2084
+ onDetach: handleDetachContentContainer
2085
+ });
2086
+ const scrollbarContainerCallbackRef = useCallbackRef({
2087
+ onAttach: handleAttachScrollbarContainer,
2088
+ onDetach: handleDetachScrollbarContainer
2089
+ });
2090
+ const requestScroll = useCallback15(
2109
2091
  (scrollRequest) => {
2110
- const { current: scrollbarContainer } = scrollbarContainerRef;
2092
+ const { current: scrollbarContainer } = contentContainerRef;
2111
2093
  if (scrollbarContainer) {
2112
2094
  contentContainerScrolledRef.current = false;
2113
2095
  if (scrollRequest.type === "scroll-page") {
@@ -2116,7 +2098,7 @@ var useTableScroll = ({
2116
2098
  const scrollBy = direction === "down" ? clientHeight : -clientHeight;
2117
2099
  const newScrollTop = Math.min(
2118
2100
  Math.max(0, scrollTop + scrollBy),
2119
- viewport.maxScrollContainerScrollVertical
2101
+ maxScrollTop
2120
2102
  );
2121
2103
  scrollbarContainer.scrollTo({
2122
2104
  top: newScrollTop,
@@ -2125,7 +2107,7 @@ var useTableScroll = ({
2125
2107
  });
2126
2108
  } else if (scrollRequest.type === "scroll-end") {
2127
2109
  const { direction } = scrollRequest;
2128
- const scrollTo = direction === "end" ? viewport.maxScrollContainerScrollVertical : 0;
2110
+ const scrollTo = direction === "end" ? maxScrollTop : 0;
2129
2111
  scrollbarContainer.scrollTo({
2130
2112
  top: scrollTo,
2131
2113
  left: scrollbarContainer.scrollLeft,
@@ -2134,39 +2116,40 @@ var useTableScroll = ({
2134
2116
  }
2135
2117
  }
2136
2118
  },
2137
- [viewport.maxScrollContainerScrollVertical]
2119
+ [maxScrollTop]
2138
2120
  );
2139
2121
  return {
2140
2122
  /** Ref to be assigned to ScrollbarContainer */
2141
- scrollbarContainerRef,
2142
- /** Scroll handler to be attached to ScrollbarContainer */
2143
- onScrollbarContainerScroll: handleScrollbarContainerScroll,
2123
+ scrollbarContainerRef: scrollbarContainerCallbackRef,
2144
2124
  /** Ref to be assigned to ContentContainer */
2145
- contentContainerRef,
2146
- /** Scroll handler to be attached to ContentContainer */
2147
- onContentContainerScroll: handleContentContainerScroll,
2148
- /** Ref to be assigned to TableContainer */
2149
- tableContainerRef,
2150
- /** Scroll handler to be attached to TableContainer */
2151
- onTableContainerScroll: handleTableContainerScroll,
2125
+ contentContainerRef: contentContainerCallbackRef,
2152
2126
  /** Scroll the table */
2153
2127
  requestScroll
2154
2128
  };
2155
2129
  };
2156
2130
 
2157
2131
  // src/useTableViewport.ts
2158
- import { useMemo as useMemo4 } from "react";
2132
+ import { useCallback as useCallback16, useMemo as useMemo4, useRef as useRef13 } from "react";
2133
+ import {
2134
+ actualRowPositioning,
2135
+ virtualRowPositioning
2136
+ } from "@vuu-ui/vuu-utils";
2137
+ var MAX_RAW_ROWS = 15e5;
2159
2138
  var UNMEASURED_VIEWPORT = {
2160
- fillerHeight: 0,
2139
+ contentHeight: 0,
2140
+ contentWidth: 0,
2141
+ getRowAtPosition: () => -1,
2142
+ getRowOffset: () => -1,
2143
+ horizontalScrollbarHeight: 0,
2161
2144
  maxScrollContainerScrollHorizontal: 0,
2162
2145
  maxScrollContainerScrollVertical: 0,
2163
2146
  pinnedWidthLeft: 0,
2164
2147
  pinnedWidthRight: 0,
2165
2148
  rowCount: 0,
2166
- scrollContentHeight: 0,
2167
- scrollbarSize: 0,
2168
- scrollContentWidth: 0,
2169
- totalHeaderHeight: 0
2149
+ setPctScrollTop: () => void 0,
2150
+ totalHeaderHeight: 0,
2151
+ verticalScrollbarWidth: 0,
2152
+ viewportBodyHeight: 0
2170
2153
  };
2171
2154
  var measurePinnedColumns = (columns) => {
2172
2155
  let pinnedWidthLeft = 0;
@@ -2193,66 +2176,101 @@ var useTableViewport = ({
2193
2176
  rowHeight,
2194
2177
  size
2195
2178
  }) => {
2179
+ const pctScrollTopRef = useRef13(0);
2180
+ const appliedRowCount = Math.min(rowCount, MAX_RAW_ROWS);
2181
+ const appliedContentHeight = appliedRowCount * rowHeight;
2182
+ const virtualContentHeight = rowCount * rowHeight;
2183
+ const virtualisedExtent = virtualContentHeight - appliedContentHeight;
2196
2184
  const { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth } = useMemo4(
2197
2185
  () => measurePinnedColumns(columns),
2198
2186
  [columns]
2199
2187
  );
2200
- const viewportMeasurements = useMemo4(() => {
2188
+ const [actualRowOffset, actualRowAtPosition] = useMemo4(
2189
+ () => actualRowPositioning(rowHeight),
2190
+ [rowHeight]
2191
+ );
2192
+ const [getRowOffset, getRowAtPosition] = useMemo4(() => {
2193
+ if (virtualisedExtent) {
2194
+ return virtualRowPositioning(
2195
+ rowHeight,
2196
+ virtualisedExtent,
2197
+ pctScrollTopRef
2198
+ );
2199
+ } else {
2200
+ return [actualRowOffset, actualRowAtPosition];
2201
+ }
2202
+ }, [actualRowAtPosition, actualRowOffset, virtualisedExtent, rowHeight]);
2203
+ const setPctScrollTop = useCallback16((scrollPct) => {
2204
+ pctScrollTopRef.current = scrollPct;
2205
+ }, []);
2206
+ return useMemo4(() => {
2201
2207
  var _a;
2202
2208
  if (size) {
2203
2209
  const headingsDepth = headings.length;
2204
2210
  const scrollbarSize = 15;
2205
- const contentHeight = rowCount * rowHeight;
2206
- const scrollContentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2207
- const maxScrollContainerScrollVertical = contentHeight + headerHeight - (((_a = size == null ? void 0 : size.height) != null ? _a : 0) - headerHeight - scrollbarSize);
2208
- const maxScrollContainerScrollHorizontal = scrollContentWidth - size.width + pinnedWidthLeft;
2211
+ const contentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2212
+ const horizontalScrollbarHeight = contentWidth > size.width ? scrollbarSize : 0;
2213
+ const totalHeaderHeight = headerHeight * (1 + headingsDepth);
2214
+ const maxScrollContainerScrollVertical = appliedContentHeight - (((_a = size == null ? void 0 : size.height) != null ? _a : 0) - horizontalScrollbarHeight) + totalHeaderHeight;
2215
+ const maxScrollContainerScrollHorizontal = contentWidth - size.width + pinnedWidthLeft;
2209
2216
  const visibleRows = (size.height - headerHeight) / rowHeight;
2210
2217
  const count = Number.isInteger(visibleRows) ? visibleRows + 1 : Math.ceil(visibleRows);
2218
+ const viewportBodyHeight = size.height - totalHeaderHeight;
2219
+ const verticalScrollbarWidth = appliedContentHeight > viewportBodyHeight ? scrollbarSize : 0;
2211
2220
  return {
2212
- fillerHeight: (rowCount - count) * rowHeight,
2221
+ contentHeight: appliedContentHeight,
2222
+ getRowAtPosition,
2223
+ getRowOffset,
2224
+ horizontalScrollbarHeight,
2213
2225
  maxScrollContainerScrollHorizontal,
2214
2226
  maxScrollContainerScrollVertical,
2215
2227
  pinnedWidthLeft,
2216
2228
  pinnedWidthRight,
2217
2229
  rowCount: count,
2218
- scrollContentHeight: headerHeight + contentHeight + scrollbarSize,
2219
- scrollbarSize,
2220
- scrollContentWidth,
2221
- totalHeaderHeight: headerHeight * (1 + headingsDepth)
2230
+ contentWidth,
2231
+ setPctScrollTop,
2232
+ totalHeaderHeight,
2233
+ verticalScrollbarWidth,
2234
+ viewportBodyHeight
2222
2235
  };
2223
2236
  } else {
2224
2237
  return UNMEASURED_VIEWPORT;
2225
2238
  }
2226
2239
  }, [
2227
- headerHeight,
2240
+ size,
2228
2241
  headings.length,
2229
2242
  pinnedWidthLeft,
2243
+ unpinnedWidth,
2230
2244
  pinnedWidthRight,
2231
- rowCount,
2245
+ appliedContentHeight,
2246
+ headerHeight,
2232
2247
  rowHeight,
2233
- size,
2234
- unpinnedWidth
2248
+ getRowAtPosition,
2249
+ getRowOffset,
2250
+ setPctScrollTop
2235
2251
  ]);
2236
- return viewportMeasurements;
2237
2252
  };
2238
2253
 
2239
2254
  // src/useVirtualViewport.ts
2240
- import { getColumnsInViewport, itemsChanged } from "@vuu-ui/vuu-utils";
2241
- import { useCallback as useCallback17, useEffect as useEffect4, useMemo as useMemo5, useRef as useRef13, useState as useState5 } from "react";
2255
+ import {
2256
+ getColumnsInViewport,
2257
+ itemsChanged
2258
+ } from "@vuu-ui/vuu-utils";
2259
+ import { useCallback as useCallback17, useEffect as useEffect4, useMemo as useMemo5, useRef as useRef14, useState as useState4 } from "react";
2242
2260
  var useVirtualViewport = ({
2243
2261
  columns,
2244
- rowHeight,
2262
+ getRowAtPosition,
2245
2263
  setRange,
2246
2264
  viewportMeasurements
2247
2265
  }) => {
2248
- const firstRowRef = useRef13(-1);
2266
+ const firstRowRef = useRef14(-1);
2249
2267
  const {
2250
2268
  rowCount: viewportRowCount,
2251
- scrollContentWidth: contentWidth,
2269
+ contentWidth,
2252
2270
  maxScrollContainerScrollHorizontal
2253
2271
  } = viewportMeasurements;
2254
2272
  const availableWidth = contentWidth - maxScrollContainerScrollHorizontal;
2255
- const scrollLeftRef = useRef13(0);
2273
+ const scrollLeftRef = useRef14(0);
2256
2274
  const [visibleColumns, preSpan] = useMemo5(
2257
2275
  () => getColumnsInViewport(
2258
2276
  columns,
@@ -2261,11 +2279,11 @@ var useVirtualViewport = ({
2261
2279
  ),
2262
2280
  [availableWidth, columns]
2263
2281
  );
2264
- const preSpanRef = useRef13(preSpan);
2282
+ const preSpanRef = useRef14(preSpan);
2265
2283
  useEffect4(() => {
2266
2284
  setColumnsWithinViewport(visibleColumns);
2267
2285
  }, [visibleColumns]);
2268
- const [columnsWithinViewport, setColumnsWithinViewport] = useState5(visibleColumns);
2286
+ const [columnsWithinViewport, setColumnsWithinViewport] = useState4(visibleColumns);
2269
2287
  const handleHorizontalScroll = useCallback17(
2270
2288
  (scrollLeft) => {
2271
2289
  scrollLeftRef.current = scrollLeft;
@@ -2283,13 +2301,13 @@ var useVirtualViewport = ({
2283
2301
  );
2284
2302
  const handleVerticalScroll = useCallback17(
2285
2303
  (scrollTop) => {
2286
- const firstRow = Math.floor(scrollTop / rowHeight);
2304
+ const firstRow = getRowAtPosition(scrollTop);
2287
2305
  if (firstRow !== firstRowRef.current) {
2288
2306
  firstRowRef.current = firstRow;
2289
2307
  setRange({ from: firstRow, to: firstRow + viewportRowCount });
2290
2308
  }
2291
2309
  },
2292
- [rowHeight, setRange, viewportRowCount]
2310
+ [getRowAtPosition, setRange, viewportRowCount]
2293
2311
  );
2294
2312
  return {
2295
2313
  columnsWithinViewport,
@@ -2300,10 +2318,10 @@ var useVirtualViewport = ({
2300
2318
  };
2301
2319
  };
2302
2320
 
2303
- // src/useDataTable.ts
2321
+ // src/useTable.ts
2304
2322
  var NO_ROWS = [];
2305
- var { KEY: KEY2, IS_EXPANDED: IS_EXPANDED2, IS_LEAF: IS_LEAF2 } = metadataKeys9;
2306
- var useDataTable = ({
2323
+ var { KEY: KEY2, IS_EXPANDED: IS_EXPANDED2, IS_LEAF: IS_LEAF2 } = metadataKeys8;
2324
+ var useTable = ({
2307
2325
  config,
2308
2326
  dataSource,
2309
2327
  headerHeight,
@@ -2314,13 +2332,12 @@ var useDataTable = ({
2314
2332
  renderBufferSize = 0,
2315
2333
  rowHeight,
2316
2334
  selectionModel,
2317
- tableLayout,
2318
2335
  ...measuredProps
2319
2336
  }) => {
2320
2337
  var _a, _b;
2321
- const [rowCount, setRowCount] = useState6(0);
2322
- const expectConfigChangeRef = useRef14(false);
2323
- const dataSourceRef = useRef14();
2338
+ const [rowCount, setRowCount] = useState5(0);
2339
+ const expectConfigChangeRef = useRef15(false);
2340
+ const dataSourceRef = useRef15();
2324
2341
  dataSourceRef.current = dataSource;
2325
2342
  if (dataSource === void 0) {
2326
2343
  throw Error("no data source provided to DataTable");
@@ -2340,11 +2357,16 @@ var useDataTable = ({
2340
2357
  },
2341
2358
  [dispatchColumnAction]
2342
2359
  );
2343
- const handleContextMenuAction = useContextMenu3({
2360
+ const handleContextMenuAction = useContextMenu({
2344
2361
  dataSource,
2345
2362
  onPersistentColumnOperation: handlePersistentColumnOperation
2346
2363
  });
2347
- const viewportMeasurements = useTableViewport({
2364
+ const {
2365
+ getRowAtPosition,
2366
+ getRowOffset,
2367
+ setPctScrollTop,
2368
+ ...viewportMeasurements
2369
+ } = useTableViewport({
2348
2370
  columns,
2349
2371
  headerHeight,
2350
2372
  headings,
@@ -2386,7 +2408,7 @@ var useDataTable = ({
2386
2408
  renderBufferSize,
2387
2409
  viewportRowCount: viewportMeasurements.rowCount
2388
2410
  });
2389
- const dataRef = useRef14();
2411
+ const dataRef = useRef15();
2390
2412
  dataRef.current = data;
2391
2413
  const handleSort = useCallback18(
2392
2414
  (column, extendSort = false, sortType) => {
@@ -2465,14 +2487,20 @@ var useDataTable = ({
2465
2487
  virtualColSpan
2466
2488
  } = useVirtualViewport({
2467
2489
  columns,
2468
- rowHeight,
2490
+ getRowAtPosition,
2469
2491
  setRange,
2470
2492
  viewportMeasurements
2471
2493
  });
2494
+ const handleVerticalScroll = useCallback18(
2495
+ (scrollTop, pctScrollTop) => {
2496
+ setPctScrollTop(pctScrollTop);
2497
+ onVerticalScroll(scrollTop);
2498
+ },
2499
+ [onVerticalScroll, setPctScrollTop]
2500
+ );
2472
2501
  const { requestScroll, ...scrollProps } = useTableScroll({
2473
2502
  onHorizontalScroll,
2474
- // onRangeChange: setRange,
2475
- onVerticalScroll,
2503
+ onVerticalScroll: handleVerticalScroll,
2476
2504
  viewport: viewportMeasurements,
2477
2505
  viewportHeight: ((_b = (_a = containerMeasurements.innerSize) == null ? void 0 : _a.height) != null ? _b : 0) - headerHeight
2478
2506
  });
@@ -2486,10 +2514,14 @@ var useDataTable = ({
2486
2514
  });
2487
2515
  const handleRemoveColumnFromGroupBy = useCallback18(
2488
2516
  (column) => {
2489
- if (dataSource && dataSource.groupBy.includes(column.name)) {
2490
- dataSource.groupBy = dataSource.groupBy.filter(
2491
- (columnName) => columnName !== column.name
2492
- );
2517
+ if (column) {
2518
+ if (dataSource && dataSource.groupBy.includes(column.name)) {
2519
+ dataSource.groupBy = dataSource.groupBy.filter(
2520
+ (columnName) => columnName !== column.name
2521
+ );
2522
+ }
2523
+ } else {
2524
+ dataSource.groupBy = [];
2493
2525
  }
2494
2526
  },
2495
2527
  [dataSource]
@@ -2506,9 +2538,7 @@ var useDataTable = ({
2506
2538
  [dataSource, dispatchColumnAction]
2507
2539
  );
2508
2540
  const draggableHook = useDraggableColumn({
2509
- onDrop: handleDropColumn,
2510
- tableContainerRef: scrollProps.tableContainerRef,
2511
- tableLayout
2541
+ onDrop: handleDropColumn
2512
2542
  });
2513
2543
  useEffect5(() => {
2514
2544
  if (dataSourceRef.current) {
@@ -2546,11 +2576,11 @@ var useDataTable = ({
2546
2576
  const { current: currentData } = dataRef;
2547
2577
  const { current: currentDataSource } = dataSourceRef;
2548
2578
  const target = evt.target;
2549
- const cellEl = target == null ? void 0 : target.closest("td");
2550
- const rowEl = target == null ? void 0 : target.closest("tr");
2579
+ const cellEl = target == null ? void 0 : target.closest("div[role='cell']");
2580
+ const rowEl = target == null ? void 0 : target.closest(".vuuTableRow");
2551
2581
  if (cellEl && rowEl && currentData && currentDataSource) {
2552
2582
  const { columns: columns2, selectedRowsCount } = currentDataSource;
2553
- const columnMap = buildColumnMap(columns2);
2583
+ const columnMap = buildColumnMap2(columns2);
2554
2584
  const rowIndex = parseInt((_a2 = rowEl.ariaRowIndex) != null ? _a2 : "-1");
2555
2585
  const cellIndex = Array.from(rowEl.childNodes).indexOf(cellEl);
2556
2586
  const row = currentData.find(([idx]) => idx === rowIndex);
@@ -2573,6 +2603,7 @@ var useDataTable = ({
2573
2603
  columnsWithinViewport,
2574
2604
  data,
2575
2605
  dispatchColumnAction,
2606
+ getRowOffset,
2576
2607
  handleContextMenuAction,
2577
2608
  headings,
2578
2609
  onColumnResize: handleColumnResize,
@@ -2590,10 +2621,10 @@ var useDataTable = ({
2590
2621
  };
2591
2622
 
2592
2623
  // src/Table.tsx
2593
- import cx8 from "classnames";
2624
+ import cx7 from "classnames";
2594
2625
  import { isDataLoading } from "@vuu-ui/vuu-utils";
2595
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2596
- var classBase7 = "vuuTable";
2626
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2627
+ var classBase6 = "vuuTable";
2597
2628
  var Table = ({
2598
2629
  allowConfigEditing: showSettings = false,
2599
2630
  className: classNameProp,
@@ -2611,7 +2642,6 @@ var Table = ({
2611
2642
  rowHeight = 20,
2612
2643
  selectionModel = "extended",
2613
2644
  style: styleProp,
2614
- tableLayout: tableLayoutProp = "row",
2615
2645
  width,
2616
2646
  zebraStripes = false,
2617
2647
  ...props
@@ -2625,10 +2655,9 @@ var Table = ({
2625
2655
  draggedItemIndex,
2626
2656
  handleContextMenuAction,
2627
2657
  scrollProps,
2628
- tableLayout,
2629
2658
  viewportMeasurements,
2630
2659
  ...tableProps
2631
- } = useDataTable({
2660
+ } = useTable({
2632
2661
  config,
2633
2662
  dataSource,
2634
2663
  renderBufferSize,
@@ -2640,43 +2669,36 @@ var Table = ({
2640
2669
  onSelectionChange,
2641
2670
  rowHeight,
2642
2671
  selectionModel,
2643
- tableLayout: tableLayoutProp,
2644
2672
  width
2645
2673
  });
2646
2674
  const style = {
2647
2675
  ...outerSize,
2648
- "--content-height": `${viewportMeasurements.scrollContentHeight}px`,
2649
- "--content-width": `${viewportMeasurements.scrollContentWidth}px`,
2650
- "--filler-height": `${viewportMeasurements.fillerHeight}px`,
2676
+ "--content-height": `${viewportMeasurements.contentHeight}px`,
2677
+ "--horizontal-scrollbar-height": `${viewportMeasurements.horizontalScrollbarHeight}px`,
2678
+ "--content-width": `${viewportMeasurements.contentWidth}px`,
2651
2679
  "--pinned-width-left": `${viewportMeasurements.pinnedWidthLeft}px`,
2652
2680
  "--pinned-width-right": `${viewportMeasurements.pinnedWidthRight}px`,
2653
2681
  "--header-height": `${headerHeight}px`,
2654
2682
  "--row-height": `${rowHeight}px`,
2655
- "--scrollbar-size": `${viewportMeasurements.scrollbarSize}px`,
2656
2683
  "--table-height": `${innerSize == null ? void 0 : innerSize.height}px`,
2657
2684
  "--table-width": `${innerSize == null ? void 0 : innerSize.width}px`,
2658
- "--total-header-height": `${viewportMeasurements == null ? void 0 : viewportMeasurements.totalHeaderHeight}px`
2685
+ "--total-header-height": `${viewportMeasurements.totalHeaderHeight}px`,
2686
+ "--vertical-scrollbar-width": `${viewportMeasurements.verticalScrollbarWidth}px`,
2687
+ "--viewport-body-height": `${viewportMeasurements.viewportBodyHeight}px`
2659
2688
  };
2660
- const scrollbarContainerStyle = {
2661
- left: viewportMeasurements.pinnedWidthLeft - 1,
2662
- // The -1 is to align the top border, might cause innaccuracy
2663
- // It is compensated by a hardcoded adjustment in css
2664
- // top: measurements.top - 1 + headerHeight,
2665
- top: (viewportMeasurements == null ? void 0 : viewportMeasurements.totalHeaderHeight) - 1
2666
- };
2667
- const Table2 = tableLayout === "column" ? ColumnBasedTable : RowBasedTable;
2668
- const className = cx8(classBase7, classNameProp, {
2669
- [`${classBase7}-zebra`]: zebraStripes,
2670
- [`${classBase7}-loading`]: isDataLoading(tableProps.columns)
2689
+ const className = cx7(classBase6, classNameProp, {
2690
+ [`${classBase6}-zebra`]: zebraStripes,
2691
+ [`${classBase6}-loading`]: isDataLoading(tableProps.columns)
2671
2692
  });
2672
- return /* @__PURE__ */ jsx11(
2693
+ return /* @__PURE__ */ jsx10(
2673
2694
  ContextMenuProvider,
2674
2695
  {
2675
2696
  menuActionHandler: handleContextMenuAction,
2676
2697
  menuBuilder: buildContextMenuDescriptors(dataSource),
2677
- children: /* @__PURE__ */ jsxs8(
2698
+ children: /* @__PURE__ */ jsxs7(
2678
2699
  "div",
2679
2700
  {
2701
+ ...props,
2680
2702
  ...containerProps,
2681
2703
  className,
2682
2704
  id,
@@ -2684,49 +2706,36 @@ var Table = ({
2684
2706
  style,
2685
2707
  tabIndex: -1,
2686
2708
  children: [
2687
- innerSize ? /* @__PURE__ */ jsx11(
2709
+ innerSize ? /* @__PURE__ */ jsx10(
2688
2710
  "div",
2689
2711
  {
2690
- className: `${classBase7}-scrollbarContainer`,
2691
- onScroll: scrollProps.onScrollbarContainerScroll,
2712
+ className: `${classBase6}-scrollbarContainer`,
2692
2713
  ref: scrollProps.scrollbarContainerRef,
2693
- style: scrollbarContainerStyle,
2694
- children: /* @__PURE__ */ jsx11("div", { className: `${classBase7}-scrollContent` })
2714
+ children: /* @__PURE__ */ jsx10("div", { className: `${classBase6}-scrollbarContent` })
2695
2715
  }
2696
2716
  ) : null,
2697
- innerSize ? /* @__PURE__ */ jsxs8(
2717
+ innerSize ? /* @__PURE__ */ jsxs7(
2698
2718
  "div",
2699
2719
  {
2700
- className: `${classBase7}-contentContainer`,
2701
- onScroll: scrollProps.onContentContainerScroll,
2720
+ className: `${classBase6}-contentContainer`,
2702
2721
  ref: scrollProps.contentContainerRef,
2703
- ...props,
2704
2722
  children: [
2705
- /* @__PURE__ */ jsx11("div", { className: `${classBase7}-scrollContent` }),
2706
- /* @__PURE__ */ jsx11(
2707
- "div",
2723
+ /* @__PURE__ */ jsx10(
2724
+ RowBasedTable,
2708
2725
  {
2709
- className: `${classBase7}-tableContainer`,
2710
- onScroll: scrollProps.onTableContainerScroll,
2711
- ref: scrollProps.tableContainerRef,
2712
- children: /* @__PURE__ */ jsx11(
2713
- Table2,
2714
- {
2715
- ...tableProps,
2716
- headerHeight,
2717
- rowHeight
2718
- }
2719
- )
2726
+ ...tableProps,
2727
+ headerHeight,
2728
+ tableId: id
2720
2729
  }
2721
2730
  ),
2722
2731
  draggable
2723
2732
  ]
2724
2733
  }
2725
2734
  ) : null,
2726
- showSettings && innerSize ? /* @__PURE__ */ jsx11(
2735
+ showSettings && innerSize ? /* @__PURE__ */ jsx10(
2727
2736
  Button,
2728
2737
  {
2729
- className: `${classBase7}-settings`,
2738
+ className: `${classBase6}-settings`,
2730
2739
  "data-icon": "settings",
2731
2740
  onClick: onShowSettings,
2732
2741
  variant: "secondary"
@@ -2740,15 +2749,15 @@ var Table = ({
2740
2749
  };
2741
2750
 
2742
2751
  // src/cell-renderers/json-cell/JsonCell.tsx
2743
- import cx9 from "classnames";
2752
+ import cx8 from "classnames";
2744
2753
  import {
2745
2754
  isJsonAttribute,
2746
- metadataKeys as metadataKeys10,
2755
+ metadataKeys as metadataKeys9,
2747
2756
  registerComponent
2748
2757
  } from "@vuu-ui/vuu-utils";
2749
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2750
- var classBase8 = "vuuJsonCell";
2751
- var { IS_EXPANDED: IS_EXPANDED3, KEY: KEY3 } = metadataKeys10;
2758
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2759
+ var classBase7 = "vuuJsonCell";
2760
+ var { IS_EXPANDED: IS_EXPANDED3, KEY: KEY3 } = metadataKeys9;
2752
2761
  var localKey = (key) => {
2753
2762
  const pos = key.lastIndexOf("|");
2754
2763
  if (pos === -1) {
@@ -2769,19 +2778,19 @@ var JsonCell = ({ column, row }) => {
2769
2778
  isToggle = true;
2770
2779
  }
2771
2780
  const rowKey = localKey(row[KEY3]);
2772
- const className = cx9({
2773
- [`${classBase8}-name`]: rowKey === value,
2774
- [`${classBase8}-value`]: rowKey !== value,
2775
- [`${classBase8}-group`]: isToggle
2781
+ const className = cx8({
2782
+ [`${classBase7}-name`]: rowKey === value,
2783
+ [`${classBase7}-value`]: rowKey !== value,
2784
+ [`${classBase7}-group`]: isToggle
2776
2785
  });
2777
2786
  if (isToggle) {
2778
2787
  const toggleIcon = row[IS_EXPANDED3] ? "minus-box" : "plus-box";
2779
- return /* @__PURE__ */ jsxs9("span", { className, children: [
2780
- /* @__PURE__ */ jsx12("span", { className: `${classBase8}-value`, children: value }),
2781
- /* @__PURE__ */ jsx12("span", { className: `${classBase8}-toggle`, "data-icon": toggleIcon })
2788
+ return /* @__PURE__ */ jsxs8("span", { className, children: [
2789
+ /* @__PURE__ */ jsx11("span", { className: `${classBase7}-value`, children: value }),
2790
+ /* @__PURE__ */ jsx11("span", { className: `${classBase7}-toggle`, "data-icon": toggleIcon })
2782
2791
  ] });
2783
2792
  } else if (value) {
2784
- return /* @__PURE__ */ jsx12("span", { className, children: value });
2793
+ return /* @__PURE__ */ jsx11("span", { className, children: value });
2785
2794
  } else {
2786
2795
  return null;
2787
2796
  }