@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/cjs/index.js CHANGED
@@ -39,498 +39,8 @@ module.exports = __toCommonJS(src_exports);
39
39
  var import_vuu_popups4 = require("@vuu-ui/vuu-popups");
40
40
  var import_core = require("@salt-ds/core");
41
41
 
42
- // src/ColumnBasedTable.tsx
43
- var import_vuu_utils4 = require("@vuu-ui/vuu-utils");
44
- var import_react8 = require("react");
45
- var import_classnames6 = __toESM(require("classnames"));
46
-
47
- // src/TableRow.tsx
48
- var import_vuu_utils3 = require("@vuu-ui/vuu-utils");
49
- var import_classnames2 = __toESM(require("classnames"));
50
- var import_react3 = require("react");
51
-
52
- // src/TableCell.tsx
53
- var import_vuu_utils = require("@vuu-ui/vuu-utils");
54
- var import_salt_lab = require("@heswell/salt-lab");
55
- var import_classnames = __toESM(require("classnames"));
56
- var import_react = require("react");
57
- var import_jsx_runtime = require("react/jsx-runtime");
58
- var { KEY } = import_vuu_utils.metadataKeys;
59
- var TableCell = (0, import_react.memo)(
60
- ({ className: classNameProp, column, onClick, row }) => {
61
- const labelFieldRef = (0, import_react.useRef)(null);
62
- const {
63
- align,
64
- CellRenderer,
65
- key,
66
- pin,
67
- editable,
68
- resizing,
69
- valueFormatter
70
- } = column;
71
- const [editing, setEditing] = (0, import_react.useState)(false);
72
- const value = valueFormatter(row[key]);
73
- const [editableValue, setEditableValue] = (0, import_react.useState)(value);
74
- const handleTitleMouseDown = () => {
75
- var _a;
76
- (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
77
- };
78
- const handleTitleKeyDown = (evt) => {
79
- if (evt.key === "Enter") {
80
- setEditing(true);
81
- }
82
- };
83
- const handleClick = (0, import_react.useCallback)(() => {
84
- onClick == null ? void 0 : onClick(column);
85
- }, [column, onClick]);
86
- const handleEnterEditMode = () => {
87
- setEditing(true);
88
- };
89
- const handleExitEditMode = (originalValue = "", finalValue = "", allowDeactivation = true, editCancelled = false) => {
90
- var _a;
91
- setEditing(false);
92
- if (editCancelled) {
93
- setEditableValue(originalValue);
94
- } else if (finalValue !== originalValue) {
95
- setEditableValue(finalValue);
96
- }
97
- if (allowDeactivation === false) {
98
- (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
99
- }
100
- };
101
- const className = (0, import_classnames.default)(classNameProp, {
102
- vuuAlignRight: align === "right",
103
- vuuPinFloating: pin === "floating",
104
- vuuPinLeft: pin === "left",
105
- vuuPinRight: pin === "right",
106
- "vuuTableCell-resizing": resizing
107
- }) || void 0;
108
- const pinnedStyle = (0, import_vuu_utils.getColumnPinStyle)(column);
109
- return editable ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
110
- "td",
111
- {
112
- className,
113
- "data-editable": true,
114
- style: pinnedStyle,
115
- onKeyDown: handleTitleKeyDown,
116
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
117
- import_salt_lab.EditableLabel,
118
- {
119
- editing,
120
- value: editableValue,
121
- onChange: setEditableValue,
122
- onMouseDownCapture: handleTitleMouseDown,
123
- onEnterEditMode: handleEnterEditMode,
124
- onExitEditMode: handleExitEditMode,
125
- onKeyDown: handleTitleKeyDown,
126
- ref: labelFieldRef,
127
- tabIndex: 0
128
- },
129
- "title"
130
- )
131
- }
132
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className, style: pinnedStyle, onClick: handleClick, children: CellRenderer ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CellRenderer, { column, row }) : value });
133
- },
134
- cellValuesAreEqual
135
- );
136
- TableCell.displayName = "TableCell";
137
- function cellValuesAreEqual(prev, next) {
138
- 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];
139
- }
140
-
141
- // src/TableGroupCell.tsx
142
- var import_vuu_utils2 = require("@vuu-ui/vuu-utils");
143
- var import_react2 = require("react");
144
- var import_jsx_runtime2 = require("react/jsx-runtime");
145
- var { DEPTH, IS_LEAF } = import_vuu_utils2.metadataKeys;
146
- var getGroupValueAndOffset = (columns, row) => {
147
- const { [DEPTH]: depth, [IS_LEAF]: isLeaf } = row;
148
- if (isLeaf || depth > columns.length) {
149
- return [null, depth === null ? 0 : depth - 1];
150
- } else if (depth === 0) {
151
- return ["$root", 0];
152
- } else {
153
- const { key, valueFormatter } = columns[depth - 1];
154
- const value = valueFormatter(row[key]);
155
- return [value, depth - 1];
156
- }
157
- };
158
- var TableGroupCell = ({ column, onClick, row }) => {
159
- const { columns } = column;
160
- const [value, offset] = getGroupValueAndOffset(columns, row);
161
- const handleClick = (0, import_react2.useCallback)(() => {
162
- onClick == null ? void 0 : onClick(column);
163
- }, [column, onClick]);
164
- const style = {
165
- left: column.pin == "left" ? column.pinnedOffset : void 0
166
- };
167
- const isLeaf = row[IS_LEAF];
168
- const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vuuTableGroupCell-spacer" }, i));
169
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
170
- "td",
171
- {
172
- className: "vuuTableGroupCell vuuPinLeft",
173
- onClick: isLeaf ? void 0 : handleClick,
174
- style,
175
- children: [
176
- spacers,
177
- isLeaf ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vuuTableGroupCell-toggle", "data-icon": "triangle-right" }),
178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: value })
179
- ]
180
- }
181
- );
182
- };
183
-
184
- // src/TableRow.tsx
185
- var import_jsx_runtime3 = require("react/jsx-runtime");
186
- var { IDX, IS_EXPANDED, SELECTED } = import_vuu_utils3.metadataKeys;
187
- var classBase = "vuuTableRow";
188
- var TableRow = (0, import_react3.memo)(function Row({
189
- columns,
190
- height,
191
- index,
192
- onClick,
193
- onToggleGroup,
194
- virtualColSpan = 0,
195
- row
196
- }) {
197
- const {
198
- [IDX]: rowIndex,
199
- [IS_EXPANDED]: isExpanded,
200
- [SELECTED]: isSelected
201
- } = row;
202
- const className = (0, import_classnames2.default)(classBase, {
203
- [`${classBase}-even`]: rowIndex % 2 === 0,
204
- [`${classBase}-expanded`]: isExpanded,
205
- [`${classBase}-preSelected`]: isSelected === 2
206
- });
207
- const offset = rowIndex - index;
208
- const handleRowClick = (0, import_react3.useCallback)(
209
- (evt) => {
210
- const rangeSelect = evt.shiftKey;
211
- const keepExistingSelection = evt.ctrlKey || evt.metaKey;
212
- onClick == null ? void 0 : onClick(row, rangeSelect, keepExistingSelection);
213
- },
214
- [onClick, row]
215
- );
216
- const handleGroupCellClick = (0, import_react3.useCallback)(
217
- (column) => {
218
- if ((0, import_vuu_utils3.isGroupColumn)(column) || (0, import_vuu_utils3.isJsonGroup)(column, row)) {
219
- onToggleGroup == null ? void 0 : onToggleGroup(row, column);
220
- }
221
- },
222
- [onToggleGroup, row]
223
- );
224
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
225
- "tr",
226
- {
227
- "aria-selected": isSelected === 1 ? true : void 0,
228
- "aria-rowindex": rowIndex,
229
- className,
230
- onClick: handleRowClick,
231
- style: {
232
- transform: `translate(0px, ${offset * height}px)`
233
- },
234
- children: [
235
- virtualColSpan > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { colSpan: virtualColSpan }) : null,
236
- columns.filter(import_vuu_utils3.notHidden).map((column) => {
237
- const isGroup = (0, import_vuu_utils3.isGroupColumn)(column);
238
- const isJsonCell = (0, import_vuu_utils3.isJsonColumn)(column);
239
- const Cell = isGroup ? TableGroupCell : TableCell;
240
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
241
- Cell,
242
- {
243
- column,
244
- onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
245
- row
246
- },
247
- column.name
248
- );
249
- })
250
- ]
251
- }
252
- );
253
- });
254
-
255
- // src/TableHeaderCell.tsx
256
- var import_classnames5 = __toESM(require("classnames"));
257
- var import_react7 = require("react");
258
-
259
- // src/ColumnResizer.tsx
260
- var import_react4 = require("react");
261
- var import_jsx_runtime4 = require("react/jsx-runtime");
262
- var NOOP = () => void 0;
263
- var baseClass = "vuuColumnResizer";
264
- var ColumnResizer = ({
265
- onDrag,
266
- onDragEnd = NOOP,
267
- onDragStart = NOOP
268
- }) => {
269
- const position = (0, import_react4.useRef)(0);
270
- const onMouseMove = (0, import_react4.useCallback)(
271
- (e) => {
272
- if (e.stopPropagation) {
273
- e.stopPropagation();
274
- }
275
- if (e.preventDefault) {
276
- e.preventDefault();
277
- }
278
- const x = Math.round(e.clientX);
279
- const moveBy = x - position.current;
280
- position.current = x;
281
- if (moveBy !== 0) {
282
- onDrag(e, moveBy);
283
- }
284
- },
285
- [onDrag]
286
- );
287
- const onMouseUp = (0, import_react4.useCallback)(
288
- (e) => {
289
- window.removeEventListener("mouseup", onMouseUp);
290
- window.removeEventListener("mousemove", onMouseMove);
291
- onDragEnd(e);
292
- },
293
- [onDragEnd, onMouseMove]
294
- );
295
- const handleMouseDown = (0, import_react4.useCallback)(
296
- (e) => {
297
- onDragStart(e);
298
- position.current = Math.round(e.clientX);
299
- window.addEventListener("mouseup", onMouseUp);
300
- window.addEventListener("mousemove", onMouseMove);
301
- if (e.stopPropagation) {
302
- e.stopPropagation();
303
- }
304
- if (e.preventDefault) {
305
- e.preventDefault();
306
- }
307
- },
308
- [onDragStart, onMouseMove, onMouseUp]
309
- );
310
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: baseClass, onMouseDown: handleMouseDown });
311
- };
312
-
313
- // src/SortIndicator.tsx
314
- var import_classnames3 = __toESM(require("classnames"));
315
- var import_jsx_runtime5 = require("react/jsx-runtime");
316
- var classBase2 = "vuuSortIndicator";
317
- var SortIndicator = ({ sorted }) => {
318
- if (!sorted) {
319
- return null;
320
- }
321
- const direction = typeof sorted === "number" ? sorted < 0 ? "dsc" : "asc" : sorted === "A" ? "asc" : "dsc";
322
- return typeof sorted === "number" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: (0, import_classnames3.default)(classBase2, "multi-col", direction), children: [
323
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "data-icon": `sorted-${direction}` }),
324
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vuuSortPosition", children: Math.abs(sorted) })
325
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: (0, import_classnames3.default)(classBase2, "single-col"), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "data-icon": `sorted-${direction}` }) });
326
- };
327
-
328
- // src/useTableColumnResize.tsx
329
- var import_react5 = require("react");
330
- var useTableColumnResize = ({
331
- column,
332
- onResize,
333
- rootRef
334
- }) => {
335
- const widthRef = (0, import_react5.useRef)(0);
336
- const isResizing = (0, import_react5.useRef)(false);
337
- const { name } = column;
338
- const handleResizeStart = (0, import_react5.useCallback)(() => {
339
- if (onResize && rootRef.current) {
340
- const { width } = rootRef.current.getBoundingClientRect();
341
- widthRef.current = Math.round(width);
342
- isResizing.current = true;
343
- onResize == null ? void 0 : onResize("begin", name);
344
- }
345
- }, [name, onResize, rootRef]);
346
- const handleResize = (0, import_react5.useCallback)(
347
- (_evt, moveBy) => {
348
- if (rootRef.current) {
349
- if (onResize) {
350
- const { width } = rootRef.current.getBoundingClientRect();
351
- const newWidth = Math.round(width) + moveBy;
352
- if (newWidth !== widthRef.current && newWidth > 0) {
353
- onResize("resize", name, newWidth);
354
- widthRef.current = newWidth;
355
- }
356
- }
357
- }
358
- },
359
- [name, onResize, rootRef]
360
- );
361
- const handleResizeEnd = (0, import_react5.useCallback)(() => {
362
- if (onResize) {
363
- onResize("end", name, widthRef.current);
364
- setTimeout(() => {
365
- isResizing.current = false;
366
- }, 100);
367
- }
368
- }, [name, onResize]);
369
- return {
370
- isResizing: isResizing.current,
371
- onDrag: handleResize,
372
- onDragStart: handleResizeStart,
373
- onDragEnd: handleResizeEnd
374
- };
375
- };
376
-
377
- // src/TableHeaderCell.tsx
378
- var import_vuu_popups2 = require("@vuu-ui/vuu-popups");
379
-
380
- // src/filter-indicator.tsx
381
- var import_vuu_popups = require("@vuu-ui/vuu-popups");
382
- var import_classnames4 = __toESM(require("classnames"));
383
- var import_react6 = require("react");
384
- var import_jsx_runtime6 = require("react/jsx-runtime");
385
- var FilterIndicator = ({ column, filter }) => {
386
- const showContextMenu = (0, import_vuu_popups.useContextMenu)();
387
- const handleClick = (0, import_react6.useCallback)(
388
- (evt) => {
389
- evt.stopPropagation();
390
- showContextMenu(evt, "filter", { column, filter });
391
- },
392
- [column, filter, showContextMenu]
393
- );
394
- if (!column.filter) {
395
- return null;
396
- }
397
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
398
- "div",
399
- {
400
- className: (0, import_classnames4.default)("vuuFilterIndicator"),
401
- "data-icon": "filter",
402
- onClick: handleClick
403
- }
404
- );
405
- };
406
-
407
- // src/TableHeaderCell.tsx
408
- var import_jsx_runtime7 = require("react/jsx-runtime");
409
- var classBase3 = "vuuTable-headerCell";
410
- var TableHeaderCell = ({
411
- column,
412
- className: classNameProp,
413
- onClick,
414
- onDragStart,
415
- onResize,
416
- ...props
417
- }) => {
418
- const rootRef = (0, import_react7.useRef)(null);
419
- const { isResizing, ...resizeProps } = useTableColumnResize({
420
- column,
421
- onResize,
422
- rootRef
423
- });
424
- const showContextMenu = (0, import_vuu_popups2.useContextMenu)();
425
- const dragTimerRef = (0, import_react7.useRef)(null);
426
- const handleContextMenu = (e) => {
427
- showContextMenu(e, "header", { column });
428
- };
429
- const handleClick = (0, import_react7.useCallback)(
430
- (evt) => !isResizing && (onClick == null ? void 0 : onClick(evt)),
431
- [isResizing, onClick]
432
- );
433
- const handleMouseDown = (0, import_react7.useCallback)(
434
- (evt) => {
435
- dragTimerRef.current = window.setTimeout(() => {
436
- onDragStart == null ? void 0 : onDragStart(evt);
437
- dragTimerRef.current = null;
438
- }, 250);
439
- },
440
- [onDragStart]
441
- );
442
- const handleMouseUp = (0, import_react7.useCallback)(() => {
443
- if (dragTimerRef.current !== null) {
444
- window.clearTimeout(dragTimerRef.current);
445
- dragTimerRef.current = null;
446
- }
447
- }, []);
448
- const className = (0, import_classnames5.default)(classBase3, classNameProp, {
449
- vuuPinFloating: column.pin === "floating",
450
- vuuPinLeft: column.pin === "left",
451
- vuuPinRight: column.pin === "right",
452
- vuuEndPin: column.endPin,
453
- [`${classBase3}-resizing`]: column.resizing,
454
- [`${classBase3}-right`]: column.align === "right"
455
- });
456
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
457
- "th",
458
- {
459
- className,
460
- ...props,
461
- onClick: handleClick,
462
- onContextMenu: handleContextMenu,
463
- onMouseDown: handleMouseDown,
464
- onMouseUp: handleMouseUp,
465
- ref: rootRef,
466
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `${classBase3}-inner`, children: [
467
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FilterIndicator, { column }),
468
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `${classBase3}-label`, children: column.label }),
469
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SortIndicator, { sorted: column.sorted }),
470
- column.resizeable !== false ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ColumnResizer, { ...resizeProps }) : null
471
- ] })
472
- }
473
- );
474
- };
475
-
476
- // src/ColumnBasedTable.tsx
477
- var import_jsx_runtime8 = require("react/jsx-runtime");
478
- var classBase4 = "vuuTable";
479
- var { RENDER_IDX } = import_vuu_utils4.metadataKeys;
480
- var ColumnBasedTable = ({
481
- columns,
482
- data,
483
- headerHeight,
484
- onHeaderCellDragEnd,
485
- rowHeight
486
- }) => {
487
- const handleDragEnd = (0, import_react8.useCallback)(() => {
488
- onHeaderCellDragEnd == null ? void 0 : onHeaderCellDragEnd();
489
- }, [onHeaderCellDragEnd]);
490
- console.log(`ColumnBasedTable render`);
491
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: columns.map((column, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
492
- "table",
493
- {
494
- className: (0, import_classnames6.default)(`${classBase4}-table`, `${classBase4}-columnBased`, {
495
- vuuPinLeft: column.pin === "left"
496
- }),
497
- "data-idx": i,
498
- id: `col-${i}`,
499
- style: {
500
- width: column.width,
501
- left: column.pinnedOffset,
502
- "--vuuTableHeaderHeight": `${headerHeight}px`,
503
- "--row-height": `${rowHeight}px`
504
- },
505
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tbody", { children: [
506
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
507
- TableHeaderCell,
508
- {
509
- column,
510
- "data-idx": i,
511
- onDragEnd: handleDragEnd
512
- },
513
- i
514
- ) }, "header"),
515
- data.map((row, j) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
516
- TableRow,
517
- {
518
- columns: [column],
519
- height: rowHeight,
520
- index: j,
521
- row
522
- },
523
- row[RENDER_IDX]
524
- )),
525
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { className: "vuuTable-filler" })
526
- ] })
527
- },
528
- column.name
529
- )) });
530
- };
531
-
532
42
  // src/context-menu/buildContextMenuDescriptors.ts
