@vuu-ui/vuu-table 0.7.2-debug → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.js CHANGED
@@ -1,2861 +1,2 @@
1
- // src/context-menu/buildContextMenuDescriptors.ts
2
- import { isNumericColumn } from "@vuu-ui/vuu-utils";
3
- var buildContextMenuDescriptors = (dataSource) => (location, options) => {
4
- const descriptors = [];
5
- if (dataSource === void 0) {
6
- return descriptors;
7
- }
8
- if (location === "header") {
9
- descriptors.push(
10
- ...buildSortMenuItems(options, dataSource)
11
- );
12
- descriptors.push(
13
- ...buildGroupMenuItems(options, dataSource)
14
- );
15
- descriptors.push(
16
- ...buildAggregationMenuItems(options, dataSource)
17
- );
18
- descriptors.push(...buildColumnDisplayMenuItems(options));
19
- } else if (location === "filter") {
20
- const { column, filter } = options;
21
- const colIsOnlyFilter = (filter == null ? void 0 : filter.column) === (column == null ? void 0 : column.name);
22
- descriptors.push({
23
- label: "Edit filter",
24
- action: "filter-edit",
25
- options
26
- });
27
- descriptors.push({
28
- label: "Remove filter",
29
- action: "filter-remove-column",
30
- options
31
- });
32
- if (column && !colIsOnlyFilter) {
33
- descriptors.push({
34
- label: `Remove all filters`,
35
- action: "remove-filters",
36
- options
37
- });
38
- }
39
- }
40
- return descriptors;
41
- };
42
- function buildSortMenuItems(options, { sort: { sortDefs } }) {
43
- const { column } = options;
44
- const menuItems = [];
45
- if (column === void 0) {
46
- return menuItems;
47
- }
48
- const hasSort = sortDefs.length > 0;
49
- if (column.sorted === "A") {
50
- menuItems.push({
51
- label: "Reverse Sort (DSC)",
52
- action: "sort-dsc",
53
- options
54
- });
55
- } else if (column.sorted === "D") {
56
- menuItems.push({
57
- label: "Reverse Sort (ASC)",
58
- action: "sort-asc",
59
- options
60
- });
61
- } else if (typeof column.sorted === "number") {
62
- if (column.sorted > 0) {
63
- menuItems.push({
64
- label: "Reverse Sort (DSC)",
65
- action: "sort-add-dsc",
66
- options
67
- });
68
- } else {
69
- menuItems.push({
70
- label: "Reverse Sort (ASC)",
71
- action: "sort-add-asc",
72
- options
73
- });
74
- }
75
- if (hasSort && Math.abs(column.sorted) < sortDefs.length) {
76
- menuItems.push({
77
- label: "Remove from sort",
78
- action: "sort-remove",
79
- options
80
- });
81
- }
82
- menuItems.push({
83
- label: "New Sort",
84
- children: [
85
- { label: "Ascending", action: "sort-asc", options },
86
- { label: "Descending", action: "sort-dsc", options }
87
- ]
88
- });
89
- } else if (hasSort) {
90
- menuItems.push({
91
- label: "Add to sort",
92
- children: [
93
- { label: "Ascending", action: "sort-add-asc", options },
94
- { label: "Descending", action: "sort-add-dsc", options }
95
- ]
96
- });
97
- menuItems.push({
98
- label: "New Sort",
99
- children: [
100
- { label: "Ascending", action: "sort-asc", options },
101
- { label: "Descending", action: "sort-dsc", options }
102
- ]
103
- });
104
- } else {
105
- menuItems.push({
106
- label: "Sort",
107
- children: [
108
- { label: "Ascending", action: "sort-asc", options },
109
- { label: "Descending", action: "sort-dsc", options }
110
- ]
111
- });
112
- }
113
- return menuItems;
114
- }
115
- function buildAggregationMenuItems(options, dataSource) {
116
- const { column } = options;
117
- if (column === void 0 || dataSource.groupBy.length === 0) {
118
- return [];
119
- }
120
- const { name, label = name } = column;
121
- return [
122
- {
123
- label: `Aggregate ${label}`,
124
- children: [{ label: "Count", action: "agg-count", options }].concat(
125
- isNumericColumn(column) ? [
126
- { label: "Sum", action: "agg-sum", options },
127
- { label: "Avg", action: "agg-avg", options },
128
- { label: "High", action: "agg-high", options },
129
- { label: "Low", action: "agg-low", options }
130
- ] : []
131
- )
132
- }
133
- ];
134
- }
135
- var pinColumn = (options, pinLocation) => ({
136
- label: `Pin ${pinLocation}`,
137
- action: `column-pin-${pinLocation}`,
138
- options
139
- });
140
- var pinLeft = (options) => pinColumn(options, "left");
141
- var pinFloating = (options) => pinColumn(options, "floating");
142
- var pinRight = (options) => pinColumn(options, "right");
143
- function buildColumnDisplayMenuItems(options) {
144
- const { column } = options;
145
- if (column === void 0) {
146
- return [];
147
- }
148
- const { pin } = column;
149
- const menuItems = [
150
- {
151
- label: `Hide column`,
152
- action: "column-hide",
153
- options
154
- },
155
- {
156
- label: `Remove column`,
157
- action: "column-remove",
158
- options
159
- }
160
- ];
161
- if (pin === void 0) {
162
- menuItems.push({
163
- label: `Pin column`,
164
- children: [pinLeft(options), pinFloating(options), pinRight(options)]
165
- });
166
- } else if (pin === "left") {
167
- menuItems.push(
168
- { label: "Unpin column", action: "column-unpin", options },
169
- {
170
- label: `Pin column`,
171
- children: [pinFloating(options), pinRight(options)]
172
- }
173
- );
174
- } else if (pin === "right") {
175
- menuItems.push(
176
- { label: "Unpin column", action: "column-unpin", options },
177
- {
178
- label: `Pin column`,
179
- children: [pinLeft(options), pinFloating(options)]
180
- }
181
- );
182
- } else if (pin === "floating") {
183
- menuItems.push(
184
- { label: "Unpin column", action: "column-unpin", options },
185
- {
186
- label: `Pin column`,
187
- children: [pinLeft(options), pinRight(options)]
188
- }
189
- );
190
- }
191
- return menuItems;
192
- }
193
- function buildGroupMenuItems(options, { groupBy }) {
194
- const { column } = options;
195
- const menuItems = [];
196
- if (column === void 0) {
197
- return menuItems;
198
- }
199
- const { name, label = name } = column;
200
- if (groupBy.length === 0) {
201
- menuItems.push({
202
- label: `Group by ${label}`,
203
- action: "group",
204
- options
205
- });
206
- } else {
207
- menuItems.push({
208
- label: `Add ${label} to group by`,
209
- action: "group-add",
210
- options
211
- });
212
- }
213
- return menuItems;
214
- }
215
-
216
- // src/context-menu/useTableContextMenu.ts
217
- import { removeColumnFromFilter } from "@vuu-ui/vuu-filters";
218
- import {
219
- addGroupColumn,
220
- addSortColumn,
221
- AggregationType,
222
- setAggregations,
223
- setSortColumn
224
- } from "@vuu-ui/vuu-utils";
225
- var removeFilterColumn = (dataSourceFilter, column) => {
226
- if (dataSourceFilter.filterStruct && column) {
227
- const [filterStruct, filter] = removeColumnFromFilter(
228
- column,
229
- dataSourceFilter.filterStruct
230
- );
231
- return {
232
- filter,
233
- filterStruct
234
- };
235
- } else {
236
- return dataSourceFilter;
237
- }
238
- };
239
- var { Average, Count, High, Low, Sum } = AggregationType;
240
- var useTableContextMenu = ({
241
- dataSource,
242
- onPersistentColumnOperation
243
- }) => {
244
- const handleContextMenuAction = (type, options) => {
245
- const gridOptions = options;
246
- if (gridOptions.column && dataSource) {
247
- const { column } = gridOptions;
248
- switch (type) {
249
- case "sort-asc":
250
- return dataSource.sort = setSortColumn(dataSource.sort, column, "A"), true;
251
- case "sort-dsc":
252
- return dataSource.sort = setSortColumn(dataSource.sort, column, "D"), true;
253
- case "sort-add-asc":
254
- return dataSource.sort = addSortColumn(dataSource.sort, column, "A"), true;
255
- case "sort-add-dsc":
256
- return dataSource.sort = addSortColumn(dataSource.sort, column, "D"), true;
257
- case "group":
258
- return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
259
- case "group-add":
260
- return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
261
- case "column-hide":
262
- return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
263
- case "column-remove":
264
- return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
265
- case "filter-remove-column":
266
- return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
267
- case "remove-filters":
268
- return dataSource.filter = { filter: "" }, true;
269
- case "agg-avg":
270
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Average), true;
271
- case "agg-high":
272
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, High), true;
273
- case "agg-low":
274
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Low), true;
275
- case "agg-count":
276
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Count), true;
277
- case "agg-sum":
278
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Sum), true;
279
- case "column-pin-floating":
280
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
281
- case "column-pin-left":
282
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
283
- case "column-pin-right":
284
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
285
- case "column-unpin":
286
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
287
- default:
288
- }
289
- }
290
- return false;
291
- };
292
- return handleContextMenuAction;
293
- };
294
-
295
- // src/Table.tsx
296
- import { ContextMenuProvider } from "@vuu-ui/vuu-popups";
297
- import { Button, useIdMemo } from "@salt-ds/core";
298
-
299
- // src/RowBasedTable.tsx
300
- import {
301
- buildColumnMap,
302
- getColumnStyle as getColumnStyle3,
303
- isGroupColumn as isGroupColumn2,
304
- metadataKeys as metadataKeys4,
305
- notHidden as notHidden2,
306
- visibleColumnAtIndex
307
- } from "@vuu-ui/vuu-utils";
308
- import { useCallback as useCallback8, useMemo } from "react";
309
-
310
- // src/TableRow.tsx
311
- import {
312
- isGroupColumn,
313
- isJsonColumn,
314
- isJsonGroup,
315
- metadataKeys as metadataKeys3,
316
- notHidden
317
- } from "@vuu-ui/vuu-utils";
318
- import cx2 from "classnames";
319
- import { memo as memo2, useCallback as useCallback3 } from "react";
320
-
321
- // src/TableCell.tsx
322
- import { getColumnStyle, metadataKeys } from "@vuu-ui/vuu-utils";
323
- import { EditableLabel } from "@heswell/salt-lab";
324
- import cx from "classnames";
325
- import {
326
- memo,
327
- useCallback,
328
- useRef,
329
- useState
330
- } from "react";
331
- import { jsx } from "react/jsx-runtime";
332
- var { KEY } = metadataKeys;
333
- var TableCell = memo(
334
- ({
335
- className: classNameProp,
336
- column,
337
- columnMap,
338
- onClick,
339
- row
340
- }) => {
341
- const labelFieldRef = useRef(null);
342
- const {
343
- align,
344
- CellRenderer,
345
- key,
346
- pin,
347
- editable,
348
- resizing,
349
- valueFormatter
350
- } = column;
351
- const [editing, setEditing] = useState(false);
352
- const value = valueFormatter(row[key]);
353
- const [editableValue, setEditableValue] = useState(value);
354
- const handleTitleMouseDown = () => {
355
- var _a;
356
- (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
357
- };
358
- const handleTitleKeyDown = (evt) => {
359
- if (evt.key === "Enter") {
360
- setEditing(true);
361
- }
362
- };
363
- const handleClick = useCallback(
364
- (evt) => {
365
- onClick == null ? void 0 : onClick(evt, column);
366
- },
367
- [column, onClick]
368
- );
369
- const handleEnterEditMode = () => {
370
- setEditing(true);
371
- };
372
- const handleExitEditMode = (originalValue = "", finalValue = "", allowDeactivation = true, editCancelled = false) => {
373
- var _a;
374
- setEditing(false);
375
- if (editCancelled) {
376
- setEditableValue(originalValue);
377
- } else if (finalValue !== originalValue) {
378
- setEditableValue(finalValue);
379
- }
380
- if (allowDeactivation === false) {
381
- (_a = labelFieldRef.current) == null ? void 0 : _a.focus();
382
- }
383
- };
384
- const className = cx(classNameProp, {
385
- vuuAlignRight: align === "right",
386
- vuuPinFloating: pin === "floating",
387
- vuuPinLeft: pin === "left",
388
- vuuPinRight: pin === "right",
389
- "vuuTableCell-resizing": resizing
390
- }) || void 0;
391
- const style = getColumnStyle(column);
392
- return editable ? /* @__PURE__ */ jsx(
393
- "div",
394
- {
395
- className,
396
- "data-editable": true,
397
- role: "cell",
398
- style,
399
- onKeyDown: handleTitleKeyDown,
400
- children: /* @__PURE__ */ jsx(
401
- EditableLabel,
402
- {
403
- editing,
404
- value: editableValue,
405
- onChange: setEditableValue,
406
- onMouseDownCapture: handleTitleMouseDown,
407
- onEnterEditMode: handleEnterEditMode,
408
- onExitEditMode: handleExitEditMode,
409
- onKeyDown: handleTitleKeyDown,
410
- ref: labelFieldRef,
411
- tabIndex: 0
412
- },
413
- "title"
414
- )
415
- }
416
- ) : /* @__PURE__ */ jsx(
417
- "div",
418
- {
419
- className,
420
- role: "cell",
421
- style,
422
- onClick: handleClick,
423
- children: CellRenderer ? /* @__PURE__ */ jsx(CellRenderer, { column, columnMap, row }) : value
424
- }
425
- );
426
- },
427
- cellValuesAreEqual
428
- );
429
- TableCell.displayName = "TableCell";
430
- function cellValuesAreEqual(prev, next) {
431
- 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];
432
- }
433
-
434
- // src/TableGroupCell.tsx
435
- import { getColumnStyle as getColumnStyle2, metadataKeys as metadataKeys2 } from "@vuu-ui/vuu-utils";
436
- import { useCallback as useCallback2 } from "react";
437
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
438
- var { DEPTH, IS_LEAF } = metadataKeys2;
439
- var getGroupValueAndOffset = (columns, row) => {
440
- const { [DEPTH]: depth, [IS_LEAF]: isLeaf } = row;
441
- if (isLeaf || depth > columns.length) {
442
- return [null, depth === null ? 0 : depth - 1];
443
- } else if (depth === 0) {
444
- return ["$root", 0];
445
- } else {
446
- const { key, valueFormatter } = columns[depth - 1];
447
- const value = valueFormatter(row[key]);
448
- return [value, depth - 1];
449
- }
450
- };
451
- var TableGroupCell = ({ column, onClick, row }) => {
452
- const { columns } = column;
453
- const [value, offset] = getGroupValueAndOffset(columns, row);
454
- const handleClick = useCallback2(
455
- (evt) => {
456
- onClick == null ? void 0 : onClick(evt, column);
457
- },
458
- [column, onClick]
459
- );
460
- const style = getColumnStyle2(column);
461
- const isLeaf = row[IS_LEAF];
462
- const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ jsx2("span", { className: "vuuTableGroupCell-spacer" }, i));
463
- return /* @__PURE__ */ jsxs(
464
- "div",
465
- {
466
- className: "vuuTableGroupCell vuuPinLeft",
467
- onClick: isLeaf ? void 0 : handleClick,
468
- role: "cell",
469
- style,
470
- children: [
471
- spacers,
472
- isLeaf ? null : /* @__PURE__ */ jsx2("span", { className: "vuuTableGroupCell-toggle", "data-icon": "triangle-right" }),
473
- /* @__PURE__ */ jsx2("span", { children: value })
474
- ]
475
- }
476
- );
477
- };
478
-
479
- // src/TableRow.tsx
480
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
481
- var { IDX, IS_EXPANDED, SELECTED } = metadataKeys3;
482
- var classBase = "vuuTableRow";
483
- var TableRow = memo2(function Row({
484
- columnMap,
485
- columns,
486
- offset,
487
- onClick,
488
- onToggleGroup,
489
- virtualColSpan = 0,
490
- row
491
- }) {
492
- const {
493
- [IDX]: rowIndex,
494
- [IS_EXPANDED]: isExpanded,
495
- [SELECTED]: isSelected
496
- } = row;
497
- const className = cx2(classBase, {
498
- [`${classBase}-even`]: rowIndex % 2 === 0,
499
- [`${classBase}-expanded`]: isExpanded,
500
- [`${classBase}-preSelected`]: isSelected === 2
501
- });
502
- const handleRowClick = useCallback3(
503
- (evt) => {
504
- const rangeSelect = evt.shiftKey;
505
- const keepExistingSelection = evt.ctrlKey || evt.metaKey;
506
- onClick == null ? void 0 : onClick(row, rangeSelect, keepExistingSelection);
507
- },
508
- [onClick, row]
509
- );
510
- const handleGroupCellClick = useCallback3(
511
- (evt, column) => {
512
- if (isGroupColumn(column) || isJsonGroup(column, row)) {
513
- evt.stopPropagation();
514
- onToggleGroup == null ? void 0 : onToggleGroup(row, column);
515
- }
516
- },
517
- [onToggleGroup, row]
518
- );
519
- return /* @__PURE__ */ jsxs2(
520
- "div",
521
- {
522
- "aria-selected": isSelected === 1 ? true : void 0,
523
- "aria-rowindex": rowIndex,
524
- className,
525
- onClick: handleRowClick,
526
- role: "row",
527
- style: {
528
- transform: `translate3d(0px, ${offset}px, 0px)`
529
- },
530
- children: [
531
- virtualColSpan > 0 ? /* @__PURE__ */ jsx3("div", { role: "cell", style: { width: virtualColSpan } }) : null,
532
- columns.filter(notHidden).map((column) => {
533
- const isGroup = isGroupColumn(column);
534
- const isJsonCell = isJsonColumn(column);
535
- const Cell = isGroup ? TableGroupCell : TableCell;
536
- return /* @__PURE__ */ jsx3(
537
- Cell,
538
- {
539
- column,
540
- columnMap,
541
- onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
542
- row
543
- },
544
- column.name
545
- );
546
- })
547
- ]
548
- }
549
- );
550
- });
551
-
552
- // src/TableGroupHeaderCell.tsx
553
- import cx3 from "classnames";
554
- import { useRef as useRef4 } from "react";
555
-
556
- // src/ColumnResizer.tsx
557
- import { useCallback as useCallback4, useRef as useRef2 } from "react";
558
- import { jsx as jsx4 } from "react/jsx-runtime";
559
- var NOOP = () => void 0;
560
- var baseClass = "vuuColumnResizer";
561
- var ColumnResizer = ({
562
- onDrag,
563
- onDragEnd = NOOP,
564
- onDragStart = NOOP
565
- }) => {
566
- const position = useRef2(0);
567
- const onMouseMove = useCallback4(
568
- (e) => {
569
- if (e.stopPropagation) {
570
- e.stopPropagation();
571
- }
572
- if (e.preventDefault) {
573
- e.preventDefault();
574
- }
575
- const x = Math.round(e.clientX);
576
- const moveBy = x - position.current;
577
- position.current = x;
578
- if (moveBy !== 0) {
579
- onDrag(e, moveBy);
580
- }
581
- },
582
- [onDrag]
583
- );
584
- const onMouseUp = useCallback4(
585
- (e) => {
586
- window.removeEventListener("mouseup", onMouseUp);
587
- window.removeEventListener("mousemove", onMouseMove);
588
- onDragEnd(e);
589
- },
590
- [onDragEnd, onMouseMove]
591
- );
592
- const handleMouseDown = useCallback4(
593
- (e) => {
594
- onDragStart(e);
595
- position.current = Math.round(e.clientX);
596
- window.addEventListener("mouseup", onMouseUp);
597
- window.addEventListener("mousemove", onMouseMove);
598
- if (e.stopPropagation) {
599
- e.stopPropagation();
600
- }
601
- if (e.preventDefault) {
602
- e.preventDefault();
603
- }
604
- },
605
- [onDragStart, onMouseMove, onMouseUp]
606
- );
607
- return /* @__PURE__ */ jsx4("div", { className: baseClass, "data-align": "end", onMouseDown: handleMouseDown });
608
- };
609
-
610
- // src/useTableColumnResize.tsx
611
- import { useCallback as useCallback5, useRef as useRef3 } from "react";
612
- var useTableColumnResize = ({
613
- column,
614
- onResize,
615
- rootRef
616
- }) => {
617
- const widthRef = useRef3(0);
618
- const isResizing = useRef3(false);
619
- const { name } = column;
620
- const handleResizeStart = useCallback5(() => {
621
- if (onResize && rootRef.current) {
622
- const { width } = rootRef.current.getBoundingClientRect();
623
- widthRef.current = Math.round(width);
624
- isResizing.current = true;
625
- onResize == null ? void 0 : onResize("begin", name);
626
- }
627
- }, [name, onResize, rootRef]);
628
- const handleResize = useCallback5(
629
- (_evt, moveBy) => {
630
- if (rootRef.current) {
631
- if (onResize) {
632
- const { width } = rootRef.current.getBoundingClientRect();
633
- const newWidth = Math.round(width) + moveBy;
634
- if (newWidth !== widthRef.current && newWidth > 0) {
635
- onResize("resize", name, newWidth);
636
- widthRef.current = newWidth;
637
- }
638
- }
639
- }
640
- },
641
- [name, onResize, rootRef]
642
- );
643
- const handleResizeEnd = useCallback5(() => {
644
- if (onResize) {
645
- onResize("end", name, widthRef.current);
646
- setTimeout(() => {
647
- isResizing.current = false;
648
- }, 100);
649
- }
650
- }, [name, onResize]);
651
- return {
652
- isResizing: isResizing.current,
653
- onDrag: handleResize,
654
- onDragStart: handleResizeStart,
655
- onDragEnd: handleResizeEnd
656
- };
657
- };
658
-
659
- // src/TableGroupHeaderCell.tsx
660
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
661
- var classBase2 = "vuuTable-groupHeaderCell";
662
- var RemoveButton = ({
663
- column,
664
- onClick,
665
- ...htmlAttributes
666
- }) => {
667
- return /* @__PURE__ */ jsx5(
668
- "span",
669
- {
670
- ...htmlAttributes,
671
- className: `${classBase2}-close`,
672
- "data-icon": "close-circle",
673
- onClick: () => onClick == null ? void 0 : onClick(column)
674
- }
675
- );
676
- };
677
- var ColHeader = (props) => {
678
- const { children, column, className } = props;
679
- return /* @__PURE__ */ jsxs3("div", { className: cx3(`${classBase2}-col`, className), role: "columnheader", children: [
680
- /* @__PURE__ */ jsx5("span", { className: `${classBase2}-label`, children: column.name }),
681
- children
682
- ] });
683
- };
684
- var TableGroupHeaderCell = ({
685
- column: groupColumn,
686
- className: classNameProp,
687
- onRemoveColumn,
688
- onResize,
689
- ...props
690
- }) => {
691
- const rootRef = useRef4(null);
692
- const { isResizing, ...resizeProps } = useTableColumnResize({
693
- column: groupColumn,
694
- onResize,
695
- rootRef
696
- });
697
- const className = cx3(classBase2, classNameProp, {
698
- vuuPinLeft: groupColumn.pin === "left",
699
- [`${classBase2}-right`]: groupColumn.align === "right",
700
- [`${classBase2}-resizing`]: groupColumn.resizing,
701
- [`${classBase2}-pending`]: groupColumn.groupConfirmed === false
702
- });
703
- const { columns } = groupColumn;
704
- return /* @__PURE__ */ jsx5("div", { className, ref: rootRef, ...props, children: /* @__PURE__ */ jsxs3("div", { className: `${classBase2}-inner`, children: [
705
- columns.map((column) => /* @__PURE__ */ jsx5(ColHeader, { column, children: columns.length > 1 ? /* @__PURE__ */ jsx5(RemoveButton, { column, onClick: onRemoveColumn }) : null }, column.key)),
706
- /* @__PURE__ */ jsx5(RemoveButton, { "data-align": "end", onClick: onRemoveColumn }),
707
- groupColumn.resizeable !== false ? /* @__PURE__ */ jsx5(ColumnResizer, { ...resizeProps }) : null
708
- ] }) });
709
- };
710
-
711
- // src/TableHeaderCell.tsx
712
- import cx6 from "classnames";
713
- import { useCallback as useCallback7, useRef as useRef5 } from "react";
714
-
715
- // src/SortIndicator.tsx
716
- import cx4 from "classnames";
717
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
718
- var classBase3 = "vuuSortIndicator";
719
- var SortIndicator = ({ sorted }) => {
720
- if (!sorted) {
721
- return null;
722
- }
723
- const direction = typeof sorted === "number" ? sorted < 0 ? "dsc" : "asc" : sorted === "A" ? "asc" : "dsc";
724
- return typeof sorted === "number" ? /* @__PURE__ */ jsxs4("div", { className: cx4(classBase3, "multi-col", direction), children: [
725
- /* @__PURE__ */ jsx6("span", { "data-icon": `sorted-${direction}` }),
726
- /* @__PURE__ */ jsx6("span", { className: "vuuSortPosition", children: Math.abs(sorted) })
727
- ] }) : /* @__PURE__ */ jsx6("div", { className: cx4(classBase3, "single-col"), children: /* @__PURE__ */ jsx6("span", { "data-icon": `sorted-${direction}` }) });
728
- };
729
-
730
- // src/TableHeaderCell.tsx
731
- import { useContextMenu as useContextMenu2 } from "@vuu-ui/vuu-popups";
732
-
733
- // src/filter-indicator.tsx
734
- import { useContextMenu } from "@vuu-ui/vuu-popups";
735
- import cx5 from "classnames";
736
- import { useCallback as useCallback6 } from "react";
737
- import { jsx as jsx7 } from "react/jsx-runtime";
738
- var FilterIndicator = ({ column, filter }) => {
739
- const showContextMenu = useContextMenu();
740
- const handleClick = useCallback6(
741
- (evt) => {
742
- evt.stopPropagation();
743
- showContextMenu(evt, "filter", { column, filter });
744
- },
745
- [column, filter, showContextMenu]
746
- );
747
- if (!column.filter) {
748
- return null;
749
- }
750
- return /* @__PURE__ */ jsx7(
751
- "div",
752
- {
753
- className: cx5("vuuFilterIndicator"),
754
- "data-icon": "filter",
755
- onClick: handleClick
756
- }
757
- );
758
- };
759
-
760
- // src/TableHeaderCell.tsx
761
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
762
- var classBase4 = "vuuTable-headerCell";
763
- var TableHeaderCell = ({
764
- column,
765
- className: classNameProp,
766
- onClick,
767
- onDragStart,
768
- onResize,
769
- ...props
770
- }) => {
771
- const rootRef = useRef5(null);
772
- const { isResizing, ...resizeProps } = useTableColumnResize({
773
- column,
774
- onResize,
775
- rootRef
776
- });
777
- const showContextMenu = useContextMenu2();
778
- const dragTimerRef = useRef5(null);
779
- const handleContextMenu = (e) => {
780
- showContextMenu(e, "header", { column });
781
- };
782
- const handleClick = useCallback7(
783
- (evt) => !isResizing && (onClick == null ? void 0 : onClick(evt)),
784
- [isResizing, onClick]
785
- );
786
- const handleMouseDown = useCallback7(
787
- (evt) => {
788
- dragTimerRef.current = window.setTimeout(() => {
789
- onDragStart == null ? void 0 : onDragStart(evt);
790
- dragTimerRef.current = null;
791
- }, 500);
792
- },
793
- [onDragStart]
794
- );
795
- const handleMouseUp = useCallback7(() => {
796
- if (dragTimerRef.current !== null) {
797
- window.clearTimeout(dragTimerRef.current);
798
- dragTimerRef.current = null;
799
- }
800
- }, []);
801
- const className = cx6(classBase4, classNameProp, {
802
- vuuPinFloating: column.pin === "floating",
803
- vuuPinLeft: column.pin === "left",
804
- vuuPinRight: column.pin === "right",
805
- vuuEndPin: column.endPin,
806
- [`${classBase4}-resizing`]: column.resizing,
807
- [`${classBase4}-right`]: column.align === "right"
808
- });
809
- return /* @__PURE__ */ jsx8(
810
- "div",
811
- {
812
- className,
813
- ...props,
814
- onClick: handleClick,
815
- onContextMenu: handleContextMenu,
816
- onMouseDown: handleMouseDown,
817
- onMouseUp: handleMouseUp,
818
- ref: rootRef,
819
- children: /* @__PURE__ */ jsxs5("div", { className: `${classBase4}-inner`, children: [
820
- /* @__PURE__ */ jsx8(FilterIndicator, { column }),
821
- /* @__PURE__ */ jsx8("div", { className: `${classBase4}-label`, children: column.label }),
822
- /* @__PURE__ */ jsx8(SortIndicator, { sorted: column.sorted }),
823
- column.resizeable !== false ? /* @__PURE__ */ jsx8(ColumnResizer, { ...resizeProps }) : null
824
- ] })
825
- }
826
- );
827
- };
828
-
829
- // src/RowBasedTable.tsx
830
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
831
- var classBase5 = "vuuTable";
832
- var { RENDER_IDX } = metadataKeys4;
833
- var RowBasedTable = ({
834
- columns,
835
- columnsWithinViewport,
836
- data,
837
- getRowOffset,
838
- headings,
839
- onColumnResize,
840
- onHeaderCellDragStart,
841
- onContextMenu,
842
- onRemoveColumnFromGroupBy,
843
- onRowClick,
844
- onSort,
845
- onToggleGroup,
846
- tableId,
847
- virtualColSpan = 0,
848
- rowCount
849
- }) => {
850
- const handleDragStart = useCallback8(
851
- (evt) => {
852
- onHeaderCellDragStart == null ? void 0 : onHeaderCellDragStart(evt);
853
- },
854
- [onHeaderCellDragStart]
855
- );
856
- const visibleColumns = useMemo(() => {
857
- return columns.filter(notHidden2);
858
- }, [columns]);
859
- const columnMap = useMemo(() => buildColumnMap(columns), [columns]);
860
- const handleHeaderClick = useCallback8(
861
- (evt) => {
862
- var _a;
863
- const targetElement = evt.target;
864
- const headerCell = targetElement.closest(
865
- ".vuuTable-headerCell"
866
- );
867
- const colIdx = parseInt((_a = headerCell == null ? void 0 : headerCell.dataset.idx) != null ? _a : "-1");
868
- const column = visibleColumnAtIndex(columns, colIdx);
869
- const isAdditive = evt.shiftKey;
870
- column && onSort(column, isAdditive);
871
- },
872
- [columns, onSort]
873
- );
874
- return /* @__PURE__ */ jsxs6("div", { "aria-rowcount": rowCount, className: `${classBase5}-table`, role: "table", children: [
875
- /* @__PURE__ */ jsxs6("div", { className: `${classBase5}-headers`, role: "rowGroup", children: [
876
- headings.map((colHeaders, i) => /* @__PURE__ */ jsx9("div", { className: "vuuTable-heading", children: colHeaders.map(({ label, width }, j) => /* @__PURE__ */ jsx9("div", { className: "vuuTable-headingCell", style: { width }, children: label }, j)) }, i)),
877
- /* @__PURE__ */ jsx9("div", { role: "row", children: visibleColumns.map((column, i) => {
878
- const style = getColumnStyle3(column);
879
- return isGroupColumn2(column) ? /* @__PURE__ */ jsx9(
880
- TableGroupHeaderCell,
881
- {
882
- column,
883
- "data-idx": i,
884
- onRemoveColumn: onRemoveColumnFromGroupBy,
885
- onResize: onColumnResize,
886
- role: "columnHeader",
887
- style
888
- },
889
- i
890
- ) : /* @__PURE__ */ jsx9(
891
- TableHeaderCell,
892
- {
893
- column,
894
- "data-idx": i,
895
- id: `${tableId}-${i}`,
896
- onClick: handleHeaderClick,
897
- onDragStart: handleDragStart,
898
- onResize: onColumnResize,
899
- role: "columnHeader",
900
- style
901
- },
902
- i
903
- );
904
- }) })
905
- ] }),
906
- /* @__PURE__ */ jsx9(
907
- "div",
908
- {
909
- className: `${classBase5}-body`,
910
- onContextMenu,
911
- role: "rowGroup",
912
- children: data == null ? void 0 : data.map((row) => /* @__PURE__ */ jsx9(
913
- TableRow,
914
- {
915
- columnMap,
916
- columns: columnsWithinViewport,
917
- offset: getRowOffset(row),
918
- onClick: onRowClick,
919
- virtualColSpan,
920
- onToggleGroup,
921
- row
922
- },
923
- row[RENDER_IDX]
924
- ))
925
- }
926
- )
927
- ] });
928
- };
929
-
930
- // src/useTable.ts
931
- import { useContextMenu as usePopupContextMenu } from "@vuu-ui/vuu-popups";
932
- import {
933
- applySort,
934
- buildColumnMap as buildColumnMap2,
935
- isJsonGroup as isJsonGroup2,
936
- metadataKeys as metadataKeys8,
937
- moveItem as moveItem2
938
- } from "@vuu-ui/vuu-utils";
939
- import {
940
- useCallback as useCallback18,
941
- useEffect as useEffect5,
942
- useMemo as useMemo7,
943
- useRef as useRef15,
944
- useState as useState5
945
- } from "react";
946
-
947
- // src/useDataSource.ts
948
- import {
949
- isVuuFeatureAction,
950
- isVuuFeatureInvocation
951
- } from "@vuu-ui/vuu-data";
952
- import { getFullRange, metadataKeys as metadataKeys5, WindowRange } from "@vuu-ui/vuu-utils";
953
- import { useCallback as useCallback9, useEffect, useMemo as useMemo2, useRef as useRef6, useState as useState2 } from "react";
954
- var { SELECTED: SELECTED2 } = metadataKeys5;
955
- function useDataSource({
956
- dataSource,
957
- onConfigChange,
958
- onFeatureEnabled,
959
- onFeatureInvocation,
960
- onSizeChange,
961
- onSubscribed,
962
- range = { from: 0, to: 0 },
963
- renderBufferSize = 0,
964
- viewportRowCount
965
- }) {
966
- const [, forceUpdate] = useState2(null);
967
- const isMounted = useRef6(true);
968
- const hasUpdated = useRef6(false);
969
- const rangeRef = useRef6({ from: 0, to: 0 });
970
- const rafHandle = useRef6(null);
971
- const data = useRef6([]);
972
- const dataWindow = useMemo2(
973
- () => new MovingWindow(getFullRange(range)),
974
- // eslint-disable-next-line react-hooks/exhaustive-deps
975
- []
976
- );
977
- const setData = useCallback9(
978
- (updates) => {
979
- for (const row of updates) {
980
- dataWindow.add(row);
981
- }
982
- data.current = dataWindow.data;
983
- hasUpdated.current = true;
984
- },
985
- [dataWindow]
986
- );
987
- const datasourceMessageHandler = useCallback9(
988
- (message) => {
989
- if (message.type === "subscribed") {
990
- onSubscribed == null ? void 0 : onSubscribed(message);
991
- } else if (message.type === "viewport-update") {
992
- if (typeof message.size === "number") {
993
- onSizeChange == null ? void 0 : onSizeChange(message.size);
994
- dataWindow.setRowCount(message.size);
995
- }
996
- if (message.rows) {
997
- setData(message.rows);
998
- } else if (typeof message.size === "number") {
999
- data.current = dataWindow.data;
1000
- hasUpdated.current = true;
1001
- }
1002
- } else if (isVuuFeatureAction(message)) {
1003
- onFeatureEnabled == null ? void 0 : onFeatureEnabled(message);
1004
- } else if (isVuuFeatureInvocation(message)) {
1005
- onFeatureInvocation == null ? void 0 : onFeatureInvocation(message);
1006
- } else {
1007
- console.log(`useDataSource unexpected message ${message.type}`);
1008
- }
1009
- },
1010
- [
1011
- dataWindow,
1012
- onFeatureEnabled,
1013
- onFeatureInvocation,
1014
- onSizeChange,
1015
- onSubscribed,
1016
- setData
1017
- ]
1018
- );
1019
- useEffect(
1020
- () => () => {
1021
- if (rafHandle.current) {
1022
- cancelAnimationFrame(rafHandle.current);
1023
- rafHandle.current = null;
1024
- }
1025
- isMounted.current = false;
1026
- },
1027
- []
1028
- );
1029
- const refreshIfUpdated = useCallback9(() => {
1030
- if (isMounted.current) {
1031
- if (hasUpdated.current) {
1032
- forceUpdate({});
1033
- hasUpdated.current = false;
1034
- }
1035
- rafHandle.current = requestAnimationFrame(refreshIfUpdated);
1036
- }
1037
- }, [forceUpdate]);
1038
- useEffect(() => {
1039
- rafHandle.current = requestAnimationFrame(refreshIfUpdated);
1040
- }, [refreshIfUpdated]);
1041
- const adjustRange = useCallback9(
1042
- (rowCount) => {
1043
- const { from } = dataSource.range;
1044
- const rowRange = { from, to: from + rowCount };
1045
- const fullRange = getFullRange(rowRange, renderBufferSize);
1046
- dataWindow.setRange(fullRange);
1047
- dataSource.range = rangeRef.current = fullRange;
1048
- dataSource.emit("range", rowRange);
1049
- },
1050
- [dataSource, dataWindow, renderBufferSize]
1051
- );
1052
- const setRange = useCallback9(
1053
- (range2) => {
1054
- const fullRange = getFullRange(range2, renderBufferSize);
1055
- dataWindow.setRange(fullRange);
1056
- dataSource.range = rangeRef.current = fullRange;
1057
- dataSource.emit("range", range2);
1058
- },
1059
- [dataSource, dataWindow, renderBufferSize]
1060
- );
1061
- const getSelectedRows = useCallback9(() => {
1062
- return dataWindow.getSelectedRows();
1063
- }, [dataWindow]);
1064
- useEffect(() => {
1065
- dataSource == null ? void 0 : dataSource.subscribe(
1066
- {
1067
- range: rangeRef.current
1068
- },
1069
- datasourceMessageHandler
1070
- );
1071
- }, [dataSource, datasourceMessageHandler, onConfigChange]);
1072
- useEffect(() => {
1073
- adjustRange(viewportRowCount);
1074
- }, [adjustRange, viewportRowCount]);
1075
- return {
1076
- data: data.current,
1077
- getSelectedRows,
1078
- range: rangeRef.current,
1079
- setRange,
1080
- dataSource
1081
- };
1082
- }
1083
- var MovingWindow = class {
1084
- constructor({ from, to }) {
1085
- this.rowCount = 0;
1086
- this.setRowCount = (rowCount) => {
1087
- if (rowCount < this.data.length) {
1088
- this.data.length = rowCount;
1089
- }
1090
- this.rowCount = rowCount;
1091
- };
1092
- this.range = new WindowRange(from, to);
1093
- this.data = new Array(to - from);
1094
- this.rowCount = 0;
1095
- }
1096
- add(data) {
1097
- var _a;
1098
- const [index] = data;
1099
- if (this.isWithinRange(index)) {
1100
- const internalIndex = index - this.range.from;
1101
- this.data[internalIndex] = data;
1102
- const isSelected = data[SELECTED2];
1103
- const preSelected = (_a = this.data[internalIndex - 1]) == null ? void 0 : _a[SELECTED2];
1104
- if (preSelected === 0 && isSelected) {
1105
- this.data[internalIndex - 1][SELECTED2] = 2;
1106
- } else if (preSelected === 2 && !isSelected) {
1107
- this.data[internalIndex - 1][SELECTED2] = 0;
1108
- }
1109
- }
1110
- }
1111
- getAtIndex(index) {
1112
- return this.range.isWithin(index) && this.data[index - this.range.from] != null ? this.data[index - this.range.from] : void 0;
1113
- }
1114
- isWithinRange(index) {
1115
- return this.range.isWithin(index);
1116
- }
1117
- setRange({ from, to }) {
1118
- if (from !== this.range.from || to !== this.range.to) {
1119
- const [overlapFrom, overlapTo] = this.range.overlap(from, to);
1120
- const newData = new Array(Math.max(0, to - from));
1121
- for (let i = overlapFrom; i < overlapTo; i++) {
1122
- const data = this.getAtIndex(i);
1123
- if (data) {
1124
- const index = i - from;
1125
- newData[index] = data;
1126
- }
1127
- }
1128
- this.data = newData;
1129
- this.range.from = from;
1130
- this.range.to = to;
1131
- }
1132
- }
1133
- getSelectedRows() {
1134
- return this.data.filter((row) => row[SELECTED2] === 1);
1135
- }
1136
- };
1137
-
1138
- // src/useDraggableColumn.ts
1139
- import { useDragDrop } from "@heswell/salt-lab";
1140
- import { useCallback as useCallback10, useRef as useRef7 } from "react";
1141
- var useDraggableColumn = ({ onDrop }) => {
1142
- const mousePosRef = useRef7();
1143
- const containerRef = useRef7(null);
1144
- const handleDropSettle = useCallback10(() => {
1145
- console.log(`handleDropSettle`);
1146
- mousePosRef.current = void 0;
1147
- containerRef.current = null;
1148
- }, []);
1149
- const { draggable, draggedItemIndex, onMouseDown } = useDragDrop({
1150
- // allowDragDrop: "drop-indicator",
1151
- allowDragDrop: true,
1152
- draggableClassName: "vuuTable-headerCell",
1153
- orientation: "horizontal",
1154
- containerRef,
1155
- itemQuery: ".vuuTable-headerCell",
1156
- onDrop,
1157
- onDropSettle: handleDropSettle
1158
- });
1159
- const onHeaderCellDragStart = useCallback10(
1160
- (evt) => {
1161
- const { clientX, clientY } = evt;
1162
- console.log(
1163
- `useDraggableColumn handleHeaderCellDragStart means mouseDown fired on a column in RowBasedTable`
1164
- );
1165
- const sourceElement = evt.target;
1166
- const columnHeaderCell = sourceElement.closest(".vuuTable-headerCell");
1167
- containerRef.current = columnHeaderCell == null ? void 0 : columnHeaderCell.closest(
1168
- "[role='row']"
1169
- );
1170
- const {
1171
- dataset: { idx = "-1" }
1172
- } = columnHeaderCell;
1173
- mousePosRef.current = {
1174
- clientX,
1175
- clientY,
1176
- idx
1177
- };
1178
- onMouseDown == null ? void 0 : onMouseDown(evt);
1179
- },
1180
- [onMouseDown]
1181
- );
1182
- return {
1183
- draggable,
1184
- draggedItemIndex,
1185
- onHeaderCellDragStart
1186
- };
1187
- };
1188
-
1189
- // src/useKeyboardNavigation.ts
1190
- import { withinRange } from "@vuu-ui/vuu-utils";
1191
- import {
1192
- useCallback as useCallback11,
1193
- useEffect as useEffect2,
1194
- useLayoutEffect,
1195
- useMemo as useMemo3,
1196
- useRef as useRef8
1197
- } from "react";
1198
-
1199
- // src/keyUtils.ts
1200
- function union(set1, ...sets) {
1201
- const result = new Set(set1);
1202
- for (let set of sets) {
1203
- for (let element of set) {
1204
- result.add(element);
1205
- }
1206
- }
1207
- return result;
1208
- }
1209
- var ArrowUp = "ArrowUp";
1210
- var ArrowDown = "ArrowDown";
1211
- var ArrowLeft = "ArrowLeft";
1212
- var ArrowRight = "ArrowRight";
1213
- var Home = "Home";
1214
- var End = "End";
1215
- var PageUp = "PageUp";
1216
- var PageDown = "PageDown";
1217
- var actionKeys = /* @__PURE__ */ new Set(["Enter", "Delete", " "]);
1218
- var focusKeys = /* @__PURE__ */ new Set(["Tab"]);
1219
- var arrowLeftRightKeys = /* @__PURE__ */ new Set(["ArrowRight", "ArrowLeft"]);
1220
- var navigationKeys = /* @__PURE__ */ new Set([
1221
- Home,
1222
- End,
1223
- PageUp,
1224
- PageDown,
1225
- ArrowDown,
1226
- ArrowLeft,
1227
- ArrowRight,
1228
- ArrowUp
1229
- ]);
1230
- var functionKeys = /* @__PURE__ */ new Set([
1231
- "F1",
1232
- "F2",
1233
- "F3",
1234
- "F4",
1235
- "F5",
1236
- "F6",
1237
- "F7",
1238
- "F8",
1239
- "F9",
1240
- "F10",
1241
- "F11",
1242
- "F12"
1243
- ]);
1244
- var specialKeys = union(
1245
- actionKeys,
1246
- navigationKeys,
1247
- arrowLeftRightKeys,
1248
- functionKeys,
1249
- focusKeys
1250
- );
1251
- var PageKeys = ["Home", "End", "PageUp", "PageDown"];
1252
- var isPagingKey = (key) => PageKeys.includes(key);
1253
- var isNavigationKey = (key) => {
1254
- return navigationKeys.has(key);
1255
- };
1256
-
1257
- // src/useKeyboardNavigation.ts
1258
- var headerCellQuery = (colIdx) => `.vuuTable-headers .vuuTable-headerCell:nth-child(${colIdx + 1})`;
1259
- var dataCellQuery = (rowIdx, colIdx) => `.vuuTable-body > [aria-rowindex='${rowIdx}'] > [role='cell']:nth-child(${colIdx + 1})`;
1260
- var NULL_CELL_POS = [-1, -1];
1261
- function nextCellPos(key, [rowIdx, colIdx], columnCount, rowCount) {
1262
- if (key === ArrowUp) {
1263
- if (rowIdx > -1) {
1264
- return [rowIdx - 1, colIdx];
1265
- } else {
1266
- return [rowIdx, colIdx];
1267
- }
1268
- } else if (key === ArrowDown) {
1269
- if (rowIdx === -1) {
1270
- return [0, colIdx];
1271
- } else if (rowIdx === rowCount - 1) {
1272
- return [rowIdx, colIdx];
1273
- } else {
1274
- return [rowIdx + 1, colIdx];
1275
- }
1276
- } else if (key === ArrowRight) {
1277
- if (colIdx < columnCount - 1) {
1278
- return [rowIdx, colIdx + 1];
1279
- } else {
1280
- return [rowIdx, colIdx];
1281
- }
1282
- } else if (key === ArrowLeft) {
1283
- if (colIdx > 0) {
1284
- return [rowIdx, colIdx - 1];
1285
- } else {
1286
- return [rowIdx, colIdx];
1287
- }
1288
- }
1289
- return [rowIdx, colIdx];
1290
- }
1291
- var useKeyboardNavigation = ({
1292
- columnCount = 0,
1293
- containerRef,
1294
- disableHighlightOnFocus,
1295
- data,
1296
- requestScroll,
1297
- rowCount = 0,
1298
- viewportRange
1299
- }) => {
1300
- var _a;
1301
- const { from: viewportFirstRow, to: viewportLastRow } = viewportRange;
1302
- const focusedCellPos = useRef8([-1, -1]);
1303
- const focusableCell = useRef8();
1304
- const activeCellPos = useRef8([-1, 0]);
1305
- const getTableCell = useCallback11(
1306
- ([rowIdx, colIdx]) => {
1307
- var _a2;
1308
- const cssQuery = rowIdx === -1 ? headerCellQuery(colIdx) : dataCellQuery(rowIdx, colIdx);
1309
- return (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector(
1310
- cssQuery
1311
- );
1312
- },
1313
- [containerRef]
1314
- );
1315
- const getFocusedCell = (element) => element == null ? void 0 : element.closest(
1316
- "[role='columnHeader'],[role='cell']"
1317
- );
1318
- const getTableCellPos = (tableCell) => {
1319
- var _a2, _b;
1320
- if (tableCell.role === "columnHeader") {
1321
- const colIdx = parseInt((_a2 = tableCell.dataset.idx) != null ? _a2 : "-1", 10);
1322
- return [-1, colIdx];
1323
- } else {
1324
- const focusedRow = tableCell.closest("[role='row']");
1325
- if (focusedRow) {
1326
- const rowIdx = parseInt((_b = focusedRow.ariaRowIndex) != null ? _b : "-1", 10);
1327
- const colIdx = Array.from(focusedRow.childNodes).indexOf(tableCell);
1328
- return [rowIdx, colIdx];
1329
- }
1330
- }
1331
- return NULL_CELL_POS;
1332
- };
1333
- const focusCell = useCallback11(
1334
- (cellPos) => {
1335
- var _a2;
1336
- if (containerRef.current) {
1337
- const activeCell = getTableCell(cellPos);
1338
- if (activeCell) {
1339
- if (activeCell !== focusableCell.current) {
1340
- (_a2 = focusableCell.current) == null ? void 0 : _a2.setAttribute("tabindex", "");
1341
- focusableCell.current = activeCell;
1342
- activeCell.setAttribute("tabindex", "0");
1343
- }
1344
- activeCell.focus();
1345
- } else if (!withinRange(cellPos[0], viewportRange)) {
1346
- focusableCell.current = void 0;
1347
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "up" });
1348
- }
1349
- }
1350
- },
1351
- // TODO we recreate this function whenever viewportRange changes, which will
1352
- // be often whilst scrolling - store range in a a ref ?
1353
- [containerRef, getTableCell, requestScroll, viewportRange]
1354
- );
1355
- const setActiveCell = useCallback11(
1356
- (rowIdx, colIdx, fromKeyboard = false) => {
1357
- const pos = [rowIdx, colIdx];
1358
- activeCellPos.current = pos;
1359
- focusCell(pos);
1360
- if (fromKeyboard) {
1361
- focusedCellPos.current = pos;
1362
- }
1363
- },
1364
- [focusCell]
1365
- );
1366
- const virtualizeActiveCell = useCallback11(() => {
1367
- var _a2;
1368
- (_a2 = focusableCell.current) == null ? void 0 : _a2.setAttribute("tabindex", "");
1369
- focusableCell.current = void 0;
1370
- }, []);
1371
- const nextPageItemIdx = useCallback11(
1372
- async (key, cellPos) => {
1373
- switch (key) {
1374
- case PageDown:
1375
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "down" });
1376
- break;
1377
- case PageUp:
1378
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "up" });
1379
- break;
1380
- case Home:
1381
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-end", direction: "home" });
1382
- break;
1383
- case End:
1384
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-end", direction: "end" });
1385
- break;
1386
- }
1387
- return cellPos;
1388
- },
1389
- [requestScroll]
1390
- );
1391
- const handleFocus = useCallback11(() => {
1392
- var _a2;
1393
- if (disableHighlightOnFocus !== true) {
1394
- if ((_a2 = containerRef.current) == null ? void 0 : _a2.contains(document.activeElement)) {
1395
- const focusedCell = getFocusedCell(document.activeElement);
1396
- if (focusedCell) {
1397
- focusedCellPos.current = getTableCellPos(focusedCell);
1398
- }
1399
- }
1400
- }
1401
- }, [disableHighlightOnFocus, containerRef]);
1402
- const navigateChildItems = useCallback11(
1403
- async (key) => {
1404
- const [nextRowIdx, nextColIdx] = isPagingKey(key) ? await nextPageItemIdx(key, activeCellPos.current) : nextCellPos(key, activeCellPos.current, columnCount, rowCount);
1405
- const [rowIdx, colIdx] = activeCellPos.current;
1406
- if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {
1407
- setActiveCell(nextRowIdx, nextColIdx, true);
1408
- }
1409
- },
1410
- [columnCount, nextPageItemIdx, rowCount, setActiveCell]
1411
- );
1412
- const handleKeyDown = useCallback11(
1413
- (e) => {
1414
- if (data.length > 0 && isNavigationKey(e.key)) {
1415
- e.preventDefault();
1416
- e.stopPropagation();
1417
- void navigateChildItems(e.key);
1418
- }
1419
- },
1420
- [data, navigateChildItems]
1421
- );
1422
- const handleClick = useCallback11(
1423
- // Might not be a cell e.g the Settings button
1424
- (evt) => {
1425
- const target = evt.target;
1426
- const focusedCell = getFocusedCell(target);
1427
- if (focusedCell) {
1428
- const [rowIdx, colIdx] = getTableCellPos(focusedCell);
1429
- setActiveCell(rowIdx, colIdx);
1430
- }
1431
- },
1432
- [setActiveCell]
1433
- );
1434
- const containerProps = useMemo3(() => {
1435
- return {
1436
- onClick: handleClick,
1437
- onFocus: handleFocus,
1438
- onKeyDown: handleKeyDown
1439
- };
1440
- }, [handleClick, handleFocus, handleKeyDown]);
1441
- useLayoutEffect(() => {
1442
- const { current: cellPos } = activeCellPos;
1443
- const withinViewport = cellPos[0] >= viewportFirstRow && cellPos[0] <= viewportLastRow;
1444
- if (focusableCell.current && !withinViewport) {
1445
- virtualizeActiveCell();
1446
- } else if (!focusableCell.current && withinViewport) {
1447
- focusCell(cellPos);
1448
- }
1449
- }, [focusCell, viewportFirstRow, viewportLastRow, virtualizeActiveCell]);
1450
- const fullyRendered = ((_a = containerRef.current) == null ? void 0 : _a.firstChild) != null;
1451
- useEffect2(() => {
1452
- var _a2;
1453
- if (fullyRendered && focusableCell.current === void 0) {
1454
- const headerCell = (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector(
1455
- headerCellQuery(0)
1456
- );
1457
- if (headerCell) {
1458
- headerCell.setAttribute("tabindex", "0");
1459
- focusableCell.current = headerCell;
1460
- }
1461
- }
1462
- }, [containerRef, fullyRendered]);
1463
- return containerProps;
1464
- };
1465
-
1466
- // src/useMeasuredContainer.ts
1467
- import { isValidNumber } from "@vuu-ui/vuu-utils";
1468
- import { useCallback as useCallback13, useMemo as useMemo4, useRef as useRef10, useState as useState3 } from "react";
1469
-
1470
- // src/useResizeObserver.ts
1471
- import { useCallback as useCallback12, useEffect as useEffect3, useRef as useRef9 } from "react";
1472
- var observedMap = /* @__PURE__ */ new Map();
1473
- var getTargetSize = (element, size, dimension) => {
1474
- switch (dimension) {
1475
- case "height":
1476
- return size.height;
1477
- case "clientHeight":
1478
- return element.clientHeight;
1479
- case "clientWidth":
1480
- return element.clientWidth;
1481
- case "contentHeight":
1482
- return size.contentHeight;
1483
- case "contentWidth":
1484
- return size.contentWidth;
1485
- case "scrollHeight":
1486
- return Math.ceil(element.scrollHeight);
1487
- case "scrollWidth":
1488
- return Math.ceil(element.scrollWidth);
1489
- case "width":
1490
- return size.width;
1491
- default:
1492
- return 0;
1493
- }
1494
- };
1495
- var resizeObserver = new ResizeObserver((entries) => {
1496
- for (const entry of entries) {
1497
- const { target, borderBoxSize, contentBoxSize } = entry;
1498
- const observedTarget = observedMap.get(target);
1499
- if (observedTarget) {
1500
- const [{ blockSize: height, inlineSize: width }] = borderBoxSize;
1501
- const [{ blockSize: contentHeight, inlineSize: contentWidth }] = contentBoxSize;
1502
- const { onResize, measurements } = observedTarget;
1503
- let sizeChanged = false;
1504
- for (const [dimension, size] of Object.entries(measurements)) {
1505
- const newSize = getTargetSize(
1506
- target,
1507
- { height, width, contentHeight, contentWidth },
1508
- dimension
1509
- );
1510
- if (newSize !== size) {
1511
- sizeChanged = true;
1512
- measurements[dimension] = newSize;
1513
- }
1514
- }
1515
- if (sizeChanged) {
1516
- onResize && onResize(measurements);
1517
- }
1518
- }
1519
- }
1520
- });
1521
- function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false) {
1522
- const dimensionsRef = useRef9(dimensions);
1523
- const measure = useCallback12((target) => {
1524
- const { width, height } = target.getBoundingClientRect();
1525
- const { clientWidth: contentWidth, clientHeight: contentHeight } = target;
1526
- return dimensionsRef.current.reduce(
1527
- (map, dim) => {
1528
- map[dim] = getTargetSize(
1529
- target,
1530
- { width, height, contentHeight, contentWidth },
1531
- dim
1532
- );
1533
- return map;
1534
- },
1535
- {}
1536
- );
1537
- }, []);
1538
- useEffect3(() => {
1539
- const target = ref.current;
1540
- async function registerObserver() {
1541
- observedMap.set(target, { measurements: {} });
1542
- await document.fonts.ready;
1543
- const observedTarget = observedMap.get(target);
1544
- if (observedTarget) {
1545
- const measurements = measure(target);
1546
- observedTarget.measurements = measurements;
1547
- resizeObserver.observe(target);
1548
- if (reportInitialSize) {
1549
- onResize(measurements);
1550
- }
1551
- } else {
1552
- console.log(
1553
- `%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation`,
1554
- "font-weight:bold; color:red;"
1555
- );
1556
- }
1557
- }
1558
- if (target) {
1559
- if (observedMap.has(target)) {
1560
- throw Error(
1561
- "useResizeObserver attemping to observe same element twice"
1562
- );
1563
- }
1564
- registerObserver();
1565
- }
1566
- return () => {
1567
- if (target && observedMap.has(target)) {
1568
- resizeObserver.unobserve(target);
1569
- observedMap.delete(target);
1570
- }
1571
- };
1572
- }, [measure, ref]);
1573
- useEffect3(() => {
1574
- const target = ref.current;
1575
- const record = observedMap.get(target);
1576
- if (record) {
1577
- if (dimensionsRef.current !== dimensions) {
1578
- dimensionsRef.current = dimensions;
1579
- const measurements = measure(target);
1580
- record.measurements = measurements;
1581
- }
1582
- record.onResize = onResize;
1583
- }
1584
- }, [dimensions, measure, ref, onResize]);
1585
- }
1586
-
1587
- // src/useMeasuredContainer.ts
1588
- var ClientWidthHeight = ["clientHeight", "clientWidth"];
1589
- var isNumber = (val) => Number.isFinite(val);
1590
- var FULL_SIZE = { height: "100%", width: "100%" };
1591
- var getInitialCssSize = (height, width) => {
1592
- if (isValidNumber(height) && isValidNumber(width)) {
1593
- return {
1594
- height: `${height}px`,
1595
- width: `${width}px`
1596
- };
1597
- } else {
1598
- return FULL_SIZE;
1599
- }
1600
- };
1601
- var getInitialInnerSize = (height, width) => {
1602
- if (isValidNumber(height) && isValidNumber(width)) {
1603
- return {
1604
- height,
1605
- width
1606
- };
1607
- }
1608
- };
1609
- var useMeasuredContainer = ({
1610
- defaultHeight = 0,
1611
- defaultWidth = 0,
1612
- height,
1613
- width
1614
- }) => {
1615
- const containerRef = useRef10(null);
1616
- const [size, setSize] = useState3({
1617
- css: getInitialCssSize(height, width),
1618
- inner: getInitialInnerSize(height, width),
1619
- outer: {
1620
- height: height != null ? height : "100%",
1621
- width: width != null ? width : "100%"
1622
- }
1623
- });
1624
- useMemo4(() => {
1625
- setSize((currentSize) => {
1626
- const { inner, outer } = currentSize;
1627
- if (isValidNumber(height) && isValidNumber(width) && inner && outer) {
1628
- const { height: innerHeight, width: innerWidth } = inner;
1629
- const { height: outerHeight, width: outerWidth } = outer;
1630
- if (outerHeight !== height || outerWidth !== width) {
1631
- const heightDiff = isValidNumber(outerHeight) ? outerHeight - innerHeight : 0;
1632
- const widthDiff = isValidNumber(outerWidth) ? outerWidth - innerWidth : 0;
1633
- return {
1634
- ...currentSize,
1635
- outer: { height, width },
1636
- inner: { height: height - heightDiff, width: width - widthDiff }
1637
- };
1638
- }
1639
- }
1640
- return currentSize;
1641
- });
1642
- }, [height, width]);
1643
- const onResize = useCallback13(
1644
- ({ clientWidth, clientHeight }) => {
1645
- setSize((currentSize) => {
1646
- const { css, inner, outer } = currentSize;
1647
- return isNumber(clientHeight) && isNumber(clientWidth) && (clientWidth !== (inner == null ? void 0 : inner.width) || clientHeight !== (inner == null ? void 0 : inner.height)) ? {
1648
- css,
1649
- outer,
1650
- inner: {
1651
- width: Math.floor(clientWidth) || defaultWidth,
1652
- height: Math.floor(clientHeight) || defaultHeight
1653
- }
1654
- } : currentSize;
1655
- });
1656
- },
1657
- [defaultHeight, defaultWidth]
1658
- );
1659
- useResizeObserver(containerRef, ClientWidthHeight, onResize, true);
1660
- return {
1661
- containerRef,
1662
- cssSize: size.css,
1663
- outerSize: size.outer,
1664
- innerSize: size.inner
1665
- };
1666
- };
1667
-
1668
- // src/useSelection.ts
1669
- import { deselectItem, metadataKeys as metadataKeys6, selectItem } from "@vuu-ui/vuu-utils";
1670
- import { useCallback as useCallback14, useRef as useRef11 } from "react";
1671
- var { IDX: IDX2, SELECTED: SELECTED3 } = metadataKeys6;
1672
- var NO_SELECTION = [];
1673
- var useSelection = ({
1674
- selectionModel,
1675
- onSelectionChange
1676
- }) => {
1677
- selectionModel === "extended" || selectionModel === "checkbox";
1678
- const lastActiveRef = useRef11(-1);
1679
- const selectedRef = useRef11(NO_SELECTION);
1680
- const handleSelectionChange = useCallback14(
1681
- (row, rangeSelect, keepExistingSelection) => {
1682
- const { [IDX2]: idx, [SELECTED3]: isSelected } = row;
1683
- const { current: active } = lastActiveRef;
1684
- const { current: selected } = selectedRef;
1685
- const selectOperation = isSelected ? deselectItem : selectItem;
1686
- const newSelected = selectOperation(
1687
- selectionModel,
1688
- selected,
1689
- idx,
1690
- rangeSelect,
1691
- keepExistingSelection,
1692
- active
1693
- );
1694
- selectedRef.current = newSelected;
1695
- lastActiveRef.current = idx;
1696
- if (onSelectionChange) {
1697
- onSelectionChange(newSelected);
1698
- }
1699
- },
1700
- [onSelectionChange, selectionModel]
1701
- );
1702
- return handleSelectionChange;
1703
- };
1704
-
1705
- // src/useTableModel.ts
1706
- import { moveItem } from "@heswell/salt-lab";
1707
- import {
1708
- applyFilterToColumns,
1709
- applyGroupByToColumns,
1710
- applySortToColumns,
1711
- findColumn,
1712
- getCellRenderer,
1713
- getColumnName,
1714
- getTableHeadings,
1715
- getValueFormatter,
1716
- isFilteredColumn,
1717
- isGroupColumn as isGroupColumn3,
1718
- isPinned,
1719
- isTypeDescriptor,
1720
- logger,
1721
- metadataKeys as metadataKeys7,
1722
- sortPinnedColumns,
1723
- stripFilterFromColumns
1724
- } from "@vuu-ui/vuu-utils";
1725
- import { useReducer } from "react";
1726
- var { info } = logger("useTableModel");
1727
- var DEFAULT_COLUMN_WIDTH = 100;
1728
- var KEY_OFFSET = metadataKeys7.count;
1729
- var columnWithoutDataType = ({ serverDataType }) => serverDataType === void 0;
1730
- var getCellRendererForColumn = (column) => {
1731
- var _a;
1732
- if (isTypeDescriptor(column.type)) {
1733
- return getCellRenderer((_a = column.type) == null ? void 0 : _a.renderer);
1734
- }
1735
- };
1736
- var getDataType = (column, columnNames, dataTypes) => {
1737
- var _a;
1738
- const index = columnNames.indexOf(column.name);
1739
- if (index !== -1 && dataTypes[index]) {
1740
- return dataTypes[index];
1741
- } else {
1742
- return (_a = column.serverDataType) != null ? _a : "string";
1743
- }
1744
- };
1745
- var numericTypes = ["int", "long", "double"];
1746
- var getDefaultAlignment = (serverDataType) => serverDataType === void 0 ? void 0 : numericTypes.includes(serverDataType) ? "right" : "left";
1747
- var columnReducer = (state, action) => {
1748
- info == null ? void 0 : info(`GridModelReducer ${action.type}`);
1749
- switch (action.type) {
1750
- case "init":
1751
- return init(action);
1752
- case "moveColumn":
1753
- return moveColumn(state, action);
1754
- case "resizeColumn":
1755
- return resizeColumn(state, action);
1756
- case "setTypes":
1757
- return setTypes(state, action);
1758
- case "hideColumns":
1759
- return hideColumns(state, action);
1760
- case "showColumns":
1761
- return showColumns(state, action);
1762
- case "pinColumn":
1763
- return pinColumn2(state, action);
1764
- case "updateColumnProp":
1765
- return updateColumnProp(state, action);
1766
- case "tableConfig":
1767
- return updateTableConfig(state, action);
1768
- default:
1769
- console.log(`unhandled action ${action.type}`);
1770
- return state;
1771
- }
1772
- };
1773
- var useTableModel = (tableConfig, dataSourceConfig) => {
1774
- const [state, dispatchColumnAction] = useReducer(columnReducer, { tableConfig, dataSourceConfig }, init);
1775
- return {
1776
- columns: state.columns,
1777
- dispatchColumnAction,
1778
- headings: state.headings
1779
- };
1780
- };
1781
- function init({ dataSourceConfig, tableConfig }) {
1782
- const columns = tableConfig.columns.map(
1783
- toKeyedColumWithDefaults(tableConfig)
1784
- );
1785
- const maybePinnedColumns = columns.some(isPinned) ? sortPinnedColumns(columns) : columns;
1786
- const state = {
1787
- columns: maybePinnedColumns,
1788
- headings: getTableHeadings(maybePinnedColumns)
1789
- };
1790
- if (dataSourceConfig) {
1791
- const { columns: columns2, ...rest } = dataSourceConfig;
1792
- return updateTableConfig(state, {
1793
- type: "tableConfig",
1794
- ...rest
1795
- });
1796
- } else {
1797
- return state;
1798
- }
1799
- }
1800
- var getLabel = (label, columnFormatHeader) => {
1801
- if (columnFormatHeader === "uppercase") {
1802
- return label.toUpperCase();
1803
- } else if (columnFormatHeader === "capitalize") {
1804
- return label[0].toUpperCase() + label.slice(1).toLowerCase();
1805
- }
1806
- return label;
1807
- };
1808
- var toKeyedColumWithDefaults = (options) => (column, index) => {
1809
- const { columnDefaultWidth = DEFAULT_COLUMN_WIDTH, columnFormatHeader } = options;
1810
- const {
1811
- align = getDefaultAlignment(column.serverDataType),
1812
- key,
1813
- name,
1814
- label = name,
1815
- width = columnDefaultWidth,
1816
- ...rest
1817
- } = column;
1818
- const keyedColumnWithDefaults = {
1819
- ...rest,
1820
- align,
1821
- CellRenderer: getCellRendererForColumn(column),
1822
- label: getLabel(label, columnFormatHeader),
1823
- key: key != null ? key : index + KEY_OFFSET,
1824
- name,
1825
- originalIdx: index,
1826
- valueFormatter: getValueFormatter(column),
1827
- width
1828
- };
1829
- if (isGroupColumn3(keyedColumnWithDefaults)) {
1830
- keyedColumnWithDefaults.columns = keyedColumnWithDefaults.columns.map(
1831
- (col) => toKeyedColumWithDefaults(options)(col, col.key)
1832
- );
1833
- }
1834
- return keyedColumnWithDefaults;
1835
- };
1836
- function moveColumn(state, { column, moveBy, moveTo }) {
1837
- const { columns } = state;
1838
- if (typeof moveBy === "number") {
1839
- const idx = columns.indexOf(column);
1840
- const newColumns = columns.slice();
1841
- const [movedColumns] = newColumns.splice(idx, 1);
1842
- newColumns.splice(idx + moveBy, 0, movedColumns);
1843
- return {
1844
- ...state,
1845
- columns: newColumns
1846
- };
1847
- } else if (typeof moveTo === "number") {
1848
- const index = columns.indexOf(column);
1849
- return {
1850
- ...state,
1851
- columns: moveItem(columns, index, moveTo)
1852
- };
1853
- }
1854
- return state;
1855
- }
1856
- function hideColumns(state, { columns }) {
1857
- if (columns.some((col) => col.hidden !== true)) {
1858
- return columns.reduce((s, c) => {
1859
- if (c.hidden !== true) {
1860
- return updateColumnProp(s, {
1861
- type: "updateColumnProp",
1862
- column: c,
1863
- hidden: true
1864
- });
1865
- } else {
1866
- return s;
1867
- }
1868
- }, state);
1869
- } else {
1870
- return state;
1871
- }
1872
- }
1873
- function showColumns(state, { columns }) {
1874
- if (columns.some((col) => col.hidden)) {
1875
- return columns.reduce((s, c) => {
1876
- if (c.hidden) {
1877
- return updateColumnProp(s, {
1878
- type: "updateColumnProp",
1879
- column: c,
1880
- hidden: false
1881
- });
1882
- } else {
1883
- return s;
1884
- }
1885
- }, state);
1886
- } else {
1887
- return state;
1888
- }
1889
- }
1890
- function resizeColumn(state, { column, phase, width }) {
1891
- const type = "updateColumnProp";
1892
- const resizing = phase !== "end";
1893
- switch (phase) {
1894
- case "begin":
1895
- case "end":
1896
- return updateColumnProp(state, { type, column, resizing });
1897
- case "resize":
1898
- return updateColumnProp(state, { type, column, width });
1899
- default:
1900
- throw Error(`useTableModel.resizeColumn, invalid resizePhase ${phase}`);
1901
- }
1902
- }
1903
- function setTypes(state, { columnNames, serverDataTypes }) {
1904
- const { columns } = state;
1905
- if (columns.some(columnWithoutDataType)) {
1906
- const cols = columns.map((column) => {
1907
- var _a;
1908
- const serverDataType = getDataType(column, columnNames, serverDataTypes);
1909
- return {
1910
- ...column,
1911
- align: (_a = column.align) != null ? _a : getDefaultAlignment(serverDataType),
1912
- serverDataType
1913
- };
1914
- });
1915
- return {
1916
- ...state,
1917
- columns: cols
1918
- };
1919
- } else {
1920
- return state;
1921
- }
1922
- }
1923
- function pinColumn2(state, action) {
1924
- let { columns } = state;
1925
- const { column, pin } = action;
1926
- const targetColumn = columns.find((col) => col.name === column.name);
1927
- if (targetColumn) {
1928
- columns = replaceColumn(columns, { ...targetColumn, pin });
1929
- columns = sortPinnedColumns(columns);
1930
- return {
1931
- ...state,
1932
- columns
1933
- };
1934
- } else {
1935
- return state;
1936
- }
1937
- }
1938
- function updateColumnProp(state, action) {
1939
- let { columns } = state;
1940
- const { align, column, hidden, label, resizing, width } = action;
1941
- const targetColumn = columns.find((col) => col.name === column.name);
1942
- if (targetColumn) {
1943
- if (align === "left" || align === "right") {
1944
- columns = replaceColumn(columns, { ...targetColumn, align });
1945
- }
1946
- if (typeof label === "string") {
1947
- columns = replaceColumn(columns, { ...targetColumn, label });
1948
- }
1949
- if (typeof resizing === "boolean") {
1950
- columns = replaceColumn(columns, { ...targetColumn, resizing });
1951
- }
1952
- if (typeof hidden === "boolean") {
1953
- columns = replaceColumn(columns, { ...targetColumn, hidden });
1954
- }
1955
- if (typeof width === "number") {
1956
- columns = replaceColumn(columns, { ...targetColumn, width });
1957
- }
1958
- }
1959
- return {
1960
- ...state,
1961
- columns
1962
- };
1963
- }
1964
- function updateTableConfig(state, { columns, confirmed, filter, groupBy, sort }) {
1965
- const hasColumns = columns && columns.length > 0;
1966
- const hasGroupBy = groupBy !== void 0;
1967
- const hasFilter = typeof (filter == null ? void 0 : filter.filter) === "string";
1968
- const hasSort = sort && sort.sortDefs.length > 0;
1969
- let result = state;
1970
- if (hasColumns) {
1971
- result = {
1972
- ...state,
1973
- columns: columns.map((colName, index) => {
1974
- const columnName = getColumnName(colName);
1975
- const key = index + KEY_OFFSET;
1976
- const col = findColumn(result.columns, columnName);
1977
- if (col) {
1978
- if (col.key === key) {
1979
- return col;
1980
- } else {
1981
- return {
1982
- ...col,
1983
- key
1984
- };
1985
- }
1986
- }
1987
- throw Error(`useTableModel column ${colName} not found`);
1988
- })
1989
- };
1990
- }
1991
- if (hasGroupBy) {
1992
- result = {
1993
- ...state,
1994
- columns: applyGroupByToColumns(result.columns, groupBy, confirmed)
1995
- };
1996
- }
1997
- if (hasSort) {
1998
- result = {
1999
- ...state,
2000
- columns: applySortToColumns(result.columns, sort)
2001
- };
2002
- }
2003
- if (hasFilter) {
2004
- result = {
2005
- ...state,
2006
- columns: applyFilterToColumns(result.columns, filter)
2007
- };
2008
- } else if (result.columns.some(isFilteredColumn)) {
2009
- result = {
2010
- ...state,
2011
- columns: stripFilterFromColumns(result.columns)
2012
- };
2013
- }
2014
- return result;
2015
- }
2016
- function replaceColumn(state, column) {
2017
- return state.map((col) => col.name === column.name ? column : col);
2018
- }
2019
-
2020
- // src/useTableScroll.ts
2021
- import { useCallback as useCallback15, useRef as useRef12 } from "react";
2022
- var getPctScroll = (container) => {
2023
- const { scrollLeft, scrollTop } = container;
2024
- const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2025
- const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);
2026
- const pctScrollTop = scrollTop / (scrollHeight - clientHeight);
2027
- return [pctScrollLeft, pctScrollTop];
2028
- };
2029
- var getMaxScroll = (container) => {
2030
- const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2031
- return [scrollWidth - clientWidth, scrollHeight - clientHeight];
2032
- };
2033
- var useCallbackRef = ({
2034
- onAttach,
2035
- onDetach
2036
- }) => {
2037
- const ref = useRef12(null);
2038
- const callbackRef = useCallback15(
2039
- (el) => {
2040
- if (el) {
2041
- ref.current = el;
2042
- onAttach == null ? void 0 : onAttach(el);
2043
- } else if (ref.current) {
2044
- const { current: originalRef } = ref;
2045
- ref.current = el;
2046
- onDetach == null ? void 0 : onDetach(originalRef);
2047
- }
2048
- },
2049
- [onAttach, onDetach]
2050
- );
2051
- return callbackRef;
2052
- };
2053
- var useTableScroll = ({
2054
- onHorizontalScroll,
2055
- onVerticalScroll,
2056
- viewport
2057
- }) => {
2058
- const contentContainerScrolledRef = useRef12(false);
2059
- const scrollPosRef = useRef12({ scrollTop: 0, scrollLeft: 0 });
2060
- const scrollbarContainerRef = useRef12(null);
2061
- const contentContainerRef = useRef12(null);
2062
- const {
2063
- maxScrollContainerScrollHorizontal: maxScrollLeft,
2064
- maxScrollContainerScrollVertical: maxScrollTop
2065
- } = viewport;
2066
- const handleScrollbarContainerScroll = useCallback15(() => {
2067
- const { current: contentContainer } = contentContainerRef;
2068
- const { current: scrollbarContainer } = scrollbarContainerRef;
2069
- const { current: contentContainerScrolled } = contentContainerScrolledRef;
2070
- if (contentContainerScrolled) {
2071
- contentContainerScrolledRef.current = false;
2072
- } else if (contentContainer && scrollbarContainer) {
2073
- const [pctScrollLeft, pctScrollTop] = getPctScroll(scrollbarContainer);
2074
- const [maxScrollLeft2, maxScrollTop2] = getMaxScroll(contentContainer);
2075
- const rootScrollLeft = Math.round(pctScrollLeft * maxScrollLeft2);
2076
- const rootScrollTop = Math.round(pctScrollTop * maxScrollTop2);
2077
- contentContainer.scrollTo({
2078
- left: rootScrollLeft,
2079
- top: rootScrollTop,
2080
- behavior: "auto"
2081
- });
2082
- }
2083
- }, []);
2084
- const handleContentContainerScroll = useCallback15(() => {
2085
- const { current: contentContainer } = contentContainerRef;
2086
- const { current: scrollbarContainer } = scrollbarContainerRef;
2087
- const { current: scrollPos } = scrollPosRef;
2088
- if (contentContainer && scrollbarContainer) {
2089
- const { scrollLeft, scrollTop } = contentContainer;
2090
- const [pctScrollLeft, pctScrollTop] = getPctScroll(contentContainer);
2091
- contentContainerScrolledRef.current = true;
2092
- scrollbarContainer.scrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2093
- scrollbarContainer.scrollTop = Math.round(pctScrollTop * maxScrollTop);
2094
- if (scrollPos.scrollTop !== scrollTop) {
2095
- scrollPos.scrollTop = scrollTop;
2096
- onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop, pctScrollTop);
2097
- }
2098
- if (scrollPos.scrollLeft !== scrollLeft) {
2099
- scrollPos.scrollLeft = scrollLeft;
2100
- onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2101
- }
2102
- }
2103
- }, [maxScrollLeft, maxScrollTop, onHorizontalScroll, onVerticalScroll]);
2104
- const handleAttachScrollbarContainer = useCallback15(
2105
- (el) => {
2106
- scrollbarContainerRef.current = el;
2107
- el.addEventListener("scroll", handleScrollbarContainerScroll, {
2108
- passive: true
2109
- });
2110
- },
2111
- [handleScrollbarContainerScroll]
2112
- );
2113
- const handleDetachScrollbarContainer = useCallback15(
2114
- (el) => {
2115
- scrollbarContainerRef.current = null;
2116
- el.removeEventListener("scroll", handleScrollbarContainerScroll);
2117
- },
2118
- [handleScrollbarContainerScroll]
2119
- );
2120
- const handleAttachContentContainer = useCallback15(
2121
- (el) => {
2122
- contentContainerRef.current = el;
2123
- el.addEventListener("scroll", handleContentContainerScroll, {
2124
- passive: true
2125
- });
2126
- },
2127
- [handleContentContainerScroll]
2128
- );
2129
- const handleDetachContentContainer = useCallback15(
2130
- (el) => {
2131
- contentContainerRef.current = null;
2132
- el.removeEventListener("scroll", handleContentContainerScroll);
2133
- },
2134
- [handleContentContainerScroll]
2135
- );
2136
- const contentContainerCallbackRef = useCallbackRef({
2137
- onAttach: handleAttachContentContainer,
2138
- onDetach: handleDetachContentContainer
2139
- });
2140
- const scrollbarContainerCallbackRef = useCallbackRef({
2141
- onAttach: handleAttachScrollbarContainer,
2142
- onDetach: handleDetachScrollbarContainer
2143
- });
2144
- const requestScroll = useCallback15(
2145
- (scrollRequest) => {
2146
- const { current: scrollbarContainer } = contentContainerRef;
2147
- if (scrollbarContainer) {
2148
- contentContainerScrolledRef.current = false;
2149
- if (scrollRequest.type === "scroll-page") {
2150
- const { clientHeight, scrollLeft, scrollTop } = scrollbarContainer;
2151
- const { direction } = scrollRequest;
2152
- const scrollBy = direction === "down" ? clientHeight : -clientHeight;
2153
- const newScrollTop = Math.min(
2154
- Math.max(0, scrollTop + scrollBy),
2155
- maxScrollTop
2156
- );
2157
- scrollbarContainer.scrollTo({
2158
- top: newScrollTop,
2159
- left: scrollLeft,
2160
- behavior: "auto"
2161
- });
2162
- } else if (scrollRequest.type === "scroll-end") {
2163
- const { direction } = scrollRequest;
2164
- const scrollTo = direction === "end" ? maxScrollTop : 0;
2165
- scrollbarContainer.scrollTo({
2166
- top: scrollTo,
2167
- left: scrollbarContainer.scrollLeft,
2168
- behavior: "auto"
2169
- });
2170
- }
2171
- }
2172
- },
2173
- [maxScrollTop]
2174
- );
2175
- return {
2176
- /** Ref to be assigned to ScrollbarContainer */
2177
- scrollbarContainerRef: scrollbarContainerCallbackRef,
2178
- /** Ref to be assigned to ContentContainer */
2179
- contentContainerRef: contentContainerCallbackRef,
2180
- /** Scroll the table */
2181
- requestScroll
2182
- };
2183
- };
2184
-
2185
- // src/useTableViewport.ts
2186
- import { useCallback as useCallback16, useMemo as useMemo5, useRef as useRef13 } from "react";
2187
- import {
2188
- actualRowPositioning,
2189
- virtualRowPositioning
2190
- } from "@vuu-ui/vuu-utils";
2191
- var MAX_RAW_ROWS = 15e5;
2192
- var UNMEASURED_VIEWPORT = {
2193
- contentHeight: 0,
2194
- contentWidth: 0,
2195
- getRowAtPosition: () => -1,
2196
- getRowOffset: () => -1,
2197
- horizontalScrollbarHeight: 0,
2198
- maxScrollContainerScrollHorizontal: 0,
2199
- maxScrollContainerScrollVertical: 0,
2200
- pinnedWidthLeft: 0,
2201
- pinnedWidthRight: 0,
2202
- rowCount: 0,
2203
- setPctScrollTop: () => void 0,
2204
- totalHeaderHeight: 0,
2205
- verticalScrollbarWidth: 0,
2206
- viewportBodyHeight: 0
2207
- };
2208
- var measurePinnedColumns = (columns) => {
2209
- let pinnedWidthLeft = 0;
2210
- let pinnedWidthRight = 0;
2211
- let unpinnedWidth = 0;
2212
- for (const column of columns) {
2213
- const { hidden, pin, width } = column;
2214
- const visibleWidth = hidden ? 0 : width;
2215
- if (pin === "left") {
2216
- pinnedWidthLeft += visibleWidth;
2217
- } else if (pin === "right") {
2218
- pinnedWidthRight += visibleWidth;
2219
- } else {
2220
- unpinnedWidth += visibleWidth;
2221
- }
2222
- }
2223
- return { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth };
2224
- };
2225
- var useTableViewport = ({
2226
- columns,
2227
- headerHeight,
2228
- headings,
2229
- rowCount,
2230
- rowHeight,
2231
- size
2232
- }) => {
2233
- const pctScrollTopRef = useRef13(0);
2234
- const appliedRowCount = Math.min(rowCount, MAX_RAW_ROWS);
2235
- const appliedContentHeight = appliedRowCount * rowHeight;
2236
- const virtualContentHeight = rowCount * rowHeight;
2237
- const virtualisedExtent = virtualContentHeight - appliedContentHeight;
2238
- const { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth } = useMemo5(
2239
- () => measurePinnedColumns(columns),
2240
- [columns]
2241
- );
2242
- const [actualRowOffset, actualRowAtPosition] = useMemo5(
2243
- () => actualRowPositioning(rowHeight),
2244
- [rowHeight]
2245
- );
2246
- const [getRowOffset, getRowAtPosition] = useMemo5(() => {
2247
- if (virtualisedExtent) {
2248
- return virtualRowPositioning(
2249
- rowHeight,
2250
- virtualisedExtent,
2251
- pctScrollTopRef
2252
- );
2253
- } else {
2254
- return [actualRowOffset, actualRowAtPosition];
2255
- }
2256
- }, [actualRowAtPosition, actualRowOffset, virtualisedExtent, rowHeight]);
2257
- const setPctScrollTop = useCallback16((scrollPct) => {
2258
- pctScrollTopRef.current = scrollPct;
2259
- }, []);
2260
- return useMemo5(() => {
2261
- var _a;
2262
- if (size) {
2263
- const headingsDepth = headings.length;
2264
- const scrollbarSize = 15;
2265
- const contentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2266
- const horizontalScrollbarHeight = contentWidth > size.width ? scrollbarSize : 0;
2267
- const totalHeaderHeight = headerHeight * (1 + headingsDepth);
2268
- const maxScrollContainerScrollVertical = appliedContentHeight - (((_a = size == null ? void 0 : size.height) != null ? _a : 0) - horizontalScrollbarHeight) + totalHeaderHeight;
2269
- const maxScrollContainerScrollHorizontal = contentWidth - size.width + pinnedWidthLeft;
2270
- const visibleRows = (size.height - headerHeight) / rowHeight;
2271
- const count = Number.isInteger(visibleRows) ? visibleRows + 1 : Math.ceil(visibleRows);
2272
- const viewportBodyHeight = size.height - totalHeaderHeight;
2273
- const verticalScrollbarWidth = appliedContentHeight > viewportBodyHeight ? scrollbarSize : 0;
2274
- return {
2275
- contentHeight: appliedContentHeight,
2276
- getRowAtPosition,
2277
- getRowOffset,
2278
- horizontalScrollbarHeight,
2279
- maxScrollContainerScrollHorizontal,
2280
- maxScrollContainerScrollVertical,
2281
- pinnedWidthLeft,
2282
- pinnedWidthRight,
2283
- rowCount: count,
2284
- contentWidth,
2285
- setPctScrollTop,
2286
- totalHeaderHeight,
2287
- verticalScrollbarWidth,
2288
- viewportBodyHeight
2289
- };
2290
- } else {
2291
- return UNMEASURED_VIEWPORT;
2292
- }
2293
- }, [
2294
- size,
2295
- headings.length,
2296
- pinnedWidthLeft,
2297
- unpinnedWidth,
2298
- pinnedWidthRight,
2299
- appliedContentHeight,
2300
- headerHeight,
2301
- rowHeight,
2302
- getRowAtPosition,
2303
- getRowOffset,
2304
- setPctScrollTop
2305
- ]);
2306
- };
2307
-
2308
- // src/useVirtualViewport.ts
2309
- import {
2310
- getColumnsInViewport,
2311
- itemsChanged
2312
- } from "@vuu-ui/vuu-utils";
2313
- import { useCallback as useCallback17, useEffect as useEffect4, useMemo as useMemo6, useRef as useRef14, useState as useState4 } from "react";
2314
- var useVirtualViewport = ({
2315
- columns,
2316
- getRowAtPosition,
2317
- setRange,
2318
- viewportMeasurements
2319
- }) => {
2320
- const firstRowRef = useRef14(-1);
2321
- const {
2322
- rowCount: viewportRowCount,
2323
- contentWidth,
2324
- maxScrollContainerScrollHorizontal
2325
- } = viewportMeasurements;
2326
- const availableWidth = contentWidth - maxScrollContainerScrollHorizontal;
2327
- const scrollLeftRef = useRef14(0);
2328
- const [visibleColumns, preSpan] = useMemo6(
2329
- () => getColumnsInViewport(
2330
- columns,
2331
- scrollLeftRef.current,
2332
- scrollLeftRef.current + availableWidth
2333
- ),
2334
- [availableWidth, columns]
2335
- );
2336
- const preSpanRef = useRef14(preSpan);
2337
- useEffect4(() => {
2338
- setColumnsWithinViewport(visibleColumns);
2339
- }, [visibleColumns]);
2340
- const [columnsWithinViewport, setColumnsWithinViewport] = useState4(visibleColumns);
2341
- const handleHorizontalScroll = useCallback17(
2342
- (scrollLeft) => {
2343
- scrollLeftRef.current = scrollLeft;
2344
- const [visibleColumns2, pre] = getColumnsInViewport(
2345
- columns,
2346
- scrollLeft,
2347
- scrollLeft + availableWidth
2348
- );
2349
- if (itemsChanged(columnsWithinViewport, visibleColumns2)) {
2350
- preSpanRef.current = pre;
2351
- setColumnsWithinViewport(visibleColumns2);
2352
- }
2353
- },
2354
- [availableWidth, columns, columnsWithinViewport]
2355
- );
2356
- const handleVerticalScroll = useCallback17(
2357
- (scrollTop) => {
2358
- const firstRow = getRowAtPosition(scrollTop);
2359
- if (firstRow !== firstRowRef.current) {
2360
- firstRowRef.current = firstRow;
2361
- setRange({ from: firstRow, to: firstRow + viewportRowCount });
2362
- }
2363
- },
2364
- [getRowAtPosition, setRange, viewportRowCount]
2365
- );
2366
- return {
2367
- columnsWithinViewport,
2368
- onHorizontalScroll: handleHorizontalScroll,
2369
- onVerticalScroll: handleVerticalScroll,
2370
- /** number of leading columns not rendered because of virtualization */
2371
- virtualColSpan: preSpanRef.current
2372
- };
2373
- };
2374
-
2375
- // src/useTable.ts
2376
- var NO_ROWS = [];
2377
- var { KEY: KEY2, IS_EXPANDED: IS_EXPANDED2, IS_LEAF: IS_LEAF2 } = metadataKeys8;
2378
- var useTable = ({
2379
- config,
2380
- dataSource,
2381
- headerHeight,
2382
- onConfigChange,
2383
- onFeatureEnabled,
2384
- onFeatureInvocation,
2385
- onSelectionChange,
2386
- renderBufferSize = 0,
2387
- rowHeight,
2388
- selectionModel,
2389
- ...measuredProps
2390
- }) => {
2391
- var _a, _b;
2392
- const [rowCount, setRowCount] = useState5(dataSource.size);
2393
- const expectConfigChangeRef = useRef15(false);
2394
- const dataSourceRef = useRef15();
2395
- dataSourceRef.current = dataSource;
2396
- if (dataSource === void 0) {
2397
- throw Error("no data source provided to Vuu Table");
2398
- }
2399
- const containerMeasurements = useMeasuredContainer(measuredProps);
2400
- const onDataRowcountChange = useCallback18((size) => {
2401
- setRowCount(size);
2402
- }, []);
2403
- const { columns, dispatchColumnAction, headings } = useTableModel(
2404
- config,
2405
- dataSource.config
2406
- );
2407
- const {
2408
- getRowAtPosition,
2409
- getRowOffset,
2410
- setPctScrollTop,
2411
- ...viewportMeasurements
2412
- } = useTableViewport({
2413
- columns,
2414
- headerHeight,
2415
- headings,
2416
- rowCount,
2417
- rowHeight,
2418
- size: containerMeasurements.innerSize
2419
- });
2420
- const onSubscribed = useCallback18(
2421
- (subscription) => {
2422
- if (subscription.tableMeta) {
2423
- const { columns: columnNames, dataTypes: serverDataTypes } = subscription.tableMeta;
2424
- expectConfigChangeRef.current = true;
2425
- dispatchColumnAction({
2426
- type: "setTypes",
2427
- columnNames,
2428
- serverDataTypes
2429
- });
2430
- }
2431
- },
2432
- [dispatchColumnAction]
2433
- );
2434
- const handleSelectionChange = useCallback18(
2435
- (selected) => {
2436
- dataSource.select(selected);
2437
- onSelectionChange == null ? void 0 : onSelectionChange(selected);
2438
- },
2439
- [dataSource, onSelectionChange]
2440
- );
2441
- const handleRowClick = useSelection({
2442
- onSelectionChange: handleSelectionChange,
2443
- selectionModel
2444
- });
2445
- const { data, getSelectedRows, range, setRange } = useDataSource({
2446
- dataSource,
2447
- onFeatureEnabled,
2448
- onFeatureInvocation,
2449
- onSubscribed,
2450
- onSizeChange: onDataRowcountChange,
2451
- renderBufferSize,
2452
- viewportRowCount: viewportMeasurements.rowCount
2453
- });
2454
- const dataRef = useRef15();
2455
- dataRef.current = data;
2456
- const onPersistentColumnOperation = useCallback18(
2457
- (action) => {
2458
- expectConfigChangeRef.current = true;
2459
- dispatchColumnAction(action);
2460
- },
2461
- [dispatchColumnAction]
2462
- );
2463
- const handleContextMenuAction = useTableContextMenu({
2464
- dataSource,
2465
- onPersistentColumnOperation
2466
- });
2467
- const handleSort = useCallback18(
2468
- (column, extendSort = false, sortType) => {
2469
- if (dataSource) {
2470
- dataSource.sort = applySort(
2471
- dataSource.sort,
2472
- column,
2473
- extendSort,
2474
- sortType
2475
- );
2476
- }
2477
- },
2478
- [dataSource]
2479
- );
2480
- const handleColumnResize = useCallback18(
2481
- (phase, columnName, width) => {
2482
- const column = columns.find((column2) => column2.name === columnName);
2483
- if (column) {
2484
- if (phase === "end") {
2485
- expectConfigChangeRef.current = true;
2486
- }
2487
- dispatchColumnAction({
2488
- type: "resizeColumn",
2489
- phase,
2490
- column,
2491
- width
2492
- });
2493
- } else {
2494
- throw Error(
2495
- `useDataTable.handleColumnResize, column ${columnName} not found`
2496
- );
2497
- }
2498
- },
2499
- [columns, dispatchColumnAction]
2500
- );
2501
- const handleToggleGroup = useCallback18(
2502
- (row, column) => {
2503
- const isJson = isJsonGroup2(column, row);
2504
- const key = row[KEY2];
2505
- if (row[IS_EXPANDED2]) {
2506
- dataSource.closeTreeNode(key, true);
2507
- if (isJson) {
2508
- const idx = columns.indexOf(column);
2509
- const rows = dataSource.getRowsAtDepth(idx + 1);
2510
- if (!rows.some((row2) => row2[IS_EXPANDED2] || row2[IS_LEAF2])) {
2511
- dispatchColumnAction({
2512
- type: "hideColumns",
2513
- columns: columns.slice(idx + 2)
2514
- });
2515
- }
2516
- }
2517
- } else {
2518
- dataSource.openTreeNode(key);
2519
- if (isJson) {
2520
- const childRows = dataSource.getChildRows(key);
2521
- const idx = columns.indexOf(column) + 1;
2522
- const columnsToShow = [columns[idx]];
2523
- if (childRows.some((row2) => row2[IS_LEAF2])) {
2524
- columnsToShow.push(columns[idx + 1]);
2525
- }
2526
- if (columnsToShow.some((col) => col.hidden)) {
2527
- dispatchColumnAction({
2528
- type: "showColumns",
2529
- columns: columnsToShow
2530
- });
2531
- }
2532
- }
2533
- }
2534
- },
2535
- [columns, dataSource, dispatchColumnAction]
2536
- );
2537
- const {
2538
- onVerticalScroll,
2539
- onHorizontalScroll,
2540
- columnsWithinViewport,
2541
- virtualColSpan
2542
- } = useVirtualViewport({
2543
- columns,
2544
- getRowAtPosition,
2545
- setRange,
2546
- viewportMeasurements
2547
- });
2548
- const handleVerticalScroll = useCallback18(
2549
- (scrollTop, pctScrollTop) => {
2550
- setPctScrollTop(pctScrollTop);
2551
- onVerticalScroll(scrollTop);
2552
- },
2553
- [onVerticalScroll, setPctScrollTop]
2554
- );
2555
- const { requestScroll, ...scrollProps } = useTableScroll({
2556
- onHorizontalScroll,
2557
- onVerticalScroll: handleVerticalScroll,
2558
- viewport: viewportMeasurements,
2559
- viewportHeight: ((_b = (_a = containerMeasurements.innerSize) == null ? void 0 : _a.height) != null ? _b : 0) - headerHeight
2560
- });
2561
- const containerProps = useKeyboardNavigation({
2562
- columnCount: columns.length,
2563
- containerRef: containerMeasurements.containerRef,
2564
- data,
2565
- requestScroll,
2566
- rowCount: dataSource == null ? void 0 : dataSource.size,
2567
- viewportRange: range
2568
- });
2569
- const handleRemoveColumnFromGroupBy = useCallback18(
2570
- (column) => {
2571
- if (column) {
2572
- if (dataSource && dataSource.groupBy.includes(column.name)) {
2573
- dataSource.groupBy = dataSource.groupBy.filter(
2574
- (columnName) => columnName !== column.name
2575
- );
2576
- }
2577
- } else {
2578
- dataSource.groupBy = [];
2579
- }
2580
- },
2581
- [dataSource]
2582
- );
2583
- const handleDropColumn = useCallback18(
2584
- (fromIndex, toIndex) => {
2585
- const column = dataSource.columns[fromIndex];
2586
- const columns2 = moveItem2(dataSource.columns, column, toIndex);
2587
- if (columns2 !== dataSource.columns) {
2588
- dataSource.columns = columns2;
2589
- dispatchColumnAction({ type: "tableConfig", columns: columns2 });
2590
- }
2591
- },
2592
- [dataSource, dispatchColumnAction]
2593
- );
2594
- const draggableHook = useDraggableColumn({
2595
- onDrop: handleDropColumn
2596
- });
2597
- useEffect5(() => {
2598
- if (dataSourceRef.current) {
2599
- expectConfigChangeRef.current = true;
2600
- dispatchColumnAction({
2601
- type: "init",
2602
- tableConfig: config,
2603
- dataSourceConfig: dataSourceRef.current.config
2604
- });
2605
- }
2606
- }, [config, dispatchColumnAction]);
2607
- useEffect5(() => {
2608
- dataSource.on("config", (config2, confirmed) => {
2609
- expectConfigChangeRef.current = true;
2610
- dispatchColumnAction({
2611
- type: "tableConfig",
2612
- ...config2,
2613
- confirmed
2614
- });
2615
- });
2616
- }, [dataSource, dispatchColumnAction]);
2617
- useMemo7(() => {
2618
- if (expectConfigChangeRef.current) {
2619
- onConfigChange == null ? void 0 : onConfigChange({
2620
- ...config,
2621
- columns
2622
- });
2623
- expectConfigChangeRef.current = false;
2624
- }
2625
- }, [columns, config, onConfigChange]);
2626
- const showContextMenu = usePopupContextMenu();
2627
- const onContextMenu = useCallback18(
2628
- (evt) => {
2629
- var _a2;
2630
- const { current: currentData } = dataRef;
2631
- const { current: currentDataSource } = dataSourceRef;
2632
- const target = evt.target;
2633
- const cellEl = target == null ? void 0 : target.closest("div[role='cell']");
2634
- const rowEl = target == null ? void 0 : target.closest(".vuuTableRow");
2635
- if (cellEl && rowEl && currentData && currentDataSource) {
2636
- const { columns: columns2, selectedRowsCount } = currentDataSource;
2637
- const columnMap = buildColumnMap2(columns2);
2638
- const rowIndex = parseInt((_a2 = rowEl.ariaRowIndex) != null ? _a2 : "-1");
2639
- const cellIndex = Array.from(rowEl.childNodes).indexOf(cellEl);
2640
- const row = currentData.find(([idx]) => idx === rowIndex);
2641
- const columnName = columns2[cellIndex];
2642
- showContextMenu(evt, "grid", {
2643
- columnMap,
2644
- columnName,
2645
- row,
2646
- selectedRows: selectedRowsCount === 0 ? NO_ROWS : getSelectedRows(),
2647
- viewport: dataSource == null ? void 0 : dataSource.viewport
2648
- });
2649
- }
2650
- },
2651
- [dataSource == null ? void 0 : dataSource.viewport, getSelectedRows, showContextMenu]
2652
- );
2653
- return {
2654
- columns,
2655
- columnsWithinViewport,
2656
- containerMeasurements,
2657
- containerProps,
2658
- data,
2659
- dispatchColumnAction,
2660
- getRowOffset,
2661
- handleContextMenuAction,
2662
- headings,
2663
- onColumnResize: handleColumnResize,
2664
- onContextMenu,
2665
- onRemoveColumnFromGroupBy: handleRemoveColumnFromGroupBy,
2666
- onRowClick: handleRowClick,
2667
- onSort: handleSort,
2668
- onToggleGroup: handleToggleGroup,
2669
- virtualColSpan,
2670
- scrollProps,
2671
- rowCount,
2672
- viewportMeasurements,
2673
- ...draggableHook
2674
- };
2675
- };
2676
-
2677
- // src/Table.tsx
2678
- import cx7 from "classnames";
2679
- import { isDataLoading } from "@vuu-ui/vuu-utils";
2680
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2681
- var classBase6 = "vuuTable";
2682
- var Table = ({
2683
- allowConfigEditing: showSettings = false,
2684
- className: classNameProp,
2685
- config,
2686
- dataSource,
2687
- headerHeight = 25,
2688
- height,
2689
- id: idProp,
2690
- onConfigChange,
2691
- onFeatureEnabled,
2692
- onFeatureInvocation,
2693
- onSelectionChange,
2694
- onShowConfigEditor: onShowSettings,
2695
- renderBufferSize = 0,
2696
- rowHeight = 20,
2697
- selectionModel = "extended",
2698
- style: styleProp,
2699
- width,
2700
- zebraStripes = false,
2701
- ...htmlAttributes
2702
- }) => {
2703
- const id = useIdMemo(idProp);
2704
- const {
2705
- containerMeasurements: { containerRef, innerSize, outerSize },
2706
- containerProps,
2707
- dispatchColumnAction,
2708
- draggable,
2709
- draggedItemIndex,
2710
- handleContextMenuAction,
2711
- scrollProps,
2712
- viewportMeasurements,
2713
- ...tableProps
2714
- } = useTable({
2715
- config,
2716
- dataSource,
2717
- renderBufferSize,
2718
- headerHeight,
2719
- height,
2720
- onConfigChange,
2721
- onFeatureEnabled,
2722
- onFeatureInvocation,
2723
- onSelectionChange,
2724
- rowHeight,
2725
- selectionModel,
2726
- width
2727
- });
2728
- const style = {
2729
- ...outerSize,
2730
- "--content-height": `${viewportMeasurements.contentHeight}px`,
2731
- "--horizontal-scrollbar-height": `${viewportMeasurements.horizontalScrollbarHeight}px`,
2732
- "--content-width": `${viewportMeasurements.contentWidth}px`,
2733
- "--pinned-width-left": `${viewportMeasurements.pinnedWidthLeft}px`,
2734
- "--pinned-width-right": `${viewportMeasurements.pinnedWidthRight}px`,
2735
- "--header-height": `${headerHeight}px`,
2736
- "--row-height": `${rowHeight}px`,
2737
- "--table-height": `${innerSize == null ? void 0 : innerSize.height}px`,
2738
- "--table-width": `${innerSize == null ? void 0 : innerSize.width}px`,
2739
- "--total-header-height": `${viewportMeasurements.totalHeaderHeight}px`,
2740
- "--vertical-scrollbar-width": `${viewportMeasurements.verticalScrollbarWidth}px`,
2741
- "--viewport-body-height": `${viewportMeasurements.viewportBodyHeight}px`
2742
- };
2743
- const className = cx7(classBase6, classNameProp, {
2744
- [`${classBase6}-zebra`]: zebraStripes,
2745
- [`${classBase6}-loading`]: isDataLoading(tableProps.columns)
2746
- });
2747
- return /* @__PURE__ */ jsx10(
2748
- ContextMenuProvider,
2749
- {
2750
- menuActionHandler: handleContextMenuAction,
2751
- menuBuilder: buildContextMenuDescriptors(dataSource),
2752
- children: /* @__PURE__ */ jsxs7(
2753
- "div",
2754
- {
2755
- ...htmlAttributes,
2756
- ...containerProps,
2757
- className,
2758
- id,
2759
- ref: containerRef,
2760
- style,
2761
- tabIndex: -1,
2762
- children: [
2763
- innerSize ? /* @__PURE__ */ jsx10(
2764
- "div",
2765
- {
2766
- className: `${classBase6}-scrollbarContainer`,
2767
- ref: scrollProps.scrollbarContainerRef,
2768
- children: /* @__PURE__ */ jsx10("div", { className: `${classBase6}-scrollbarContent` })
2769
- }
2770
- ) : null,
2771
- innerSize ? /* @__PURE__ */ jsxs7(
2772
- "div",
2773
- {
2774
- className: `${classBase6}-contentContainer`,
2775
- ref: scrollProps.contentContainerRef,
2776
- children: [
2777
- /* @__PURE__ */ jsx10(
2778
- RowBasedTable,
2779
- {
2780
- ...tableProps,
2781
- headerHeight,
2782
- tableId: id
2783
- }
2784
- ),
2785
- draggable
2786
- ]
2787
- }
2788
- ) : null,
2789
- showSettings && innerSize ? /* @__PURE__ */ jsx10(
2790
- Button,
2791
- {
2792
- className: `${classBase6}-settings`,
2793
- "data-icon": "settings",
2794
- onClick: onShowSettings,
2795
- variant: "secondary"
2796
- }
2797
- ) : null
2798
- ]
2799
- }
2800
- )
2801
- }
2802
- );
2803
- };
2804
-
2805
- // src/cell-renderers/json-cell/JsonCell.tsx
2806
- import cx8 from "classnames";
2807
- import {
2808
- isJsonAttribute,
2809
- metadataKeys as metadataKeys9,
2810
- registerComponent
2811
- } from "@vuu-ui/vuu-utils";
2812
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2813
- var classBase7 = "vuuJsonCell";
2814
- var { IS_EXPANDED: IS_EXPANDED3, KEY: KEY3 } = metadataKeys9;
2815
- var localKey = (key) => {
2816
- const pos = key.lastIndexOf("|");
2817
- if (pos === -1) {
2818
- return "";
2819
- } else {
2820
- return key.slice(pos + 1);
2821
- }
2822
- };
2823
- var JsonCell = ({ column, row }) => {
2824
- const {
2825
- key: columnKey
2826
- /*, type, valueFormatter */
2827
- } = column;
2828
- let value = row[columnKey];
2829
- let isToggle = false;
2830
- if (isJsonAttribute(value)) {
2831
- value = value.slice(0, -1);
2832
- isToggle = true;
2833
- }
2834
- const rowKey = localKey(row[KEY3]);
2835
- const className = cx8({
2836
- [`${classBase7}-name`]: rowKey === value,
2837
- [`${classBase7}-value`]: rowKey !== value,
2838
- [`${classBase7}-group`]: isToggle
2839
- });
2840
- if (isToggle) {
2841
- const toggleIcon = row[IS_EXPANDED3] ? "minus-box" : "plus-box";
2842
- return /* @__PURE__ */ jsxs8("span", { className, children: [
2843
- /* @__PURE__ */ jsx11("span", { className: `${classBase7}-value`, children: value }),
2844
- /* @__PURE__ */ jsx11("span", { className: `${classBase7}-toggle`, "data-icon": toggleIcon })
2845
- ] });
2846
- } else if (value) {
2847
- return /* @__PURE__ */ jsx11("span", { className, children: value });
2848
- } else {
2849
- return null;
2850
- }
2851
- };
2852
- registerComponent("json", JsonCell, "cell-renderer", {});
2853
- export {
2854
- Table,
2855
- buildContextMenuDescriptors,
2856
- useMeasuredContainer,
2857
- useTableContextMenu,
2858
- useTableModel,
2859
- useTableViewport
2860
- };
1
+ import{isNumericColumn as Rn}from"@vuu-ui/vuu-utils";var Ge=e=>(t,n)=>{let o=[];if(e===void 0)return o;if(t==="header")o.push(...Tn(n,e)),o.push(...Hn(n,e)),o.push(...Dn(n,e)),o.push(...xn(n));else if(t==="filter"){let{column:r,filter:i}=n,s=(i==null?void 0:i.column)===(r==null?void 0:r.name);o.push({label:"Edit filter",action:"filter-edit",options:n}),o.push({label:"Remove filter",action:"filter-remove-column",options:n}),r&&!s&&o.push({label:"Remove all filters",action:"remove-filters",options:n})}return o};function Tn(e,{sort:{sortDefs:t}}){let{column:n}=e,o=[];if(n===void 0)return o;let r=t.length>0;return n.sorted==="A"?o.push({label:"Reverse Sort (DSC)",action:"sort-dsc",options:e}):n.sorted==="D"?o.push({label:"Reverse Sort (ASC)",action:"sort-asc",options:e}):typeof n.sorted=="number"?(n.sorted>0?o.push({label:"Reverse Sort (DSC)",action:"sort-add-dsc",options:e}):o.push({label:"Reverse Sort (ASC)",action:"sort-add-asc",options:e}),r&&Math.abs(n.sorted)<t.length&&o.push({label:"Remove from sort",action:"sort-remove",options:e}),o.push({label:"New Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]})):r?(o.push({label:"Add to sort",children:[{label:"Ascending",action:"sort-add-asc",options:e},{label:"Descending",action:"sort-add-dsc",options:e}]}),o.push({label:"New Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]})):o.push({label:"Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]}),o}function Dn(e,t){let{column:n}=e;if(n===void 0||t.groupBy.length===0)return[];let{name:o,label:r=o}=n;return[{label:`Aggregate ${r}`,children:[{label:"Count",action:"agg-count",options:e}].concat(Rn(n)?[{label:"Sum",action:"agg-sum",options:e},{label:"Avg",action:"agg-avg",options:e},{label:"High",action:"agg-high",options:e},{label:"Low",action:"agg-low",options:e}]:[])}]}var be=(e,t)=>({label:`Pin ${t}`,action:`column-pin-${t}`,options:e}),fe=e=>be(e,"left"),ge=e=>be(e,"floating"),Ce=e=>be(e,"right");function xn(e){let{column:t}=e;if(t===void 0)return[];let{pin:n}=t,o=[{label:"Hide column",action:"column-hide",options:e},{label:"Remove column",action:"column-remove",options:e}];return n===void 0?o.push({label:"Pin column",children:[fe(e),ge(e),Ce(e)]}):n==="left"?o.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[ge(e),Ce(e)]}):n==="right"?o.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[fe(e),ge(e)]}):n==="floating"&&o.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[fe(e),Ce(e)]}),o}function Hn(e,{groupBy:t}){let{column:n}=e,o=[];if(n===void 0)return o;let{name:r,label:i=r}=n;return t.length===0?o.push({label:`Group by ${i}`,action:"group",options:e}):o.push({label:`Add ${i} to group by`,action:"group-add",options:e}),o}import{removeColumnFromFilter as Pn}from"@vuu-ui/vuu-filters";import{addGroupColumn as Be,addSortColumn as Ue,AggregationType as En,setAggregations as Z,setSortColumn as _e}from"@vuu-ui/vuu-utils";var Sn=(e,t)=>{if(e.filterStruct&&t){let[n,o]=Pn(t,e.filterStruct);return{filter:o,filterStruct:n}}else return e},{Average:An,Count:Ln,High:kn,Low:Kn,Sum:zn}=En,Je=({dataSource:e,onPersistentColumnOperation:t})=>(o,r)=>{let i=r;if(i.column&&e){let{column:s}=i;switch(o){case"sort-asc":return e.sort=_e(e.sort,s,"A"),!0;case"sort-dsc":return e.sort=_e(e.sort,s,"D"),!0;case"sort-add-asc":return e.sort=Ue(e.sort,s,"A"),!0;case"sort-add-dsc":return e.sort=Ue(e.sort,s,"D"),!0;case"group":return e.groupBy=Be(e.groupBy,s),!0;case"group-add":return e.groupBy=Be(e.groupBy,s),!0;case"column-hide":return t({type:"hideColumns",columns:[s]}),!0;case"column-remove":return e.columns=e.columns.filter(l=>l!==s.name),!0;case"filter-remove-column":return e.filter=Sn(e.filter,s),!0;case"remove-filters":return e.filter={filter:""},!0;case"agg-avg":return e.aggregations=Z(e.aggregations,s,An),!0;case"agg-high":return e.aggregations=Z(e.aggregations,s,kn),!0;case"agg-low":return e.aggregations=Z(e.aggregations,s,Kn),!0;case"agg-count":return e.aggregations=Z(e.aggregations,s,Ln),!0;case"agg-sum":return e.aggregations=Z(e.aggregations,s,zn),!0;case"column-pin-floating":return t({type:"pinColumn",column:s,pin:"floating"}),!0;case"column-pin-left":return t({type:"pinColumn",column:s,pin:"left"}),!0;case"column-pin-right":return t({type:"pinColumn",column:s,pin:"right"}),!0;case"column-unpin":return t({type:"pinColumn",column:s,pin:void 0}),!0;default:}}return!1};import{ContextMenuProvider as cs}from"@vuu-ui/vuu-popups";import{Button as as,useIdMemo as us}from"@salt-ds/core";import{buildColumnMap as yo,getColumnStyle as wo,isGroupColumn as Mo,metadataKeys as Ro,notHidden as To,visibleColumnAtIndex as Do}from"@vuu-ui/vuu-utils";import{useCallback as ft,useMemo as gt}from"react";import{isGroupColumn as je,isJsonColumn as Qn,isJsonGroup as Zn,metadataKeys as jn,notHidden as qn}from"@vuu-ui/vuu-utils";import eo from"classnames";import{memo as to,useCallback as qe}from"react";import{getColumnStyle as Nn,metadataKeys as In}from"@vuu-ui/vuu-utils";import{EditableLabel as Fn}from"@heswell/salt-lab";import Vn from"classnames";import{memo as Wn,useCallback as $n,useRef as On,useState as Xe}from"react";import{jsx as ie}from"react/jsx-runtime";var{KEY:Ye}=In,he=Wn(({className:e,column:t,columnMap:n,onClick:o,row:r})=>{let i=On(null),{align:s,CellRenderer:l,key:a,pin:u,editable:c,resizing:p,valueFormatter:d}=t,[g,h]=Xe(!1),f=d(r[a]),[R,y]=Xe(f),m=()=>{var P;(P=i.current)==null||P.focus()},b=P=>{P.key==="Enter"&&h(!0)},T=$n(P=>{o==null||o(P,t)},[t,o]),w=()=>{h(!0)},v=(P="",C="",M=!0,E=!1)=>{var x;h(!1),E?y(P):C!==P&&y(C),M===!1&&((x=i.current)==null||x.focus())},D=Vn(e,{vuuAlignRight:s==="right",vuuPinFloating:u==="floating",vuuPinLeft:u==="left",vuuPinRight:u==="right","vuuTableCell-resizing":p})||void 0,S=Nn(t);return c?ie("div",{className:D,"data-editable":!0,role:"cell",style:S,onKeyDown:b,children:ie(Fn,{editing:g,value:R,onChange:y,onMouseDownCapture:m,onEnterEditMode:w,onExitEditMode:v,onKeyDown:b,ref:i,tabIndex:0},"title")}):ie("div",{className:D,role:"cell",style:S,onClick:T,children:l?ie(l,{column:t,columnMap:n,row:r}):f})},Gn);he.displayName="TableCell";function Gn(e,t){return e.column===t.column&&e.onClick===t.onClick&&e.row[Ye]===t.row[Ye]&&e.row[e.column.key]===t.row[t.column.key]}import{getColumnStyle as Bn,metadataKeys as Un}from"@vuu-ui/vuu-utils";import{useCallback as _n}from"react";import{jsx as ve,jsxs as Yn}from"react/jsx-runtime";var{DEPTH:Jn,IS_LEAF:Qe}=Un,Xn=(e,t)=>{let{[Jn]:n,[Qe]:o}=t;if(o||n>e.length)return[null,n===null?0:n-1];if(n===0)return["$root",0];{let{key:r,valueFormatter:i}=e[n-1];return[i(t[r]),n-1]}},Ze=({column:e,onClick:t,row:n})=>{let{columns:o}=e,[r,i]=Xn(o,n),s=_n(c=>{t==null||t(c,e)},[e,t]),l=Bn(e),a=n[Qe],u=Array(i).fill(0).map((c,p)=>ve("span",{className:"vuuTableGroupCell-spacer"},p));return Yn("div",{className:"vuuTableGroupCell vuuPinLeft",onClick:a?void 0:s,role:"cell",style:l,children:[u,a?null:ve("span",{className:"vuuTableGroupCell-toggle","data-icon":"triangle-right"}),ve("span",{children:r})]})};import{jsx as et,jsxs as so}from"react/jsx-runtime";var{IDX:no,IS_EXPANDED:oo,SELECTED:ro}=jn,le="vuuTableRow",tt=to(function({columnMap:t,columns:n,offset:o,onClick:r,onToggleGroup:i,virtualColSpan:s=0,row:l}){let{[no]:a,[oo]:u,[ro]:c}=l,p=eo(le,{[`${le}-even`]:a%2===0,[`${le}-expanded`]:u,[`${le}-preSelected`]:c===2}),d=qe(h=>{let f=h.shiftKey,R=h.ctrlKey||h.metaKey;r==null||r(l,f,R)},[r,l]),g=qe((h,f)=>{(je(f)||Zn(f,l))&&(h.stopPropagation(),i==null||i(l,f))},[i,l]);return so("div",{"aria-selected":c===1?!0:void 0,"aria-rowindex":a,className:p,onClick:d,role:"row",style:{transform:`translate3d(0px, ${o}px, 0px)`},children:[s>0?et("div",{role:"cell",style:{width:s}}):null,n.filter(qn).map(h=>{let f=je(h),R=Qn(h);return et(f?Ze:he,{column:h,columnMap:t,onClick:f||R?g:void 0,row:l},h.name)})]})});import st from"classnames";import{useRef as ao}from"react";import{useCallback as ye,useRef as io}from"react";import{jsx as co}from"react/jsx-runtime";var nt=()=>{},lo="vuuColumnResizer",ce=({onDrag:e,onDragEnd:t=nt,onDragStart:n=nt})=>{let o=io(0),r=ye(l=>{l.stopPropagation&&l.stopPropagation(),l.preventDefault&&l.preventDefault();let a=Math.round(l.clientX),u=a-o.current;o.current=a,u!==0&&e(l,u)},[e]),i=ye(l=>{window.removeEventListener("mouseup",i),window.removeEventListener("mousemove",r),t(l)},[t,r]),s=ye(l=>{n(l),o.current=Math.round(l.clientX),window.addEventListener("mouseup",i),window.addEventListener("mousemove",r),l.stopPropagation&&l.stopPropagation(),l.preventDefault&&l.preventDefault()},[n,r,i]);return co("div",{className:lo,"data-align":"end",onMouseDown:s})};import{useCallback as we,useRef as ot}from"react";var ae=({column:e,onResize:t,rootRef:n})=>{let o=ot(0),r=ot(!1),{name:i}=e,s=we(()=>{if(t&&n.current){let{width:u}=n.current.getBoundingClientRect();o.current=Math.round(u),r.current=!0,t==null||t("begin",i)}},[i,t,n]),l=we((u,c)=>{if(n.current&&t){let{width:p}=n.current.getBoundingClientRect(),d=Math.round(p)+c;d!==o.current&&d>0&&(t("resize",i,d),o.current=d)}},[i,t,n]),a=we(()=>{t&&(t("end",i,o.current),setTimeout(()=>{r.current=!1},100))},[i,t]);return{isResizing:r.current,onDrag:l,onDragStart:s,onDragEnd:a}};import{jsx as G,jsxs as lt}from"react/jsx-runtime";var V="vuuTable-groupHeaderCell",rt=({column:e,onClick:t,...n})=>G("span",{...n,className:`${V}-close`,"data-icon":"close-circle",onClick:()=>t==null?void 0:t(e)}),uo=e=>{let{children:t,column:n,className:o}=e;return lt("div",{className:st(`${V}-col`,o),role:"columnheader",children:[G("span",{className:`${V}-label`,children:n.name}),t]})},it=({column:e,className:t,onRemoveColumn:n,onResize:o,...r})=>{let i=ao(null),{isResizing:s,...l}=ae({column:e,onResize:o,rootRef:i}),a=st(V,t,{vuuPinLeft:e.pin==="left",[`${V}-right`]:e.align==="right",[`${V}-resizing`]:e.resizing,[`${V}-pending`]:e.groupConfirmed===!1}),{columns:u}=e;return G("div",{className:a,ref:i,...r,children:lt("div",{className:`${V}-inner`,children:[u.map(c=>G(uo,{column:c,children:u.length>1?G(rt,{column:c,onClick:n}):null},c.key)),G(rt,{"data-align":"end",onClick:n}),e.resizeable!==!1?G(ce,{...l}):null]})})};import bo from"classnames";import{useCallback as Me,useRef as dt}from"react";import ct from"classnames";import{jsx as ue,jsxs as mo}from"react/jsx-runtime";var at="vuuSortIndicator",ut=({sorted:e})=>{if(!e)return null;let t=typeof e=="number"?e<0?"dsc":"asc":e==="A"?"asc":"dsc";return typeof e=="number"?mo("div",{className:ct(at,"multi-col",t),children:[ue("span",{"data-icon":`sorted-${t}`}),ue("span",{className:"vuuSortPosition",children:Math.abs(e)})]}):ue("div",{className:ct(at,"single-col"),children:ue("span",{"data-icon":`sorted-${t}`})})};import{useContextMenu as ho}from"@vuu-ui/vuu-popups";import{useContextMenu as po}from"@vuu-ui/vuu-popups";import fo from"classnames";import{useCallback as go}from"react";import{jsx as Co}from"react/jsx-runtime";var mt=({column:e,filter:t})=>{let n=po(),o=go(r=>{r.stopPropagation(),n(r,"filter",{column:e,filter:t})},[e,t,n]);return e.filter?Co("div",{className:fo("vuuFilterIndicator"),"data-icon":"filter",onClick:o}):null};import{jsx as q,jsxs as vo}from"react/jsx-runtime";var j="vuuTable-headerCell",pt=({column:e,className:t,onClick:n,onDragStart:o,onResize:r,...i})=>{let s=dt(null),{isResizing:l,...a}=ae({column:e,onResize:r,rootRef:s}),u=ho(),c=dt(null),p=R=>{u(R,"header",{column:e})},d=Me(R=>!l&&(n==null?void 0:n(R)),[l,n]),g=Me(R=>{c.current=window.setTimeout(()=>{o==null||o(R),c.current=null},500)},[o]),h=Me(()=>{c.current!==null&&(window.clearTimeout(c.current),c.current=null)},[]),f=bo(j,t,{vuuPinFloating:e.pin==="floating",vuuPinLeft:e.pin==="left",vuuPinRight:e.pin==="right",vuuEndPin:e.endPin,[`${j}-resizing`]:e.resizing,[`${j}-right`]:e.align==="right"});return q("div",{className:f,...i,onClick:d,onContextMenu:p,onMouseDown:g,onMouseUp:h,ref:s,children:vo("div",{className:`${j}-inner`,children:[q(mt,{column:e}),q("div",{className:`${j}-label`,children:e.label}),q(ut,{sorted:e.sorted}),e.resizeable!==!1?q(ce,{...a}):null]})})};import{jsx as B,jsxs as Ct}from"react/jsx-runtime";var Re="vuuTable",{RENDER_IDX:xo}=Ro,bt=({columns:e,columnsWithinViewport:t,data:n,getRowOffset:o,headings:r,onColumnResize:i,onHeaderCellDragStart:s,onContextMenu:l,onRemoveColumnFromGroupBy:a,onRowClick:u,onSort:c,onToggleGroup:p,tableId:d,virtualColSpan:g=0,rowCount:h})=>{let f=ft(b=>{s==null||s(b)},[s]),R=gt(()=>e.filter(To),[e]),y=gt(()=>yo(e),[e]),m=ft(b=>{var P;let w=b.target.closest(".vuuTable-headerCell"),v=parseInt((P=w==null?void 0:w.dataset.idx)!=null?P:"-1"),D=Do(e,v),S=b.shiftKey;D&&c(D,S)},[e,c]);return Ct("div",{"aria-rowcount":h,className:`${Re}-table`,role:"table",children:[Ct("div",{className:`${Re}-headers`,role:"rowGroup",children:[r.map((b,T)=>B("div",{className:"vuuTable-heading",children:b.map(({label:w,width:v},D)=>B("div",{className:"vuuTable-headingCell",style:{width:v},children:w},D))},T)),B("div",{role:"row",children:R.map((b,T)=>{let w=wo(b);return Mo(b)?B(it,{column:b,"data-idx":T,onRemoveColumn:a,onResize:i,role:"columnHeader",style:w},T):B(pt,{column:b,"data-idx":T,id:`${d}-${T}`,onClick:m,onDragStart:f,onResize:i,role:"columnHeader",style:w},T)})})]}),B("div",{className:`${Re}-body`,onContextMenu:l,role:"rowGroup",children:n==null?void 0:n.map(b=>B(tt,{columnMap:y,columns:t,offset:o(b),onClick:u,virtualColSpan:g,onToggleGroup:p,row:b},b[xo]))})]})};import{useContextMenu as jr}from"@vuu-ui/vuu-popups";import{applySort as qr,buildColumnMap as es,isJsonGroup as ts,metadataKeys as ns,moveItem as os}from"@vuu-ui/vuu-utils";import{useCallback as z,useEffect as Yt,useMemo as rs,useRef as Ie,useState as ss}from"react";import{isVuuFeatureAction as Ho,isVuuFeatureInvocation as Po}from"@vuu-ui/vuu-data";import{getFullRange as Te,metadataKeys as Eo,WindowRange as So}from"@vuu-ui/vuu-utils";import{useCallback as Y,useEffect as me,useMemo as Ao,useRef as ee,useState as Lo}from"react";var{SELECTED:te}=Eo;function ht({dataSource:e,onConfigChange:t,onFeatureEnabled:n,onFeatureInvocation:o,onSizeChange:r,onSubscribed:i,range:s={from:0,to:0},renderBufferSize:l=0,viewportRowCount:a}){let[,u]=Lo(null),c=ee(!0),p=ee(!1),d=ee({from:0,to:0}),g=ee(null),h=ee([]),f=Ao(()=>new De(Te(s)),[]),R=Y(v=>{for(let D of v)f.add(D);h.current=f.data,p.current=!0},[f]),y=Y(v=>{v.type==="subscribed"?i==null||i(v):v.type==="viewport-update"?(typeof v.size=="number"&&(r==null||r(v.size),f.setRowCount(v.size)),v.rows?R(v.rows):typeof v.size=="number"&&(h.current=f.data,p.current=!0)):Ho(v)?n==null||n(v):Po(v)?o==null||o(v):console.log(`useDataSource unexpected message ${v.type}`)},[f,n,o,r,i,R]);me(()=>()=>{g.current&&(cancelAnimationFrame(g.current),g.current=null),c.current=!1},[]);let m=Y(()=>{c.current&&(p.current&&(u({}),p.current=!1),g.current=requestAnimationFrame(m))},[u]);me(()=>{g.current=requestAnimationFrame(m)},[m]);let b=Y(v=>{let{from:D}=e.range,S={from:D,to:D+v},P=Te(S,l);f.setRange(P),e.range=d.current=P,e.emit("range",S)},[e,f,l]),T=Y(v=>{let D=Te(v,l);f.setRange(D),e.range=d.current=D,e.emit("range",v)},[e,f,l]),w=Y(()=>f.getSelectedRows(),[f]);return me(()=>{e==null||e.subscribe({range:d.current},y)},[e,y,t]),me(()=>{b(a)},[b,a]),{data:h.current,getSelectedRows:w,range:d.current,setRange:T,dataSource:e}}var De=class{constructor({from:t,to:n}){this.rowCount=0;this.setRowCount=t=>{t<this.data.length&&(this.data.length=t),this.rowCount=t};this.range=new So(t,n),this.data=new Array(n-t),this.rowCount=0}add(t){var o;let[n]=t;if(this.isWithinRange(n)){let r=n-this.range.from;this.data[r]=t;let i=t[te],s=(o=this.data[r-1])==null?void 0:o[te];s===0&&i?this.data[r-1][te]=2:s===2&&!i&&(this.data[r-1][te]=0)}}getAtIndex(t){return this.range.isWithin(t)&&this.data[t-this.range.from]!=null?this.data[t-this.range.from]:void 0}isWithinRange(t){return this.range.isWithin(t)}setRange({from:t,to:n}){if(t!==this.range.from||n!==this.range.to){let[o,r]=this.range.overlap(t,n),i=new Array(Math.max(0,n-t));for(let s=o;s<r;s++){let l=this.getAtIndex(s);if(l){let a=s-t;i[a]=l}}this.data=i,this.range.from=t,this.range.to=n}}getSelectedRows(){return this.data.filter(t=>t[te]===1)}};import{useDragDrop as ko}from"@heswell/salt-lab";import{useCallback as vt,useRef as yt}from"react";var wt=({onDrop:e})=>{let t=yt(),n=yt(null),o=vt(()=>{console.log("handleDropSettle"),t.current=void 0,n.current=null},[]),{draggable:r,draggedItemIndex:i,onMouseDown:s}=ko({allowDragDrop:!0,draggableClassName:"vuuTable-headerCell",orientation:"horizontal",containerRef:n,itemQuery:".vuuTable-headerCell",onDrop:e,onDropSettle:o}),l=vt(a=>{let{clientX:u,clientY:c}=a;console.log("useDraggableColumn handleHeaderCellDragStart means mouseDown fired on a column in RowBasedTable");let d=a.target.closest(".vuuTable-headerCell");n.current=d==null?void 0:d.closest("[role='row']");let{dataset:{idx:g="-1"}}=d;t.current={clientX:u,clientY:c,idx:g},s==null||s(a)},[s]);return{draggable:r,draggedItemIndex:i,onHeaderCellDragStart:l}};import{withinRange as Wo}from"@vuu-ui/vuu-utils";import{useCallback as F,useEffect as $o,useLayoutEffect as Oo,useMemo as Go,useRef as Ke}from"react";function Ko(e,...t){let n=new Set(e);for(let o of t)for(let r of o)n.add(r);return n}var xe="ArrowUp",He="ArrowDown",Pe="ArrowLeft",Ee="ArrowRight";var Se="Home",Ae="End",Le="PageUp",ke="PageDown";var zo=new Set(["Enter","Delete"," "]),No=new Set(["Tab"]),Io=new Set(["ArrowRight","ArrowLeft"]),Mt=new Set([Se,Ae,Le,ke,He,Pe,Ee,xe]),Fo=new Set(["F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12"]),Pl=Ko(zo,Mt,Io,Fo,No);var Vo=["Home","End","PageUp","PageDown"],Rt=e=>Vo.includes(e),Tt=e=>Mt.has(e);var Dt=e=>`.vuuTable-headers .vuuTable-headerCell:nth-child(${e+1})`,Bo=(e,t)=>`.vuuTable-body > [aria-rowindex='${e}'] > [role='cell']:nth-child(${t+1})`,Uo=[-1,-1];function _o(e,[t,n],o,r){return e===xe?t>-1?[t-1,n]:[t,n]:e===He?t===-1?[0,n]:t===r-1?[t,n]:[t+1,n]:e===Ee?n<o-1?[t,n+1]:[t,n]:e===Pe?n>0?[t,n-1]:[t,n]:[t,n]}var xt=({columnCount:e=0,containerRef:t,disableHighlightOnFocus:n,data:o,requestScroll:r,rowCount:i=0,viewportRange:s})=>{var P;let{from:l,to:a}=s,u=Ke([-1,-1]),c=Ke(),p=Ke([-1,0]),d=F(([C,M])=>{var x;let E=C===-1?Dt(M):Bo(C,M);return(x=t.current)==null?void 0:x.querySelector(E)},[t]),g=C=>C==null?void 0:C.closest("[role='columnHeader'],[role='cell']"),h=C=>{var M,E;if(C.role==="columnHeader")return[-1,parseInt((M=C.dataset.idx)!=null?M:"-1",10)];{let x=C.closest("[role='row']");if(x){let K=parseInt((E=x.ariaRowIndex)!=null?E:"-1",10),J=Array.from(x.childNodes).indexOf(C);return[K,J]}}return Uo},f=F(C=>{var M;if(t.current){let E=d(C);E?(E!==c.current&&((M=c.current)==null||M.setAttribute("tabindex",""),c.current=E,E.setAttribute("tabindex","0")),E.focus()):Wo(C[0],s)||(c.current=void 0,r==null||r({type:"scroll-page",direction:"up"}))}},[t,d,r,s]),R=F((C,M,E=!1)=>{let x=[C,M];p.current=x,f(x),E&&(u.current=x)},[f]),y=F(()=>{var C;(C=c.current)==null||C.setAttribute("tabindex",""),c.current=void 0},[]),m=F(async(C,M)=>{switch(C){case ke:r==null||r({type:"scroll-page",direction:"down"});break;case Le:r==null||r({type:"scroll-page",direction:"up"});break;case Se:r==null||r({type:"scroll-end",direction:"home"});break;case Ae:r==null||r({type:"scroll-end",direction:"end"});break}return M},[r]),b=F(()=>{var C;if(n!==!0&&(C=t.current)!=null&&C.contains(document.activeElement)){let M=g(document.activeElement);M&&(u.current=h(M))}},[n,t]),T=F(async C=>{let[M,E]=Rt(C)?await m(C,p.current):_o(C,p.current,e,i),[x,K]=p.current;(M!==x||E!==K)&&R(M,E,!0)},[e,m,i,R]),w=F(C=>{o.length>0&&Tt(C.key)&&(C.preventDefault(),C.stopPropagation(),T(C.key))},[o,T]),v=F(C=>{let M=C.target,E=g(M);if(E){let[x,K]=h(E);R(x,K)}},[R]),D=Go(()=>({onClick:v,onFocus:b,onKeyDown:w}),[v,b,w]);Oo(()=>{let{current:C}=p,M=C[0]>=l&&C[0]<=a;c.current&&!M?y():!c.current&&M&&f(C)},[f,l,a,y]);let S=((P=t.current)==null?void 0:P.firstChild)!=null;return $o(()=>{var C;if(S&&c.current===void 0){let M=(C=t.current)==null?void 0:C.querySelector(Dt(0));M&&(M.setAttribute("tabindex","0"),c.current=M)}},[t,S]),D};import{isValidNumber as W}from"@vuu-ui/vuu-utils";import{useCallback as Yo,useMemo as Qo,useRef as Zo,useState as jo}from"react";import{useCallback as Jo,useEffect as Ht,useRef as Xo}from"react";var U=new Map,Et=(e,t,n)=>{switch(n){case"height":return t.height;case"clientHeight":return e.clientHeight;case"clientWidth":return e.clientWidth;case"contentHeight":return t.contentHeight;case"contentWidth":return t.contentWidth;case"scrollHeight":return Math.ceil(e.scrollHeight);case"scrollWidth":return Math.ceil(e.scrollWidth);case"width":return t.width;default:return 0}},Pt=new ResizeObserver(e=>{for(let t of e){let{target:n,borderBoxSize:o,contentBoxSize:r}=t,i=U.get(n);if(i){let[{blockSize:s,inlineSize:l}]=o,[{blockSize:a,inlineSize:u}]=r,{onResize:c,measurements:p}=i,d=!1;for(let[g,h]of Object.entries(p)){let f=Et(n,{height:s,width:l,contentHeight:a,contentWidth:u},g);f!==h&&(d=!0,p[g]=f)}d&&c&&c(p)}}});function St(e,t,n,o=!1){let r=Xo(t),i=Jo(s=>{let{width:l,height:a}=s.getBoundingClientRect(),{clientWidth:u,clientHeight:c}=s;return r.current.reduce((p,d)=>(p[d]=Et(s,{width:l,height:a,contentHeight:c,contentWidth:u},d),p),{})},[]);Ht(()=>{let s=e.current;async function l(){U.set(s,{measurements:{}}),await document.fonts.ready;let a=U.get(s);if(a){let u=i(s);a.measurements=u,Pt.observe(s),o&&n(u)}else console.log("%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation","font-weight:bold; color:red;")}if(s){if(U.has(s))throw Error("useResizeObserver attemping to observe same element twice");l()}return()=>{s&&U.has(s)&&(Pt.unobserve(s),U.delete(s))}},[i,e]),Ht(()=>{let s=e.current,l=U.get(s);if(l){if(r.current!==t){r.current=t;let a=i(s);l.measurements=a}l.onResize=n}},[t,i,e,n])}var qo=["clientHeight","clientWidth"],At=e=>Number.isFinite(e),er={height:"100%",width:"100%"},tr=(e,t)=>W(e)&&W(t)?{height:`${e}px`,width:`${t}px`}:er,nr=(e,t)=>{if(W(e)&&W(t))return{height:e,width:t}},Lt=({defaultHeight:e=0,defaultWidth:t=0,height:n,width:o})=>{let r=Zo(null),[i,s]=jo({css:tr(n,o),inner:nr(n,o),outer:{height:n!=null?n:"100%",width:o!=null?o:"100%"}});Qo(()=>{s(a=>{let{inner:u,outer:c}=a;if(W(n)&&W(o)&&u&&c){let{height:p,width:d}=u,{height:g,width:h}=c;if(g!==n||h!==o){let f=W(g)?g-p:0,R=W(h)?h-d:0;return{...a,outer:{height:n,width:o},inner:{height:n-f,width:o-R}}}}return a})},[n,o]);let l=Yo(({clientWidth:a,clientHeight:u})=>{s(c=>{let{css:p,inner:d,outer:g}=c;return At(u)&&At(a)&&(a!==(d==null?void 0:d.width)||u!==(d==null?void 0:d.height))?{css:p,outer:g,inner:{width:Math.floor(a)||t,height:Math.floor(u)||e}}:c})},[e,t]);return St(r,qo,l,!0),{containerRef:r,cssSize:i.css,outerSize:i.outer,innerSize:i.inner}};import{deselectItem as or,metadataKeys as rr,selectItem as sr}from"@vuu-ui/vuu-utils";import{useCallback as ir,useRef as kt}from"react";var{IDX:lr,SELECTED:cr}=rr,ar=[],Kt=({selectionModel:e,onSelectionChange:t})=>{let n=kt(-1),o=kt(ar);return ir((i,s,l)=>{let{[lr]:a,[cr]:u}=i,{current:c}=n,{current:p}=o,g=(u?or:sr)(e,p,a,s,l,c);o.current=g,n.current=a,t&&t(g)},[t,e])};import{moveItem as ur}from"@heswell/salt-lab";import{applyFilterToColumns as mr,applyGroupByToColumns as dr,applySortToColumns as pr,findColumn as fr,getCellRenderer as gr,getColumnName as Cr,getTableHeadings as br,getValueFormatter as hr,isFilteredColumn as vr,isGroupColumn as yr,isPinned as wr,isTypeDescriptor as Mr,logger as Rr,metadataKeys as Tr,sortPinnedColumns as zt,stripFilterFromColumns as Dr}from"@vuu-ui/vuu-utils";import{useReducer as xr}from"react";var{info:ze}=Rr("useTableModel"),Hr=100,Nt=Tr.count,Pr=({serverDataType:e})=>e===void 0,Er=e=>{var t;if(Mr(e.type))return gr((t=e.type)==null?void 0:t.renderer)},Sr=(e,t,n)=>{var r;let o=t.indexOf(e.name);return o!==-1&&n[o]?n[o]:(r=e.serverDataType)!=null?r:"string"},Ar=["int","long","double"],It=e=>e===void 0?void 0:Ar.includes(e)?"right":"left",Lr=(e,t)=>{switch(ze==null||ze(`GridModelReducer ${t.type}`),t.type){case"init":return Vt(t);case"moveColumn":return Kr(e,t);case"resizeColumn":return Ir(e,t);case"setTypes":return Fr(e,t);case"hideColumns":return zr(e,t);case"showColumns":return Nr(e,t);case"pinColumn":return Vr(e,t);case"updateColumnProp":return ne(e,t);case"tableConfig":return $t(e,t);default:return console.log(`unhandled action ${t.type}`),e}},Ft=(e,t)=>{let[n,o]=xr(Lr,{tableConfig:e,dataSourceConfig:t},Vt);return{columns:n.columns,dispatchColumnAction:o,headings:n.headings}};function Vt({dataSourceConfig:e,tableConfig:t}){let n=t.columns.map(Wt(t)),o=n.some(wr)?zt(n):n,r={columns:o,headings:br(o)};if(e){let{columns:i,...s}=e;return $t(r,{type:"tableConfig",...s})}else return r}var kr=(e,t)=>t==="uppercase"?e.toUpperCase():t==="capitalize"?e[0].toUpperCase()+e.slice(1).toLowerCase():e,Wt=e=>(t,n)=>{let{columnDefaultWidth:o=Hr,columnFormatHeader:r}=e,{align:i=It(t.serverDataType),key:s,name:l,label:a=l,width:u=o,...c}=t,p={...c,align:i,CellRenderer:Er(t),label:kr(a,r),key:s!=null?s:n+Nt,name:l,originalIdx:n,valueFormatter:hr(t),width:u};return yr(p)&&(p.columns=p.columns.map(d=>Wt(e)(d,d.key))),p};function Kr(e,{column:t,moveBy:n,moveTo:o}){let{columns:r}=e;if(typeof n=="number"){let i=r.indexOf(t),s=r.slice(),[l]=s.splice(i,1);return s.splice(i+n,0,l),{...e,columns:s}}else if(typeof o=="number"){let i=r.indexOf(t);return{...e,columns:ur(r,i,o)}}return e}function zr(e,{columns:t}){return t.some(n=>n.hidden!==!0)?t.reduce((n,o)=>o.hidden!==!0?ne(n,{type:"updateColumnProp",column:o,hidden:!0}):n,e):e}function Nr(e,{columns:t}){return t.some(n=>n.hidden)?t.reduce((n,o)=>o.hidden?ne(n,{type:"updateColumnProp",column:o,hidden:!1}):n,e):e}function Ir(e,{column:t,phase:n,width:o}){let r="updateColumnProp",i=n!=="end";switch(n){case"begin":case"end":return ne(e,{type:r,column:t,resizing:i});case"resize":return ne(e,{type:r,column:t,width:o});default:throw Error(`useTableModel.resizeColumn, invalid resizePhase ${n}`)}}function Fr(e,{columnNames:t,serverDataTypes:n}){let{columns:o}=e;if(o.some(Pr)){let r=o.map(i=>{var l;let s=Sr(i,t,n);return{...i,align:(l=i.align)!=null?l:It(s),serverDataType:s}});return{...e,columns:r}}else return e}function Vr(e,t){let{columns:n}=e,{column:o,pin:r}=t,i=n.find(s=>s.name===o.name);return i?(n=Q(n,{...i,pin:r}),n=zt(n),{...e,columns:n}):e}function ne(e,t){let{columns:n}=e,{align:o,column:r,hidden:i,label:s,resizing:l,width:a}=t,u=n.find(c=>c.name===r.name);return u&&((o==="left"||o==="right")&&(n=Q(n,{...u,align:o})),typeof s=="string"&&(n=Q(n,{...u,label:s})),typeof l=="boolean"&&(n=Q(n,{...u,resizing:l})),typeof i=="boolean"&&(n=Q(n,{...u,hidden:i})),typeof a=="number"&&(n=Q(n,{...u,width:a}))),{...e,columns:n}}function $t(e,{columns:t,confirmed:n,filter:o,groupBy:r,sort:i}){let s=t&&t.length>0,l=r!==void 0,a=typeof(o==null?void 0:o.filter)=="string",u=i&&i.sortDefs.length>0,c=e;return s&&(c={...e,columns:t.map((p,d)=>{let g=Cr(p),h=d+Nt,f=fr(c.columns,g);if(f)return f.key===h?f:{...f,key:h};throw Error(`useTableModel column ${p} not found`)})}),l&&(c={...e,columns:dr(c.columns,r,n)}),u&&(c={...e,columns:pr(c.columns,i)}),a?c={...e,columns:mr(c.columns,o)}:c.columns.some(vr)&&(c={...e,columns:Dr(c.columns)}),c}function Q(e,t){return e.map(n=>n.name===t.name?t:n)}import{useCallback as $,useRef as oe}from"react";var Ot=e=>{let{scrollLeft:t,scrollTop:n}=e,{clientHeight:o,clientWidth:r,scrollHeight:i,scrollWidth:s}=e,l=t/(s-r),a=n/(i-o);return[l,a]},Wr=e=>{let{clientHeight:t,clientWidth:n,scrollHeight:o,scrollWidth:r}=e;return[r-n,o-t]},Gt=({onAttach:e,onDetach:t})=>{let n=oe(null);return $(r=>{if(r)n.current=r,e==null||e(r);else if(n.current){let{current:i}=n;n.current=r,t==null||t(i)}},[e,t])},Bt=({onHorizontalScroll:e,onVerticalScroll:t,viewport:n})=>{let o=oe(!1),r=oe({scrollTop:0,scrollLeft:0}),i=oe(null),s=oe(null),{maxScrollContainerScrollHorizontal:l,maxScrollContainerScrollVertical:a}=n,u=$(()=>{let{current:m}=s,{current:b}=i,{current:T}=o;if(T)o.current=!1;else if(m&&b){let[w,v]=Ot(b),[D,S]=Wr(m),P=Math.round(w*D),C=Math.round(v*S);m.scrollTo({left:P,top:C,behavior:"auto"})}},[]),c=$(()=>{let{current:m}=s,{current:b}=i,{current:T}=r;if(m&&b){let{scrollLeft:w,scrollTop:v}=m,[D,S]=Ot(m);o.current=!0,b.scrollLeft=Math.round(D*l),b.scrollTop=Math.round(S*a),T.scrollTop!==v&&(T.scrollTop=v,t==null||t(v,S)),T.scrollLeft!==w&&(T.scrollLeft=w,e==null||e(w))}},[l,a,e,t]),p=$(m=>{i.current=m,m.addEventListener("scroll",u,{passive:!0})},[u]),d=$(m=>{i.current=null,m.removeEventListener("scroll",u)},[u]),g=$(m=>{s.current=m,m.addEventListener("scroll",c,{passive:!0})},[c]),h=$(m=>{s.current=null,m.removeEventListener("scroll",c)},[c]),f=Gt({onAttach:g,onDetach:h}),R=Gt({onAttach:p,onDetach:d}),y=$(m=>{let{current:b}=s;if(b){if(o.current=!1,m.type==="scroll-page"){let{clientHeight:T,scrollLeft:w,scrollTop:v}=b,{direction:D}=m,S=D==="down"?T:-T,P=Math.min(Math.max(0,v+S),a);b.scrollTo({top:P,left:w,behavior:"auto"})}else if(m.type==="scroll-end"){let{direction:T}=m,w=T==="end"?a:0;b.scrollTo({top:w,left:b.scrollLeft,behavior:"auto"})}}},[a]);return{scrollbarContainerRef:R,contentContainerRef:f,requestScroll:y}};import{useCallback as $r,useMemo as de,useRef as Or}from"react";import{actualRowPositioning as Gr,virtualRowPositioning as Br}from"@vuu-ui/vuu-utils";var Ur=15e5,_r={contentHeight:0,contentWidth:0,getRowAtPosition:()=>-1,getRowOffset:()=>-1,horizontalScrollbarHeight:0,maxScrollContainerScrollHorizontal:0,maxScrollContainerScrollVertical:0,pinnedWidthLeft:0,pinnedWidthRight:0,rowCount:0,setPctScrollTop:()=>{},totalHeaderHeight:0,verticalScrollbarWidth:0,viewportBodyHeight:0},Jr=e=>{let t=0,n=0,o=0;for(let r of e){let{hidden:i,pin:s,width:l}=r,a=i?0:l;s==="left"?t+=a:s==="right"?n+=a:o+=a}return{pinnedWidthLeft:t,pinnedWidthRight:n,unpinnedWidth:o}},Ut=({columns:e,headerHeight:t,headings:n,rowCount:o,rowHeight:r,size:i})=>{let s=Or(0),a=Math.min(o,Ur)*r,c=o*r-a,{pinnedWidthLeft:p,pinnedWidthRight:d,unpinnedWidth:g}=de(()=>Jr(e),[e]),[h,f]=de(()=>Gr(r),[r]),[R,y]=de(()=>c?Br(r,c,s):[h,f],[f,h,c,r]),m=$r(b=>{s.current=b},[]);return de(()=>{var b;if(i){let T=n.length,w=15,v=p+g+d,D=v>i.width?w:0,S=t*(1+T),P=a-(((b=i==null?void 0:i.height)!=null?b:0)-D)+S,C=v-i.width+p,M=(i.height-t)/r,E=Number.isInteger(M)?M+1:Math.ceil(M),x=i.height-S,K=a>x?w:0;return{contentHeight:a,getRowAtPosition:y,getRowOffset:R,horizontalScrollbarHeight:D,maxScrollContainerScrollHorizontal:C,maxScrollContainerScrollVertical:P,pinnedWidthLeft:p,pinnedWidthRight:d,rowCount:E,contentWidth:v,setPctScrollTop:m,totalHeaderHeight:S,verticalScrollbarWidth:K,viewportBodyHeight:x}}else return _r},[i,n.length,p,g,d,a,t,r,y,R,m])};import{getColumnsInViewport as _t,itemsChanged as Xr}from"@vuu-ui/vuu-utils";import{useCallback as Jt,useEffect as Yr,useMemo as Qr,useRef as Ne,useState as Zr}from"react";var Xt=({columns:e,getRowAtPosition:t,setRange:n,viewportMeasurements:o})=>{let r=Ne(-1),{rowCount:i,contentWidth:s,maxScrollContainerScrollHorizontal:l}=o,a=s-l,u=Ne(0),[c,p]=Qr(()=>_t(e,u.current,u.current+a),[a,e]),d=Ne(p);Yr(()=>{h(c)},[c]);let[g,h]=Zr(c),f=Jt(y=>{u.current=y;let[m,b]=_t(e,y,y+a);Xr(g,m)&&(d.current=b,h(m))},[a,e,g]),R=Jt(y=>{let m=t(y);m!==r.current&&(r.current=m,n({from:m,to:m+i}))},[t,n,i]);return{columnsWithinViewport:g,onHorizontalScroll:f,onVerticalScroll:R,virtualColSpan:d.current}};var is=[],{KEY:ls,IS_EXPANDED:Qt,IS_LEAF:Zt}=ns,jt=({config:e,dataSource:t,headerHeight:n,onConfigChange:o,onFeatureEnabled:r,onFeatureInvocation:i,onSelectionChange:s,renderBufferSize:l=0,rowHeight:a,selectionModel:u,...c})=>{var $e,Oe;let[p,d]=ss(t.size),g=Ie(!1),h=Ie();if(h.current=t,t===void 0)throw Error("no data source provided to Vuu Table");let f=Lt(c),R=z(H=>{d(H)},[]),{columns:y,dispatchColumnAction:m,headings:b}=Ft(e,t.config),{getRowAtPosition:T,getRowOffset:w,setPctScrollTop:v,...D}=Ut({columns:y,headerHeight:n,headings:b,rowCount:p,rowHeight:a,size:f.innerSize}),S=z(H=>{if(H.tableMeta){let{columns:A,dataTypes:k}=H.tableMeta;g.current=!0,m({type:"setTypes",columnNames:A,serverDataTypes:k})}},[m]),P=z(H=>{t.select(H),s==null||s(H)},[t,s]),C=Kt({onSelectionChange:P,selectionModel:u}),{data:M,getSelectedRows:E,range:x,setRange:K}=ht({dataSource:t,onFeatureEnabled:r,onFeatureInvocation:i,onSubscribed:S,onSizeChange:R,renderBufferSize:l,viewportRowCount:D.rowCount}),J=Ie();J.current=M;let pe=z(H=>{g.current=!0,m(H)},[m]),en=Je({dataSource:t,onPersistentColumnOperation:pe}),tn=z((H,A=!1,k)=>{t&&(t.sort=qr(t.sort,H,A,k))},[t]),nn=z((H,A,k)=>{let L=y.find(N=>N.name===A);if(L)H==="end"&&(g.current=!0),m({type:"resizeColumn",phase:H,column:L,width:k});else throw Error(`useDataTable.handleColumnResize, column ${A} not found`)},[y,m]),on=z((H,A)=>{let k=ts(A,H),L=H[ls];if(H[Qt]){if(t.closeTreeNode(L,!0),k){let N=y.indexOf(A);t.getRowsAtDepth(N+1).some(I=>I[Qt]||I[Zt])||m({type:"hideColumns",columns:y.slice(N+2)})}}else if(t.openTreeNode(L),k){let N=t.getChildRows(L),O=y.indexOf(A)+1,I=[y[O]];N.some(X=>X[Zt])&&I.push(y[O+1]),I.some(X=>X.hidden)&&m({type:"showColumns",columns:I})}},[y,t,m]),{onVerticalScroll:Ve,onHorizontalScroll:rn,columnsWithinViewport:sn,virtualColSpan:ln}=Xt({columns:y,getRowAtPosition:T,setRange:K,viewportMeasurements:D}),cn=z((H,A)=>{v(A),Ve(H)},[Ve,v]),{requestScroll:an,...un}=Bt({onHorizontalScroll:rn,onVerticalScroll:cn,viewport:D,viewportHeight:((Oe=($e=f.innerSize)==null?void 0:$e.height)!=null?Oe:0)-n}),mn=xt({columnCount:y.length,containerRef:f.containerRef,data:M,requestScroll:an,rowCount:t==null?void 0:t.size,viewportRange:x}),dn=z(H=>{H?t&&t.groupBy.includes(H.name)&&(t.groupBy=t.groupBy.filter(A=>A!==H.name)):t.groupBy=[]},[t]),pn=z((H,A)=>{let k=t.columns[H],L=os(t.columns,k,A);L!==t.columns&&(t.columns=L,m({type:"tableConfig",columns:L}))},[t,m]),fn=wt({onDrop:pn});Yt(()=>{h.current&&(g.current=!0,m({type:"init",tableConfig:e,dataSourceConfig:h.current.config}))},[e,m]),Yt(()=>{t.on("config",(H,A)=>{g.current=!0,m({type:"tableConfig",...H,confirmed:A})})},[t,m]),rs(()=>{g.current&&(o==null||o({...e,columns:y}),g.current=!1)},[y,e,o]);let We=jr(),gn=z(H=>{var I;let{current:A}=J,{current:k}=h,L=H.target,N=L==null?void 0:L.closest("div[role='cell']"),O=L==null?void 0:L.closest(".vuuTableRow");if(N&&O&&A&&k){let{columns:X,selectedRowsCount:Cn}=k,bn=es(X),hn=parseInt((I=O.ariaRowIndex)!=null?I:"-1"),vn=Array.from(O.childNodes).indexOf(N),yn=A.find(([Mn])=>Mn===hn),wn=X[vn];We(H,"grid",{columnMap:bn,columnName:wn,row:yn,selectedRows:Cn===0?is:E(),viewport:t==null?void 0:t.viewport})}},[t==null?void 0:t.viewport,E,We]);return{columns:y,columnsWithinViewport:sn,containerMeasurements:f,containerProps:mn,data:M,dispatchColumnAction:m,getRowOffset:w,handleContextMenuAction:en,headings:b,onColumnResize:nn,onContextMenu:gn,onRemoveColumnFromGroupBy:dn,onRowClick:C,onSort:tn,onToggleGroup:on,virtualColSpan:ln,scrollProps:un,rowCount:p,viewportMeasurements:D,...fn}};import ms from"classnames";import{isDataLoading as ds}from"@vuu-ui/vuu-utils";import{jsx as re,jsxs as qt}from"react/jsx-runtime";var _="vuuTable",Bc=({allowConfigEditing:e=!1,className:t,config:n,dataSource:o,headerHeight:r=25,height:i,id:s,onConfigChange:l,onFeatureEnabled:a,onFeatureInvocation:u,onSelectionChange:c,onShowConfigEditor:p,renderBufferSize:d=0,rowHeight:g=20,selectionModel:h="extended",style:f,width:R,zebraStripes:y=!1,...m})=>{let b=us(s),{containerMeasurements:{containerRef:T,innerSize:w,outerSize:v},containerProps:D,dispatchColumnAction:S,draggable:P,draggedItemIndex:C,handleContextMenuAction:M,scrollProps:E,viewportMeasurements:x,...K}=jt({config:n,dataSource:o,renderBufferSize:d,headerHeight:r,height:i,onConfigChange:l,onFeatureEnabled:a,onFeatureInvocation:u,onSelectionChange:c,rowHeight:g,selectionModel:h,width:R}),J={...v,"--content-height":`${x.contentHeight}px`,"--horizontal-scrollbar-height":`${x.horizontalScrollbarHeight}px`,"--content-width":`${x.contentWidth}px`,"--pinned-width-left":`${x.pinnedWidthLeft}px`,"--pinned-width-right":`${x.pinnedWidthRight}px`,"--header-height":`${r}px`,"--row-height":`${g}px`,"--table-height":`${w==null?void 0:w.height}px`,"--table-width":`${w==null?void 0:w.width}px`,"--total-header-height":`${x.totalHeaderHeight}px`,"--vertical-scrollbar-width":`${x.verticalScrollbarWidth}px`,"--viewport-body-height":`${x.viewportBodyHeight}px`},pe=ms(_,t,{[`${_}-zebra`]:y,[`${_}-loading`]:ds(K.columns)});return re(cs,{menuActionHandler:M,menuBuilder:Ge(o),children:qt("div",{...m,...D,className:pe,id:b,ref:T,style:J,tabIndex:-1,children:[w?re("div",{className:`${_}-scrollbarContainer`,ref:E.scrollbarContainerRef,children:re("div",{className:`${_}-scrollbarContent`})}):null,w?qt("div",{className:`${_}-contentContainer`,ref:E.contentContainerRef,children:[re(bt,{...K,headerHeight:r,tableId:b}),P]}):null,e&&w?re(as,{className:`${_}-settings`,"data-icon":"settings",onClick:p,variant:"secondary"}):null]})})};import ps from"classnames";import{isJsonAttribute as fs,metadataKeys as gs,registerComponent as Cs}from"@vuu-ui/vuu-utils";import{jsx as Fe,jsxs as ws}from"react/jsx-runtime";var se="vuuJsonCell",{IS_EXPANDED:bs,KEY:hs}=gs,vs=e=>{let t=e.lastIndexOf("|");return t===-1?"":e.slice(t+1)},ys=({column:e,row:t})=>{let{key:n}=e,o=t[n],r=!1;fs(o)&&(o=o.slice(0,-1),r=!0);let i=vs(t[hs]),s=ps({[`${se}-name`]:i===o,[`${se}-value`]:i!==o,[`${se}-group`]:r});if(r){let l=t[bs]?"minus-box":"plus-box";return ws("span",{className:s,children:[Fe("span",{className:`${se}-value`,children:o}),Fe("span",{className:`${se}-toggle`,"data-icon":l})]})}else return o?Fe("span",{className:s,children:o}):null};Cs("json",ys,"cell-renderer",{});export{Bc as Table,Ge as buildContextMenuDescriptors,Lt as useMeasuredContainer,Je as useTableContextMenu,Ft as useTableModel,Ut as useTableViewport};
2861
2
  //# sourceMappingURL=index.js.map