533
- var import_vuu_utils5 = require("@vuu-ui/vuu-utils");
43
+ var import_vuu_utils = require("@vuu-ui/vuu-utils");
534
44
  var buildContextMenuDescriptors = (dataSource) => (location, options) => {
535
45
  const descriptors = [];
536
46
  if (dataSource === void 0) {
@@ -634,210 +144,547 @@ function buildSortMenuItems(options, { sort: { sortDefs } }) {
634
144
  });
635
145
  } else {
636
146
  menuItems.push({
637
- label: "Sort",
638
- children: [
639
- { label: "Ascending", action: "sort-asc", options },
640
- { label: "Descending", action: "sort-dsc", options }
641
- ]
147
+ label: "Sort",
148
+ children: [
149
+ { label: "Ascending", action: "sort-asc", options },
150
+ { label: "Descending", action: "sort-dsc", options }
151
+ ]
152
+ });
153
+ }
154
+ return menuItems;
155
+ }
156
+ function buildAggregationMenuItems(options, dataSource) {
157
+ const { column } = options;
158
+ if (column === void 0 || dataSource.groupBy.length === 0) {
159
+ return [];
160
+ }
161
+ const { name, label = name } = column;
162
+ return [
163
+ {
164
+ label: `Aggregate ${label}`,
165
+ children: [{ label: "Count", action: "agg-count", options }].concat(
166
+ (0, import_vuu_utils.isNumericColumn)(column) ? [
167
+ { label: "Sum", action: "agg-sum", options },
168
+ { label: "Avg", action: "agg-avg", options },
169
+ { label: "High", action: "agg-high", options },
170
+ { label: "Low", action: "agg-low", options }
171
+ ] : []
172
+ )
173
+ }
174
+ ];
175
+ }
176
+ var pinColumn = (options, pinLocation) => ({
177
+ label: `Pin ${pinLocation}`,
178
+ action: `column-pin-${pinLocation}`,
179
+ options
180
+ });
181
+ var pinLeft = (options) => pinColumn(options, "left");
182
+ var pinFloating = (options) => pinColumn(options, "floating");
183
+ var pinRight = (options) => pinColumn(options, "right");
184
+ function buildColumnDisplayMenuItems(options) {
185
+ const { column } = options;
186
+ if (column === void 0) {
187
+ return [];
188
+ }
189
+ const { pin } = column;
190
+ const menuItems = [
191
+ {
192
+ label: `Hide column`,
193
+ action: "column-hide",
194
+ options
195
+ },
196
+ {
197
+ label: `Remove column`,
198
+ action: "column-remove",
199
+ options
200
+ }
201
+ ];
202
+ if (pin === void 0) {
203
+ menuItems.push({
204
+ label: `Pin column`,
205
+ children: [pinLeft(options), pinFloating(options), pinRight(options)]
206
+ });
207
+ } else if (pin === "left") {
208
+ menuItems.push(
209
+ { label: "Unpin column", action: "column-unpin", options },
210
+ {
211
+ label: `Pin column`,
212
+ children: [pinFloating(options), pinRight(options)]
213
+ }
214
+ );
215
+ } else if (pin === "right") {
216
+ menuItems.push(
217
+ { label: "Unpin column", action: "column-unpin", options },
218
+ {
219
+ label: `Pin column`,
220
+ children: [pinLeft(options), pinFloating(options)]
221
+ }
222
+ );
223
+ } else if (pin === "floating") {
224
+ menuItems.push(
225
+ { label: "Unpin column", action: "column-unpin", options },
226
+ {
227
+ label: `Pin column`,
228
+ children: [pinLeft(options), pinRight(options)]
229
+ }
230
+ );
231
+ }
232
+ return menuItems;
233
+ }
234
+ function buildGroupMenuItems(options, { groupBy }) {
235
+ const { column } = options;
236
+ const menuItems = [];
237
+ if (column === void 0) {
238
+ return menuItems;
239
+ }
240
+ const { name, label = name } = column;
241
+ if (groupBy.length === 0) {
242
+ menuItems.push({
243
+ label: `Group by ${label}`,
244
+ action: "group",
245
+ options
246
+ });
247
+ } else {
248
+ menuItems.push({
249
+ label: `Add ${label} to group by`,
250
+ action: "group-add",
251
+ options
642
252
  });
643
253
  }
644
254
  return menuItems;
645
255
  }
646
- function buildAggregationMenuItems(options, dataSource) {
647
- const { column } = options;
648
- if (column === void 0 || dataSource.groupBy.length === 0) {
649
- return [];
256
+
257
+ // src/context-menu/useContextMenu.ts
258
+ var import_vuu_filters = require("@vuu-ui/vuu-filters");
259
+ var import_vuu_utils2 = require("@vuu-ui/vuu-utils");
260
+ var removeFilterColumn = (dataSourceFilter, column) => {
261
+ if (dataSourceFilter.filterStruct && column) {
262
+ const [filterStruct, filter] = (0, import_vuu_filters.removeColumnFromFilter)(
263
+ column,
264
+ dataSourceFilter.filterStruct
265
+ );
266
+ return {
267
+ filter,
268
+ filterStruct
269
+ };
270
+ } else {
271
+ return dataSourceFilter;
650
272
  }
651
- const { name, label = name } = column;
652
- return [
653
- {
654
- label: `Aggregate ${label}`,
655
- children: [{ label: "Count", action: "agg-count", options }].concat(
656
- (0, import_vuu_utils5.isNumericColumn)(column) ? [
657
- { label: "Sum", action: "agg-sum", options },
658
- { label: "Avg", action: "agg-avg", options },
659
- { label: "High", action: "agg-high", options },
660
- { label: "Low", action: "agg-low", options }
661
- ] : []
662
- )
273
+ };
274
+ var { Average, Count, High, Low, Sum } = import_vuu_utils2.AggregationType;
275
+ var useContextMenu = ({
276
+ dataSource,
277
+ onPersistentColumnOperation
278
+ }) => {
279
+ const handleContextMenuAction = (type, options) => {
280
+ const gridOptions = options;
281
+ if (gridOptions.column && dataSource) {
282
+ const { column } = gridOptions;
283
+ switch (type) {
284
+ case "sort-asc":
285
+ return dataSource.sort = (0, import_vuu_utils2.setSortColumn)(dataSource.sort, column, "A"), true;
286
+ case "sort-dsc":
287
+ return dataSource.sort = (0, import_vuu_utils2.setSortColumn)(dataSource.sort, column, "D"), true;
288
+ case "sort-add-asc":
289
+ return dataSource.sort = (0, import_vuu_utils2.addSortColumn)(dataSource.sort, column, "A"), true;
290
+ case "sort-add-dsc":
291
+ return dataSource.sort = (0, import_vuu_utils2.addSortColumn)(dataSource.sort, column, "D"), true;
292
+ case "group":
293
+ return dataSource.groupBy = (0, import_vuu_utils2.addGroupColumn)(dataSource.groupBy, column), true;
294
+ case "group-add":
295
+ return dataSource.groupBy = (0, import_vuu_utils2.addGroupColumn)(dataSource.groupBy, column), true;
296
+ case "column-hide":
297
+ return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
298
+ case "column-remove":
299
+ return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
300
+ case "filter-remove-column":
301
+ return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
302
+ case "remove-filters":
303
+ return dataSource.filter = { filter: "" }, true;
304
+ case "agg-avg":
305
+ return dataSource.aggregations = (0, import_vuu_utils2.setAggregations)(dataSource.aggregations, column, Average), true;
306
+ case "agg-high":
307
+ return dataSource.aggregations = (0, import_vuu_utils2.setAggregations)(dataSource.aggregations, column, High), true;
308
+ case "agg-low":
309
+ return dataSource.aggregations = (0, import_vuu_utils2.setAggregations)(dataSource.aggregations, column, Low), true;
310
+ case "agg-count":
311
+ return dataSource.aggregations = (0, import_vuu_utils2.setAggregations)(dataSource.aggregations, column, Count), true;
312
+ case "agg-sum":
313
+ return dataSource.aggregations = (0, import_vuu_utils2.setAggregations)(dataSource.aggregations, column, Sum), true;
314
+ case "column-pin-floating":
315
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
316
+ case "column-pin-left":
317
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
318
+ case "column-pin-right":
319
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
320
+ case "column-unpin":
321
+ return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
322
+ default:
323
+ }
663
324
  }
664
- ];
325
+ return false;
326
+ };
327
+ return handleContextMenuAction;
328
+ };
329
+
330
+ // src/RowBasedTable.tsx
331
+ var import_vuu_utils6 = require("@vuu-ui/vuu-utils");
332
+ var import_react9 = require("react");
333
+
334
+ // src/TableRow.tsx
335
+ var import_vuu_utils5 = require("@vuu-ui/vuu-utils");
336
+ var import_classnames2 = __toESM(require("classnames"));
337
+ var import_react3 = require("react");
338
+
339
+ // src/TableCell.tsx
340
+ var import_vuu_utils3 = require("@vuu-ui/vuu-utils");
341
+ var import_salt_lab = require("@heswell/salt-lab");
342
+ var import_classnames = __toESM(require("classnames"));
343
+ var import_react = require("react");
344
+ var import_jsx_runtime = require("react/jsx-runtime");
345
+ var { KEY } = import_vuu_utils3.metadataKeys;
346
+ var TableCell = (0, import_react.memo)(
347
+ ({
348
+ className: classNameProp,
349
+ column,
350
+ columnMap,
351
+ onClick,
352
+ row
353
+ }) => {
354
+ const labelFieldRef = (0, import_react.useRef)(null);
355
+ const {
356
+ align,
357
+ CellRenderer,
358
+ key,
359
+ pin,
360
+ editable,
361
+ resizing,
362
+ valueFormatter
363
+ } = column;
364
+ const [editing, setEditing] = (0, import_react.useState)(false);
365
+ const value = valueFormatter(row[key]);
366
+ const [editableValue, setEditableValue] = (0, import_react.useState)(value);
367
+ const handleTitleMouseDown = () => {
368
+ var _a;
369
+ (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
370
+ };
371
+ const handleTitleKeyDown = (evt) => {
372
+ if (evt.key === "Enter") {
373
+ setEditing(true);
374
+ }
375
+ };
376
+ const handleClick = (0, import_react.useCallback)(() => {
377
+ onClick == null ? void 0 : onClick(column);
378
+ }, [column, onClick]);
379
+ const handleEnterEditMode = () => {
380
+ setEditing(true);
381
+ };
382
+ const handleExitEditMode = (originalValue = "", finalValue = "", allowDeactivation = true, editCancelled = false) => {
383
+ var _a;
384
+ setEditing(false);
385
+ if (editCancelled) {
386
+ setEditableValue(originalValue);
387
+ } else if (finalValue !== originalValue) {
388
+ setEditableValue(finalValue);
389
+ }
390
+ if (allowDeactivation === false) {
391
+ (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
392
+ }
393
+ };
394
+ const className = (0, import_classnames.default)(classNameProp, {
395
+ vuuAlignRight: align === "right",
396
+ vuuPinFloating: pin === "floating",
397
+ vuuPinLeft: pin === "left",
398
+ vuuPinRight: pin === "right",
399
+ "vuuTableCell-resizing": resizing
400
+ }) || void 0;
401
+ const style = (0, import_vuu_utils3.getColumnStyle)(column);
402
+ return editable ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
403
+ "div",
404
+ {
405
+ className,
406
+ "data-editable": true,
407
+ role: "cell",
408
+ style,
409
+ onKeyDown: handleTitleKeyDown,
410
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
411
+ import_salt_lab.EditableLabel,
412
+ {
413
+ editing,
414
+ value: editableValue,
415
+ onChange: setEditableValue,
416
+ onMouseDownCapture: handleTitleMouseDown,
417
+ onEnterEditMode: handleEnterEditMode,
418
+ onExitEditMode: handleExitEditMode,
419
+ onKeyDown: handleTitleKeyDown,
420
+ ref: labelFieldRef,
421
+ tabIndex: 0
422
+ },
423
+ "title"
424
+ )
425
+ }
426
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
427
+ "div",
428
+ {
429
+ className,
430
+ role: "cell",
431
+ style,
432
+ onClick: handleClick,
433
+ children: CellRenderer ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CellRenderer, { column, columnMap, row }) : value
434
+ }
435
+ );
436
+ },
437
+ cellValuesAreEqual
438
+ );
439
+ TableCell.displayName = "TableCell";
440
+ function cellValuesAreEqual(prev, next) {
441
+ 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];
665
442
  }
666
- var pinColumn = (options, pinLocation) => ({
667
- label: `Pin ${pinLocation}`,
668
- action: `column-pin-${pinLocation}`,
669
- options
670
- });
671
- var pinLeft = (options) => pinColumn(options, "left");
672
- var pinFloating = (options) => pinColumn(options, "floating");
673
- var pinRight = (options) => pinColumn(options, "right");
674
- function buildColumnDisplayMenuItems(options) {
675
- const { column } = options;
676
- if (column === void 0) {
677
- return [];
443
+
444
+ // src/TableGroupCell.tsx
445
+ var import_vuu_utils4 = require("@vuu-ui/vuu-utils");
446
+ var import_react2 = require("react");
447
+ var import_jsx_runtime2 = require("react/jsx-runtime");
448
+ var { DEPTH, IS_LEAF } = import_vuu_utils4.metadataKeys;
449
+ var getGroupValueAndOffset = (columns, row) => {
450
+ const { [DEPTH]: depth, [IS_LEAF]: isLeaf } = row;
451
+ if (isLeaf || depth > columns.length) {
452
+ return [null, depth === null ? 0 : depth - 1];
453
+ } else if (depth === 0) {
454
+ return ["$root", 0];
455
+ } else {
456
+ const { key, valueFormatter } = columns[depth - 1];
457
+ const value = valueFormatter(row[key]);
458
+ return [value, depth - 1];
678
459
  }
679
- const { pin } = column;
680
- const menuItems = [
460
+ };
461
+ var TableGroupCell = ({ column, onClick, row }) => {
462
+ const { columns } = column;
463
+ const [value, offset] = getGroupValueAndOffset(columns, row);
464
+ const handleClick = (0, import_react2.useCallback)(() => {
465
+ onClick == null ? void 0 : onClick(column);
466
+ }, [column, onClick]);
467
+ const style = (0, import_vuu_utils4.getColumnStyle)(column);
468
+ const isLeaf = row[IS_LEAF];
469
+ const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vuuTableGroupCell-spacer" }, i));
470
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
471
+ "div",
681
472
  {
682
- label: `Hide column`,
683
- action: "column-hide",
684
- options
473
+ className: "vuuTableGroupCell vuuPinLeft",
474
+ onClick: isLeaf ? void 0 : handleClick,
475
+ role: "cell",
476
+ style,
477
+ children: [
478
+ spacers,
479
+ isLeaf ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vuuTableGroupCell-toggle", "data-icon": "triangle-right" }),
480
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: value })
481
+ ]
482
+ }
483
+ );
484
+ };
485
+
486
+ // src/TableRow.tsx
487
+ var import_jsx_runtime3 = require("react/jsx-runtime");
488
+ var { IDX, IS_EXPANDED, SELECTED } = import_vuu_utils5.metadataKeys;
489
+ var classBase = "vuuTableRow";
490
+ var TableRow = (0, import_react3.memo)(function Row({
491
+ columnMap,
492
+ columns,
493
+ offset,
494
+ onClick,
495
+ onToggleGroup,
496
+ virtualColSpan = 0,
497
+ row
498
+ }) {
499
+ const {
500
+ [IDX]: rowIndex,
501
+ [IS_EXPANDED]: isExpanded,
502
+ [SELECTED]: isSelected
503
+ } = row;
504
+ const className = (0, import_classnames2.default)(classBase, {
505
+ [`${classBase}-even`]: rowIndex % 2 === 0,
506
+ [`${classBase}-expanded`]: isExpanded,
507
+ [`${classBase}-preSelected`]: isSelected === 2
508
+ });
509
+ const handleRowClick = (0, import_react3.useCallback)(
510
+ (evt) => {
511
+ const rangeSelect = evt.shiftKey;
512
+ const keepExistingSelection = evt.ctrlKey || evt.metaKey;
513
+ onClick == null ? void 0 : onClick(row, rangeSelect, keepExistingSelection);
685
514
  },
515
+ [onClick, row]
516
+ );
517
+ const handleGroupCellClick = (0, import_react3.useCallback)(
518
+ (column) => {
519
+ if ((0, import_vuu_utils5.isGroupColumn)(column) || (0, import_vuu_utils5.isJsonGroup)(column, row)) {
520
+ onToggleGroup == null ? void 0 : onToggleGroup(row, column);
521
+ }
522
+ },
523
+ [onToggleGroup, row]
524
+ );
525
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
526
+ "div",
686
527
  {
687
- label: `Remove column`,
688
- action: "column-remove",
689
- options
528
+ "aria-selected": isSelected === 1 ? true : void 0,
529
+ "aria-rowindex": rowIndex,
530
+ className,
531
+ onClick: handleRowClick,
532
+ role: "row",
533
+ style: {
534
+ transform: `translate3d(0px, ${offset}px, 0px)`
535
+ },
536
+ children: [
537
+ virtualColSpan > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { role: "cell", style: { width: virtualColSpan } }) : null,
538
+ columns.filter(import_vuu_utils5.notHidden).map((column) => {
539
+ const isGroup = (0, import_vuu_utils5.isGroupColumn)(column);
540
+ const isJsonCell = (0, import_vuu_utils5.isJsonColumn)(column);
541
+ const Cell = isGroup ? TableGroupCell : TableCell;
542
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
543
+ Cell,
544
+ {
545
+ column,
546
+ columnMap,
547
+ onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
548
+ row
549
+ },
550
+ column.name
551
+ );
552
+ })
553
+ ]
690
554
  }
691
- ];
692
- if (pin === void 0) {
693
- menuItems.push({
694
- label: `Pin column`,
695
- children: [pinLeft(options), pinFloating(options), pinRight(options)]
696
- });
697
- } else if (pin === "left") {
698
- menuItems.push(
699
- { label: "Unpin column", action: "column-unpin", options },
700
- {
701
- label: `Pin column`,
702
- children: [pinFloating(options), pinRight(options)]
555
+ );
556
+ });
557
+
558
+ // src/TableGroupHeaderCell.tsx
559
+ var import_classnames3 = __toESM(require("classnames"));
560
+ var import_react6 = require("react");
561
+
562
+ // src/ColumnResizer.tsx
563
+ var import_react4 = require("react");
564
+ var import_jsx_runtime4 = require("react/jsx-runtime");
565
+ var NOOP = () => void 0;
566
+ var baseClass = "vuuColumnResizer";
567
+ var ColumnResizer = ({
568
+ onDrag,
569
+ onDragEnd = NOOP,
570
+ onDragStart = NOOP
571
+ }) => {
572
+ const position = (0, import_react4.useRef)(0);
573
+ const onMouseMove = (0, import_react4.useCallback)(
574
+ (e) => {
575
+ if (e.stopPropagation) {
576
+ e.stopPropagation();
703
577
  }
704
- );
705
- } else if (pin === "right") {
706
- menuItems.push(
707
- { label: "Unpin column", action: "column-unpin", options },
708
- {
709
- label: `Pin column`,
710
- children: [pinLeft(options), pinFloating(options)]
578
+ if (e.preventDefault) {
579
+ e.preventDefault();
711
580
  }
712
- );
713
- } else if (pin === "floating") {
714
- menuItems.push(
715
- { label: "Unpin column", action: "column-unpin", options },
716
- {
717
- label: `Pin column`,
718
- children: [pinLeft(options), pinRight(options)]
581
+ const x = Math.round(e.clientX);
582
+ const moveBy = x - position.current;
583
+ position.current = x;
584
+ if (moveBy !== 0) {
585
+ onDrag(e, moveBy);
719
586
  }
720
- );
721
- }
722
- return menuItems;
723
- }
724
- function buildGroupMenuItems(options, { groupBy }) {
725
- const { column } = options;
726
- const menuItems = [];
727
- if (column === void 0) {
728
- return menuItems;
729
- }
730
- const { name, label = name } = column;
731
- if (groupBy.length === 0) {
732
- menuItems.push({
733
- label: `Group by ${label}`,
734
- action: "group",
735
- options
736
- });
737
- } else {
738
- menuItems.push({
739
- label: `Add ${label} to group by`,
740
- action: "group-add",
741
- options
742
- });
743
- }
744
- return menuItems;
745
- }
746
-
747
- // src/context-menu/useContextMenu.ts
748
- var import_vuu_filters = require("@vuu-ui/vuu-filters");
749
- var import_vuu_utils6 = require("@vuu-ui/vuu-utils");
750
- var removeFilterColumn = (dataSourceFilter, column) => {
751
- if (dataSourceFilter.filterStruct && column) {
752
- const [filterStruct, filter] = (0, import_vuu_filters.removeColumnFromFilter)(
753
- column,
754
- dataSourceFilter.filterStruct
755
- );
756
- return {
757
- filter,
758
- filterStruct
759
- };
760
- } else {
761
- return dataSourceFilter;
762
- }
587
+ },
588
+ [onDrag]
589
+ );
590
+ const onMouseUp = (0, import_react4.useCallback)(
591
+ (e) => {
592
+ window.removeEventListener("mouseup", onMouseUp);
593
+ window.removeEventListener("mousemove", onMouseMove);
594
+ onDragEnd(e);
595
+ },
596
+ [onDragEnd, onMouseMove]
597
+ );
598
+ const handleMouseDown = (0, import_react4.useCallback)(
599
+ (e) => {
600
+ onDragStart(e);
601
+ position.current = Math.round(e.clientX);
602
+ window.addEventListener("mouseup", onMouseUp);
603
+ window.addEventListener("mousemove", onMouseMove);
604
+ if (e.stopPropagation) {
605
+ e.stopPropagation();
606
+ }
607
+ if (e.preventDefault) {
608
+ e.preventDefault();
609
+ }
610
+ },
611
+ [onDragStart, onMouseMove, onMouseUp]
612
+ );
613
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: baseClass, "data-align": "end", onMouseDown: handleMouseDown });
763
614
  };
764
- var { Average, Count, High, Low, Sum } = import_vuu_utils6.AggregationType;
765
- var useContextMenu3 = ({
766
- dataSource,
767
- onPersistentColumnOperation
615
+
616
+ // src/useTableColumnResize.tsx
617
+ var import_react5 = require("react");
618
+ var useTableColumnResize = ({
619
+ column,
620
+ onResize,
621
+ rootRef
768
622
  }) => {
769
- const handleContextMenuAction = (type, options) => {
770
- const gridOptions = options;
771
- if (gridOptions.column && dataSource) {
772
- const { column } = gridOptions;
773
- switch (type) {
774
- case "sort-asc":
775
- return dataSource.sort = (0, import_vuu_utils6.setSortColumn)(dataSource.sort, column, "A"), true;
776
- case "sort-dsc":
777
- return dataSource.sort = (0, import_vuu_utils6.setSortColumn)(dataSource.sort, column, "D"), true;
778
- case "sort-add-asc":
779
- return dataSource.sort = (0, import_vuu_utils6.addSortColumn)(dataSource.sort, column, "A"), true;
780
- case "sort-add-dsc":
781
- return dataSource.sort = (0, import_vuu_utils6.addSortColumn)(dataSource.sort, column, "D"), true;
782
- case "group":
783
- return dataSource.groupBy = (0, import_vuu_utils6.addGroupColumn)(dataSource.groupBy, column), true;
784
- case "group-add":
785
- return dataSource.groupBy = (0, import_vuu_utils6.addGroupColumn)(dataSource.groupBy, column), true;
786
- case "column-hide":
787
- return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
788
- case "column-remove":
789
- return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
790
- case "filter-remove-column":
791
- return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
792
- case "remove-filters":
793
- return dataSource.filter = { filter: "" }, true;
794
- case "agg-avg":
795
- return dataSource.aggregations = (0, import_vuu_utils6.setAggregations)(dataSource.aggregations, column, Average), true;
796
- case "agg-high":
797
- return dataSource.aggregations = (0, import_vuu_utils6.setAggregations)(dataSource.aggregations, column, High), true;
798
- case "agg-low":
799
- return dataSource.aggregations = (0, import_vuu_utils6.setAggregations)(dataSource.aggregations, column, Low), true;
800
- case "agg-count":
801
- return dataSource.aggregations = (0, import_vuu_utils6.setAggregations)(dataSource.aggregations, column, Count), true;
802
- case "agg-sum":
803
- return dataSource.aggregations = (0, import_vuu_utils6.setAggregations)(dataSource.aggregations, column, Sum), true;
804
- case "column-pin-floating":
805
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
806
- case "column-pin-left":
807
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
808
- case "column-pin-right":
809
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
810
- case "column-unpin":
811
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
812
- default:
623
+ const widthRef = (0, import_react5.useRef)(0);
624
+ const isResizing = (0, import_react5.useRef)(false);
625
+ const { name } = column;
626
+ const handleResizeStart = (0, import_react5.useCallback)(() => {
627
+ if (onResize && rootRef.current) {
628
+ const { width } = rootRef.current.getBoundingClientRect();
629
+ widthRef.current = Math.round(width);
630
+ isResizing.current = true;
631
+ onResize == null ? void 0 : onResize("begin", name);
632
+ }
633
+ }, [name, onResize, rootRef]);
634
+ const handleResize = (0, import_react5.useCallback)(
635
+ (_evt, moveBy) => {
636
+ if (rootRef.current) {
637
+ if (onResize) {
638
+ const { width } = rootRef.current.getBoundingClientRect();
639
+ const newWidth = Math.round(width) + moveBy;
640
+ if (newWidth !== widthRef.current && newWidth > 0) {
641
+ onResize("resize", name, newWidth);
642
+ widthRef.current = newWidth;
643
+ }
644
+ }
813
645
  }
646
+ },
647
+ [name, onResize, rootRef]
648
+ );
649
+ const handleResizeEnd = (0, import_react5.useCallback)(() => {
650
+ if (onResize) {
651
+ onResize("end", name, widthRef.current);
652
+ setTimeout(() => {
653
+ isResizing.current = false;
654
+ }, 100);
814
655
  }
815
- return false;
656
+ }, [name, onResize]);
657
+ return {
658
+ isResizing: isResizing.current,
659
+ onDrag: handleResize,
660
+ onDragStart: handleResizeStart,
661
+ onDragEnd: handleResizeEnd
816
662
  };
817
- return handleContextMenuAction;
818
663
  };
819
664
 
820
- // src/RowBasedTable.tsx
821
- var import_vuu_utils7 = require("@vuu-ui/vuu-utils");
822
- var import_react10 = require("react");
823
-
824
665
  // src/TableGroupHeaderCell.tsx
825
- var import_classnames7 = __toESM(require("classnames"));
826
- var import_react9 = require("react");
827
- var import_jsx_runtime9 = require("react/jsx-runtime");
828
- var classBase5 = "vuuTable-groupHeaderCell";
666
+ var import_jsx_runtime5 = require("react/jsx-runtime");
667
+ var classBase2 = "vuuTable-groupHeaderCell";
668
+ var RemoveButton = ({
669
+ column,
670
+ onClick,
671
+ ...htmlAttributes
672
+ }) => {
673
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
674
+ "span",
675
+ {
676
+ ...htmlAttributes,
677
+ className: `${classBase2}-close`,
678
+ "data-icon": "close-circle",
679
+ onClick: () => onClick == null ? void 0 : onClick(column)
680
+ }
681
+ );
682
+ };
829
683
  var ColHeader = (props) => {
830
- const { column, className, onRemoveColumn } = props;
831
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: (0, import_classnames7.default)(`${classBase5}-col`, className), role: "columnheader", children: [
832
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: `${classBase5}-label`, children: column.name }),
833
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
834
- "span",
835
- {
836
- className: `${classBase5}-close`,
837
- "data-icon": "close-circle",
838
- onClick: () => onRemoveColumn == null ? void 0 : onRemoveColumn(column)
839
- }
840
- )
684
+ const { children, column, className } = props;
685
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: (0, import_classnames3.default)(`${classBase2}-col`, className), role: "columnheader", children: [
686
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `${classBase2}-label`, children: column.name }),
687
+ children
841
688
  ] });
842
689
  };
843
690
  var TableGroupHeaderCell = ({
@@ -847,40 +694,153 @@ var TableGroupHeaderCell = ({
847
694
  onResize,
848
695
  ...props
849
696
  }) => {
850
- const rootRef = (0, import_react9.useRef)(null);
697
+ const rootRef = (0, import_react6.useRef)(null);
851
698
  const { isResizing, ...resizeProps } = useTableColumnResize({
852
699
  column: groupColumn,
853
700
  onResize,
854
701
  rootRef
855
702
  });
856
- const className = (0, import_classnames7.default)(classBase5, classNameProp, {
703
+ const className = (0, import_classnames3.default)(classBase2, classNameProp, {
857
704
  vuuPinLeft: groupColumn.pin === "left",
858
- [`${classBase5}-right`]: groupColumn.align === "right",
859
- [`${classBase5}-resizing`]: groupColumn.resizing,
860
- [`${classBase5}-pending`]: groupColumn.groupConfirmed === false
705
+ [`${classBase2}-right`]: groupColumn.align === "right",
706
+ [`${classBase2}-resizing`]: groupColumn.resizing,
707
+ [`${classBase2}-pending`]: groupColumn.groupConfirmed === false
861
708
  });
862
709
  const { columns } = groupColumn;
863
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className, ref: rootRef, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `${classBase5}-inner`, children: [
864
- columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
865
- ColHeader,
866
- {
867
- column,
868
- onRemoveColumn
869
- },
870
- column.key
871
- )),
872
- groupColumn.resizeable !== false ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ColumnResizer, { ...resizeProps }) : null
710
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className, ref: rootRef, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `${classBase2}-inner`, children: [
711
+ columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ColHeader, { column, children: columns.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RemoveButton, { column, onClick: onRemoveColumn }) : null }, column.key)),
712
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RemoveButton, { "data-align": "end", onClick: onRemoveColumn }),
713
+ groupColumn.resizeable !== false ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ColumnResizer, { ...resizeProps }) : null
873
714
  ] }) });
874
715
  };
875
716
 
717
+ // src/TableHeaderCell.tsx
718
+ var import_classnames6 = __toESM(require("classnames"));
719
+ var import_react8 = require("react");
720
+
721
+ // src/SortIndicator.tsx
722
+ var import_classnames4 = __toESM(require("classnames"));
723
+ var import_jsx_runtime6 = require("react/jsx-runtime");
724
+ var classBase3 = "vuuSortIndicator";
725
+ var SortIndicator = ({ sorted }) => {
726
+ if (!sorted) {
727
+ return null;
728
+ }
729
+ const direction = typeof sorted === "number" ? sorted < 0 ? "dsc" : "asc" : sorted === "A" ? "asc" : "dsc";
730
+ return typeof sorted === "number" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: (0, import_classnames4.default)(classBase3, "multi-col", direction), children: [
731
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "data-icon": `sorted-${direction}` }),
732
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vuuSortPosition", children: Math.abs(sorted) })
733
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_classnames4.default)(classBase3, "single-col"), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "data-icon": `sorted-${direction}` }) });
734
+ };
735
+
736
+ // src/TableHeaderCell.tsx
737
+ var import_vuu_popups2 = require("@vuu-ui/vuu-popups");
738
+
739
+ // src/filter-indicator.tsx
740
+ var import_vuu_popups = require("@vuu-ui/vuu-popups");
741
+ var import_classnames5 = __toESM(require("classnames"));
742
+ var import_react7 = require("react");
743
+ var import_jsx_runtime7 = require("react/jsx-runtime");
744
+ var FilterIndicator = ({ column, filter }) => {
745
+ const showContextMenu = (0, import_vuu_popups.useContextMenu)();
746
+ const handleClick = (0, import_react7.useCallback)(
747
+ (evt) => {
748
+ evt.stopPropagation();
749
+ showContextMenu(evt, "filter", { column, filter });
750
+ },
751
+ [column, filter, showContextMenu]
752
+ );
753
+ if (!column.filter) {
754
+ return null;
755
+ }
756
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
757
+ "div",
758
+ {
759
+ className: (0, import_classnames5.default)("vuuFilterIndicator"),
760
+ "data-icon": "filter",
761
+ onClick: handleClick
762
+ }
763
+ );
764
+ };
765
+
766
+ // src/TableHeaderCell.tsx
767
+ var import_jsx_runtime8 = require("react/jsx-runtime");
768
+ var classBase4 = "vuuTable-headerCell";
769
+ var TableHeaderCell = ({
770
+ column,
771
+ className: classNameProp,
772
+ onClick,
773
+ onDragStart,
774
+ onResize,
775
+ ...props
776
+ }) => {
777
+ const rootRef = (0, import_react8.useRef)(null);
778
+ const { isResizing, ...resizeProps } = useTableColumnResize({
779
+ column,
780
+ onResize,
781
+ rootRef
782
+ });
783
+ const showContextMenu = (0, import_vuu_popups2.useContextMenu)();
784
+ const dragTimerRef = (0, import_react8.useRef)(null);
785
+ const handleContextMenu = (e) => {
786
+ showContextMenu(e, "header", { column });
787
+ };
788
+ const handleClick = (0, import_react8.useCallback)(
789
+ (evt) => !isResizing && (onClick == null ? void 0 : onClick(evt)),
790
+ [isResizing, onClick]
791
+ );
792
+ const handleMouseDown = (0, import_react8.useCallback)(
793
+ (evt) => {
794
+ dragTimerRef.current = window.setTimeout(() => {
795
+ onDragStart == null ? void 0 : onDragStart(evt);
796
+ dragTimerRef.current = null;
797
+ }, 500);
798
+ },
799
+ [onDragStart]
800
+ );
801
+ const handleMouseUp = (0, import_react8.useCallback)(() => {
802
+ if (dragTimerRef.current !== null) {
803
+ window.clearTimeout(dragTimerRef.current);
804
+ dragTimerRef.current = null;
805
+ }
806
+ }, []);
807
+ const className = (0, import_classnames6.default)(classBase4, classNameProp, {
808
+ vuuPinFloating: column.pin === "floating",
809
+ vuuPinLeft: column.pin === "left",
810
+ vuuPinRight: column.pin === "right",
811
+ vuuEndPin: column.endPin,
812
+ [`${classBase4}-resizing`]: column.resizing,
813
+ [`${classBase4}-right`]: column.align === "right"
814
+ });
815
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
816
+ "div",
817
+ {
818
+ className,
819
+ ...props,
820
+ onClick: handleClick,
821
+ onContextMenu: handleContextMenu,
822
+ onMouseDown: handleMouseDown,
823
+ onMouseUp: handleMouseUp,
824
+ ref: rootRef,
825
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `${classBase4}-inner`, children: [
826
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FilterIndicator, { column }),
827
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `${classBase4}-label`, children: column.label }),
828
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SortIndicator, { sorted: column.sorted }),
829
+ column.resizeable !== false ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ColumnResizer, { ...resizeProps }) : null
830
+ ] })
831
+ }
832
+ );
833
+ };
834
+
876
835
  // src/RowBasedTable.tsx
877
- var import_jsx_runtime10 = require("react/jsx-runtime");
878
- var classBase6 = "vuuTable";
879
- var { RENDER_IDX: RENDER_IDX2 } = import_vuu_utils7.metadataKeys;
836
+ var import_jsx_runtime9 = require("react/jsx-runtime");
837
+ var classBase5 = "vuuTable";
838
+ var { RENDER_IDX } = import_vuu_utils6.metadataKeys;
880
839
  var RowBasedTable = ({
881
840
  columns,
882
841
  columnsWithinViewport,
883
842
  data,
843
+ getRowOffset,
884
844
  headings,
885
845
  onColumnResize,
886
846
  onHeaderCellDragStart,
@@ -889,20 +849,21 @@ var RowBasedTable = ({
889
849
  onRowClick,
890
850
  onSort,
891
851
  onToggleGroup,
852
+ tableId,
892
853
  virtualColSpan = 0,
893
- rowCount,
894
- rowHeight
854
+ rowCount
895
855
  }) => {
896
- const handleDragStart = (0, import_react10.useCallback)(
856
+ const handleDragStart = (0, import_react9.useCallback)(
897
857
  (evt) => {
898
858
  onHeaderCellDragStart == null ? void 0 : onHeaderCellDragStart(evt);
899
859
  },
900
860
  [onHeaderCellDragStart]
901
861
  );
902
- const visibleColumns = (0, import_react10.useMemo)(() => {
903
- return columns.filter(import_vuu_utils7.notHidden);
862
+ const visibleColumns = (0, import_react9.useMemo)(() => {
863
+ return columns.filter(import_vuu_utils6.notHidden);
904
864
  }, [columns]);
905
- const handleHeaderClick = (0, import_react10.useCallback)(
865
+ const columnMap = (0, import_react9.useMemo)(() => (0, import_vuu_utils6.buildColumnMap)(columns), [columns]);
866
+ const handleHeaderClick = (0, import_react9.useCallback)(
906
867
  (evt) => {
907
868
  var _a;
908
869
  const targetElement = evt.target;
@@ -910,71 +871,78 @@ var RowBasedTable = ({
910
871
  ".vuuTable-headerCell"
911
872
  );
912
873
  const colIdx = parseInt((_a = headerCell == null ? void 0 : headerCell.dataset.idx) != null ? _a : "-1");
913
- const column = (0, import_vuu_utils7.visibleColumnAtIndex)(columns, colIdx);
874
+ const column = (0, import_vuu_utils6.visibleColumnAtIndex)(columns, colIdx);
914
875
  const isAdditive = evt.shiftKey;
915
876
  column && onSort(column, isAdditive);
916
877
  },
917
878
  [columns, onSort]
918
879
  );
919
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { "aria-rowcount": rowCount, className: `${classBase6}-table`, children: [
920
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("colgroup", { children: visibleColumns.map((column, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("col", { width: `${column.width}px` }, i)) }),
921
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("thead", { children: [
922
- headings.map((colHeaders, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { className: "vuuTable-heading", children: colHeaders.map(({ label, span }, j) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { colSpan: span, className: "vuuTable-headingCell", children: label }, j)) }, i)),
923
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: visibleColumns.map((column, i) => {
924
- const style = (0, import_vuu_utils7.getColumnPinStyle)(column);
925
- return (0, import_vuu_utils7.isGroupColumn)(column) ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
880
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "aria-rowcount": rowCount, className: `${classBase5}-table`, role: "table", children: [
881
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `${classBase5}-headers`, role: "rowGroup", children: [
882
+ headings.map((colHeaders, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "vuuTable-heading", children: colHeaders.map(({ label, width }, j) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "vuuTable-headingCell", style: { width }, children: label }, j)) }, i)),
883
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "row", children: visibleColumns.map((column, i) => {
884
+ const style = (0, import_vuu_utils6.getColumnStyle)(column);
885
+ return (0, import_vuu_utils6.isGroupColumn)(column) ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
926
886
  TableGroupHeaderCell,
927
887
  {
928
888
  column,
929
889
  "data-idx": i,
930
890
  onRemoveColumn: onRemoveColumnFromGroupBy,
931
891
  onResize: onColumnResize,
892
+ role: "columnHeader",
932
893
  style
933
894
  },
934
895
  i
935
- ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
896
+ ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
936
897
  TableHeaderCell,
937
898
  {
938
899
  column,
939
900
  "data-idx": i,
901
+ id: `${tableId}-${i}`,
940
902
  onClick: handleHeaderClick,
941
903
  onDragStart: handleDragStart,
942
904
  onResize: onColumnResize,
905
+ role: "columnHeader",
943
906
  style
944
907
  },
945
908
  i
946
909
  );
947
910
  }) })
948
911
  ] }),
949
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tbody", { onContextMenu, children: [
950
- data == null ? void 0 : data.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
951
- TableRow,
952
- {
953
- columns: columnsWithinViewport,
954
- height: rowHeight,
955
- index: i,
956
- onClick: onRowClick,
957
- virtualColSpan,
958
- onToggleGroup,
959
- row
960
- },
961
- row[RENDER_IDX2]
962
- )),
963
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { className: `${classBase6}-filler` })
964
- ] })
912
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
913
+ "div",
914
+ {
915
+ className: `${classBase5}-body`,
916
+ onContextMenu,
917
+ role: "rowGroup",
918
+ children: data == null ? void 0 : data.map((row) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
919
+ TableRow,
920
+ {
921
+ columnMap,
922
+ columns: columnsWithinViewport,
923
+ offset: getRowOffset(row),
924
+ onClick: onRowClick,
925
+ virtualColSpan,
926
+ onToggleGroup,
927
+ row
928
+ },
929
+ row[RENDER_IDX]
930
+ ))
931
+ }
932
+ )
965
933
  ] });
966
934
  };
967
935
 
968
- // src/useDataTable.ts
936
+ // src/useTable.ts
969
937
  var import_vuu_popups3 = require("@vuu-ui/vuu-popups");
970
938
  var import_vuu_utils13 = require("@vuu-ui/vuu-utils");
971
- var import_react21 = require("react");
939
+ var import_react20 = require("react");
972
940
 
973
941
  // src/useDataSource.ts
974
942
  var import_vuu_data = require("@vuu-ui/vuu-data");
975
- var import_vuu_utils8 = require("@vuu-ui/vuu-utils");
976
- var import_react11 = require("react");
977
- var { SELECTED: SELECTED2 } = import_vuu_utils8.metadataKeys;
943
+ var import_vuu_utils7 = require("@vuu-ui/vuu-utils");
944
+ var import_react10 = require("react");
945
+ var { SELECTED: SELECTED2 } = import_vuu_utils7.metadataKeys;
978
946
  function useDataSource({
979
947
  dataSource,
980
948
  onConfigChange,
@@ -986,18 +954,18 @@ function useDataSource({
986
954
  renderBufferSize = 0,
987
955
  viewportRowCount
988
956
  }) {
989
- const [, forceUpdate] = (0, import_react11.useState)(null);
990
- const isMounted = (0, import_react11.useRef)(true);
991
- const hasUpdated = (0, import_react11.useRef)(false);
992
- const rangeRef = (0, import_react11.useRef)({ from: 0, to: 0 });
993
- const rafHandle = (0, import_react11.useRef)(null);
994
- const data = (0, import_react11.useRef)([]);
995
- const dataWindow = (0, import_react11.useMemo)(
996
- () => new MovingWindow((0, import_vuu_utils8.getFullRange)(range)),
957
+ const [, forceUpdate] = (0, import_react10.useState)(null);
958
+ const isMounted = (0, import_react10.useRef)(true);
959
+ const hasUpdated = (0, import_react10.useRef)(false);
960
+ const rangeRef = (0, import_react10.useRef)({ from: 0, to: 0 });
961
+ const rafHandle = (0, import_react10.useRef)(null);
962
+ const data = (0, import_react10.useRef)([]);
963
+ const dataWindow = (0, import_react10.useMemo)(
964
+ () => new MovingWindow((0, import_vuu_utils7.getFullRange)(range)),
997
965
  // eslint-disable-next-line react-hooks/exhaustive-deps
998
966
  []
999
967
  );
1000
- const setData = (0, import_react11.useCallback)(
968
+ const setData = (0, import_react10.useCallback)(
1001
969
  (updates) => {
1002
970
  for (const row of updates) {
1003
971
  dataWindow.add(row);
@@ -1007,7 +975,7 @@ function useDataSource({
1007
975
  },
1008
976
  [dataWindow]
1009
977
  );
1010
- const datasourceMessageHandler = (0, import_react11.useCallback)(
978
+ const datasourceMessageHandler = (0, import_react10.useCallback)(
1011
979
  (message) => {
1012
980
  if (message.type === "subscribed") {
1013
981
  onSubscribed == null ? void 0 : onSubscribed(message);
@@ -1039,7 +1007,7 @@ function useDataSource({
1039
1007
  setData
1040
1008
  ]
1041
1009
  );
1042
- (0, import_react11.useEffect)(
1010
+ (0, import_react10.useEffect)(
1043
1011
  () => () => {
1044
1012
  if (rafHandle.current) {
1045
1013
  cancelAnimationFrame(rafHandle.current);
@@ -1049,7 +1017,7 @@ function useDataSource({
1049
1017
  },
1050
1018
  []
1051
1019
  );
1052
- const refreshIfUpdated = (0, import_react11.useCallback)(() => {
1020
+ const refreshIfUpdated = (0, import_react10.useCallback)(() => {
1053
1021
  if (isMounted.current) {
1054
1022
  if (hasUpdated.current) {
1055
1023
  forceUpdate({});
@@ -1058,33 +1026,33 @@ function useDataSource({
1058
1026
  rafHandle.current = requestAnimationFrame(refreshIfUpdated);
1059
1027
  }
1060
1028
  }, [forceUpdate]);
1061
- (0, import_react11.useEffect)(() => {
1029
+ (0, import_react10.useEffect)(() => {
1062
1030
  rafHandle.current = requestAnimationFrame(refreshIfUpdated);
1063
1031
  }, [refreshIfUpdated]);
1064
- const adjustRange = (0, import_react11.useCallback)(
1032
+ const adjustRange = (0, import_react10.useCallback)(
1065
1033
  (rowCount) => {
1066
1034
  const { from } = dataSource.range;
1067
1035
  const rowRange = { from, to: from + rowCount };
1068
- const fullRange = (0, import_vuu_utils8.getFullRange)(rowRange, renderBufferSize);
1036
+ const fullRange = (0, import_vuu_utils7.getFullRange)(rowRange, renderBufferSize);
1037
+ dataWindow.setRange(fullRange);
1069
1038
  dataSource.range = rangeRef.current = fullRange;
1070
1039
  dataSource.emit("range", rowRange);
1071
- dataWindow.setRange(fullRange);
1072
1040
  },
1073
1041
  [dataSource, dataWindow, renderBufferSize]
1074
1042
  );
1075
- const setRange = (0, import_react11.useCallback)(
1043
+ const setRange = (0, import_react10.useCallback)(
1076
1044
  (range2) => {
1077
- const fullRange = (0, import_vuu_utils8.getFullRange)(range2, renderBufferSize);
1078
- dataSource.range = rangeRef.current = fullRange;
1045
+ const fullRange = (0, import_vuu_utils7.getFullRange)(range2, renderBufferSize);
1079
1046
  dataWindow.setRange(fullRange);
1047
+ dataSource.range = rangeRef.current = fullRange;
1080
1048
  dataSource.emit("range", range2);
1081
1049
  },
1082
1050
  [dataSource, dataWindow, renderBufferSize]
1083
1051
  );
1084
- const getSelectedRows = (0, import_react11.useCallback)(() => {
1052
+ const getSelectedRows = (0, import_react10.useCallback)(() => {
1085
1053
  return dataWindow.getSelectedRows();
1086
1054
  }, [dataWindow]);
1087
- (0, import_react11.useEffect)(() => {
1055
+ (0, import_react10.useEffect)(() => {
1088
1056
  dataSource == null ? void 0 : dataSource.subscribe(
1089
1057
  {
1090
1058
  range: rangeRef.current
@@ -1092,7 +1060,7 @@ function useDataSource({
1092
1060
  datasourceMessageHandler
1093
1061
  );
1094
1062
  }, [dataSource, datasourceMessageHandler, onConfigChange]);
1095
- (0, import_react11.useEffect)(() => {
1063
+ (0, import_react10.useEffect)(() => {
1096
1064
  adjustRange(viewportRowCount);
1097
1065
  }, [adjustRange, viewportRowCount]);
1098
1066
  return {
@@ -1112,7 +1080,7 @@ var MovingWindow = class {
1112
1080
  }
1113
1081
  this.rowCount = rowCount;
1114
1082
  };
1115
- this.range = new import_vuu_utils8.WindowRange(from, to);
1083
+ this.range = new import_vuu_utils7.WindowRange(from, to);
1116
1084
  this.data = new Array(to - from);
1117
1085
  this.rowCount = 0;
1118
1086
  }
@@ -1140,7 +1108,7 @@ var MovingWindow = class {
1140
1108
  setRange({ from, to }) {
1141
1109
  if (from !== this.range.from || to !== this.range.to) {
1142
1110
  const [overlapFrom, overlapTo] = this.range.overlap(from, to);
1143
- const newData = new Array(to - from);
1111
+ const newData = new Array(Math.max(0, to - from));
1144
1112
  for (let i = overlapFrom; i < overlapTo; i++) {
1145
1113
  const data = this.getAtIndex(i);
1146
1114
  if (data) {
@@ -1160,76 +1128,58 @@ var MovingWindow = class {
1160
1128
 
1161
1129
  // src/useDraggableColumn.ts
1162
1130
  var import_salt_lab2 = require("@heswell/salt-lab");
1163
- var import_react12 = require("react");
1164
- var useDraggableColumn = ({
1165
- onDrop,
1166
- tableContainerRef,
1167
- tableLayout: tableLayoutProp
1168
- }) => {
1169
- const [tableLayout, setTableLayout] = (0, import_react12.useState)(tableLayoutProp);
1170
- const mousePosRef = (0, import_react12.useRef)();
1171
- const handleDropSettle = (0, import_react12.useCallback)(() => {
1131
+ var import_react11 = require("react");
1132
+ var useDraggableColumn = ({ onDrop }) => {
1133
+ const mousePosRef = (0, import_react11.useRef)();
1134
+ const containerRef = (0, import_react11.useRef)(null);
1135
+ const handleDropSettle = (0, import_react11.useCallback)(() => {
1172
1136
  console.log(`handleDropSettle`);
1173
1137
  mousePosRef.current = void 0;
1174
- setTableLayout("row");
1138
+ containerRef.current = null;
1175
1139
  }, []);
1176
1140
  const { draggable, draggedItemIndex, onMouseDown } = (0, import_salt_lab2.useDragDrop)({
1141
+ // allowDragDrop: "drop-indicator",
1177
1142
  allowDragDrop: true,
1178
- draggableClassName: "table-column",
1143
+ draggableClassName: "vuuTable-headerCell",
1179
1144
  orientation: "horizontal",
1180
- containerRef: tableContainerRef,
1181
- itemQuery: ".vuuTable-table",
1145
+ containerRef,
1146
+ itemQuery: ".vuuTable-headerCell",
1182
1147
  onDrop,
1183
1148
  onDropSettle: handleDropSettle
1184
1149
  });
1185
- const handleHeaderCellDragStart = (0, import_react12.useCallback)((evt) => {
1186
- const { clientX, clientY } = evt;
1187
- console.log(
1188
- `useDraggableColumn handleHeaderCellDragStart means mouseDown fired on a column in RowBasedTable`
1189
- );
1190
- const sourceElement = evt.target;
1191
- const thElement = sourceElement.closest(".vuuTable-headerCell");
1192
- const {
1193
- dataset: { idx = "-1" }
1194
- } = thElement;
1195
- mousePosRef.current = {
1196
- clientX,
1197
- clientY,
1198
- idx
1199
- };
1200
- setTableLayout("column");
1201
- }, []);
1202
- (0, import_react12.useLayoutEffect)(() => {
1203
- var _a;
1204
- if (tableLayout === "column" && mousePosRef.current && !draggable) {
1205
- const { clientX, clientY, idx } = mousePosRef.current;
1206
- const target = (_a = tableContainerRef.current) == null ? void 0 : _a.querySelector(
1207
- `.vuuTable-table[data-idx="${idx}"]`
1150
+ const onHeaderCellDragStart = (0, import_react11.useCallback)(
1151
+ (evt) => {
1152
+ const { clientX, clientY } = evt;
1153
+ console.log(
1154
+ `useDraggableColumn handleHeaderCellDragStart means mouseDown fired on a column in RowBasedTable`
1208
1155
  );
1209
- if (target) {
1210
- const evt = {
1211
- persist: () => void 0,
1212
- nativeEvent: {
1213
- clientX,
1214
- clientY,
1215
- target
1216
- }
1217
- };
1218
- onMouseDown == null ? void 0 : onMouseDown(evt);
1219
- }
1220
- }
1221
- }, [draggable, onMouseDown, tableContainerRef, tableLayout]);
1156
+ const sourceElement = evt.target;
1157
+ const columnHeaderCell = sourceElement.closest(".vuuTable-headerCell");
1158
+ containerRef.current = columnHeaderCell == null ? void 0 : columnHeaderCell.closest(
1159
+ "[role='row']"
1160
+ );
1161
+ const {
1162
+ dataset: { idx = "-1" }
1163
+ } = columnHeaderCell;
1164
+ mousePosRef.current = {
1165
+ clientX,
1166
+ clientY,
1167
+ idx
1168
+ };
1169
+ onMouseDown == null ? void 0 : onMouseDown(evt);
1170
+ },
1171
+ [onMouseDown]
1172
+ );
1222
1173
  return {
1223
1174
  draggable,
1224
1175
  draggedItemIndex,
1225
- tableLayout,
1226
- onHeaderCellDragStart: tableLayout === "row" ? handleHeaderCellDragStart : void 0
1176
+ onHeaderCellDragStart
1227
1177
  };
1228
1178
  };
1229
1179
 
1230
1180
  // src/useKeyboardNavigation.ts
1231
- var import_vuu_utils9 = require("@vuu-ui/vuu-utils");
1232
- var import_react13 = require("react");
1181
+ var import_vuu_utils8 = require("@vuu-ui/vuu-utils");
1182
+ var import_react12 = require("react");
1233
1183
 
1234
1184
  // src/keyUtils.ts
1235
1185
  function union(set1, ...sets) {
@@ -1290,8 +1240,8 @@ var isNavigationKey = (key) => {
1290
1240
  };
1291
1241
 
1292
1242
  // src/useKeyboardNavigation.ts
1293
- var headerCellQuery = (colIdx) => `thead th:nth-child(${colIdx + 1})`;
1294
- var dataCellQuery = (rowIdx, colIdx) => `tbody > tr[aria-rowindex='${rowIdx}'] > td:nth-child(${colIdx + 1})`;
1243
+ var headerCellQuery = (colIdx) => `.vuuTable-headers .vuuTable-headerCell:nth-child(${colIdx + 1})`;
1244
+ var dataCellQuery = (rowIdx, colIdx) => `.vuuTable-body > [aria-rowindex='${rowIdx}'] > [role='cell']:nth-child(${colIdx + 1})`;
1295
1245
  var NULL_CELL_POS = [-1, -1];
1296
1246
  function nextCellPos(key, [rowIdx, colIdx], columnCount, rowCount) {
1297
1247
  if (key === ArrowUp) {
@@ -1334,10 +1284,10 @@ var useKeyboardNavigation = ({
1334
1284
  }) => {
1335
1285
  var _a;
1336
1286
  const { from: viewportFirstRow, to: viewportLastRow } = viewportRange;
1337
- const focusedCellPos = (0, import_react13.useRef)([-1, -1]);
1338
- const focusableCell = (0, import_react13.useRef)();
1339
- const activeCellPos = (0, import_react13.useRef)([-1, 0]);
1340
- const getTableCell = (0, import_react13.useCallback)(
1287
+ const focusedCellPos = (0, import_react12.useRef)([-1, -1]);
1288
+ const focusableCell = (0, import_react12.useRef)();
1289
+ const activeCellPos = (0, import_react12.useRef)([-1, 0]);
1290
+ const getTableCell = (0, import_react12.useCallback)(
1341
1291
  ([rowIdx, colIdx]) => {
1342
1292
  var _a2;
1343
1293
  const cssQuery = rowIdx === -1 ? headerCellQuery(colIdx) : dataCellQuery(rowIdx, colIdx);
@@ -1347,14 +1297,16 @@ var useKeyboardNavigation = ({
1347
1297
  },
1348
1298
  [containerRef]
1349
1299
  );
1350
- const getFocusedCell = (element) => element == null ? void 0 : element.closest("th,td");
1300
+ const getFocusedCell = (element) => element == null ? void 0 : element.closest(
1301
+ "[role='columnHeader'],[role='cell']"
1302
+ );
1351
1303
  const getTableCellPos = (tableCell) => {
1352
1304
  var _a2, _b;
1353
- if (tableCell.tagName === "TH") {
1305
+ if (tableCell.role === "columnHeader") {
1354
1306
  const colIdx = parseInt((_a2 = tableCell.dataset.idx) != null ? _a2 : "-1", 10);
1355
1307
  return [-1, colIdx];
1356
1308
  } else {
1357
- const focusedRow = tableCell.closest("tr");
1309
+ const focusedRow = tableCell.closest("[role='row']");
1358
1310
  if (focusedRow) {
1359
1311
  const rowIdx = parseInt((_b = focusedRow.ariaRowIndex) != null ? _b : "-1", 10);
1360
1312
  const colIdx = Array.from(focusedRow.childNodes).indexOf(tableCell);
@@ -1363,7 +1315,7 @@ var useKeyboardNavigation = ({
1363
1315
  }
1364
1316
  return NULL_CELL_POS;
1365
1317
  };
1366
- const focusCell = (0, import_react13.useCallback)(
1318
+ const focusCell = (0, import_react12.useCallback)(
1367
1319
  (cellPos) => {
1368
1320
  var _a2;
1369
1321
  if (containerRef.current) {
@@ -1375,7 +1327,7 @@ var useKeyboardNavigation = ({
1375
1327
  activeCell.setAttribute("tabindex", "0");
1376
1328
  }
1377
1329
  activeCell.focus();
1378
- } else if (!(0, import_vuu_utils9.withinRange)(cellPos[0], viewportRange)) {
1330
+ } else if (!(0, import_vuu_utils8.withinRange)(cellPos[0], viewportRange)) {
1379
1331
  focusableCell.current = void 0;
1380
1332
  requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "up" });
1381
1333
  }
@@ -1385,7 +1337,7 @@ var useKeyboardNavigation = ({
1385
1337
  // be often whilst scrolling - store range in a a ref ?
1386
1338
  [containerRef, getTableCell, requestScroll, viewportRange]
1387
1339
  );
1388
- const setActiveCell = (0, import_react13.useCallback)(
1340
+ const setActiveCell = (0, import_react12.useCallback)(
1389
1341
  (rowIdx, colIdx, fromKeyboard = false) => {
1390
1342
  const pos = [rowIdx, colIdx];
1391
1343
  activeCellPos.current = pos;
@@ -1396,12 +1348,12 @@ var useKeyboardNavigation = ({
1396
1348
  },
1397
1349
  [focusCell]
1398
1350
  );
1399
- const virtualizeActiveCell = (0, import_react13.useCallback)(() => {
1351
+ const virtualizeActiveCell = (0, import_react12.useCallback)(() => {
1400
1352
  var _a2;
1401
1353
  (_a2 = focusableCell.current) == null ? void 0 : _a2.setAttribute("tabindex", "");
1402
1354
  focusableCell.current = void 0;
1403
1355
  }, []);
1404
- const nextPageItemIdx = (0, import_react13.useCallback)(
1356
+ const nextPageItemIdx = (0, import_react12.useCallback)(
1405
1357
  async (key, cellPos) => {
1406
1358
  switch (key) {
1407
1359
  case PageDown:
@@ -1421,7 +1373,7 @@ var useKeyboardNavigation = ({
1421
1373
  },
1422
1374
  [requestScroll]
1423
1375
  );
1424
- const handleFocus = (0, import_react13.useCallback)(() => {
1376
+ const handleFocus = (0, import_react12.useCallback)(() => {
1425
1377
  var _a2;
1426
1378
  if (disableHighlightOnFocus !== true) {
1427
1379
  if ((_a2 = containerRef.current) == null ? void 0 : _a2.contains(document.activeElement)) {
@@ -1432,7 +1384,7 @@ var useKeyboardNavigation = ({
1432
1384
  }
1433
1385
  }
1434
1386
  }, [disableHighlightOnFocus, containerRef]);
1435
- const navigateChildItems = (0, import_react13.useCallback)(
1387
+ const navigateChildItems = (0, import_react12.useCallback)(
1436
1388
  async (key) => {
1437
1389
  const [nextRowIdx, nextColIdx] = isPagingKey(key) ? await nextPageItemIdx(key, activeCellPos.current) : nextCellPos(key, activeCellPos.current, columnCount, rowCount);
1438
1390
  const [rowIdx, colIdx] = activeCellPos.current;
@@ -1442,7 +1394,7 @@ var useKeyboardNavigation = ({
1442
1394
  },
1443
1395
  [columnCount, nextPageItemIdx, rowCount, setActiveCell]
1444
1396
  );
1445
- const handleKeyDown = (0, import_react13.useCallback)(
1397
+ const handleKeyDown = (0, import_react12.useCallback)(
1446
1398
  (e) => {
1447
1399
  if (data.length > 0 && isNavigationKey(e.key)) {
1448
1400
  e.preventDefault();
@@ -1452,7 +1404,7 @@ var useKeyboardNavigation = ({
1452
1404
  },
1453
1405
  [data, navigateChildItems]
1454
1406
  );
1455
- const handleClick = (0, import_react13.useCallback)(
1407
+ const handleClick = (0, import_react12.useCallback)(
1456
1408
  // Might not be a cell e.g the Settings button
1457
1409
  (evt) => {
1458
1410
  const target = evt.target;
@@ -1464,14 +1416,14 @@ var useKeyboardNavigation = ({
1464
1416
  },
1465
1417
  [setActiveCell]
1466
1418
  );
1467
- const containerProps = (0, import_react13.useMemo)(() => {
1419
+ const containerProps = (0, import_react12.useMemo)(() => {
1468
1420
  return {
1469
1421
  onClick: handleClick,
1470
1422
  onFocus: handleFocus,
1471
1423
  onKeyDown: handleKeyDown
1472
1424
  };
1473
1425
  }, [handleClick, handleFocus, handleKeyDown]);
1474
- (0, import_react13.useLayoutEffect)(() => {
1426
+ (0, import_react12.useLayoutEffect)(() => {
1475
1427
  const { current: cellPos } = activeCellPos;
1476
1428
  const withinViewport = cellPos[0] >= viewportFirstRow && cellPos[0] <= viewportLastRow;
1477
1429
  if (focusableCell.current && !withinViewport) {
@@ -1481,7 +1433,7 @@ var useKeyboardNavigation = ({
1481
1433
  }
1482
1434
  }, [focusCell, viewportFirstRow, viewportLastRow, virtualizeActiveCell]);
1483
1435
  const fullyRendered = ((_a = containerRef.current) == null ? void 0 : _a.firstChild) != null;
1484
- (0, import_react13.useEffect)(() => {
1436
+ (0, import_react12.useEffect)(() => {
1485
1437
  var _a2;
1486
1438
  if (fullyRendered && focusableCell.current === void 0) {
1487
1439
  const headerCell = (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector(
@@ -1497,10 +1449,10 @@ var useKeyboardNavigation = ({
1497
1449
  };
1498
1450
 
1499
1451
  // src/useMeasuredContainer.ts
1500
- var import_react15 = require("react");
1452
+ var import_react14 = require("react");
1501
1453
 
1502
1454
  // src/useResizeObserver.ts
1503
- var import_react14 = require("react");
1455
+ var import_react13 = require("react");
1504
1456
  var observedMap = /* @__PURE__ */ new Map();
1505
1457
  var getTargetSize = (element, size, dimension) => {
1506
1458
  switch (dimension) {
@@ -1551,8 +1503,8 @@ var resizeObserver = new ResizeObserver((entries) => {
1551
1503
  }
1552
1504
  });
1553
1505
  function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false) {
1554
- const dimensionsRef = (0, import_react14.useRef)(dimensions);
1555
- const measure = (0, import_react14.useCallback)((target) => {
1506
+ const dimensionsRef = (0, import_react13.useRef)(dimensions);
1507
+ const measure = (0, import_react13.useCallback)((target) => {
1556
1508
  const { width, height } = target.getBoundingClientRect();
1557
1509
  const { clientWidth: contentWidth, clientHeight: contentHeight } = target;
1558
1510
  return dimensionsRef.current.reduce(
@@ -1567,7 +1519,7 @@ function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false)
1567
1519
  {}
1568
1520
  );
1569
1521
  }, []);
1570
- (0, import_react14.useEffect)(() => {
1522
+ (0, import_react13.useEffect)(() => {
1571
1523
  const target = ref.current;
1572
1524
  async function registerObserver() {
1573
1525
  observedMap.set(target, { measurements: {} });
@@ -1602,7 +1554,7 @@ function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false)
1602
1554
  }
1603
1555
  };
1604
1556
  }, [measure, ref]);
1605
- (0, import_react14.useEffect)(() => {
1557
+ (0, import_react13.useEffect)(() => {
1606
1558
  const target = ref.current;
1607
1559
  const record = observedMap.get(target);
1608
1560
  if (record) {
@@ -1625,15 +1577,16 @@ var useMeasuredContainer = ({
1625
1577
  height,
1626
1578
  width
1627
1579
  }) => {
1628
- const containerRef = (0, import_react15.useRef)(null);
1629
- const [size, setSize] = (0, import_react15.useState)({
1580
+ const containerRef = (0, import_react14.useRef)(null);
1581
+ const [size, setSize] = (0, import_react14.useState)({
1630
1582
  outer: {
1631
1583
  height: height != null ? height : "100%",
1632
1584
  width: width != null ? width : "100%"
1633
1585
  }
1634
1586
  });
1635
- const onResize = (0, import_react15.useCallback)(
1587
+ const onResize = (0, import_react14.useCallback)(
1636
1588
  ({ clientWidth, clientHeight }) => {
1589
+ console.log(`Resize ${clientHeight}`);
1637
1590
  setSize((currentSize) => {
1638
1591
  const { inner, outer } = currentSize;
1639
1592
  return isNumber(clientHeight) && isNumber(clientWidth) && (clientWidth !== (inner == null ? void 0 : inner.width) || clientHeight !== (inner == null ? void 0 : inner.height)) ? {
@@ -1656,23 +1609,23 @@ var useMeasuredContainer = ({
1656
1609
  };
1657
1610
 
1658
1611
  // src/useSelection.ts
1659
- var import_vuu_utils10 = require("@vuu-ui/vuu-utils");
1660
- var import_react16 = require("react");
1661
- var { IDX: IDX2, SELECTED: SELECTED3 } = import_vuu_utils10.metadataKeys;
1612
+ var import_vuu_utils9 = require("@vuu-ui/vuu-utils");
1613
+ var import_react15 = require("react");
1614
+ var { IDX: IDX2, SELECTED: SELECTED3 } = import_vuu_utils9.metadataKeys;
1662
1615
  var NO_SELECTION = [];
1663
1616
  var useSelection = ({
1664
1617
  selectionModel,
1665
1618
  onSelectionChange
1666
1619
  }) => {
1667
1620
  selectionModel === "extended" || selectionModel === "checkbox";
1668
- const lastActiveRef = (0, import_react16.useRef)(-1);
1669
- const selectedRef = (0, import_react16.useRef)(NO_SELECTION);
1670
- const handleSelectionChange = (0, import_react16.useCallback)(
1621
+ const lastActiveRef = (0, import_react15.useRef)(-1);
1622
+ const selectedRef = (0, import_react15.useRef)(NO_SELECTION);
1623
+ const handleSelectionChange = (0, import_react15.useCallback)(
1671
1624
  (row, rangeSelect, keepExistingSelection) => {
1672
1625
  const { [IDX2]: idx, [SELECTED3]: isSelected } = row;
1673
1626
  const { current: active } = lastActiveRef;
1674
1627
  const { current: selected } = selectedRef;
1675
- const selectOperation = isSelected ? import_vuu_utils10.deselectItem : import_vuu_utils10.selectItem;
1628
+ const selectOperation = isSelected ? import_vuu_utils9.deselectItem : import_vuu_utils9.selectItem;
1676
1629
  const newSelected = selectOperation(
1677
1630
  selectionModel,
1678
1631
  selected,
@@ -1694,16 +1647,16 @@ var useSelection = ({
1694
1647
 
1695
1648
  // src/useTableModel.ts
1696
1649
  var import_salt_lab3 = require("@heswell/salt-lab");
1697
- var import_vuu_utils11 = require("@vuu-ui/vuu-utils");
1698
- var import_react17 = require("react");
1699
- var { info } = (0, import_vuu_utils11.logger)("useTableModel");
1650
+ var import_vuu_utils10 = require("@vuu-ui/vuu-utils");
1651
+ var import_react16 = require("react");
1652
+ var { info } = (0, import_vuu_utils10.logger)("useTableModel");
1700
1653
  var DEFAULT_COLUMN_WIDTH = 100;
1701
- var KEY_OFFSET = import_vuu_utils11.metadataKeys.count;
1654
+ var KEY_OFFSET = import_vuu_utils10.metadataKeys.count;
1702
1655
  var columnWithoutDataType = ({ serverDataType }) => serverDataType === void 0;
1703
1656
  var getCellRendererForColumn = (column) => {
1704
1657
  var _a;
1705
- if ((0, import_vuu_utils11.isTypeDescriptor)(column.type)) {
1706
- return (0, import_vuu_utils11.getCellRenderer)((_a = column.type) == null ? void 0 : _a.renderer);
1658
+ if ((0, import_vuu_utils10.isTypeDescriptor)(column.type)) {
1659
+ return (0, import_vuu_utils10.getCellRenderer)((_a = column.type) == null ? void 0 : _a.renderer);
1707
1660
  }
1708
1661
  };
1709
1662
  var getDataType = (column, columnNames, dataTypes) => {
@@ -1744,7 +1697,7 @@ var columnReducer = (state, action) => {
1744
1697
  }
1745
1698
  };
1746
1699
  var useTableModel = (tableConfig, dataSourceConfig) => {
1747
- const [state, dispatchColumnAction] = (0, import_react17.useReducer)(columnReducer, { tableConfig, dataSourceConfig }, init);
1700
+ const [state, dispatchColumnAction] = (0, import_react16.useReducer)(columnReducer, { tableConfig, dataSourceConfig }, init);
1748
1701
  return {
1749
1702
  columns: state.columns,
1750
1703
  dispatchColumnAction,
@@ -1755,10 +1708,10 @@ function init({ dataSourceConfig, tableConfig }) {
1755
1708
  const columns = tableConfig.columns.map(
1756
1709
  toKeyedColumWithDefaults(tableConfig)
1757
1710
  );
1758
- const maybePinnedColumns = columns.some(import_vuu_utils11.isPinned) ? (0, import_vuu_utils11.sortPinnedColumns)(columns) : columns;
1711
+ const maybePinnedColumns = columns.some(import_vuu_utils10.isPinned) ? (0, import_vuu_utils10.sortPinnedColumns)(columns) : columns;
1759
1712
  const state = {
1760
1713
  columns: maybePinnedColumns,
1761
- headings: (0, import_vuu_utils11.getTableHeadings)(maybePinnedColumns)
1714
+ headings: (0, import_vuu_utils10.getTableHeadings)(maybePinnedColumns)
1762
1715
  };
1763
1716
  if (dataSourceConfig) {
1764
1717
  const { columns: columns2, ...rest } = dataSourceConfig;
@@ -1796,10 +1749,10 @@ var toKeyedColumWithDefaults = (options) => (column, index) => {
1796
1749
  key: key != null ? key : index + KEY_OFFSET,
1797
1750
  name,
1798
1751
  originalIdx: index,
1799
- valueFormatter: (0, import_vuu_utils11.getValueFormatter)(column),
1752
+ valueFormatter: (0, import_vuu_utils10.getValueFormatter)(column),
1800
1753
  width
1801
1754
  };
1802
- if ((0, import_vuu_utils11.isGroupColumn)(keyedColumnWithDefaults)) {
1755
+ if ((0, import_vuu_utils10.isGroupColumn)(keyedColumnWithDefaults)) {
1803
1756
  keyedColumnWithDefaults.columns = keyedColumnWithDefaults.columns.map(
1804
1757
  (col) => toKeyedColumWithDefaults(options)(col, col.key)
1805
1758
  );
@@ -1899,7 +1852,7 @@ function pinColumn2(state, action) {
1899
1852
  const targetColumn = columns.find((col) => col.name === column.name);
1900
1853
  if (targetColumn) {
1901
1854
  columns = replaceColumn(columns, { ...targetColumn, pin });
1902
- columns = (0, import_vuu_utils11.sortPinnedColumns)(columns);
1855
+ columns = (0, import_vuu_utils10.sortPinnedColumns)(columns);
1903
1856
  return {
1904
1857
  ...state,
1905
1858
  columns
@@ -1944,9 +1897,9 @@ function updateTableConfig(state, { columns, confirmed, filter, groupBy, sort })
1944
1897
  result = {
1945
1898
  ...state,
1946
1899
  columns: columns.map((colName, index) => {
1947
- const columnName = (0, import_vuu_utils11.getColumnName)(colName);
1900
+ const columnName = (0, import_vuu_utils10.getColumnName)(colName);
1948
1901
  const key = index + KEY_OFFSET;
1949
- const col = (0, import_vuu_utils11.findColumn)(result.columns, columnName);
1902
+ const col = (0, import_vuu_utils10.findColumn)(result.columns, columnName);
1950
1903
  if (col) {
1951
1904
  if (col.key === key) {
1952
1905
  return col;
@@ -1964,24 +1917,24 @@ function updateTableConfig(state, { columns, confirmed, filter, groupBy, sort })
1964
1917
  if (hasGroupBy) {
1965
1918
  result = {
1966
1919
  ...state,
1967
- columns: (0, import_vuu_utils11.applyGroupByToColumns)(result.columns, groupBy, confirmed)
1920
+ columns: (0, import_vuu_utils10.applyGroupByToColumns)(result.columns, groupBy, confirmed)
1968
1921
  };
1969
1922
  }
1970
1923
  if (hasSort) {
1971
1924
  result = {
1972
1925
  ...state,
1973
- columns: (0, import_vuu_utils11.applySortToColumns)(result.columns, sort)
1926
+ columns: (0, import_vuu_utils10.applySortToColumns)(result.columns, sort)
1974
1927
  };
1975
1928
  }
1976
1929
  if (hasFilter) {
1977
1930
  result = {
1978
1931
  ...state,
1979
- columns: (0, import_vuu_utils11.applyFilterToColumns)(result.columns, filter)
1932
+ columns: (0, import_vuu_utils10.applyFilterToColumns)(result.columns, filter)
1980
1933
  };
1981
- } else if (result.columns.some(import_vuu_utils11.isFilteredColumn)) {
1934
+ } else if (result.columns.some(import_vuu_utils10.isFilteredColumn)) {
1982
1935
  result = {
1983
1936
  ...state,
1984
- columns: (0, import_vuu_utils11.stripFilterFromColumns)(result.columns)
1937
+ columns: (0, import_vuu_utils10.stripFilterFromColumns)(result.columns)
1985
1938
  };
1986
1939
  }
1987
1940
  return result;
@@ -1991,78 +1944,52 @@ function replaceColumn(state, column) {
1991
1944
  }
1992
1945
 
1993
1946
  // src/useTableScroll.ts
1994
- var import_react18 = require("react");
1947
+ var import_react17 = require("react");
1995
1948
  var getPctScroll = (container) => {
1996
1949
  const { scrollLeft, scrollTop } = container;
1997
1950
  const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
1998
1951
  const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);
1999
1952
  const pctScrollTop = scrollTop / (scrollHeight - clientHeight);
2000
- return [pctScrollLeft, pctScrollTop, scrollLeft, scrollTop];
1953
+ return [pctScrollLeft, pctScrollTop];
2001
1954
  };
2002
1955
  var getMaxScroll = (container) => {
2003
1956
  const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2004
1957
  return [scrollWidth - clientWidth, scrollHeight - clientHeight];
2005
1958
  };
1959
+ var useCallbackRef = ({
1960
+ onAttach,
1961
+ onDetach
1962
+ }) => {
1963
+ const ref = (0, import_react17.useRef)(null);
1964
+ const callbackRef = (0, import_react17.useCallback)(
1965
+ (el) => {
1966
+ if (el) {
1967
+ ref.current = el;
1968
+ onAttach == null ? void 0 : onAttach(el);
1969
+ } else if (ref.current) {
1970
+ const { current: originalRef } = ref;
1971
+ ref.current = el;
1972
+ onDetach == null ? void 0 : onDetach(originalRef);
1973
+ }
1974
+ },
1975
+ [onAttach, onDetach]
1976
+ );
1977
+ return callbackRef;
1978
+ };
2006
1979
  var useTableScroll = ({
2007
1980
  onHorizontalScroll,
2008
1981
  onVerticalScroll,
2009
1982
  viewport
2010
1983
  }) => {
2011
- const scrollPosRef = (0, import_react18.useRef)({ scrollTop: 0, scrollLeft: 0 });
2012
- const scrollbarContainerRef = (0, import_react18.useRef)(null);
2013
- const contentContainerRef = (0, import_react18.useRef)(null);
2014
- const tableContainerRef = (0, import_react18.useRef)(null);
2015
- const contentContainerScrolledRef = (0, import_react18.useRef)(false);
1984
+ const contentContainerScrolledRef = (0, import_react17.useRef)(false);
1985
+ const scrollPosRef = (0, import_react17.useRef)({ scrollTop: 0, scrollLeft: 0 });
1986
+ const scrollbarContainerRef = (0, import_react17.useRef)(null);
1987
+ const contentContainerRef = (0, import_react17.useRef)(null);
2016
1988
  const {
2017
1989
  maxScrollContainerScrollHorizontal: maxScrollLeft,
2018
1990
  maxScrollContainerScrollVertical: maxScrollTop
2019
1991
  } = viewport;
2020
- const scrollTable = (0, import_react18.useCallback)(
2021
- (scrollLeft, scrollTop) => {
2022
- const { current: tableContainer } = tableContainerRef;
2023
- if (tableContainer) {
2024
- tableContainer.scrollTo({
2025
- top: scrollTop,
2026
- left: scrollLeft,
2027
- behavior: "auto"
2028
- });
2029
- }
2030
- },
2031
- [tableContainerRef]
2032
- );
2033
- const handleTableContainerScroll = (0, import_react18.useCallback)(() => {
2034
- const { current: tableContainer } = tableContainerRef;
2035
- if (tableContainer) {
2036
- const { current: scrollPos } = scrollPosRef;
2037
- const { scrollLeft, scrollTop } = tableContainer;
2038
- if (scrollPos.scrollTop !== scrollTop) {
2039
- scrollPos.scrollTop = scrollTop;
2040
- onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop);
2041
- }
2042
- if (scrollPos.scrollLeft !== scrollLeft) {
2043
- scrollPos.scrollLeft = scrollLeft;
2044
- onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2045
- }
2046
- }
2047
- }, [onHorizontalScroll, onVerticalScroll]);
2048
- const handleContentContainerScroll = (0, import_react18.useCallback)(() => {
2049
- const { current: rootContainer } = contentContainerRef;
2050
- const { current: scrollContainer } = scrollbarContainerRef;
2051
- if (rootContainer && scrollContainer) {
2052
- const [pctScrollLeft, pctScrollTop, scrollLeft, scrollTop] = getPctScroll(rootContainer);
2053
- contentContainerScrolledRef.current = true;
2054
- scrollContainer.scrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2055
- scrollContainer.scrollTop = Math.round(pctScrollTop * maxScrollTop);
2056
- scrollTable(scrollLeft, scrollTop);
2057
- }
2058
- }, [
2059
- maxScrollLeft,
2060
- maxScrollTop,
2061
- contentContainerRef,
2062
- scrollbarContainerRef,
2063
- scrollTable
2064
- ]);
2065
- const handleScrollbarContainerScroll = (0, import_react18.useCallback)(() => {
1992
+ const handleScrollbarContainerScroll = (0, import_react17.useCallback)(() => {
2066
1993
  const { current: contentContainer } = contentContainerRef;
2067
1994
  const { current: scrollbarContainer } = scrollbarContainerRef;
2068
1995
  const { current: contentContainerScrolled } = contentContainerScrolledRef;
@@ -2078,12 +2005,71 @@ var useTableScroll = ({
2078
2005
  top: rootScrollTop,
2079
2006
  behavior: "auto"
2080
2007
  });
2081
- scrollTable(rootScrollLeft, rootScrollTop);
2082
2008
  }
2083
- }, [contentContainerRef, scrollbarContainerRef, scrollTable]);
2084
- const requestScroll = (0, import_react18.useCallback)(
2009
+ }, []);
2010
+ const handleContentContainerScroll = (0, import_react17.useCallback)(() => {
2011
+ const { current: contentContainer } = contentContainerRef;
2012
+ const { current: scrollbarContainer } = scrollbarContainerRef;
2013
+ const { current: scrollPos } = scrollPosRef;
2014
+ if (contentContainer && scrollbarContainer) {
2015
+ const { scrollLeft, scrollTop } = contentContainer;
2016
+ const [pctScrollLeft, pctScrollTop] = getPctScroll(contentContainer);
2017
+ contentContainerScrolledRef.current = true;
2018
+ scrollbarContainer.scrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2019
+ scrollbarContainer.scrollTop = Math.round(pctScrollTop * maxScrollTop);
2020
+ if (scrollPos.scrollTop !== scrollTop) {
2021
+ scrollPos.scrollTop = scrollTop;
2022
+ onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop, pctScrollTop);
2023
+ }
2024
+ if (scrollPos.scrollLeft !== scrollLeft) {
2025
+ scrollPos.scrollLeft = scrollLeft;
2026
+ onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2027
+ }
2028
+ }
2029
+ }, [maxScrollLeft, maxScrollTop, onHorizontalScroll, onVerticalScroll]);
2030
+ const handleAttachScrollbarContainer = (0, import_react17.useCallback)(
2031
+ (el) => {
2032
+ scrollbarContainerRef.current = el;
2033
+ el.addEventListener("scroll", handleScrollbarContainerScroll, {
2034
+ passive: true
2035
+ });
2036
+ },
2037
+ [handleScrollbarContainerScroll]
2038
+ );
2039
+ const handleDetachScrollbarContainer = (0, import_react17.useCallback)(
2040
+ (el) => {
2041
+ scrollbarContainerRef.current = null;
2042
+ el.removeEventListener("scroll", handleScrollbarContainerScroll);
2043
+ },
2044
+ [handleScrollbarContainerScroll]
2045
+ );
2046
+ const handleAttachContentContainer = (0, import_react17.useCallback)(
2047
+ (el) => {
2048
+ contentContainerRef.current = el;
2049
+ el.addEventListener("scroll", handleContentContainerScroll, {
2050
+ passive: true
2051
+ });
2052
+ },
2053
+ [handleContentContainerScroll]
2054
+ );
2055
+ const handleDetachContentContainer = (0, import_react17.useCallback)(
2056
+ (el) => {
2057
+ contentContainerRef.current = null;
2058
+ el.removeEventListener("scroll", handleContentContainerScroll);
2059
+ },
2060
+ [handleContentContainerScroll]
2061
+ );
2062
+ const contentContainerCallbackRef = useCallbackRef({
2063
+ onAttach: handleAttachContentContainer,
2064
+ onDetach: handleDetachContentContainer
2065
+ });
2066
+ const scrollbarContainerCallbackRef = useCallbackRef({
2067
+ onAttach: handleAttachScrollbarContainer,
2068
+ onDetach: handleDetachScrollbarContainer
2069
+ });
2070
+ const requestScroll = (0, import_react17.useCallback)(
2085
2071
  (scrollRequest) => {
2086
- const { current: scrollbarContainer } = scrollbarContainerRef;
2072
+ const { current: scrollbarContainer } = contentContainerRef;
2087
2073
  if (scrollbarContainer) {
2088
2074
  contentContainerScrolledRef.current = false;
2089
2075
  if (scrollRequest.type === "scroll-page") {
@@ -2092,7 +2078,7 @@ var useTableScroll = ({
2092
2078
  const scrollBy = direction === "down" ? clientHeight : -clientHeight;
2093
2079
  const newScrollTop = Math.min(
2094
2080
  Math.max(0, scrollTop + scrollBy),
2095
- viewport.maxScrollContainerScrollVertical
2081
+ maxScrollTop
2096
2082
  );
2097
2083
  scrollbarContainer.scrollTo({
2098
2084
  top: newScrollTop,
@@ -2101,7 +2087,7 @@ var useTableScroll = ({
2101
2087
  });
2102
2088
  } else if (scrollRequest.type === "scroll-end") {
2103
2089
  const { direction } = scrollRequest;
2104
- const scrollTo = direction === "end" ? viewport.maxScrollContainerScrollVertical : 0;
2090
+ const scrollTo = direction === "end" ? maxScrollTop : 0;
2105
2091
  scrollbarContainer.scrollTo({
2106
2092
  top: scrollTo,
2107
2093
  left: scrollbarContainer.scrollLeft,
@@ -2110,39 +2096,37 @@ var useTableScroll = ({
2110
2096
  }
2111
2097
  }
2112
2098
  },
2113
- [viewport.maxScrollContainerScrollVertical]
2099
+ [maxScrollTop]
2114
2100
  );
2115
2101
  return {
2116
2102
  /** Ref to be assigned to ScrollbarContainer */
2117
- scrollbarContainerRef,
2118
- /** Scroll handler to be attached to ScrollbarContainer */
2119
- onScrollbarContainerScroll: handleScrollbarContainerScroll,
2103
+ scrollbarContainerRef: scrollbarContainerCallbackRef,
2120
2104
  /** Ref to be assigned to ContentContainer */
2121
- contentContainerRef,
2122
- /** Scroll handler to be attached to ContentContainer */
2123
- onContentContainerScroll: handleContentContainerScroll,
2124
- /** Ref to be assigned to TableContainer */
2125
- tableContainerRef,
2126
- /** Scroll handler to be attached to TableContainer */
2127
- onTableContainerScroll: handleTableContainerScroll,
2105
+ contentContainerRef: contentContainerCallbackRef,
2128
2106
  /** Scroll the table */
2129
2107
  requestScroll
2130
2108
  };
2131
2109
  };
2132
2110
 
2133
2111
  // src/useTableViewport.ts
2134
- var import_react19 = require("react");
2112
+ var import_react18 = require("react");
2113
+ var import_vuu_utils11 = require("@vuu-ui/vuu-utils");
2114
+ var MAX_RAW_ROWS = 15e5;
2135
2115
  var UNMEASURED_VIEWPORT = {
2136
- fillerHeight: 0,
2116
+ contentHeight: 0,
2117
+ contentWidth: 0,
2118
+ getRowAtPosition: () => -1,
2119
+ getRowOffset: () => -1,
2120
+ horizontalScrollbarHeight: 0,
2137
2121
  maxScrollContainerScrollHorizontal: 0,
2138
2122
  maxScrollContainerScrollVertical: 0,
2139
2123
  pinnedWidthLeft: 0,
2140
2124
  pinnedWidthRight: 0,
2141
2125
  rowCount: 0,
2142
- scrollContentHeight: 0,
2143
- scrollbarSize: 0,
2144
- scrollContentWidth: 0,
2145
- totalHeaderHeight: 0
2126
+ setPctScrollTop: () => void 0,
2127
+ totalHeaderHeight: 0,
2128
+ verticalScrollbarWidth: 0,
2129
+ viewportBodyHeight: 0
2146
2130
  };
2147
2131
  var measurePinnedColumns = (columns) => {
2148
2132
  let pinnedWidthLeft = 0;
@@ -2169,67 +2153,99 @@ var useTableViewport = ({
2169
2153
  rowHeight,
2170
2154
  size
2171
2155
  }) => {
2172
- const { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth } = (0, import_react19.useMemo)(
2156
+ const pctScrollTopRef = (0, import_react18.useRef)(0);
2157
+ const appliedRowCount = Math.min(rowCount, MAX_RAW_ROWS);
2158
+ const appliedContentHeight = appliedRowCount * rowHeight;
2159
+ const virtualContentHeight = rowCount * rowHeight;
2160
+ const virtualisedExtent = virtualContentHeight - appliedContentHeight;
2161
+ const { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth } = (0, import_react18.useMemo)(
2173
2162
  () => measurePinnedColumns(columns),
2174
2163
  [columns]
2175
2164
  );
2176
- const viewportMeasurements = (0, import_react19.useMemo)(() => {
2165
+ const [actualRowOffset, actualRowAtPosition] = (0, import_react18.useMemo)(
2166
+ () => (0, import_vuu_utils11.actualRowPositioning)(rowHeight),
2167
+ [rowHeight]
2168
+ );
2169
+ const [getRowOffset, getRowAtPosition] = (0, import_react18.useMemo)(() => {
2170
+ if (virtualisedExtent) {
2171
+ return (0, import_vuu_utils11.virtualRowPositioning)(
2172
+ rowHeight,
2173
+ virtualisedExtent,
2174
+ pctScrollTopRef
2175
+ );
2176
+ } else {
2177
+ return [actualRowOffset, actualRowAtPosition];
2178
+ }
2179
+ }, [actualRowAtPosition, actualRowOffset, virtualisedExtent, rowHeight]);
2180
+ const setPctScrollTop = (0, import_react18.useCallback)((scrollPct) => {
2181
+ pctScrollTopRef.current = scrollPct;
2182
+ }, []);
2183
+ return (0, import_react18.useMemo)(() => {
2177
2184
  var _a;
2178
2185
  if (size) {
2179
2186
  const headingsDepth = headings.length;
2180
2187
  const scrollbarSize = 15;
2181
- const contentHeight = rowCount * rowHeight;
2182
- const scrollContentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2183
- const maxScrollContainerScrollVertical = contentHeight + headerHeight - (((_a = size == null ? void 0 : size.height) != null ? _a : 0) - headerHeight - scrollbarSize);
2184
- const maxScrollContainerScrollHorizontal = scrollContentWidth - size.width + pinnedWidthLeft;
2188
+ const contentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2189
+ const horizontalScrollbarHeight = contentWidth > size.width ? scrollbarSize : 0;
2190
+ const totalHeaderHeight = headerHeight * (1 + headingsDepth);
2191
+ const maxScrollContainerScrollVertical = appliedContentHeight - (((_a = size == null ? void 0 : size.height) != null ? _a : 0) - horizontalScrollbarHeight) + totalHeaderHeight;
2192
+ const maxScrollContainerScrollHorizontal = contentWidth - size.width + pinnedWidthLeft;
2185
2193
  const visibleRows = (size.height - headerHeight) / rowHeight;
2186
2194
  const count = Number.isInteger(visibleRows) ? visibleRows + 1 : Math.ceil(visibleRows);
2195
+ const viewportBodyHeight = size.height - totalHeaderHeight;
2196
+ const verticalScrollbarWidth = appliedContentHeight > viewportBodyHeight ? scrollbarSize : 0;
2187
2197
  return {
2188
- fillerHeight: (rowCount - count) * rowHeight,
2198
+ contentHeight: appliedContentHeight,
2199
+ getRowAtPosition,
2200
+ getRowOffset,
2201
+ horizontalScrollbarHeight,
2189
2202
  maxScrollContainerScrollHorizontal,
2190
2203
  maxScrollContainerScrollVertical,
2191
2204
  pinnedWidthLeft,
2192
2205
  pinnedWidthRight,
2193
2206
  rowCount: count,
2194
- scrollContentHeight: headerHeight + contentHeight + scrollbarSize,
2195
- scrollbarSize,
2196
- scrollContentWidth,
2197
- totalHeaderHeight: headerHeight * (1 + headingsDepth)
2207
+ contentWidth,
2208
+ setPctScrollTop,
2209
+ totalHeaderHeight,
2210
+ verticalScrollbarWidth,
2211
+ viewportBodyHeight
2198
2212
  };
2199
2213
  } else {
2200
2214
  return UNMEASURED_VIEWPORT;
2201
2215
  }
2202
2216
  }, [
2203
- headerHeight,
2217
+ size,
2204
2218
  headings.length,
2205
2219
  pinnedWidthLeft,
2220
+ unpinnedWidth,
2206
2221
  pinnedWidthRight,
2207
- rowCount,
2222
+ appliedContentHeight,
2223
+ headerHeight,
2208
2224
  rowHeight,
2209
- size,
2210
- unpinnedWidth
2225
+ getRowAtPosition,
2226
+ getRowOffset,
2227
+ setPctScrollTop
2211
2228
  ]);
2212
- return viewportMeasurements;
2213
2229
  };
2214
2230
 
2215
2231
  // src/useVirtualViewport.ts
2216
2232
  var import_vuu_utils12 = require("@vuu-ui/vuu-utils");
2217
- var import_react20 = require("react");
2233
+ var import_react19 = require("react");
2218
2234
  var useVirtualViewport = ({
2219
2235
  columns,
2220
- rowHeight,
2236
+ getRowAtPosition,
2221
2237
  setRange,
2222
2238
  viewportMeasurements
2223
2239
  }) => {
2224
- const firstRowRef = (0, import_react20.useRef)(-1);
2240
+ const firstRowRef = (0, import_react19.useRef)(-1);
2225
2241
  const {
2226
2242
  rowCount: viewportRowCount,
2227
- scrollContentWidth: contentWidth,
2243
+ contentWidth,
2228
2244
  maxScrollContainerScrollHorizontal
2229
2245
  } = viewportMeasurements;
2230
2246
  const availableWidth = contentWidth - maxScrollContainerScrollHorizontal;
2231
- const scrollLeftRef = (0, import_react20.useRef)(0);
2232
- const [visibleColumns, preSpan] = (0, import_react20.useMemo)(
2247
+ const scrollLeftRef = (0, import_react19.useRef)(0);
2248
+ const [visibleColumns, preSpan] = (0, import_react19.useMemo)(
2233
2249
  () => (0, import_vuu_utils12.getColumnsInViewport)(
2234
2250
  columns,
2235
2251
  scrollLeftRef.current,
@@ -2237,12 +2253,12 @@ var useVirtualViewport = ({
2237
2253
  ),
2238
2254
  [availableWidth, columns]
2239
2255
  );
2240
- const preSpanRef = (0, import_react20.useRef)(preSpan);
2241
- (0, import_react20.useEffect)(() => {
2256
+ const preSpanRef = (0, import_react19.useRef)(preSpan);
2257
+ (0, import_react19.useEffect)(() => {
2242
2258
  setColumnsWithinViewport(visibleColumns);
2243
2259
  }, [visibleColumns]);
2244
- const [columnsWithinViewport, setColumnsWithinViewport] = (0, import_react20.useState)(visibleColumns);
2245
- const handleHorizontalScroll = (0, import_react20.useCallback)(
2260
+ const [columnsWithinViewport, setColumnsWithinViewport] = (0, import_react19.useState)(visibleColumns);
2261
+ const handleHorizontalScroll = (0, import_react19.useCallback)(
2246
2262
  (scrollLeft) => {
2247
2263
  scrollLeftRef.current = scrollLeft;
2248
2264
  const [visibleColumns2, pre] = (0, import_vuu_utils12.getColumnsInViewport)(
@@ -2257,15 +2273,15 @@ var useVirtualViewport = ({
2257
2273
  },
2258
2274
  [availableWidth, columns, columnsWithinViewport]
2259
2275
  );
2260
- const handleVerticalScroll = (0, import_react20.useCallback)(
2276
+ const handleVerticalScroll = (0, import_react19.useCallback)(
2261
2277
  (scrollTop) => {
2262
- const firstRow = Math.floor(scrollTop / rowHeight);
2278
+ const firstRow = getRowAtPosition(scrollTop);
2263
2279
  if (firstRow !== firstRowRef.current) {
2264
2280
  firstRowRef.current = firstRow;
2265
2281
  setRange({ from: firstRow, to: firstRow + viewportRowCount });
2266
2282
  }
2267
2283
  },
2268
- [rowHeight, setRange, viewportRowCount]
2284
+ [getRowAtPosition, setRange, viewportRowCount]
2269
2285
  );
2270
2286
  return {
2271
2287
  columnsWithinViewport,
@@ -2276,10 +2292,10 @@ var useVirtualViewport = ({
2276
2292
  };
2277
2293
  };
2278
2294
 
2279
- // src/useDataTable.ts
2295
+ // src/useTable.ts
2280
2296
  var NO_ROWS = [];
2281
2297
  var { KEY: KEY2, IS_EXPANDED: IS_EXPANDED2, IS_LEAF: IS_LEAF2 } = import_vuu_utils13.metadataKeys;
2282
- var useDataTable = ({
2298
+ var useTable = ({
2283
2299
  config,
2284
2300
  dataSource,
2285
2301
  headerHeight,
@@ -2290,37 +2306,41 @@ var useDataTable = ({
2290
2306
  renderBufferSize = 0,
2291
2307
  rowHeight,
2292
2308
  selectionModel,
2293
- tableLayout,
2294
2309
  ...measuredProps
2295
2310
  }) => {
2296
2311
  var _a, _b;
2297
- const [rowCount, setRowCount] = (0, import_react21.useState)(0);
2298
- const expectConfigChangeRef = (0, import_react21.useRef)(false);
2299
- const dataSourceRef = (0, import_react21.useRef)();
2312
+ const [rowCount, setRowCount] = (0, import_react20.useState)(0);
2313
+ const expectConfigChangeRef = (0, import_react20.useRef)(false);
2314
+ const dataSourceRef = (0, import_react20.useRef)();
2300
2315
  dataSourceRef.current = dataSource;
2301
2316
  if (dataSource === void 0) {
2302
2317
  throw Error("no data source provided to DataTable");
2303
2318
  }
2304
2319
  const containerMeasurements = useMeasuredContainer(measuredProps);
2305
- const onDataRowcountChange = (0, import_react21.useCallback)((size) => {
2320
+ const onDataRowcountChange = (0, import_react20.useCallback)((size) => {
2306
2321
  setRowCount(size);
2307
2322
  }, []);
2308
2323
  const { columns, dispatchColumnAction, headings } = useTableModel(
2309
2324
  config,
2310
2325
  dataSource.config
2311
2326
  );
2312
- const handlePersistentColumnOperation = (0, import_react21.useCallback)(
2327
+ const handlePersistentColumnOperation = (0, import_react20.useCallback)(
2313
2328
  (action) => {
2314
2329
  expectConfigChangeRef.current = true;
2315
2330
  dispatchColumnAction(action);
2316
2331
  },
2317
2332
  [dispatchColumnAction]
2318
2333
  );
2319
- const handleContextMenuAction = useContextMenu3({
2334
+ const handleContextMenuAction = useContextMenu({
2320
2335
  dataSource,
2321
2336
  onPersistentColumnOperation: handlePersistentColumnOperation
2322
2337
  });
2323
- const viewportMeasurements = useTableViewport({
2338
+ const {
2339
+ getRowAtPosition,
2340
+ getRowOffset,
2341
+ setPctScrollTop,
2342
+ ...viewportMeasurements
2343
+ } = useTableViewport({
2324
2344
  columns,
2325
2345
  headerHeight,
2326
2346
  headings,
@@ -2328,7 +2348,7 @@ var useDataTable = ({
2328
2348
  rowHeight,
2329
2349
  size: containerMeasurements.innerSize
2330
2350
  });
2331
- const onSubscribed = (0, import_react21.useCallback)(
2351
+ const onSubscribed = (0, import_react20.useCallback)(
2332
2352
  (subscription) => {
2333
2353
  if (subscription.tableMeta) {
2334
2354
  const { columns: columnNames, dataTypes: serverDataTypes } = subscription.tableMeta;
@@ -2342,7 +2362,7 @@ var useDataTable = ({
2342
2362
  },
2343
2363
  [dispatchColumnAction]
2344
2364
  );
2345
- const handleSelectionChange = (0, import_react21.useCallback)(
2365
+ const handleSelectionChange = (0, import_react20.useCallback)(
2346
2366
  (selected) => {
2347
2367
  dataSource.select(selected);
2348
2368
  onSelectionChange == null ? void 0 : onSelectionChange(selected);
@@ -2362,9 +2382,9 @@ var useDataTable = ({
2362
2382
  renderBufferSize,
2363
2383
  viewportRowCount: viewportMeasurements.rowCount
2364
2384
  });
2365
- const dataRef = (0, import_react21.useRef)();
2385
+ const dataRef = (0, import_react20.useRef)();
2366
2386
  dataRef.current = data;
2367
- const handleSort = (0, import_react21.useCallback)(
2387
+ const handleSort = (0, import_react20.useCallback)(
2368
2388
  (column, extendSort = false, sortType) => {
2369
2389
  if (dataSource) {
2370
2390
  dataSource.sort = (0, import_vuu_utils13.applySort)(
@@ -2377,7 +2397,7 @@ var useDataTable = ({
2377
2397
  },
2378
2398
  [dataSource]
2379
2399
  );
2380
- const handleColumnResize = (0, import_react21.useCallback)(
2400
+ const handleColumnResize = (0, import_react20.useCallback)(
2381
2401
  (phase, columnName, width) => {
2382
2402
  const column = columns.find((column2) => column2.name === columnName);
2383
2403
  if (column) {
@@ -2398,7 +2418,7 @@ var useDataTable = ({
2398
2418
  },
2399
2419
  [columns, dispatchColumnAction]
2400
2420
  );
2401
- const handleToggleGroup = (0, import_react21.useCallback)(
2421
+ const handleToggleGroup = (0, import_react20.useCallback)(
2402
2422
  (row, column) => {
2403
2423
  const isJson = (0, import_vuu_utils13.isJsonGroup)(column, row);
2404
2424
  const key = row[KEY2];
@@ -2441,14 +2461,20 @@ var useDataTable = ({
2441
2461
  virtualColSpan
2442
2462
  } = useVirtualViewport({
2443
2463
  columns,
2444
- rowHeight,
2464
+ getRowAtPosition,
2445
2465
  setRange,
2446
2466
  viewportMeasurements
2447
2467
  });
2468
+ const handleVerticalScroll = (0, import_react20.useCallback)(
2469
+ (scrollTop, pctScrollTop) => {
2470
+ setPctScrollTop(pctScrollTop);
2471
+ onVerticalScroll(scrollTop);
2472
+ },
2473
+ [onVerticalScroll, setPctScrollTop]
2474
+ );
2448
2475
  const { requestScroll, ...scrollProps } = useTableScroll({
2449
2476
  onHorizontalScroll,
2450
- // onRangeChange: setRange,
2451
- onVerticalScroll,
2477
+ onVerticalScroll: handleVerticalScroll,
2452
2478
  viewport: viewportMeasurements,
2453
2479
  viewportHeight: ((_b = (_a = containerMeasurements.innerSize) == null ? void 0 : _a.height) != null ? _b : 0) - headerHeight
2454
2480
  });
@@ -2460,17 +2486,21 @@ var useDataTable = ({
2460
2486
  rowCount: dataSource == null ? void 0 : dataSource.size,
2461
2487
  viewportRange: range
2462
2488
  });
2463
- const handleRemoveColumnFromGroupBy = (0, import_react21.useCallback)(
2489
+ const handleRemoveColumnFromGroupBy = (0, import_react20.useCallback)(
2464
2490
  (column) => {
2465
- if (dataSource && dataSource.groupBy.includes(column.name)) {
2466
- dataSource.groupBy = dataSource.groupBy.filter(
2467
- (columnName) => columnName !== column.name
2468
- );
2491
+ if (column) {
2492
+ if (dataSource && dataSource.groupBy.includes(column.name)) {
2493
+ dataSource.groupBy = dataSource.groupBy.filter(
2494
+ (columnName) => columnName !== column.name
2495
+ );
2496
+ }
2497
+ } else {
2498
+ dataSource.groupBy = [];
2469
2499
  }
2470
2500
  },
2471
2501
  [dataSource]
2472
2502
  );
2473
- const handleDropColumn = (0, import_react21.useCallback)(
2503
+ const handleDropColumn = (0, import_react20.useCallback)(
2474
2504
  (fromIndex, toIndex) => {
2475
2505
  const column = dataSource.columns[fromIndex];
2476
2506
  const columns2 = (0, import_vuu_utils13.moveItem)(dataSource.columns, column, toIndex);
@@ -2482,11 +2512,9 @@ var useDataTable = ({
2482
2512
  [dataSource, dispatchColumnAction]
2483
2513
  );
2484
2514
  const draggableHook = useDraggableColumn({
2485
- onDrop: handleDropColumn,
2486
- tableContainerRef: scrollProps.tableContainerRef,
2487
- tableLayout
2515
+ onDrop: handleDropColumn
2488
2516
  });
2489
- (0, import_react21.useEffect)(() => {
2517
+ (0, import_react20.useEffect)(() => {
2490
2518
  if (dataSourceRef.current) {
2491
2519
  expectConfigChangeRef.current = true;
2492
2520
  dispatchColumnAction({
@@ -2496,7 +2524,7 @@ var useDataTable = ({
2496
2524
  });
2497
2525
  }
2498
2526
  }, [config, dispatchColumnAction]);
2499
- (0, import_react21.useEffect)(() => {
2527
+ (0, import_react20.useEffect)(() => {
2500
2528
  dataSource.on("config", (config2, confirmed) => {
2501
2529
  expectConfigChangeRef.current = true;
2502
2530
  dispatchColumnAction({
@@ -2506,7 +2534,7 @@ var useDataTable = ({
2506
2534
  });
2507
2535
  });
2508
2536
  }, [dataSource, dispatchColumnAction]);
2509
- (0, import_react21.useMemo)(() => {
2537
+ (0, import_react20.useMemo)(() => {
2510
2538
  if (expectConfigChangeRef.current) {
2511
2539
  onConfigChange == null ? void 0 : onConfigChange({
2512
2540
  ...config,
@@ -2516,14 +2544,14 @@ var useDataTable = ({
2516
2544
  }
2517
2545
  }, [columns, config, onConfigChange]);
2518
2546
  const showContextMenu = (0, import_vuu_popups3.useContextMenu)();
2519
- const onContextMenu = (0, import_react21.useCallback)(
2547
+ const onContextMenu = (0, import_react20.useCallback)(
2520
2548
  (evt) => {
2521
2549
  var _a2;
2522
2550
  const { current: currentData } = dataRef;
2523
2551
  const { current: currentDataSource } = dataSourceRef;
2524
2552
  const target = evt.target;
2525
- const cellEl = target == null ? void 0 : target.closest("td");
2526
- const rowEl = target == null ? void 0 : target.closest("tr");
2553
+ const cellEl = target == null ? void 0 : target.closest("div[role='cell']");
2554
+ const rowEl = target == null ? void 0 : target.closest(".vuuTableRow");
2527
2555
  if (cellEl && rowEl && currentData && currentDataSource) {
2528
2556
  const { columns: columns2, selectedRowsCount } = currentDataSource;
2529
2557
  const columnMap = (0, import_vuu_utils13.buildColumnMap)(columns2);
@@ -2549,6 +2577,7 @@ var useDataTable = ({
2549
2577
  columnsWithinViewport,
2550
2578
  data,
2551
2579
  dispatchColumnAction,
2580
+ getRowOffset,
2552
2581
  handleContextMenuAction,
2553
2582
  headings,
2554
2583
  onColumnResize: handleColumnResize,
@@ -2566,10 +2595,10 @@ var useDataTable = ({
2566
2595
  };
2567
2596
 
2568
2597
  // src/Table.tsx
2569
- var import_classnames8 = __toESM(require("classnames"));
2598
+ var import_classnames7 = __toESM(require("classnames"));
2570
2599
  var import_vuu_utils14 = require("@vuu-ui/vuu-utils");
2571
- var import_jsx_runtime11 = require("react/jsx-runtime");
2572
- var classBase7 = "vuuTable";
2600
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2601
+ var classBase6 = "vuuTable";
2573
2602
  var Table = ({
2574
2603
  allowConfigEditing: showSettings = false,
2575
2604
  className: classNameProp,
@@ -2587,7 +2616,6 @@ var Table = ({
2587
2616
  rowHeight = 20,
2588
2617
  selectionModel = "extended",
2589
2618
  style: styleProp,
2590
- tableLayout: tableLayoutProp = "row",
2591
2619
  width,
2592
2620
  zebraStripes = false,
2593
2621
  ...props
@@ -2601,10 +2629,9 @@ var Table = ({
2601
2629
  draggedItemIndex,
2602
2630
  handleContextMenuAction,
2603
2631
  scrollProps,
2604
- tableLayout,
2605
2632
  viewportMeasurements,
2606
2633
  ...tableProps
2607
- } = useDataTable({
2634
+ } = useTable({
2608
2635
  config,
2609
2636
  dataSource,
2610
2637
  renderBufferSize,
@@ -2616,43 +2643,36 @@ var Table = ({
2616
2643
  onSelectionChange,
2617
2644
  rowHeight,
2618
2645
  selectionModel,
2619
- tableLayout: tableLayoutProp,
2620
2646
  width
2621
2647
  });
2622
2648
  const style = {
2623
2649
  ...outerSize,
2624
- "--content-height": `${viewportMeasurements.scrollContentHeight}px`,
2625
- "--content-width": `${viewportMeasurements.scrollContentWidth}px`,
2626
- "--filler-height": `${viewportMeasurements.fillerHeight}px`,
2650
+ "--content-height": `${viewportMeasurements.contentHeight}px`,
2651
+ "--horizontal-scrollbar-height": `${viewportMeasurements.horizontalScrollbarHeight}px`,
2652
+ "--content-width": `${viewportMeasurements.contentWidth}px`,
2627
2653
  "--pinned-width-left": `${viewportMeasurements.pinnedWidthLeft}px`,
2628
2654
  "--pinned-width-right": `${viewportMeasurements.pinnedWidthRight}px`,
2629
2655
  "--header-height": `${headerHeight}px`,
2630
2656
  "--row-height": `${rowHeight}px`,
2631
- "--scrollbar-size": `${viewportMeasurements.scrollbarSize}px`,
2632
2657
  "--table-height": `${innerSize == null ? void 0 : innerSize.height}px`,
2633
2658
  "--table-width": `${innerSize == null ? void 0 : innerSize.width}px`,
2634
- "--total-header-height": `${viewportMeasurements == null ? void 0 : viewportMeasurements.totalHeaderHeight}px`
2635
- };
2636
- const scrollbarContainerStyle = {
2637
- left: viewportMeasurements.pinnedWidthLeft - 1,
2638
- // The -1 is to align the top border, might cause innaccuracy
2639
- // It is compensated by a hardcoded adjustment in css
2640
- // top: measurements.top - 1 + headerHeight,
2641
- top: (viewportMeasurements == null ? void 0 : viewportMeasurements.totalHeaderHeight) - 1
2659
+ "--total-header-height": `${viewportMeasurements.totalHeaderHeight}px`,
2660
+ "--vertical-scrollbar-width": `${viewportMeasurements.verticalScrollbarWidth}px`,
2661
+ "--viewport-body-height": `${viewportMeasurements.viewportBodyHeight}px`
2642
2662
  };
2643
- const Table2 = tableLayout === "column" ? ColumnBasedTable : RowBasedTable;
2644
- const className = (0, import_classnames8.default)(classBase7, classNameProp, {
2645
- [`${classBase7}-zebra`]: zebraStripes,
2646
- [`${classBase7}-loading`]: (0, import_vuu_utils14.isDataLoading)(tableProps.columns)
2663
+ const className = (0, import_classnames7.default)(classBase6, classNameProp, {
2664
+ [`${classBase6}-zebra`]: zebraStripes,
2665
+ [`${classBase6}-loading`]: (0, import_vuu_utils14.isDataLoading)(tableProps.columns)
2647
2666
  });
2648
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2667
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2649
2668
  import_vuu_popups4.ContextMenuProvider,
2650
2669
  {
2651
2670
  menuActionHandler: handleContextMenuAction,
2652
2671
  menuBuilder: buildContextMenuDescriptors(dataSource),
2653
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2672
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2654
2673
  "div",
2655
2674
  {
2675
+ ...props,
2656
2676
  ...containerProps,
2657
2677
  className,
2658
2678
  id,
@@ -2660,49 +2680,36 @@ var Table = ({
2660
2680
  style,
2661
2681
  tabIndex: -1,
2662
2682
  children: [
2663
- innerSize ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2683
+ innerSize ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2664
2684
  "div",
2665
2685
  {
2666
- className: `${classBase7}-scrollbarContainer`,
2667
- onScroll: scrollProps.onScrollbarContainerScroll,
2686
+ className: `${classBase6}-scrollbarContainer`,
2668
2687
  ref: scrollProps.scrollbarContainerRef,
2669
- style: scrollbarContainerStyle,
2670
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `${classBase7}-scrollContent` })
2688
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `${classBase6}-scrollbarContent` })
2671
2689
  }
2672
2690
  ) : null,
2673
- innerSize ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2691
+ innerSize ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2674
2692
  "div",
2675
2693
  {
2676
- className: `${classBase7}-contentContainer`,
2677
- onScroll: scrollProps.onContentContainerScroll,
2694
+ className: `${classBase6}-contentContainer`,
2678
2695
  ref: scrollProps.contentContainerRef,
2679
- ...props,
2680
2696
  children: [
2681
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `${classBase7}-scrollContent` }),
2682
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2683
- "div",
2697
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2698
+ RowBasedTable,
2684
2699
  {
2685
- className: `${classBase7}-tableContainer`,
2686
- onScroll: scrollProps.onTableContainerScroll,
2687
- ref: scrollProps.tableContainerRef,
2688
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2689
- Table2,
2690
- {
2691
- ...tableProps,
2692
- headerHeight,
2693
- rowHeight
2694
- }
2695
- )
2700
+ ...tableProps,
2701
+ headerHeight,
2702
+ tableId: id
2696
2703
  }
2697
2704
  ),
2698
2705
  draggable
2699
2706
  ]
2700
2707
  }
2701
2708
  ) : null,
2702
- showSettings && innerSize ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2709
+ showSettings && innerSize ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2703
2710
  import_core.Button,
2704
2711
  {
2705
- className: `${classBase7}-settings`,
2712
+ className: `${classBase6}-settings`,
2706
2713
  "data-icon": "settings",
2707
2714
  onClick: onShowSettings,
2708
2715
  variant: "secondary"
@@ -2716,10 +2723,10 @@ var Table = ({
2716
2723
  };
2717
2724
 
2718
2725
  // src/cell-renderers/json-cell/JsonCell.tsx
2719
- var import_classnames9 = __toESM(require("classnames"));
2726
+ var import_classnames8 = __toESM(require("classnames"));
2720
2727
  var import_vuu_utils15 = require("@vuu-ui/vuu-utils");
2721
- var import_jsx_runtime12 = require("react/jsx-runtime");
2722
- var classBase8 = "vuuJsonCell";
2728
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2729
+ var classBase7 = "vuuJsonCell";
2723
2730
  var { IS_EXPANDED: IS_EXPANDED3, KEY: KEY3 } = import_vuu_utils15.metadataKeys;
2724
2731
  var localKey = (key) => {
2725
2732
  const pos = key.lastIndexOf("|");
@@ -2741,19 +2748,19 @@ var JsonCell = ({ column, row }) => {
2741
2748
  isToggle = true;
2742
2749
  }
2743
2750
  const rowKey = localKey(row[KEY3]);
2744
- const className = (0, import_classnames9.default)({
2745
- [`${classBase8}-name`]: rowKey === value,
2746
- [`${classBase8}-value`]: rowKey !== value,
2747
- [`${classBase8}-group`]: isToggle
2751
+ const className = (0, import_classnames8.default)({
2752
+ [`${classBase7}-name`]: rowKey === value,
2753
+ [`${classBase7}-value`]: rowKey !== value,
2754
+ [`${classBase7}-group`]: isToggle
2748
2755
  });
2749
2756
  if (isToggle) {
2750
2757
  const toggleIcon = row[IS_EXPANDED3] ? "minus-box" : "plus-box";
2751
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className, children: [
2752
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `${classBase8}-value`, children: value }),
2753
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `${classBase8}-toggle`, "data-icon": toggleIcon })
2758
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className, children: [
2759
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `${classBase7}-value`, children: value }),
2760
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `${classBase7}-toggle`, "data-icon": toggleIcon })
2754
2761
  ] });
2755
2762
  } else if (value) {
2756
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className, children: value });
2763
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className, children: value });
2757
2764
  } else {
2758
2765
  return null;
2759
2766
  }