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

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,3896 +1,2 @@
1
- // src/header-cell/GroupHeaderCell.tsx
2
- import { OverflowContainer } from "@vuu-ui/vuu-ui-controls";
3
- import { useLayoutEffectSkipFirst } from "@vuu-ui/vuu-utils";
4
- import cx3 from "clsx";
5
- import { useCallback as useCallback4, useRef as useRef3, useState as useState2 } from "react";
6
-
7
- // src/column-header-pill/ColumnHeaderPill.tsx
8
- import cx from "clsx";
9
- import { useCallback } from "react";
10
- import { jsx, jsxs } from "react/jsx-runtime";
11
- var classBase = "vuuColumnHeaderPill";
12
- var ColumnHeaderPill = ({
13
- children,
14
- className,
15
- column,
16
- onRemove,
17
- removable,
18
- ...htmlAttributes
19
- }) => {
20
- if (removable && typeof onRemove !== "function") {
21
- throw Error(
22
- "ColumnHeaderPill onRemove prop must be provided if Pill is removable"
23
- );
24
- }
25
- const handleClickRemove = useCallback(
26
- (evt) => {
27
- evt.preventDefault();
28
- evt.stopPropagation();
29
- onRemove == null ? void 0 : onRemove(column);
30
- },
31
- [column, onRemove]
32
- );
33
- return /* @__PURE__ */ jsxs("div", { ...htmlAttributes, className: cx(classBase, className), children: [
34
- children,
35
- removable ? /* @__PURE__ */ jsx(
36
- "span",
37
- {
38
- className: `${classBase}-removeButton`,
39
- role: "button",
40
- "data-icon": "cross",
41
- onClick: handleClickRemove
42
- }
43
- ) : null
44
- ] });
45
- };
46
-
47
- // src/column-header-pill/GroupColumnPill.tsx
48
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
49
- var GroupColumnPill = ({
50
- column,
51
- ...columnHeaderProps
52
- }) => {
53
- const { name, sorted } = column;
54
- const icon = typeof sorted === "number" ? sorted < 0 ? "arrow-down" : "arrow-up" : sorted === "A" ? "arrow-up" : sorted === "D" ? "arrow-down" : void 0;
55
- return /* @__PURE__ */ jsxs2(ColumnHeaderPill, { ...columnHeaderProps, column, children: [
56
- /* @__PURE__ */ jsx2("span", { className: "vuuGroupColumnPill-label", children: name }),
57
- icon !== void 0 ? /* @__PURE__ */ jsx2("span", { "data-icon": icon }) : null,
58
- typeof sorted === "number" ? /* @__PURE__ */ jsx2("span", { className: "vuuSortPosition", children: Math.abs(sorted) }) : null
59
- ] });
60
- };
61
-
62
- // src/column-header-pill/SortIndicator.tsx
63
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
64
- var SortIndicator = ({ column }) => {
65
- if (!column.sorted) {
66
- return null;
67
- }
68
- const icon = typeof column.sorted === "number" ? column.sorted < 0 ? "arrow-down" : "arrow-up" : column.sorted === "A" ? "arrow-up" : "arrow-down";
69
- return /* @__PURE__ */ jsxs3(ColumnHeaderPill, { column, children: [
70
- /* @__PURE__ */ jsx3("span", { "data-icon": icon }),
71
- typeof column.sorted === "number" ? /* @__PURE__ */ jsx3("span", { className: "vuuSortPosition", children: Math.abs(column.sorted) }) : null
72
- ] });
73
- };
74
-
75
- // src/column-resizing/ColumnResizer.tsx
76
- import { useCallback as useCallback2, useRef } from "react";
77
- import { jsx as jsx4 } from "react/jsx-runtime";
78
- var NOOP = () => void 0;
79
- var baseClass = "vuuColumnResizer";
80
- var ColumnResizer = ({
81
- onDrag,
82
- onDragEnd = NOOP,
83
- onDragStart = NOOP
84
- }) => {
85
- const positionRef = useRef({ start: 0, now: 0 });
86
- const onMouseMove = useCallback2(
87
- (e) => {
88
- if (e.stopPropagation) {
89
- e.stopPropagation();
90
- }
91
- if (e.preventDefault) {
92
- e.preventDefault();
93
- }
94
- const { current: position } = positionRef;
95
- const x = Math.round(e.clientX);
96
- const moveBy = x - position.now;
97
- const distanceMoved = position.now - position.start;
98
- positionRef.current.now = x;
99
- if (moveBy !== 0) {
100
- onDrag(e, moveBy, distanceMoved);
101
- }
102
- },
103
- [onDrag]
104
- );
105
- const onMouseUp = useCallback2(
106
- (e) => {
107
- window.removeEventListener("mouseup", onMouseUp);
108
- window.removeEventListener("mousemove", onMouseMove);
109
- const { current: position } = positionRef;
110
- const distanceMoved = position.now - position.start;
111
- onDragEnd(e, distanceMoved);
112
- },
113
- [onDragEnd, onMouseMove]
114
- );
115
- const handleMouseDown = useCallback2(
116
- (e) => {
117
- const { current: position } = positionRef;
118
- onDragStart(e);
119
- position.now = position.start = Math.round(e.clientX);
120
- window.addEventListener("mouseup", onMouseUp);
121
- window.addEventListener("mousemove", onMouseMove);
122
- if (e.stopPropagation) {
123
- e.stopPropagation();
124
- }
125
- if (e.preventDefault) {
126
- e.preventDefault();
127
- }
128
- },
129
- [onDragStart, onMouseMove, onMouseUp]
130
- );
131
- return /* @__PURE__ */ jsx4("div", { className: baseClass, onMouseDown: handleMouseDown });
132
- };
133
-
134
- // src/column-resizing/useTableColumnResize.tsx
135
- import { useCallback as useCallback3, useRef as useRef2, useState } from "react";
136
- var useTableColumnResize = ({
137
- column,
138
- onResize,
139
- rootRef
140
- }) => {
141
- const widthRef = useRef2({ start: 0, now: 0 });
142
- const [isResizing, setResizing] = useState(false);
143
- const { name } = column;
144
- const handleResizeStart = useCallback3(() => {
145
- if (onResize && rootRef.current) {
146
- const { current: width } = widthRef;
147
- const { width: measuredWidth } = rootRef.current.getBoundingClientRect();
148
- width.start = width.now = Math.round(measuredWidth);
149
- setResizing(true);
150
- onResize == null ? void 0 : onResize("begin", name);
151
- }
152
- }, [name, onResize, rootRef]);
153
- const handleResize = useCallback3(
154
- (_evt, moveBy, totalDistanceMoved) => {
155
- if (rootRef.current) {
156
- if (onResize) {
157
- const { current: width } = widthRef;
158
- const newWidth = width.start + totalDistanceMoved;
159
- if (newWidth !== width.now && newWidth > 0) {
160
- onResize("resize", name, newWidth);
161
- width.now = newWidth;
162
- }
163
- }
164
- }
165
- },
166
- [name, onResize, rootRef]
167
- );
168
- const handleResizeEnd = useCallback3(() => {
169
- if (onResize) {
170
- const { current: width } = widthRef;
171
- onResize("end", name, width.now);
172
- setTimeout(() => {
173
- setResizing(false);
174
- }, 80);
175
- }
176
- }, [name, onResize]);
177
- return {
178
- isResizing,
179
- onDrag: handleResize,
180
- onDragStart: handleResizeStart,
181
- onDragEnd: handleResizeEnd
182
- };
183
- };
184
-
185
- // src/useCell.ts
186
- import { getColumnStyle } from "@vuu-ui/vuu-utils";
187
- import cx2 from "clsx";
188
- import { useMemo } from "react";
189
- var useCell = (column, classBase11, isHeader) => (
190
- // TODO measure perf without the memo, might not be worth the cost
191
- useMemo(() => {
192
- const className = cx2(classBase11, {
193
- vuuPinFloating: column.pin === "floating",
194
- vuuPinLeft: column.pin === "left",
195
- vuuPinRight: column.pin === "right",
196
- vuuEndPin: isHeader && column.endPin,
197
- // [`${classBase}-resizing`]: column.resizing,
198
- [`${classBase11}-editable`]: column.editable,
199
- [`${classBase11}-right`]: column.align === "right"
200
- });
201
- const style = getColumnStyle(column);
202
- return {
203
- className,
204
- style
205
- };
206
- }, [column, classBase11, isHeader])
207
- );
208
-
209
- // src/header-cell/GroupHeaderCell.tsx
210
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
211
- import { createElement } from "react";
212
- var classBase2 = "vuuTableGroupHeaderCell";
213
- var switchIfChanged = (columns, newColumns) => {
214
- if (columns === newColumns) {
215
- return columns;
216
- } else {
217
- return newColumns;
218
- }
219
- };
220
- var GroupHeaderCell = ({
221
- column: groupColumn,
222
- className: classNameProp,
223
- onMoveColumn,
224
- onRemoveColumn,
225
- onResize,
226
- ...htmlAttributes
227
- }) => {
228
- const rootRef = useRef3(null);
229
- const { isResizing, ...resizeProps } = useTableColumnResize({
230
- column: groupColumn,
231
- onResize,
232
- rootRef
233
- });
234
- const [columns, setColumns] = useState2(groupColumn.columns);
235
- const { className, style } = useCell(groupColumn, classBase2, true);
236
- const columnPillProps = columns.length > 1 ? {
237
- removable: true,
238
- onRemove: onRemoveColumn
239
- } : void 0;
240
- const handleMoveItem = useCallback4(
241
- (fromIndex, toIndex) => {
242
- setColumns((cols) => {
243
- const newCols = cols.slice();
244
- const [tab] = newCols.splice(fromIndex, 1);
245
- if (toIndex === -1) {
246
- const result = newCols.concat(tab);
247
- onMoveColumn == null ? void 0 : onMoveColumn(result);
248
- return result;
249
- } else {
250
- newCols.splice(toIndex, 0, tab);
251
- onMoveColumn == null ? void 0 : onMoveColumn(newCols);
252
- return newCols;
253
- }
254
- });
255
- },
256
- [onMoveColumn]
257
- );
258
- useLayoutEffectSkipFirst(() => {
259
- setColumns((cols) => switchIfChanged(cols, groupColumn.columns));
260
- }, [groupColumn.columns]);
261
- return /* @__PURE__ */ jsxs4(
262
- "div",
263
- {
264
- ...htmlAttributes,
265
- className: cx3(className, classNameProp, {
266
- [`${classBase2}-pending`]: groupColumn.groupConfirmed === false
267
- }),
268
- ref: rootRef,
269
- role: "columnheader",
270
- style,
271
- children: [
272
- /* @__PURE__ */ jsx5(
273
- OverflowContainer,
274
- {
275
- allowDragDrop: true,
276
- className: `${classBase2}-inner`,
277
- onMoveItem: handleMoveItem,
278
- overflowPosition: "start",
279
- children: columns.map((column) => {
280
- return /* @__PURE__ */ createElement(
281
- GroupColumnPill,
282
- {
283
- ...columnPillProps,
284
- column,
285
- key: column.name
286
- }
287
- );
288
- })
289
- }
290
- ),
291
- /* @__PURE__ */ jsx5(
292
- ColumnHeaderPill,
293
- {
294
- column: groupColumn,
295
- removable: true,
296
- onRemove: onRemoveColumn
297
- }
298
- ),
299
- groupColumn.resizeable !== false ? /* @__PURE__ */ jsx5(ColumnResizer, { ...resizeProps }) : null
300
- ]
301
- }
302
- );
303
- };
304
-
305
- // src/header-cell/HeaderCell.tsx
306
- import { useContextMenu } from "@vuu-ui/vuu-popups";
307
- import cx5 from "clsx";
308
- import {
309
- useCallback as useCallback5,
310
- useMemo as useMemo2,
311
- useRef as useRef4
312
- } from "react";
313
-
314
- // src/column-menu/ColumnMenu.tsx
315
- import { PopupMenu } from "@vuu-ui/vuu-popups";
316
- import cx4 from "clsx";
317
- import { jsx as jsx6 } from "react/jsx-runtime";
318
- var classBase3 = "vuuColumnMenu";
319
- var ColumnMenu = ({ className, column }) => {
320
- return /* @__PURE__ */ jsx6(
321
- PopupMenu,
322
- {
323
- className: cx4(classBase3, className),
324
- "data-embedded": true,
325
- menuLocation: "column-menu",
326
- menuOptions: { column }
327
- }
328
- );
329
- };
330
-
331
- // src/header-cell/HeaderCell.tsx
332
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
333
- var classBase4 = "vuuTableHeaderCell";
334
- var HeaderCell = ({
335
- className: classNameProp,
336
- column,
337
- onClick,
338
- onResize,
339
- showMenu = true,
340
- ...htmlAttributes
341
- }) => {
342
- const { HeaderCellContentRenderer, HeaderCellLabelRenderer } = column;
343
- const rootRef = useRef4(null);
344
- const { isResizing, ...resizeProps } = useTableColumnResize({
345
- column,
346
- onResize,
347
- rootRef
348
- });
349
- const [showContextMenu] = useContextMenu();
350
- const handleContextMenu = useMemo2(() => {
351
- if (showMenu) {
352
- return void 0;
353
- } else {
354
- return (e) => showContextMenu(e, "column-menu", { column });
355
- }
356
- }, [column, showContextMenu, showMenu]);
357
- const headerItems = useMemo2(() => {
358
- var _a;
359
- const sortIndicator = /* @__PURE__ */ jsx7(SortIndicator, { column });
360
- const columnLabel = HeaderCellLabelRenderer ? /* @__PURE__ */ jsx7(
361
- HeaderCellLabelRenderer,
362
- {
363
- className: `${classBase4}-label`,
364
- column
365
- }
366
- ) : /* @__PURE__ */ jsx7("div", { className: `${classBase4}-label`, children: (_a = column.label) != null ? _a : column.name });
367
- const columnContent = HeaderCellContentRenderer ? [/* @__PURE__ */ jsx7(HeaderCellContentRenderer, { column }, "content")] : [];
368
- if (showMenu) {
369
- const columnMenu = /* @__PURE__ */ jsx7(ColumnMenu, { column });
370
- if (column.align === "right") {
371
- return [sortIndicator, columnLabel, columnContent, columnMenu];
372
- } else {
373
- return [columnMenu, columnLabel, sortIndicator, columnContent];
374
- }
375
- } else {
376
- if (column.align === "right") {
377
- return [sortIndicator, columnLabel, columnContent];
378
- } else {
379
- return [columnLabel, sortIndicator, columnContent];
380
- }
381
- }
382
- }, [HeaderCellContentRenderer, HeaderCellLabelRenderer, column, showMenu]);
383
- const handleClick = useCallback5(
384
- (evt) => {
385
- !isResizing && (onClick == null ? void 0 : onClick(evt));
386
- },
387
- [isResizing, onClick]
388
- );
389
- const handleKeyDown = useCallback5(
390
- (evt) => {
391
- if (evt.key === "Enter") {
392
- onClick == null ? void 0 : onClick(evt);
393
- }
394
- },
395
- [onClick]
396
- );
397
- const { className, style } = useCell(column, classBase4, true);
398
- return /* @__PURE__ */ jsxs5(
399
- "div",
400
- {
401
- ...htmlAttributes,
402
- className: cx5(className, classNameProp, {
403
- [`${classBase4}-resizing`]: isResizing,
404
- [`${classBase4}-noMenu`]: showMenu === false
405
- }),
406
- onClick: handleClick,
407
- onContextMenu: handleContextMenu,
408
- onKeyDown: handleKeyDown,
409
- ref: rootRef,
410
- role: "columnheader",
411
- style,
412
- children: [
413
- ...headerItems,
414
- column.resizeable !== false ? /* @__PURE__ */ jsx7(ColumnResizer, { ...resizeProps }) : null
415
- ]
416
- }
417
- );
418
- };
419
-
420
- // src/Table.tsx
421
- import { ContextMenuProvider } from "@vuu-ui/vuu-popups";
422
- import {
423
- MeasuredContainer
424
- } from "@vuu-ui/vuu-ui-controls";
425
- import { metadataKeys as metadataKeys6, useId } from "@vuu-ui/vuu-utils";
426
- import { useForkRef } from "@salt-ds/core";
427
- import cx9 from "clsx";
428
- import {
429
- forwardRef as forwardRef2,
430
- useRef as useRef15,
431
- useState as useState8
432
- } from "react";
433
-
434
- // src/Row.tsx
435
- import {
436
- isGroupColumn,
437
- isJsonColumn,
438
- isJsonGroup,
439
- metadataKeys as metadataKeys2,
440
- isNotHidden,
441
- RowSelected
442
- } from "@vuu-ui/vuu-utils";
443
- import cx7 from "clsx";
444
- import {
445
- forwardRef,
446
- memo,
447
- useCallback as useCallback8
448
- } from "react";
449
-
450
- // src/table-cell/TableCell.tsx
451
- import { isNumericColumn } from "@vuu-ui/vuu-utils";
452
- import { useCallback as useCallback6 } from "react";
453
- import { jsx as jsx8 } from "react/jsx-runtime";
454
- var classBase5 = "vuuTableCell";
455
- var TableCell = ({
456
- column,
457
- columnMap,
458
- onClick,
459
- onDataEdited,
460
- row
461
- }) => {
462
- const { className, style } = useCell(column, classBase5);
463
- const { CellRenderer, index, name, valueFormatter } = column;
464
- const dataIdx = columnMap[name];
465
- const handleDataItemEdited = useCallback6(
466
- (value) => {
467
- if (onDataEdited) {
468
- let typedValue = value;
469
- if (isNumericColumn(column) && typeof value === "string") {
470
- typedValue = column.serverDataType === "double" ? parseFloat(value) : parseInt(value);
471
- }
472
- return onDataEdited == null ? void 0 : onDataEdited(row, name, typedValue);
473
- } else {
474
- throw Error(
475
- "TableCell onDataEdited prop not supplied for an editable cell"
476
- );
477
- }
478
- },
479
- [column, name, onDataEdited, row]
480
- );
481
- const handleClick = useCallback6(
482
- (evt) => {
483
- onClick == null ? void 0 : onClick(evt, column);
484
- },
485
- [column, onClick]
486
- );
487
- return /* @__PURE__ */ jsx8(
488
- "div",
489
- {
490
- "aria-colindex": index,
491
- className,
492
- onClick: onClick ? handleClick : void 0,
493
- role: "cell",
494
- style,
495
- children: CellRenderer ? /* @__PURE__ */ jsx8(
496
- CellRenderer,
497
- {
498
- column,
499
- columnMap,
500
- onCommit: handleDataItemEdited,
501
- row
502
- }
503
- ) : valueFormatter(row[dataIdx])
504
- }
505
- );
506
- };
507
-
508
- // src/table-cell/TableGroupCell.tsx
509
- import { getGroupValueAndOffset, metadataKeys } from "@vuu-ui/vuu-utils";
510
- import { useCallback as useCallback7 } from "react";
511
- import cx6 from "clsx";
512
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
513
- var { IS_LEAF } = metadataKeys;
514
- var classBase6 = "vuuTableGroupCell";
515
- var TableGroupCell = ({
516
- column,
517
- columnMap,
518
- onClick,
519
- row
520
- }) => {
521
- const { columns } = column;
522
- const [value, offset] = getGroupValueAndOffset(columns, row, columnMap);
523
- const { className, style } = useCell(column, classBase6);
524
- const handleClick = useCallback7(
525
- (evt) => {
526
- onClick == null ? void 0 : onClick(evt, column);
527
- },
528
- [column, onClick]
529
- );
530
- const isLeaf = row[IS_LEAF];
531
- const spacers = Array(offset).fill(0).map((n, i) => /* @__PURE__ */ jsx9("span", { className: `${classBase6}-spacer` }, i));
532
- return /* @__PURE__ */ jsxs6(
533
- "div",
534
- {
535
- className: cx6(className, "vuuTableCell"),
536
- role: "cell",
537
- style,
538
- onClick: isLeaf ? void 0 : handleClick,
539
- children: [
540
- spacers,
541
- isLeaf ? null : /* @__PURE__ */ jsx9("span", { className: `${classBase6}-toggle`, "data-icon": "triangle-right" }),
542
- /* @__PURE__ */ jsx9("span", { children: value })
543
- ]
544
- }
545
- );
546
- };
547
-
548
- // src/Row.tsx
549
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
550
- var { IDX, IS_EXPANDED, SELECTED } = metadataKeys2;
551
- var classBase7 = "vuuTableRow";
552
- var RowProxy = forwardRef(
553
- function RowProxy2({ height }, forwardedRef) {
554
- return /* @__PURE__ */ jsx10(
555
- "div",
556
- {
557
- "aria-hidden": true,
558
- className: cx7(classBase7, `${classBase7}-proxy`),
559
- ref: forwardedRef,
560
- style: { height }
561
- }
562
- );
563
- }
564
- );
565
- var Row = memo(
566
- ({
567
- className: classNameProp,
568
- classNameGenerator,
569
- columnMap,
570
- columns,
571
- highlighted,
572
- row,
573
- offset,
574
- onClick,
575
- onDataEdited,
576
- onToggleGroup,
577
- virtualColSpan = 0,
578
- zebraStripes = false,
579
- ...htmlAttributes
580
- }) => {
581
- const {
582
- [IDX]: rowIndex,
583
- [IS_EXPANDED]: isExpanded,
584
- [SELECTED]: selectionStatus
585
- } = row;
586
- const handleRowClick = useCallback8(
587
- (evt) => {
588
- const rangeSelect = evt.shiftKey;
589
- const keepExistingSelection = evt.ctrlKey || evt.metaKey;
590
- onClick == null ? void 0 : onClick(evt, row, rangeSelect, keepExistingSelection);
591
- },
592
- [onClick, row]
593
- );
594
- const { True, First, Last } = RowSelected;
595
- const className = cx7(
596
- classBase7,
597
- classNameProp,
598
- classNameGenerator == null ? void 0 : classNameGenerator(row, columnMap),
599
- {
600
- [`${classBase7}-even`]: zebraStripes && rowIndex % 2 === 0,
601
- [`${classBase7}-expanded`]: isExpanded,
602
- [`${classBase7}-highlighted`]: highlighted,
603
- [`${classBase7}-selected`]: selectionStatus & True,
604
- [`${classBase7}-selectedStart`]: selectionStatus & First,
605
- [`${classBase7}-selectedEnd`]: selectionStatus & Last
606
- }
607
- );
608
- const style = { transform: `translate3d(0px, ${offset}px, 0px)` };
609
- const handleGroupCellClick = useCallback8(
610
- (evt, column) => {
611
- if (isGroupColumn(column) || isJsonGroup(column, row, columnMap)) {
612
- evt.stopPropagation();
613
- onToggleGroup == null ? void 0 : onToggleGroup(row, column);
614
- }
615
- },
616
- [columnMap, onToggleGroup, row]
617
- );
618
- return /* @__PURE__ */ jsxs7(
619
- "div",
620
- {
621
- ...htmlAttributes,
622
- role: "row",
623
- className,
624
- onClick: handleRowClick,
625
- style,
626
- children: [
627
- /* @__PURE__ */ jsx10("span", { className: `${classBase7}-selectionDecorator vuuStickyLeft` }),
628
- virtualColSpan > 0 ? /* @__PURE__ */ jsx10("div", { className: "vuuTableCell", style: { width: virtualColSpan } }) : null,
629
- columns.filter(isNotHidden).map((column) => {
630
- const isGroup = isGroupColumn(column);
631
- const isJsonCell = isJsonColumn(column);
632
- const Cell = isGroup ? TableGroupCell : TableCell;
633
- return /* @__PURE__ */ jsx10(
634
- Cell,
635
- {
636
- column,
637
- columnMap,
638
- onClick: isGroup || isJsonCell ? handleGroupCellClick : void 0,
639
- onDataEdited,
640
- row
641
- },
642
- column.name
643
- );
644
- }),
645
- /* @__PURE__ */ jsx10("span", { className: `${classBase7}-selectionDecorator vuuStickyRight` })
646
- ]
647
- }
648
- );
649
- }
650
- );
651
- Row.displayName = "Row";
652
-
653
- // src/table-header/TableHeader.tsx
654
- import { isGroupColumn as isGroupColumn2, isNotHidden as isNotHidden2 } from "@vuu-ui/vuu-utils";
655
- import cx8 from "clsx";
656
- import { memo as memo2 } from "react";
657
-
658
- // src/table-header/useTableHeader.ts
659
- import {
660
- useDragDrop
661
- } from "@vuu-ui/vuu-ui-controls";
662
- import {
663
- moveColumnTo,
664
- queryClosest,
665
- visibleColumnAtIndex
666
- } from "@vuu-ui/vuu-utils";
667
- import { useCallback as useCallback9, useRef as useRef5 } from "react";
668
- var useTableHeader = ({
669
- columns,
670
- onMoveColumn,
671
- onSortColumn,
672
- tableConfig
673
- }) => {
674
- const containerRef = useRef5(null);
675
- const scrollingContainerRef = useRef5(null);
676
- const setContainerRef = useCallback9((el) => {
677
- containerRef.current = el;
678
- if (el) {
679
- scrollingContainerRef.current = el.closest(".vuuTable-contentContainer");
680
- } else {
681
- scrollingContainerRef.current = null;
682
- }
683
- }, []);
684
- const handleDropColumnHeader = useCallback9(
685
- ({ fromIndex: moveFrom, toIndex: moveTo }) => {
686
- const column = columns[moveFrom];
687
- const orderedColumns = moveColumnTo(columns, column, moveTo);
688
- const ofColumn = ({ name }) => (col) => col.name === name;
689
- const targetIndex = orderedColumns.findIndex(ofColumn(column));
690
- const nextColumn = orderedColumns[targetIndex + 1];
691
- const insertPos = nextColumn ? tableConfig.columns.findIndex(ofColumn(nextColumn)) : -1;
692
- if (moveTo > moveFrom && insertPos !== -1) {
693
- onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos - 1));
694
- } else {
695
- onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos));
696
- }
697
- },
698
- [columns, onMoveColumn, tableConfig.columns]
699
- );
700
- const handleColumnHeaderClick = useCallback9(
701
- (evt) => {
702
- var _a;
703
- const headerCell = queryClosest(evt.target, ".vuuTableHeaderCell");
704
- const colIdx = parseInt((_a = headerCell == null ? void 0 : headerCell.dataset.index) != null ? _a : "-1");
705
- const column = visibleColumnAtIndex(columns, colIdx);
706
- const isAdditive = evt.shiftKey;
707
- column && onSortColumn(column, isAdditive);
708
- },
709
- [columns, onSortColumn]
710
- );
711
- const {
712
- onMouseDown: columnHeaderDragMouseDown,
713
- draggable: draggableColumn,
714
- ...dragDropHook
715
- } = useDragDrop({
716
- allowDragDrop: true,
717
- containerRef,
718
- draggableClassName: `vuuTable`,
719
- itemQuery: ".vuuTableHeaderCell",
720
- onDrop: handleDropColumnHeader,
721
- orientation: "horizontal",
722
- scrollingContainerRef
723
- });
724
- return {
725
- draggableColumn,
726
- draggedColumnIndex: dragDropHook.draggedItemIndex,
727
- onClick: handleColumnHeaderClick,
728
- onMouseDown: columnHeaderDragMouseDown,
729
- setContainerRef
730
- };
731
- };
732
-
733
- // src/table-header/TableHeader.tsx
734
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
735
- var TableHeader = memo2(
736
- ({
737
- classBase: classBase11 = "vuuTable",
738
- columns,
739
- headings,
740
- onMoveColumn,
741
- onMoveGroupColumn,
742
- onRemoveGroupColumn,
743
- onResizeColumn,
744
- onSortColumn,
745
- showColumnHeaderMenus,
746
- tableConfig,
747
- tableId,
748
- virtualColSpan = 0
749
- }) => {
750
- const {
751
- draggableColumn,
752
- draggedColumnIndex,
753
- onClick,
754
- onMouseDown,
755
- setContainerRef
756
- } = useTableHeader({
757
- columns,
758
- onMoveColumn,
759
- onSortColumn,
760
- tableConfig
761
- });
762
- return /* @__PURE__ */ jsxs8("div", { className: `${classBase11}-col-headings`, ref: setContainerRef, children: [
763
- headings.map((colHeaders, i) => /* @__PURE__ */ jsx11("div", { className: "vuuTable-heading", children: colHeaders.map(({ label, width }, j) => /* @__PURE__ */ jsx11("div", { className: "vuuTable-headingCell", style: { width }, children: label }, j)) }, i)),
764
- /* @__PURE__ */ jsxs8("div", { className: `${classBase11}-col-headers`, role: "row", children: [
765
- virtualColSpan > 0 ? /* @__PURE__ */ jsx11(
766
- "div",
767
- {
768
- role: "cell",
769
- className: "vuuTableCell",
770
- style: { width: virtualColSpan }
771
- }
772
- ) : null,
773
- columns.filter(isNotHidden2).map(
774
- (col, i) => isGroupColumn2(col) ? /* @__PURE__ */ jsx11(
775
- GroupHeaderCell,
776
- {
777
- "aria-colindex": col.index,
778
- column: col,
779
- "data-index": i,
780
- onMoveColumn: onMoveGroupColumn,
781
- onRemoveColumn: onRemoveGroupColumn,
782
- onResize: onResizeColumn
783
- },
784
- col.name
785
- ) : /* @__PURE__ */ jsx11(
786
- HeaderCell,
787
- {
788
- "aria-colindex": col.index,
789
- className: cx8({
790
- "vuuDraggable-dragAway": i === draggedColumnIndex
791
- }),
792
- column: col,
793
- "data-index": i,
794
- id: `${tableId}-col-${i}`,
795
- onClick,
796
- onMouseDown,
797
- onResize: onResizeColumn,
798
- showMenu: showColumnHeaderMenus
799
- },
800
- col.name
801
- )
802
- ),
803
- draggableColumn
804
- ] })
805
- ] });
806
- }
807
- );
808
- TableHeader.displayName = "TableHeader";
809
-
810
- // src/useTable.ts
811
- import {
812
- useDragDrop as useDragDrop2
813
- } from "@vuu-ui/vuu-ui-controls";
814
- import {
815
- toggleOrApplySort,
816
- asDataSourceRowObject,
817
- buildColumnMap as buildColumnMap2,
818
- getIndexFromRowElement as getIndexFromRowElement3,
819
- isGroupColumn as isGroupColumn4,
820
- isJsonGroup as isJsonGroup2,
821
- isValidNumber,
822
- metadataKeys as metadataKeys5,
823
- updateColumn,
824
- useLayoutEffectSkipFirst as useLayoutEffectSkipFirst2
825
- } from "@vuu-ui/vuu-utils";
826
- import {
827
- useCallback as useCallback18,
828
- useEffect as useEffect4,
829
- useMemo as useMemo8,
830
- useRef as useRef13,
831
- useState as useState6
832
- } from "react";
833
-
834
- // src/context-menu/buildContextMenuDescriptors.ts
835
- import { isNumericColumn as isNumericColumn2 } from "@vuu-ui/vuu-utils";
836
- var buildContextMenuDescriptors = (dataSource) => (location, options) => {
837
- const descriptors = [];
838
- if (dataSource === void 0) {
839
- return descriptors;
840
- }
841
- if (location === "header" || location === "column-menu") {
842
- descriptors.push(
843
- ...buildSortMenuItems(options, dataSource)
844
- );
845
- descriptors.push(
846
- ...buildGroupMenuItems(options, dataSource)
847
- );
848
- descriptors.push(
849
- ...buildAggregationMenuItems(options, dataSource)
850
- );
851
- descriptors.push(...buildColumnDisplayMenuItems(options));
852
- descriptors.push({
853
- action: "column-settings",
854
- icon: "cog",
855
- label: `Column Settings`,
856
- options
857
- });
858
- descriptors.push({
859
- action: "table-settings",
860
- icon: "cog",
861
- label: `DataGrid Settings`,
862
- options
863
- });
864
- }
865
- return descriptors;
866
- };
867
- function buildSortMenuItems(options, { sort: { sortDefs } }) {
868
- const { column } = options;
869
- const menuItems = [];
870
- if (column === void 0) {
871
- return menuItems;
872
- }
873
- const hasSort = sortDefs.length > 0;
874
- if (column.sorted === "A") {
875
- menuItems.push({
876
- label: "Reverse Sort (DSC)",
877
- action: "sort-dsc",
878
- options
879
- });
880
- } else if (column.sorted === "D") {
881
- menuItems.push({
882
- label: "Reverse Sort (ASC)",
883
- action: "sort-asc",
884
- options
885
- });
886
- } else if (typeof column.sorted === "number") {
887
- if (column.sorted > 0) {
888
- menuItems.push({
889
- label: "Reverse Sort (DSC)",
890
- action: "sort-add-dsc",
891
- options
892
- });
893
- } else {
894
- menuItems.push({
895
- label: "Reverse Sort (ASC)",
896
- action: "sort-add-asc",
897
- options
898
- });
899
- }
900
- if (hasSort && Math.abs(column.sorted) < sortDefs.length) {
901
- menuItems.push({
902
- label: "Remove from sort",
903
- action: "sort-remove",
904
- options
905
- });
906
- }
907
- menuItems.push({
908
- label: "New Sort",
909
- children: [
910
- { label: "Ascending", action: "sort-asc", options },
911
- { label: "Descending", action: "sort-dsc", options }
912
- ]
913
- });
914
- } else if (hasSort) {
915
- menuItems.push({
916
- label: "Add to sort",
917
- children: [
918
- { label: "Ascending", action: "sort-add-asc", options },
919
- { label: "Descending", action: "sort-add-dsc", options }
920
- ]
921
- });
922
- menuItems.push({
923
- label: "New Sort",
924
- children: [
925
- { label: "Ascending", action: "sort-asc", options },
926
- { label: "Descending", action: "sort-dsc", options }
927
- ]
928
- });
929
- } else {
930
- menuItems.push({
931
- label: "Sort",
932
- children: [
933
- { label: "Ascending", action: "sort-asc", options },
934
- { label: "Descending", action: "sort-dsc", options }
935
- ]
936
- });
937
- }
938
- return menuItems;
939
- }
940
- function buildAggregationMenuItems(options, dataSource) {
941
- const { column } = options;
942
- if (column === void 0 || dataSource.groupBy.length === 0) {
943
- return [];
944
- }
945
- const { name, label = name } = column;
946
- return [
947
- {
948
- label: `Aggregate ${label}`,
949
- children: [
950
- { label: "Count", action: "agg-count", options },
951
- { label: "Distinct", action: "agg-distinct", options }
952
- ].concat(
953
- isNumericColumn2(column) ? [
954
- { label: "Sum", action: "agg-sum", options },
955
- { label: "Avg", action: "agg-avg", options },
956
- { label: "High", action: "agg-high", options },
957
- { label: "Low", action: "agg-low", options }
958
- ] : []
959
- )
960
- }
961
- ];
962
- }
963
- var pinColumn = (options, pinLocation) => ({
964
- label: `Pin ${pinLocation}`,
965
- action: `column-pin-${pinLocation}`,
966
- options
967
- });
968
- var pinLeft = (options) => pinColumn(options, "left");
969
- var pinFloating = (options) => pinColumn(options, "floating");
970
- var pinRight = (options) => pinColumn(options, "right");
971
- function buildColumnDisplayMenuItems(options) {
972
- const { column } = options;
973
- if (column === void 0) {
974
- return [];
975
- }
976
- const { pin } = column;
977
- const menuItems = [
978
- {
979
- label: `Hide column`,
980
- action: "column-hide",
981
- options
982
- },
983
- {
984
- label: `Remove column`,
985
- action: "column-remove",
986
- options
987
- }
988
- ];
989
- if (pin === void 0) {
990
- menuItems.push({
991
- label: `Pin column`,
992
- children: [pinLeft(options), pinFloating(options), pinRight(options)]
993
- });
994
- } else if (pin === "left") {
995
- menuItems.push(
996
- { label: "Unpin column", action: "column-unpin", options },
997
- {
998
- label: `Pin column`,
999
- children: [pinFloating(options), pinRight(options)]
1000
- }
1001
- );
1002
- } else if (pin === "right") {
1003
- menuItems.push(
1004
- { label: "Unpin column", action: "column-unpin", options },
1005
- {
1006
- label: `Pin column`,
1007
- children: [pinLeft(options), pinFloating(options)]
1008
- }
1009
- );
1010
- } else if (pin === "floating") {
1011
- menuItems.push(
1012
- { label: "Unpin column", action: "column-unpin", options },
1013
- {
1014
- label: `Pin column`,
1015
- children: [pinLeft(options), pinRight(options)]
1016
- }
1017
- );
1018
- }
1019
- return menuItems;
1020
- }
1021
- function buildGroupMenuItems(options, { groupBy }) {
1022
- const { column } = options;
1023
- const menuItems = [];
1024
- if (column === void 0) {
1025
- return menuItems;
1026
- }
1027
- const { name, label = name } = column;
1028
- if (groupBy.length === 0) {
1029
- menuItems.push({
1030
- label: `Group by ${label}`,
1031
- action: "group",
1032
- options
1033
- });
1034
- } else {
1035
- menuItems.push({
1036
- label: `Add ${label} to group by`,
1037
- action: "group-add",
1038
- options
1039
- });
1040
- }
1041
- return menuItems;
1042
- }
1043
-
1044
- // src/context-menu/useHandleTableContextMenu.ts
1045
- import { removeColumnFromFilter } from "@vuu-ui/vuu-utils";
1046
- import {
1047
- addGroupColumn,
1048
- addSortColumn,
1049
- AggregationType,
1050
- setAggregations,
1051
- setSortColumn
1052
- } from "@vuu-ui/vuu-utils";
1053
- var removeFilterColumn = (dataSourceFilter, column) => {
1054
- if (dataSourceFilter.filterStruct && column) {
1055
- const [filterStruct, filter] = removeColumnFromFilter(
1056
- column,
1057
- dataSourceFilter.filterStruct
1058
- );
1059
- return {
1060
- filter,
1061
- filterStruct
1062
- };
1063
- } else {
1064
- return dataSourceFilter;
1065
- }
1066
- };
1067
- var { Average, Count, Distinct, High, Low, Sum } = AggregationType;
1068
- var useHandleTableContextMenu = ({
1069
- dataSource,
1070
- onPersistentColumnOperation
1071
- }) => {
1072
- const handleContextMenuAction = (action) => {
1073
- const gridOptions = action.options;
1074
- if (gridOptions.column && dataSource) {
1075
- const { column } = gridOptions;
1076
- switch (action.menuId) {
1077
- case "sort-asc":
1078
- return dataSource.sort = setSortColumn(dataSource.sort, column, "A"), true;
1079
- case "sort-dsc":
1080
- return dataSource.sort = setSortColumn(dataSource.sort, column, "D"), true;
1081
- case "sort-add-asc":
1082
- return dataSource.sort = addSortColumn(dataSource.sort, column, "A"), true;
1083
- case "sort-add-dsc":
1084
- return dataSource.sort = addSortColumn(dataSource.sort, column, "D"), true;
1085
- case "group":
1086
- return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
1087
- case "group-add":
1088
- return dataSource.groupBy = addGroupColumn(dataSource.groupBy, column), true;
1089
- case "column-hide":
1090
- return onPersistentColumnOperation({ type: "hideColumns", columns: [column] }), true;
1091
- case "column-remove":
1092
- return dataSource.columns = dataSource.columns.filter((name) => name !== column.name), true;
1093
- case "filter-remove-column":
1094
- return dataSource.filter = removeFilterColumn(dataSource.filter, column), true;
1095
- case "remove-filters":
1096
- return dataSource.filter = { filter: "" }, true;
1097
- case "agg-avg":
1098
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Average), true;
1099
- case "agg-high":
1100
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, High), true;
1101
- case "agg-low":
1102
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Low), true;
1103
- case "agg-count":
1104
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Count), true;
1105
- case "agg-distinct":
1106
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Distinct), true;
1107
- case "agg-sum":
1108
- return dataSource.aggregations = setAggregations(dataSource.aggregations, column, Sum), true;
1109
- case "column-pin-floating":
1110
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "floating" }), true;
1111
- case "column-pin-left":
1112
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "left" }), true;
1113
- case "column-pin-right":
1114
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: "right" }), true;
1115
- case "column-unpin":
1116
- return onPersistentColumnOperation({ type: "pinColumn", column, pin: void 0 }), true;
1117
- case "column-settings":
1118
- return onPersistentColumnOperation({ type: "columnSettings", column }), true;
1119
- case "table-settings":
1120
- return onPersistentColumnOperation({ type: "tableSettings" }), true;
1121
- default:
1122
- }
1123
- }
1124
- return false;
1125
- };
1126
- return handleContextMenuAction;
1127
- };
1128
-
1129
- // src/table-config.ts
1130
- var updateTableConfig = (config, action) => {
1131
- switch (action.type) {
1132
- case "col-size":
1133
- return {
1134
- ...config,
1135
- columns: config.columns.map(
1136
- (col) => col.name === action.column.name ? { ...col, width: action.width } : col
1137
- )
1138
- };
1139
- case "column-prop":
1140
- return {
1141
- ...config,
1142
- columns: config.columns.map(
1143
- (col) => col.name === action.column.name ? { ...col, [action.property]: action.value } : col
1144
- )
1145
- };
1146
- default:
1147
- return config;
1148
- }
1149
- };
1150
-
1151
- // src/useCellEditing.ts
1152
- import { isCharacterKey } from "@vuu-ui/vuu-utils";
1153
- import {
1154
- useCallback as useCallback10
1155
- } from "react";
1156
-
1157
- // src/table-dom-utils.ts
1158
- var headerCellQuery = (colIdx) => `.vuuTable-col-headers .vuuTableHeaderCell:nth-child(${colIdx})`;
1159
- var dataCellQuery = (rowIdx, colIdx) => `.vuuTable-body > [aria-rowindex='${rowIdx + 1}'] > [role='cell']:nth-child(${colIdx + 1})`;
1160
- var getTableCell = (containerRef, [rowIdx, colIdx]) => {
1161
- var _a;
1162
- const cssQuery = rowIdx === -1 ? headerCellQuery(colIdx) : dataCellQuery(rowIdx, colIdx);
1163
- const cell = (_a = containerRef.current) == null ? void 0 : _a.querySelector(
1164
- cssQuery
1165
- );
1166
- if (cellIsEditable(cell)) {
1167
- const focusableContent = cell.querySelector("button");
1168
- return focusableContent || cell;
1169
- } else {
1170
- return cell;
1171
- }
1172
- };
1173
- var cellIsEditable = (cell) => cell == null ? void 0 : cell.classList.contains("vuuTableCell-editable");
1174
- var cellIsTextInput = (cell) => cell.querySelector(".vuuTableInputCell") !== null;
1175
- function getRowIndex(rowEl) {
1176
- if (rowEl) {
1177
- const idx = rowEl.ariaRowIndex;
1178
- if (idx !== null) {
1179
- return parseInt(idx, 10) - 1;
1180
- }
1181
- }
1182
- return -1;
1183
- }
1184
- var closestRow = (el) => el.closest('[role="row"]');
1185
- var closestRowIndex = (el) => getRowIndex(closestRow(el));
1186
- var NO_SCROLL_NECESSARY = [void 0, void 0];
1187
- var howFarIsRowOutsideViewport = (rowEl, totalHeaderHeight, contentContainer = rowEl.closest(".vuuTable-contentContainer")) => {
1188
- if (contentContainer) {
1189
- const viewport = contentContainer == null ? void 0 : contentContainer.getBoundingClientRect();
1190
- const upperBoundary = viewport.top + totalHeaderHeight;
1191
- const row = rowEl.getBoundingClientRect();
1192
- if (row) {
1193
- if (row.bottom > viewport.bottom) {
1194
- return ["down", row.bottom - viewport.bottom];
1195
- } else if (row.top < upperBoundary) {
1196
- return ["up", row.top - upperBoundary];
1197
- } else {
1198
- return NO_SCROLL_NECESSARY;
1199
- }
1200
- } else {
1201
- throw Error("Whats going on, row not found");
1202
- }
1203
- } else {
1204
- throw Error("Whats going on, scrollbar container not found");
1205
- }
1206
- };
1207
-
1208
- // src/useCellEditing.ts
1209
- var useCellEditing = ({ navigate }) => {
1210
- const commitHandler = useCallback10(() => {
1211
- navigate();
1212
- }, [navigate]);
1213
- const editInput = useCallback10(
1214
- (evt) => {
1215
- const cellEl = evt.target;
1216
- const input = cellEl.matches("input") ? cellEl : cellEl.querySelector("input");
1217
- if (input) {
1218
- input.focus();
1219
- input.select();
1220
- }
1221
- },
1222
- []
1223
- );
1224
- const focusInput = useCallback10(
1225
- (evt) => {
1226
- const cellEl = evt.target;
1227
- const input = cellEl.querySelector("input");
1228
- if (input) {
1229
- input.focus();
1230
- input.select();
1231
- }
1232
- },
1233
- []
1234
- );
1235
- const handleKeyDown = useCallback10(
1236
- (e) => {
1237
- const el = e.target;
1238
- if (cellIsTextInput(el)) {
1239
- if (isCharacterKey(e.key)) {
1240
- editInput(e);
1241
- } else if (e.key === "Enter") {
1242
- focusInput(e);
1243
- }
1244
- }
1245
- },
1246
- [editInput, focusInput]
1247
- );
1248
- const handleDoubleClick = useCallback10(
1249
- (e) => {
1250
- const el = e.target;
1251
- if (el.matches("input") || el.querySelector("input")) {
1252
- editInput(e);
1253
- e.stopPropagation();
1254
- }
1255
- },
1256
- [editInput]
1257
- );
1258
- const handleBlur = useCallback10(
1259
- (e) => {
1260
- const el = e.target;
1261
- el.removeEventListener("vuu-commit", commitHandler, true);
1262
- },
1263
- [commitHandler]
1264
- );
1265
- const handleFocus = useCallback10(
1266
- (e) => {
1267
- const el = e.target;
1268
- el.addEventListener("vuu-commit", commitHandler, true);
1269
- },
1270
- [commitHandler]
1271
- );
1272
- return {
1273
- onBlur: handleBlur,
1274
- onDoubleClick: handleDoubleClick,
1275
- onFocus: handleFocus,
1276
- onKeyDown: handleKeyDown
1277
- };
1278
- };
1279
-
1280
- // src/useDataSource.ts
1281
- import { getFullRange, NULL_RANGE, rangesAreSame } from "@vuu-ui/vuu-utils";
1282
- import { useCallback as useCallback11, useEffect, useMemo as useMemo3, useRef as useRef6, useState as useState3 } from "react";
1283
-
1284
- // src/moving-window.ts
1285
- import {
1286
- isRowSelectedLast,
1287
- metadataKeys as metadataKeys3,
1288
- WindowRange
1289
- } from "@vuu-ui/vuu-utils";
1290
- var { SELECTED: SELECTED2 } = metadataKeys3;
1291
- var MovingWindow = class {
1292
- constructor({ from, to }) {
1293
- this.rowCount = 0;
1294
- this.setRowCount = (rowCount) => {
1295
- if (rowCount < this.data.length) {
1296
- this.data.length = rowCount;
1297
- }
1298
- this.rowCount = rowCount;
1299
- };
1300
- this.range = new WindowRange(from, to);
1301
- this.data = new Array(Math.max(0, to - from));
1302
- this.rowCount = 0;
1303
- }
1304
- add(data) {
1305
- const [index] = data;
1306
- if (this.isWithinRange(index)) {
1307
- const internalIndex = index - this.range.from;
1308
- this.data[internalIndex] = data;
1309
- if (data[SELECTED2]) {
1310
- const previousRow = this.data[internalIndex - 1];
1311
- if (isRowSelectedLast(previousRow)) {
1312
- this.data[internalIndex - 1] = previousRow.slice();
1313
- this.data[internalIndex - 1][SELECTED2] -= 4;
1314
- }
1315
- }
1316
- }
1317
- }
1318
- getAtIndex(index) {
1319
- return this.range.isWithin(index) && this.data[index - this.range.from] != null ? this.data[index - this.range.from] : void 0;
1320
- }
1321
- isWithinRange(index) {
1322
- return this.range.isWithin(index);
1323
- }
1324
- setRange({ from, to }) {
1325
- if (from !== this.range.from || to !== this.range.to) {
1326
- const [overlapFrom, overlapTo] = this.range.overlap(from, to);
1327
- const newData = new Array(Math.max(0, to - from));
1328
- for (let i = overlapFrom; i < overlapTo; i++) {
1329
- const data = this.getAtIndex(i);
1330
- if (data) {
1331
- const index = i - from;
1332
- newData[index] = data;
1333
- }
1334
- }
1335
- this.data = newData;
1336
- this.range.from = from;
1337
- this.range.to = to;
1338
- }
1339
- }
1340
- getSelectedRows() {
1341
- return this.data.filter((row) => row[SELECTED2] !== 0);
1342
- }
1343
- };
1344
-
1345
- // src/useDataSource.ts
1346
- var isVuuFeatureInvocation = (action) => action.type === "vuu-link-created" || action.type === "vuu-link-removed";
1347
- var useDataSource = ({
1348
- dataSource,
1349
- onFeatureInvocation,
1350
- onSizeChange,
1351
- onSubscribed,
1352
- range = NULL_RANGE,
1353
- renderBufferSize = 0
1354
- }) => {
1355
- const [, forceUpdate] = useState3(null);
1356
- const data = useRef6([]);
1357
- const isMounted = useRef6(true);
1358
- const hasUpdated = useRef6(false);
1359
- const rangeRef = useRef6(range);
1360
- const dataWindow = useMemo3(
1361
- () => new MovingWindow(getFullRange(range, renderBufferSize)),
1362
- // eslint-disable-next-line react-hooks/exhaustive-deps
1363
- []
1364
- );
1365
- const setData = useCallback11(
1366
- (updates) => {
1367
- for (const row of updates) {
1368
- dataWindow.add(row);
1369
- }
1370
- data.current = dataWindow.data;
1371
- if (isMounted.current) {
1372
- forceUpdate({});
1373
- } else {
1374
- }
1375
- },
1376
- [dataWindow]
1377
- );
1378
- const datasourceMessageHandler = useCallback11(
1379
- (message) => {
1380
- if (message.type === "subscribed") {
1381
- onSubscribed == null ? void 0 : onSubscribed(message);
1382
- } else if (message.type === "viewport-update") {
1383
- if (typeof message.size === "number") {
1384
- onSizeChange == null ? void 0 : onSizeChange(message.size);
1385
- dataWindow.setRowCount(message.size);
1386
- }
1387
- if (message.rows) {
1388
- setData(message.rows);
1389
- } else if (typeof message.size === "number") {
1390
- data.current = dataWindow.data;
1391
- hasUpdated.current = true;
1392
- }
1393
- } else if (isVuuFeatureInvocation(message)) {
1394
- onFeatureInvocation == null ? void 0 : onFeatureInvocation(message);
1395
- } else {
1396
- console.log(`useDataSource unexpected message ${message.type}`);
1397
- }
1398
- },
1399
- [dataWindow, onFeatureInvocation, onSizeChange, onSubscribed, setData]
1400
- );
1401
- const getSelectedRows = useCallback11(() => {
1402
- return dataWindow.getSelectedRows();
1403
- }, [dataWindow]);
1404
- useEffect(() => {
1405
- var _a;
1406
- isMounted.current = true;
1407
- (_a = dataSource.resume) == null ? void 0 : _a.call(dataSource);
1408
- return () => {
1409
- var _a2;
1410
- isMounted.current = false;
1411
- (_a2 = dataSource.suspend) == null ? void 0 : _a2.call(dataSource);
1412
- };
1413
- }, [dataSource]);
1414
- useEffect(() => {
1415
- var _a;
1416
- if (dataSource.status === "disabled") {
1417
- (_a = dataSource.enable) == null ? void 0 : _a.call(dataSource, datasourceMessageHandler);
1418
- } else {
1419
- dataSource == null ? void 0 : dataSource.subscribe(
1420
- { range: getFullRange(range, renderBufferSize) },
1421
- datasourceMessageHandler
1422
- );
1423
- }
1424
- }, [dataSource, datasourceMessageHandler, range, renderBufferSize]);
1425
- const setRange = useCallback11(
1426
- (range2) => {
1427
- if (!rangesAreSame(range2, rangeRef.current)) {
1428
- const fullRange = getFullRange(range2, renderBufferSize);
1429
- dataWindow.setRange(fullRange);
1430
- dataSource.range = rangeRef.current = fullRange;
1431
- dataSource.emit("range", range2);
1432
- }
1433
- },
1434
- [dataSource, dataWindow, renderBufferSize]
1435
- );
1436
- return {
1437
- data: data.current,
1438
- dataRef: data,
1439
- getSelectedRows,
1440
- range: rangeRef.current,
1441
- setRange
1442
- };
1443
- };
1444
-
1445
- // src/useInitialValue.ts
1446
- import { useMemo as useMemo4, useRef as useRef7 } from "react";
1447
- var useInitialValue = (value) => {
1448
- const ref = useRef7(value);
1449
- return useMemo4(() => ref.current, []);
1450
- };
1451
-
1452
- // src/useKeyboardNavigation.ts
1453
- import { getIndexFromRowElement } from "@vuu-ui/vuu-utils";
1454
- import { useControlled } from "@salt-ds/core";
1455
- import {
1456
- useCallback as useCallback12,
1457
- useEffect as useEffect2,
1458
- useRef as useRef8
1459
- } from "react";
1460
- var rowNavigationKeys = /* @__PURE__ */ new Set([
1461
- "Home",
1462
- "End",
1463
- "PageUp",
1464
- "PageDown",
1465
- "ArrowDown",
1466
- "ArrowUp"
1467
- ]);
1468
- var cellNavigationKeys = new Set(rowNavigationKeys);
1469
- cellNavigationKeys.add("ArrowLeft");
1470
- cellNavigationKeys.add("ArrowRight");
1471
- var isNavigationKey = (key, navigationStyle) => {
1472
- switch (navigationStyle) {
1473
- case "cell":
1474
- return cellNavigationKeys.has(key);
1475
- case "row":
1476
- return rowNavigationKeys.has(key);
1477
- default:
1478
- return false;
1479
- }
1480
- };
1481
- var PageKeys = ["Home", "End", "PageUp", "PageDown"];
1482
- var isPagingKey = (key) => PageKeys.includes(key);
1483
- var NULL_CELL_POS = [-1, -1];
1484
- function nextCellPos(key, [rowIdx, colIdx], columnCount, rowCount) {
1485
- if (key === "ArrowUp") {
1486
- if (rowIdx > -1) {
1487
- return [rowIdx - 1, colIdx];
1488
- } else {
1489
- return [rowIdx, colIdx];
1490
- }
1491
- } else if (key === "ArrowDown") {
1492
- if (rowIdx === -1) {
1493
- return [0, colIdx];
1494
- } else if (rowIdx === rowCount - 1) {
1495
- return [rowIdx, colIdx];
1496
- } else {
1497
- return [rowIdx + 1, colIdx];
1498
- }
1499
- } else if (key === "ArrowRight") {
1500
- if (colIdx < columnCount) {
1501
- return [rowIdx, colIdx + 1];
1502
- } else {
1503
- return [rowIdx, colIdx];
1504
- }
1505
- } else if (key === "ArrowLeft") {
1506
- if (colIdx > 1) {
1507
- return [rowIdx, colIdx - 1];
1508
- } else {
1509
- return [rowIdx, colIdx];
1510
- }
1511
- }
1512
- return [rowIdx, colIdx];
1513
- }
1514
- var useKeyboardNavigation = ({
1515
- columnCount = 0,
1516
- containerRef,
1517
- disableFocus = false,
1518
- defaultHighlightedIndex,
1519
- disableHighlightOnFocus,
1520
- highlightedIndex: highlightedIndexProp,
1521
- navigationStyle,
1522
- requestScroll,
1523
- onHighlight,
1524
- rowCount = 0,
1525
- viewportRowCount
1526
- }) => {
1527
- var _a;
1528
- const focusedCellPos = useRef8([-1, -1]);
1529
- const focusableCell = useRef8();
1530
- const activeCellPos = useRef8([-1, 0]);
1531
- const highlightedIndexRef = useRef8();
1532
- const [highlightedIndex, setHighlightedIdx] = useControlled({
1533
- controlled: highlightedIndexProp,
1534
- default: defaultHighlightedIndex,
1535
- name: "UseKeyboardNavigation"
1536
- });
1537
- highlightedIndexRef.current = highlightedIndex;
1538
- const setHighlightedIndex = useCallback12(
1539
- (idx, fromKeyboard = false) => {
1540
- onHighlight == null ? void 0 : onHighlight(idx);
1541
- setHighlightedIdx(idx);
1542
- if (fromKeyboard) {
1543
- }
1544
- },
1545
- [onHighlight, setHighlightedIdx]
1546
- );
1547
- const getFocusedCell = (element) => element == null ? void 0 : element.closest(
1548
- "[role='columnHeader'],[role='cell']"
1549
- );
1550
- const getTableCellPos = (tableCell) => {
1551
- var _a2;
1552
- if (tableCell.role === "columnHeader") {
1553
- const colIdx = parseInt((_a2 = tableCell.dataset.idx) != null ? _a2 : "-1", 10);
1554
- return [-1, colIdx];
1555
- } else {
1556
- const focusedRow = tableCell.closest("[role='row']");
1557
- if (focusedRow) {
1558
- const rowIdx = getIndexFromRowElement(focusedRow);
1559
- const colIdx = Array.from(focusedRow.childNodes).indexOf(tableCell);
1560
- return [rowIdx, colIdx];
1561
- }
1562
- }
1563
- return NULL_CELL_POS;
1564
- };
1565
- const focusCell = useCallback12(
1566
- (cellPos) => {
1567
- var _a2;
1568
- if (containerRef.current) {
1569
- const activeCell = getTableCell(containerRef, cellPos);
1570
- if (activeCell) {
1571
- if (activeCell !== focusableCell.current) {
1572
- (_a2 = focusableCell.current) == null ? void 0 : _a2.removeAttribute("tabindex");
1573
- focusableCell.current = activeCell;
1574
- activeCell.setAttribute("tabindex", "0");
1575
- }
1576
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-row", rowIndex: cellPos[0] });
1577
- activeCell.focus({ preventScroll: true });
1578
- }
1579
- }
1580
- },
1581
- // TODO we recreate this function whenever viewportRange changes, which will
1582
- // be often whilst scrolling - store range in a a ref ?
1583
- [containerRef, requestScroll]
1584
- );
1585
- const setActiveCell = useCallback12(
1586
- (rowIdx, colIdx, fromKeyboard = false) => {
1587
- const pos = [rowIdx, colIdx];
1588
- activeCellPos.current = pos;
1589
- if (navigationStyle === "row") {
1590
- setHighlightedIdx(rowIdx);
1591
- } else {
1592
- focusCell(pos);
1593
- }
1594
- if (fromKeyboard) {
1595
- focusedCellPos.current = pos;
1596
- }
1597
- },
1598
- [focusCell, navigationStyle, setHighlightedIdx]
1599
- );
1600
- const nextPageItemIdx = useCallback12(
1601
- (key, [rowIdx, colIdx]) => new Promise((resolve) => {
1602
- let newRowIdx = rowIdx;
1603
- switch (key) {
1604
- case "PageDown": {
1605
- newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);
1606
- if (newRowIdx !== rowIdx) {
1607
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "down" });
1608
- }
1609
- break;
1610
- }
1611
- case "PageUp": {
1612
- newRowIdx = Math.max(0, rowIdx - viewportRowCount);
1613
- if (newRowIdx !== rowIdx) {
1614
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-page", direction: "up" });
1615
- }
1616
- break;
1617
- }
1618
- case "Home": {
1619
- newRowIdx = 0;
1620
- if (newRowIdx !== rowIdx) {
1621
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-end", direction: "home" });
1622
- }
1623
- break;
1624
- }
1625
- case "End": {
1626
- newRowIdx = rowCount - 1;
1627
- if (newRowIdx !== rowIdx) {
1628
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-end", direction: "end" });
1629
- }
1630
- break;
1631
- }
1632
- }
1633
- setTimeout(() => {
1634
- resolve([newRowIdx, colIdx]);
1635
- }, 35);
1636
- }),
1637
- [requestScroll, rowCount, viewportRowCount]
1638
- );
1639
- const handleFocus = useCallback12(() => {
1640
- var _a2;
1641
- if (disableHighlightOnFocus !== true) {
1642
- if ((_a2 = containerRef.current) == null ? void 0 : _a2.contains(document.activeElement)) {
1643
- const focusedCell = getFocusedCell(document.activeElement);
1644
- if (focusedCell) {
1645
- focusedCellPos.current = getTableCellPos(focusedCell);
1646
- if (navigationStyle === "row") {
1647
- setHighlightedIdx(focusedCellPos.current[0]);
1648
- }
1649
- }
1650
- }
1651
- }
1652
- }, [
1653
- disableHighlightOnFocus,
1654
- containerRef,
1655
- navigationStyle,
1656
- setHighlightedIdx
1657
- ]);
1658
- const navigateChildItems = useCallback12(
1659
- async (key) => {
1660
- const [nextRowIdx, nextColIdx] = isPagingKey(key) ? await nextPageItemIdx(key, activeCellPos.current) : nextCellPos(key, activeCellPos.current, columnCount, rowCount);
1661
- const [rowIdx, colIdx] = activeCellPos.current;
1662
- if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {
1663
- setActiveCell(nextRowIdx, nextColIdx, true);
1664
- }
1665
- },
1666
- [columnCount, nextPageItemIdx, rowCount, setActiveCell]
1667
- );
1668
- const scrollRowIntoViewIfNecessary = useCallback12(
1669
- (rowIndex) => {
1670
- requestScroll == null ? void 0 : requestScroll({ type: "scroll-row", rowIndex });
1671
- },
1672
- [requestScroll]
1673
- );
1674
- const moveHighlightedRow = useCallback12(
1675
- async (key) => {
1676
- const { current: highlighted } = highlightedIndexRef;
1677
- const [nextRowIdx] = isPagingKey(key) ? await nextPageItemIdx(key, [highlighted != null ? highlighted : -1, 0]) : nextCellPos(key, [highlighted != null ? highlighted : -1, 0], columnCount, rowCount);
1678
- if (nextRowIdx !== highlighted) {
1679
- setHighlightedIndex(nextRowIdx);
1680
- scrollRowIntoViewIfNecessary(nextRowIdx);
1681
- }
1682
- },
1683
- [
1684
- columnCount,
1685
- nextPageItemIdx,
1686
- rowCount,
1687
- scrollRowIntoViewIfNecessary,
1688
- setHighlightedIndex
1689
- ]
1690
- );
1691
- useEffect2(() => {
1692
- if (highlightedIndexProp !== void 0 && highlightedIndexProp !== -1) {
1693
- scrollRowIntoViewIfNecessary(highlightedIndexProp);
1694
- }
1695
- }, [highlightedIndexProp, scrollRowIntoViewIfNecessary]);
1696
- const handleKeyDown = useCallback12(
1697
- (e) => {
1698
- if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {
1699
- e.preventDefault();
1700
- e.stopPropagation();
1701
- if (navigationStyle === "row") {
1702
- moveHighlightedRow(e.key);
1703
- } else {
1704
- void navigateChildItems(e.key);
1705
- }
1706
- }
1707
- },
1708
- [rowCount, navigationStyle, moveHighlightedRow, navigateChildItems]
1709
- );
1710
- const handleClick = useCallback12(
1711
- // Might not be a cell e.g the Settings button
1712
- (evt) => {
1713
- const target = evt.target;
1714
- const focusedCell = getFocusedCell(target);
1715
- if (focusedCell) {
1716
- const [rowIdx, colIdx] = getTableCellPos(focusedCell);
1717
- setActiveCell(rowIdx, colIdx);
1718
- }
1719
- },
1720
- [setActiveCell]
1721
- );
1722
- const handleMouseLeave = useCallback12(() => {
1723
- setHighlightedIndex(-1);
1724
- }, [setHighlightedIndex]);
1725
- const handleMouseMove = useCallback12(
1726
- (evt) => {
1727
- const idx = closestRowIndex(evt.target);
1728
- if (idx !== -1 && idx !== highlightedIndexRef.current) {
1729
- setHighlightedIndex(idx);
1730
- }
1731
- },
1732
- [setHighlightedIndex]
1733
- );
1734
- const navigate = useCallback12(() => {
1735
- navigateChildItems("ArrowDown");
1736
- }, [navigateChildItems]);
1737
- const fullyRendered = ((_a = containerRef.current) == null ? void 0 : _a.firstChild) != null;
1738
- useEffect2(() => {
1739
- if (fullyRendered && focusableCell.current === void 0 && !disableFocus) {
1740
- const { current: container } = containerRef;
1741
- const cell = (container == null ? void 0 : container.querySelector(headerCellQuery(0))) || (container == null ? void 0 : container.querySelector(dataCellQuery(0, 0)));
1742
- if (cell) {
1743
- cell.setAttribute("tabindex", "0");
1744
- focusableCell.current = cell;
1745
- }
1746
- }
1747
- }, [containerRef, disableFocus, fullyRendered]);
1748
- return {
1749
- highlightedIndexRef,
1750
- navigate,
1751
- onClick: handleClick,
1752
- onFocus: handleFocus,
1753
- onKeyDown: handleKeyDown,
1754
- onMouseLeave: navigationStyle === "row" ? handleMouseLeave : void 0,
1755
- onMouseMove: navigationStyle === "row" ? handleMouseMove : void 0
1756
- };
1757
- };
1758
-
1759
- // src/useSelection.ts
1760
- import {
1761
- deselectItem,
1762
- dispatchMouseEvent,
1763
- getRowElementAtIndex,
1764
- isRowSelected,
1765
- metadataKeys as metadataKeys4,
1766
- selectItem
1767
- } from "@vuu-ui/vuu-utils";
1768
- import {
1769
- useCallback as useCallback13,
1770
- useRef as useRef9
1771
- } from "react";
1772
- var { IDX: IDX2 } = metadataKeys4;
1773
- var NO_SELECTION = [];
1774
- var defaultSelectionKeys = ["Enter", " "];
1775
- var useSelection = ({
1776
- highlightedIndexRef,
1777
- selectionKeys = defaultSelectionKeys,
1778
- selectionModel,
1779
- onSelect,
1780
- onSelectionChange
1781
- }) => {
1782
- selectionModel === "extended" || selectionModel === "checkbox";
1783
- const lastActiveRef = useRef9(-1);
1784
- const selectedRef = useRef9(NO_SELECTION);
1785
- const isSelectionEvent = useCallback13(
1786
- (evt) => selectionKeys.includes(evt.key),
1787
- [selectionKeys]
1788
- );
1789
- const handleRowClick = useCallback13(
1790
- (evt, row, rangeSelect, keepExistingSelection) => {
1791
- const { [IDX2]: idx } = row;
1792
- const { current: active } = lastActiveRef;
1793
- const { current: selected } = selectedRef;
1794
- const selectOperation = isRowSelected(row) ? deselectItem : selectItem;
1795
- const newSelected = selectOperation(
1796
- selectionModel,
1797
- selected,
1798
- idx,
1799
- rangeSelect,
1800
- keepExistingSelection,
1801
- active
1802
- );
1803
- selectedRef.current = newSelected;
1804
- lastActiveRef.current = idx;
1805
- onSelect == null ? void 0 : onSelect(selectOperation === selectItem ? row : null);
1806
- onSelectionChange == null ? void 0 : onSelectionChange(newSelected);
1807
- },
1808
- [onSelect, onSelectionChange, selectionModel]
1809
- );
1810
- const handleKeyDown = useCallback13(
1811
- (e) => {
1812
- if (isSelectionEvent(e)) {
1813
- const { current: rowIndex } = highlightedIndexRef;
1814
- if (rowIndex !== void 0 && rowIndex !== -1) {
1815
- const rowEl = getRowElementAtIndex(e.target, rowIndex);
1816
- if (rowEl) {
1817
- dispatchMouseEvent(rowEl, "click");
1818
- }
1819
- }
1820
- }
1821
- },
1822
- [highlightedIndexRef, isSelectionEvent]
1823
- );
1824
- return {
1825
- onKeyDown: handleKeyDown,
1826
- onRowClick: handleRowClick
1827
- };
1828
- };
1829
-
1830
- // src/useTableContextMenu.ts
1831
- import { useContextMenu as usePopupContextMenu } from "@vuu-ui/vuu-popups";
1832
- import { buildColumnMap, getIndexFromRowElement as getIndexFromRowElement2 } from "@vuu-ui/vuu-utils";
1833
- import { useCallback as useCallback14 } from "react";
1834
- var NO_ROWS = [];
1835
- var useTableContextMenu = ({
1836
- columns,
1837
- data,
1838
- dataSource,
1839
- getSelectedRows
1840
- }) => {
1841
- const [showContextMenu] = usePopupContextMenu();
1842
- const onContextMenu = useCallback14(
1843
- (evt) => {
1844
- const target = evt.target;
1845
- const cellEl = target == null ? void 0 : target.closest("div[role='cell']");
1846
- const rowEl = target == null ? void 0 : target.closest("div[role='row']");
1847
- if (cellEl && rowEl) {
1848
- const { selectedRowsCount } = dataSource;
1849
- const columnMap = buildColumnMap(columns);
1850
- const rowIndex = getIndexFromRowElement2(rowEl);
1851
- const cellIndex = Array.from(rowEl.childNodes).indexOf(cellEl);
1852
- const row = data.find(([idx]) => idx === rowIndex);
1853
- const columnName = columns[cellIndex];
1854
- showContextMenu(evt, "grid", {
1855
- columnMap,
1856
- columnName,
1857
- row,
1858
- selectedRows: selectedRowsCount === 0 ? NO_ROWS : getSelectedRows(),
1859
- viewport: dataSource.viewport
1860
- });
1861
- }
1862
- },
1863
- [columns, data, dataSource, getSelectedRows, showContextMenu]
1864
- );
1865
- return onContextMenu;
1866
- };
1867
-
1868
- // src/useTableModel.ts
1869
- import {
1870
- applyFilterToColumns,
1871
- applyGroupByToColumns,
1872
- applySortToColumns,
1873
- existingSort,
1874
- getCellRenderer,
1875
- getColumnHeaderContentRenderer,
1876
- getColumnHeaderLabelRenderer,
1877
- getColumnLabel,
1878
- getTableHeadings,
1879
- getValueFormatter,
1880
- hasValidationRules,
1881
- isFilteredColumn,
1882
- isGroupColumn as isGroupColumn3,
1883
- isPinned,
1884
- logger,
1885
- removeSort,
1886
- replaceColumn,
1887
- sortPinnedColumns,
1888
- stripFilterFromColumns,
1889
- subscribedOnly
1890
- } from "@vuu-ui/vuu-utils";
1891
- import { buildValidationChecker } from "@vuu-ui/vuu-ui-controls";
1892
- import { useReducer } from "react";
1893
- var { info } = logger("useTableModel");
1894
- var DEFAULT_COLUMN_WIDTH = 100;
1895
- var columnWithoutDataType = ({ serverDataType }) => serverDataType === void 0;
1896
- var getDataType = (column, tableSchema) => {
1897
- const schemaColumn = tableSchema == null ? void 0 : tableSchema.columns.find(
1898
- ({ name }) => name === column.name
1899
- );
1900
- if (schemaColumn) {
1901
- return schemaColumn.serverDataType;
1902
- } else {
1903
- return column.serverDataType;
1904
- }
1905
- };
1906
- var numericTypes = ["int", "long", "double"];
1907
- var getDefaultAlignment = (serverDataType) => serverDataType === void 0 ? void 0 : numericTypes.includes(serverDataType) ? "right" : "left";
1908
- var isShowColumnSettings = (action) => action.type === "columnSettings";
1909
- var isShowTableSettings = (action) => action.type === "tableSettings";
1910
- var columnReducer = (state, action) => {
1911
- info == null ? void 0 : info(`TableModelReducer ${action.type}`);
1912
- switch (action.type) {
1913
- case "init":
1914
- return init(action);
1915
- case "moveColumn":
1916
- return moveColumn(state, action);
1917
- case "resizeColumn":
1918
- return resizeColumn(state, action);
1919
- case "setTableSchema":
1920
- return setTableSchema(state, action);
1921
- case "hideColumns":
1922
- return hideColumns(state, action);
1923
- case "showColumns":
1924
- return showColumns(state, action);
1925
- case "pinColumn":
1926
- return pinColumn2(state, action);
1927
- case "updateColumnProp":
1928
- return updateColumnProp(state, action);
1929
- case "tableConfig":
1930
- return updateTableConfig2(state, action);
1931
- default:
1932
- console.log(`unhandled action ${action.type}`);
1933
- return state;
1934
- }
1935
- };
1936
- var useTableModel = (tableConfigProp, dataSource) => {
1937
- const [state, dispatchTableModelAction] = useReducer(columnReducer, { tableConfig: tableConfigProp, dataSource }, init);
1938
- const { columns, headings, tableConfig, ...tableAttributes } = state;
1939
- return {
1940
- columns,
1941
- dispatchTableModelAction,
1942
- headings,
1943
- tableAttributes,
1944
- tableConfig
1945
- };
1946
- };
1947
- function init({ dataSource, tableConfig }) {
1948
- const { columns, ...tableAttributes } = tableConfig;
1949
- const { config: dataSourceConfig, tableSchema } = dataSource;
1950
- const runtimeColumns = columns.filter(subscribedOnly(dataSourceConfig == null ? void 0 : dataSourceConfig.columns)).map(
1951
- columnDescriptorToRuntimeColumDescriptor(tableAttributes, tableSchema)
1952
- );
1953
- const maybePinnedColumns = runtimeColumns.some(isPinned) ? sortPinnedColumns(runtimeColumns) : runtimeColumns;
1954
- let state = {
1955
- columns: maybePinnedColumns,
1956
- headings: getTableHeadings(maybePinnedColumns),
1957
- tableConfig,
1958
- ...tableAttributes
1959
- };
1960
- if (dataSourceConfig) {
1961
- const { columns: _, ...rest } = dataSourceConfig;
1962
- state = updateTableConfig2(state, {
1963
- type: "tableConfig",
1964
- ...rest
1965
- });
1966
- }
1967
- return state;
1968
- }
1969
- var getLabel = (label, columnFormatHeader) => {
1970
- if (columnFormatHeader === "uppercase") {
1971
- return label.toUpperCase();
1972
- } else if (columnFormatHeader === "capitalize") {
1973
- return label[0].toUpperCase() + label.slice(1).toLowerCase();
1974
- }
1975
- return label;
1976
- };
1977
- var columnDescriptorToRuntimeColumDescriptor = (tableAttributes, tableSchema) => (column, index) => {
1978
- const { columnDefaultWidth = DEFAULT_COLUMN_WIDTH, columnFormatHeader } = tableAttributes;
1979
- const serverDataType = getDataType(column, tableSchema);
1980
- const {
1981
- align = getDefaultAlignment(serverDataType),
1982
- name,
1983
- label = getColumnLabel(column),
1984
- width = columnDefaultWidth,
1985
- ...rest
1986
- } = column;
1987
- const runtimeColumnWithDefaults = {
1988
- ...rest,
1989
- align,
1990
- CellRenderer: getCellRenderer(column),
1991
- HeaderCellContentRenderer: getColumnHeaderContentRenderer(column),
1992
- HeaderCellLabelRenderer: getColumnHeaderLabelRenderer(column),
1993
- clientSideEditValidationCheck: hasValidationRules(column.type) ? buildValidationChecker(column.type.renderer.rules) : void 0,
1994
- index: index + 1,
1995
- label: getLabel(label, columnFormatHeader),
1996
- name,
1997
- originalIdx: index,
1998
- serverDataType,
1999
- valueFormatter: getValueFormatter(column, serverDataType),
2000
- width
2001
- };
2002
- if (isGroupColumn3(runtimeColumnWithDefaults)) {
2003
- runtimeColumnWithDefaults.columns = runtimeColumnWithDefaults.columns.map(
2004
- (col) => columnDescriptorToRuntimeColumDescriptor(tableAttributes)(col, index)
2005
- );
2006
- }
2007
- return runtimeColumnWithDefaults;
2008
- };
2009
- function moveColumn(state, { column, moveBy }) {
2010
- const { columns } = state;
2011
- if (typeof moveBy === "number") {
2012
- const idx = columns.indexOf(column);
2013
- const newColumns = columns.slice();
2014
- const [movedColumns] = newColumns.splice(idx, 1);
2015
- newColumns.splice(idx + moveBy, 0, movedColumns);
2016
- return {
2017
- ...state,
2018
- columns: newColumns
2019
- };
2020
- }
2021
- return state;
2022
- }
2023
- function hideColumns(state, { columns }) {
2024
- if (columns.some((col) => col.hidden !== true)) {
2025
- return columns.reduce((s, c) => {
2026
- if (c.hidden !== true) {
2027
- return updateColumnProp(s, {
2028
- type: "updateColumnProp",
2029
- column: c,
2030
- hidden: true
2031
- });
2032
- } else {
2033
- return s;
2034
- }
2035
- }, state);
2036
- } else {
2037
- return state;
2038
- }
2039
- }
2040
- function showColumns(state, { columns }) {
2041
- if (columns.some((col) => col.hidden)) {
2042
- return columns.reduce((s, c) => {
2043
- if (c.hidden) {
2044
- return updateColumnProp(s, {
2045
- type: "updateColumnProp",
2046
- column: c,
2047
- hidden: false
2048
- });
2049
- } else {
2050
- return s;
2051
- }
2052
- }, state);
2053
- } else {
2054
- return state;
2055
- }
2056
- }
2057
- function resizeColumn(state, { column, phase, width }) {
2058
- const type = "updateColumnProp";
2059
- const resizing = phase !== "end";
2060
- switch (phase) {
2061
- case "begin":
2062
- return updateColumnProp(state, { type, column, resizing });
2063
- case "end":
2064
- return updateColumnProp(state, { type, column, resizing, width });
2065
- case "resize":
2066
- return updateColumnProp(state, { type, column, width });
2067
- default:
2068
- throw Error(`useTableModel.resizeColumn, invalid resizePhase ${phase}`);
2069
- }
2070
- }
2071
- function setTableSchema(state, { tableSchema }) {
2072
- const { columns } = state;
2073
- if (columns.some(columnWithoutDataType)) {
2074
- const cols = columns.map((column) => {
2075
- var _a;
2076
- const serverDataType = getDataType(column, tableSchema);
2077
- return {
2078
- ...column,
2079
- align: (_a = column.align) != null ? _a : getDefaultAlignment(serverDataType),
2080
- serverDataType
2081
- };
2082
- });
2083
- return {
2084
- ...state,
2085
- columns: cols
2086
- };
2087
- } else {
2088
- return state;
2089
- }
2090
- }
2091
- function pinColumn2(state, action) {
2092
- let { columns } = state;
2093
- const { column, pin } = action;
2094
- const targetColumn = columns.find((col) => col.name === column.name);
2095
- if (targetColumn) {
2096
- columns = replaceColumn(columns, { ...targetColumn, pin });
2097
- columns = sortPinnedColumns(columns);
2098
- return {
2099
- ...state,
2100
- columns
2101
- };
2102
- } else {
2103
- return state;
2104
- }
2105
- }
2106
- function updateColumnProp(state, action) {
2107
- let { columns, tableConfig } = state;
2108
- const { align, column, hidden, label, resizing, width } = action;
2109
- const targetColumn = columns.find((col) => col.name === column.name);
2110
- if (targetColumn) {
2111
- if (align === "left" || align === "right") {
2112
- columns = replaceColumn(columns, { ...targetColumn, align });
2113
- }
2114
- if (typeof label === "string") {
2115
- columns = replaceColumn(columns, { ...targetColumn, label });
2116
- }
2117
- if (typeof resizing === "boolean") {
2118
- columns = replaceColumn(columns, { ...targetColumn, resizing });
2119
- }
2120
- if (typeof hidden === "boolean") {
2121
- columns = replaceColumn(columns, { ...targetColumn, hidden });
2122
- }
2123
- if (typeof width === "number") {
2124
- columns = replaceColumn(columns, { ...targetColumn, width });
2125
- const targetConfigColumn = tableConfig.columns.find(
2126
- (col) => col.name === column.name
2127
- );
2128
- if (targetConfigColumn) {
2129
- tableConfig = {
2130
- ...tableConfig,
2131
- columns: replaceColumn(tableConfig.columns, {
2132
- ...targetConfigColumn,
2133
- width
2134
- })
2135
- };
2136
- }
2137
- }
2138
- }
2139
- return {
2140
- ...state,
2141
- columns,
2142
- tableConfig
2143
- };
2144
- }
2145
- function updateTableConfig2(state, { confirmed, filter, groupBy, sort }) {
2146
- const hasGroupBy = groupBy !== void 0;
2147
- const hasFilter = typeof (filter == null ? void 0 : filter.filter) === "string";
2148
- const hasSort = sort && sort.sortDefs.length > 0;
2149
- let result = state;
2150
- if (hasGroupBy) {
2151
- result = {
2152
- ...state,
2153
- columns: applyGroupByToColumns(result.columns, groupBy, confirmed)
2154
- };
2155
- }
2156
- if (hasSort) {
2157
- result = {
2158
- ...state,
2159
- columns: applySortToColumns(result.columns, sort)
2160
- };
2161
- } else if (existingSort(result.columns)) {
2162
- result = {
2163
- ...state,
2164
- columns: removeSort(result.columns)
2165
- };
2166
- }
2167
- if (hasFilter) {
2168
- result = {
2169
- ...state,
2170
- columns: applyFilterToColumns(result.columns, filter)
2171
- };
2172
- } else if (result.columns.some(isFilteredColumn)) {
2173
- result = {
2174
- ...state,
2175
- columns: stripFilterFromColumns(result.columns)
2176
- };
2177
- }
2178
- return result;
2179
- }
2180
-
2181
- // src/useTableScroll.ts
2182
- import {
2183
- getColumnsInViewport,
2184
- getRowElementAtIndex as getRowElementAtIndex2,
2185
- itemsChanged
2186
- } from "@vuu-ui/vuu-utils";
2187
- import {
2188
- useCallback as useCallback15,
2189
- useEffect as useEffect3,
2190
- useImperativeHandle,
2191
- useMemo as useMemo5,
2192
- useRef as useRef10,
2193
- useState as useState4
2194
- } from "react";
2195
- var SCROLL_MOVE_CHECK_THRESHOLD = 100;
2196
- var HORIZONTAL_SCROLL_BUFFER = 200;
2197
- var getMaxScroll = (container) => {
2198
- const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;
2199
- return [scrollWidth - clientWidth, scrollHeight - clientHeight];
2200
- };
2201
- var getScrollDirection = (prevScrollPositions, scrollPos) => {
2202
- if (prevScrollPositions === void 0) {
2203
- return void 0;
2204
- } else {
2205
- const { scrollTop: prevTop } = prevScrollPositions;
2206
- return scrollPos > prevTop ? "fwd" : "bwd";
2207
- }
2208
- };
2209
- var getPctScroll = (container, currentScrollPos) => {
2210
- const {
2211
- clientHeight,
2212
- clientWidth,
2213
- scrollHeight,
2214
- scrollLeft,
2215
- scrollTop,
2216
- scrollWidth
2217
- } = container;
2218
- const maxScrollLeft = scrollWidth - clientWidth;
2219
- const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);
2220
- const maxScrollTop = scrollHeight - clientHeight;
2221
- let pctScrollTop = scrollTop / (scrollHeight - clientHeight);
2222
- const scrollDirection = getScrollDirection(currentScrollPos, scrollTop);
2223
- if (scrollDirection === "fwd" && pctScrollTop > 0.99) {
2224
- pctScrollTop = 1;
2225
- } else if (scrollDirection === "bwd" && pctScrollTop < 0.02) {
2226
- pctScrollTop = 0;
2227
- }
2228
- return [
2229
- scrollLeft,
2230
- pctScrollLeft,
2231
- maxScrollLeft,
2232
- scrollTop,
2233
- pctScrollTop,
2234
- maxScrollTop
2235
- ];
2236
- };
2237
- var noScrolling = {
2238
- scrollToIndex: () => void 0,
2239
- scrollToKey: () => void 0
2240
- };
2241
- var useCallbackRef = ({
2242
- onAttach,
2243
- onDetach
2244
- }) => {
2245
- const ref = useRef10(null);
2246
- const callbackRef = useCallback15(
2247
- (el) => {
2248
- if (el) {
2249
- ref.current = el;
2250
- onAttach == null ? void 0 : onAttach(el);
2251
- } else if (ref.current) {
2252
- const { current: originalRef } = ref;
2253
- ref.current = el;
2254
- onDetach == null ? void 0 : onDetach(originalRef);
2255
- }
2256
- },
2257
- [onAttach, onDetach]
2258
- );
2259
- return callbackRef;
2260
- };
2261
- var useTableScroll = ({
2262
- columns,
2263
- getRowAtPosition,
2264
- onHorizontalScroll,
2265
- onVerticalScroll,
2266
- onVerticalScrollInSitu,
2267
- rowHeight,
2268
- scrollingApiRef,
2269
- setRange,
2270
- viewportMeasurements
2271
- }) => {
2272
- const firstRowRef = useRef10(0);
2273
- const rowHeightRef = useRef10(rowHeight);
2274
- const contentContainerScrolledRef = useRef10(false);
2275
- const contentContainerPosRef = useRef10({
2276
- scrollTop: 0,
2277
- scrollLeft: 0
2278
- });
2279
- const scrollbarContainerScrolledRef = useRef10(false);
2280
- const scrollbarContainerPosRef = useRef10({
2281
- scrollTop: 0,
2282
- scrollLeft: 0
2283
- });
2284
- const scrollbarContainerRef = useRef10(null);
2285
- const contentContainerRef = useRef10(null);
2286
- const lastHorizontalScrollCheckPoint = useRef10(0);
2287
- const {
2288
- appliedPageSize,
2289
- isVirtualScroll,
2290
- rowCount: viewportRowCount,
2291
- totalHeaderHeight,
2292
- viewportWidth
2293
- } = viewportMeasurements;
2294
- const columnsWithinViewportRef = useRef10([]);
2295
- const [, forceRefresh] = useState4({});
2296
- const preSpanRef = useRef10(0);
2297
- useMemo5(() => {
2298
- const [visibleColumns, offset] = getColumnsInViewport(
2299
- columns,
2300
- contentContainerPosRef.current.scrollLeft,
2301
- contentContainerPosRef.current.scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER
2302
- );
2303
- preSpanRef.current = offset;
2304
- columnsWithinViewportRef.current = visibleColumns;
2305
- }, [viewportWidth, columns]);
2306
- const handleHorizontalScroll = useCallback15(
2307
- (scrollLeft) => {
2308
- contentContainerPosRef.current.scrollLeft = scrollLeft;
2309
- onHorizontalScroll == null ? void 0 : onHorizontalScroll(scrollLeft);
2310
- if (Math.abs(scrollLeft - lastHorizontalScrollCheckPoint.current) > SCROLL_MOVE_CHECK_THRESHOLD) {
2311
- lastHorizontalScrollCheckPoint.current = scrollLeft;
2312
- const [visibleColumns, pre] = getColumnsInViewport(
2313
- columns,
2314
- scrollLeft,
2315
- scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER
2316
- );
2317
- if (itemsChanged(columnsWithinViewportRef.current, visibleColumns)) {
2318
- preSpanRef.current = pre;
2319
- columnsWithinViewportRef.current = visibleColumns;
2320
- forceRefresh({});
2321
- }
2322
- }
2323
- },
2324
- [columns, onHorizontalScroll, viewportWidth]
2325
- );
2326
- const handleVerticalScroll = useCallback15(
2327
- (scrollTop, pctScrollTop) => {
2328
- contentContainerPosRef.current.scrollTop = scrollTop;
2329
- onVerticalScroll == null ? void 0 : onVerticalScroll(scrollTop, pctScrollTop);
2330
- const firstRow = getRowAtPosition(scrollTop);
2331
- if (firstRow !== firstRowRef.current) {
2332
- firstRowRef.current = firstRow;
2333
- setRange({ from: firstRow, to: firstRow + viewportRowCount });
2334
- }
2335
- onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(0);
2336
- },
2337
- [
2338
- getRowAtPosition,
2339
- onVerticalScroll,
2340
- onVerticalScrollInSitu,
2341
- setRange,
2342
- viewportRowCount
2343
- ]
2344
- );
2345
- const handleScrollbarContainerScroll = useCallback15(() => {
2346
- const { current: contentContainer } = contentContainerRef;
2347
- const { current: scrollbarContainer } = scrollbarContainerRef;
2348
- const { current: contentContainerScrolled } = contentContainerScrolledRef;
2349
- const { current: scrollPos } = scrollbarContainerPosRef;
2350
- if (contentContainerScrolled) {
2351
- contentContainerScrolledRef.current = false;
2352
- } else if (contentContainer && scrollbarContainer) {
2353
- scrollbarContainerScrolledRef.current = true;
2354
- const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] = getPctScroll(scrollbarContainer, scrollPos);
2355
- scrollPos.scrollLeft = scrollLeft;
2356
- scrollPos.scrollTop = scrollTop;
2357
- const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer);
2358
- const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft);
2359
- const contentScrollTop = pctScrollTop * maxScrollTop;
2360
- contentContainer.scrollTo({
2361
- left: contentScrollLeft,
2362
- top: contentScrollTop,
2363
- behavior: "auto"
2364
- });
2365
- }
2366
- onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(0);
2367
- }, [onVerticalScrollInSitu]);
2368
- const handleContentContainerScroll = useCallback15(() => {
2369
- const { current: scrollbarContainerScrolled } = scrollbarContainerScrolledRef;
2370
- const { current: contentContainer } = contentContainerRef;
2371
- const { current: scrollbarContainer } = scrollbarContainerRef;
2372
- const { current: scrollPos } = contentContainerPosRef;
2373
- if (contentContainer && scrollbarContainer) {
2374
- const [
2375
- scrollLeft,
2376
- pctScrollLeft,
2377
- maxScrollLeft,
2378
- scrollTop,
2379
- pctScrollTop,
2380
- maxScrollTop
2381
- ] = getPctScroll(contentContainer);
2382
- contentContainerScrolledRef.current = true;
2383
- if (scrollbarContainerScrolled) {
2384
- scrollbarContainerScrolledRef.current = false;
2385
- } else {
2386
- scrollbarContainer.scrollLeft = Math.round(
2387
- pctScrollLeft * maxScrollLeft
2388
- );
2389
- scrollbarContainer.scrollTop = pctScrollTop * maxScrollTop;
2390
- }
2391
- if (scrollPos.scrollTop !== scrollTop) {
2392
- handleVerticalScroll(scrollTop, pctScrollTop);
2393
- }
2394
- if (scrollPos.scrollLeft !== scrollLeft) {
2395
- handleHorizontalScroll(scrollLeft);
2396
- }
2397
- }
2398
- }, [handleVerticalScroll, handleHorizontalScroll]);
2399
- const handleAttachScrollbarContainer = useCallback15(
2400
- (el) => {
2401
- scrollbarContainerRef.current = el;
2402
- el.addEventListener("scroll", handleScrollbarContainerScroll, {
2403
- passive: true
2404
- });
2405
- },
2406
- [handleScrollbarContainerScroll]
2407
- );
2408
- const handleDetachScrollbarContainer = useCallback15(
2409
- (el) => {
2410
- scrollbarContainerRef.current = null;
2411
- el.removeEventListener("scroll", handleScrollbarContainerScroll);
2412
- },
2413
- [handleScrollbarContainerScroll]
2414
- );
2415
- const handleAttachContentContainer = useCallback15(
2416
- (el) => {
2417
- contentContainerRef.current = el;
2418
- el.addEventListener("scroll", handleContentContainerScroll, {
2419
- passive: true
2420
- });
2421
- },
2422
- [handleContentContainerScroll]
2423
- );
2424
- const handleDetachContentContainer = useCallback15(
2425
- (el) => {
2426
- contentContainerRef.current = null;
2427
- el.removeEventListener("scroll", handleContentContainerScroll);
2428
- },
2429
- [handleContentContainerScroll]
2430
- );
2431
- const contentContainerCallbackRef = useCallbackRef({
2432
- onAttach: handleAttachContentContainer,
2433
- onDetach: handleDetachContentContainer
2434
- });
2435
- const scrollbarContainerCallbackRef = useCallbackRef({
2436
- onAttach: handleAttachScrollbarContainer,
2437
- onDetach: handleDetachScrollbarContainer
2438
- });
2439
- const requestScroll = useCallback15(
2440
- (scrollRequest) => {
2441
- const { current: contentContainer } = contentContainerRef;
2442
- if (contentContainer) {
2443
- const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer);
2444
- const { scrollLeft, scrollTop } = contentContainer;
2445
- contentContainerScrolledRef.current = false;
2446
- if (scrollRequest.type === "scroll-row") {
2447
- const activeRow = getRowElementAtIndex2(
2448
- contentContainer,
2449
- scrollRequest.rowIndex
2450
- );
2451
- if (activeRow !== null) {
2452
- const [direction, distance] = howFarIsRowOutsideViewport(
2453
- activeRow,
2454
- totalHeaderHeight
2455
- );
2456
- console.log(`outside viewport ? ${direction} ${distance}`);
2457
- if (direction && distance) {
2458
- if (isVirtualScroll) {
2459
- const offset = direction === "down" ? 1 : -1;
2460
- onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(offset);
2461
- const firstRow = firstRowRef.current + offset;
2462
- firstRowRef.current = firstRow;
2463
- setRange({
2464
- from: firstRow,
2465
- to: firstRow + viewportRowCount
2466
- });
2467
- } else {
2468
- let newScrollLeft = scrollLeft;
2469
- let newScrollTop = scrollTop;
2470
- if (direction === "up" || direction === "down") {
2471
- newScrollTop = Math.min(
2472
- Math.max(0, scrollTop + distance),
2473
- maxScrollTop
2474
- );
2475
- } else {
2476
- newScrollLeft = Math.min(
2477
- Math.max(0, scrollLeft + distance),
2478
- maxScrollLeft
2479
- );
2480
- }
2481
- contentContainer.scrollTo({
2482
- top: newScrollTop,
2483
- left: newScrollLeft,
2484
- behavior: "smooth"
2485
- });
2486
- }
2487
- }
2488
- }
2489
- } else if (scrollRequest.type === "scroll-page") {
2490
- const { direction } = scrollRequest;
2491
- if (isVirtualScroll) {
2492
- const offset = direction === "down" ? viewportRowCount : -viewportRowCount;
2493
- onVerticalScrollInSitu == null ? void 0 : onVerticalScrollInSitu(offset);
2494
- const firstRow = firstRowRef.current + offset;
2495
- firstRowRef.current = firstRow;
2496
- setRange({ from: firstRow, to: firstRow + viewportRowCount });
2497
- } else {
2498
- const scrollBy = direction === "down" ? appliedPageSize : -appliedPageSize;
2499
- const newScrollTop = Math.min(
2500
- Math.max(0, scrollTop + scrollBy),
2501
- maxScrollTop
2502
- );
2503
- contentContainer.scrollTo({
2504
- top: newScrollTop,
2505
- left: scrollLeft,
2506
- behavior: "auto"
2507
- });
2508
- }
2509
- } else if (scrollRequest.type === "scroll-end") {
2510
- const { direction } = scrollRequest;
2511
- const scrollTo = direction === "end" ? maxScrollTop : 0;
2512
- contentContainer.scrollTo({
2513
- top: scrollTo,
2514
- left: contentContainer.scrollLeft,
2515
- behavior: "auto"
2516
- });
2517
- }
2518
- }
2519
- },
2520
- [
2521
- appliedPageSize,
2522
- isVirtualScroll,
2523
- onVerticalScrollInSitu,
2524
- setRange,
2525
- totalHeaderHeight,
2526
- viewportRowCount
2527
- ]
2528
- );
2529
- const scrollHandles = useMemo5(
2530
- // TODO not complete yet
2531
- () => ({
2532
- scrollToIndex: (rowIndex) => {
2533
- if (scrollbarContainerRef.current) {
2534
- const scrollPos = (rowIndex - 30) * 20;
2535
- scrollbarContainerRef.current.scrollTop = scrollPos;
2536
- }
2537
- },
2538
- scrollToKey: (rowKey) => {
2539
- console.log(`scrollToKey ${rowKey}`);
2540
- }
2541
- }),
2542
- []
2543
- );
2544
- useImperativeHandle(
2545
- scrollingApiRef,
2546
- () => {
2547
- if (scrollbarContainerRef.current) {
2548
- return scrollHandles;
2549
- } else {
2550
- return noScrolling;
2551
- }
2552
- },
2553
- [scrollHandles]
2554
- );
2555
- useEffect3(() => {
2556
- if (rowHeight !== rowHeightRef.current) {
2557
- rowHeightRef.current = rowHeight;
2558
- if (contentContainerPosRef.current.scrollTop > 0) {
2559
- if (contentContainerRef.current) {
2560
- contentContainerRef.current.scrollTop = 0;
2561
- }
2562
- }
2563
- } else {
2564
- const { current: from } = firstRowRef;
2565
- const rowRange = { from, to: from + viewportRowCount };
2566
- setRange(rowRange);
2567
- }
2568
- }, [rowHeight, setRange, viewportRowCount]);
2569
- return {
2570
- columnsWithinViewport: columnsWithinViewportRef.current,
2571
- /** Ref to be assigned to ScrollbarContainer */
2572
- scrollbarContainerRef: scrollbarContainerCallbackRef,
2573
- /** Ref to be assigned to ContentContainer */
2574
- contentContainerRef: contentContainerCallbackRef,
2575
- /** Scroll the table */
2576
- requestScroll,
2577
- /** number of leading columns not rendered because of virtualization */
2578
- virtualColSpan: preSpanRef.current
2579
- };
2580
- };
2581
-
2582
- // src/useTableViewport.ts
2583
- import {
2584
- actualRowPositioning,
2585
- measurePinnedColumns,
2586
- virtualRowPositioning
2587
- } from "@vuu-ui/vuu-utils";
2588
- import { useCallback as useCallback16, useMemo as useMemo6, useRef as useRef11 } from "react";
2589
- var MAX_PIXEL_HEIGHT = 1e7;
2590
- var UNMEASURED_VIEWPORT = {
2591
- appliedPageSize: 0,
2592
- contentHeight: 0,
2593
- contentWidth: 0,
2594
- getRowAtPosition: () => -1,
2595
- getRowOffset: () => -1,
2596
- horizontalScrollbarHeight: 0,
2597
- isVirtualScroll: false,
2598
- pinnedWidthLeft: 0,
2599
- pinnedWidthRight: 0,
2600
- rowCount: 0,
2601
- setInSituRowOffset: () => void 0,
2602
- setScrollTop: () => void 0,
2603
- totalHeaderHeight: 0,
2604
- verticalScrollbarWidth: 0,
2605
- viewportBodyHeight: 0,
2606
- viewportWidth: 0
2607
- };
2608
- var useTableViewport = ({
2609
- columns,
2610
- headerHeight,
2611
- headings,
2612
- rowCount,
2613
- rowHeight,
2614
- selectionEndSize = 4,
2615
- size
2616
- }) => {
2617
- const inSituRowOffsetRef = useRef11(0);
2618
- const pctScrollTopRef = useRef11(0);
2619
- const pixelContentHeight = Math.min(rowHeight * rowCount, MAX_PIXEL_HEIGHT);
2620
- const virtualContentHeight = rowCount * rowHeight;
2621
- const virtualisedExtent = virtualContentHeight - pixelContentHeight;
2622
- const { pinnedWidthLeft, pinnedWidthRight, unpinnedWidth } = useMemo6(
2623
- () => measurePinnedColumns(columns, selectionEndSize),
2624
- [columns, selectionEndSize]
2625
- );
2626
- const totalHeaderHeightRef = useRef11(headerHeight);
2627
- useMemo6(() => {
2628
- totalHeaderHeightRef.current = headerHeight * (1 + headings.length);
2629
- }, [headerHeight, headings.length]);
2630
- const [getRowOffset, getRowAtPosition, isVirtualScroll] = useMemo6(() => {
2631
- if (virtualisedExtent) {
2632
- const [_getRowOffset, getRowAtPosition2, _isVirtual] = virtualRowPositioning(rowHeight, virtualisedExtent, pctScrollTopRef);
2633
- const getOffset = (row) => {
2634
- return _getRowOffset(row, inSituRowOffsetRef.current);
2635
- };
2636
- return [getOffset, getRowAtPosition2, _isVirtual];
2637
- } else {
2638
- return actualRowPositioning(rowHeight);
2639
- }
2640
- }, [virtualisedExtent, rowHeight]);
2641
- const setScrollTop = useCallback16((_, scrollPct) => {
2642
- pctScrollTopRef.current = scrollPct;
2643
- }, []);
2644
- const setInSituRowOffset = useCallback16((rowIndexOffset) => {
2645
- if (rowIndexOffset === 0) {
2646
- inSituRowOffsetRef.current = 0;
2647
- } else {
2648
- inSituRowOffsetRef.current = Math.max(
2649
- 0,
2650
- inSituRowOffsetRef.current + rowIndexOffset
2651
- );
2652
- }
2653
- }, []);
2654
- return useMemo6(() => {
2655
- if (size) {
2656
- const { current: totalHeaderHeight } = totalHeaderHeightRef;
2657
- const scrollbarSize = 15;
2658
- const contentWidth = pinnedWidthLeft + unpinnedWidth + pinnedWidthRight;
2659
- const horizontalScrollbarHeight = contentWidth > size.width ? scrollbarSize : 0;
2660
- const visibleRows = (size.height - headerHeight) / rowHeight;
2661
- const count = Number.isInteger(visibleRows) ? visibleRows : Math.ceil(visibleRows);
2662
- const viewportBodyHeight = size.height - totalHeaderHeight;
2663
- const verticalScrollbarWidth = pixelContentHeight > viewportBodyHeight ? scrollbarSize : 0;
2664
- const appliedPageSize = count * rowHeight * (pixelContentHeight / virtualContentHeight);
2665
- const viewportWidth = size.width;
2666
- return {
2667
- appliedPageSize,
2668
- contentHeight: pixelContentHeight,
2669
- contentWidth,
2670
- getRowAtPosition,
2671
- getRowOffset,
2672
- isVirtualScroll,
2673
- horizontalScrollbarHeight,
2674
- pinnedWidthLeft,
2675
- pinnedWidthRight,
2676
- rowCount: count,
2677
- setInSituRowOffset,
2678
- setScrollTop,
2679
- totalHeaderHeight,
2680
- verticalScrollbarWidth,
2681
- viewportBodyHeight,
2682
- viewportWidth
2683
- };
2684
- } else {
2685
- return UNMEASURED_VIEWPORT;
2686
- }
2687
- }, [
2688
- getRowAtPosition,
2689
- getRowOffset,
2690
- headerHeight,
2691
- isVirtualScroll,
2692
- pinnedWidthLeft,
2693
- unpinnedWidth,
2694
- pinnedWidthRight,
2695
- pixelContentHeight,
2696
- rowHeight,
2697
- setInSituRowOffset,
2698
- setScrollTop,
2699
- size,
2700
- virtualContentHeight
2701
- ]);
2702
- };
2703
-
2704
- // src/useTableAndColumnSettings.ts
2705
- import { useLayoutProviderDispatch } from "@vuu-ui/vuu-layout";
2706
- import { getCalculatedColumnType } from "@vuu-ui/vuu-utils";
2707
- import { useCallback as useCallback17, useRef as useRef12, useState as useState5 } from "react";
2708
- var useTableAndColumnSettings = ({
2709
- availableColumns: availableColumnsProps,
2710
- onAvailableColumnsChange,
2711
- onConfigChange,
2712
- onCreateCalculatedColumn,
2713
- onDataSourceConfigChange,
2714
- tableConfig
2715
- }) => {
2716
- const dispatchLayoutAction = useLayoutProviderDispatch();
2717
- const showTableSettingsRef = useRef12();
2718
- const [availableColumns, setAvailableColumns] = useState5(
2719
- availableColumnsProps
2720
- );
2721
- const showContextPanel = useCallback17(
2722
- (componentType, title, props) => {
2723
- dispatchLayoutAction({
2724
- type: "set-props",
2725
- path: "#context-panel",
2726
- props: {
2727
- expanded: true,
2728
- content: {
2729
- type: componentType,
2730
- props
2731
- },
2732
- title
2733
- }
2734
- });
2735
- },
2736
- [dispatchLayoutAction]
2737
- );
2738
- const handleCancelCreateColumn = useCallback17(() => {
2739
- requestAnimationFrame(() => {
2740
- var _a;
2741
- (_a = showTableSettingsRef.current) == null ? void 0 : _a.call(showTableSettingsRef);
2742
- });
2743
- }, []);
2744
- const handleCreateCalculatedColumn = useCallback17(
2745
- (column) => {
2746
- const newAvailableColumns = availableColumns.concat({
2747
- name: column.name,
2748
- serverDataType: getCalculatedColumnType(column)
2749
- });
2750
- setAvailableColumns(newAvailableColumns);
2751
- onAvailableColumnsChange == null ? void 0 : onAvailableColumnsChange(newAvailableColumns);
2752
- requestAnimationFrame(() => {
2753
- var _a;
2754
- (_a = showTableSettingsRef.current) == null ? void 0 : _a.call(showTableSettingsRef);
2755
- });
2756
- onCreateCalculatedColumn(column);
2757
- },
2758
- [availableColumns, onAvailableColumnsChange, onCreateCalculatedColumn]
2759
- );
2760
- const showColumnSettingsPanel = useCallback17(
2761
- (action) => {
2762
- showContextPanel("ColumnSettings", "Column Settings", {
2763
- column: action.column,
2764
- onCancelCreateColumn: handleCancelCreateColumn,
2765
- onConfigChange,
2766
- onCreateCalculatedColumn: handleCreateCalculatedColumn,
2767
- tableConfig,
2768
- vuuTable: action.vuuTable
2769
- });
2770
- },
2771
- [
2772
- handleCancelCreateColumn,
2773
- handleCreateCalculatedColumn,
2774
- onConfigChange,
2775
- showContextPanel,
2776
- tableConfig
2777
- ]
2778
- );
2779
- const handleAddCalculatedColumn = useCallback17(() => {
2780
- showColumnSettingsPanel({
2781
- column: {
2782
- name: "::",
2783
- serverDataType: "string"
2784
- },
2785
- type: "columnSettings",
2786
- vuuTable: { module: "SIMUL", table: "instruments" }
2787
- });
2788
- }, [showColumnSettingsPanel]);
2789
- const handleNavigateToColumn = useCallback17(
2790
- (columnName) => {
2791
- const column = tableConfig.columns.find((c) => c.name === columnName);
2792
- if (column) {
2793
- showColumnSettingsPanel({
2794
- type: "columnSettings",
2795
- column,
2796
- //TODO where do we get this from
2797
- vuuTable: { module: "SIMUL", table: "instruments" }
2798
- });
2799
- }
2800
- },
2801
- [showColumnSettingsPanel, tableConfig.columns]
2802
- );
2803
- showTableSettingsRef.current = useCallback17(() => {
2804
- showContextPanel("TableSettings", "DataGrid Settings", {
2805
- availableColumns: availableColumns != null ? availableColumns : tableConfig.columns.map(({ name, serverDataType }) => ({
2806
- name,
2807
- serverDataType
2808
- })),
2809
- onAddCalculatedColumn: handleAddCalculatedColumn,
2810
- onConfigChange,
2811
- onDataSourceConfigChange,
2812
- onNavigateToColumn: handleNavigateToColumn,
2813
- tableConfig
2814
- });
2815
- }, [
2816
- availableColumns,
2817
- handleAddCalculatedColumn,
2818
- handleNavigateToColumn,
2819
- onConfigChange,
2820
- onDataSourceConfigChange,
2821
- showContextPanel,
2822
- tableConfig
2823
- ]);
2824
- return {
2825
- showColumnSettingsPanel,
2826
- showTableSettingsPanel: showTableSettingsRef.current
2827
- };
2828
- };
2829
-
2830
- // src/useRowClassNameGenerators.ts
2831
- import {
2832
- getRowClassNameGenerator
2833
- } from "@vuu-ui/vuu-utils";
2834
- import { useMemo as useMemo7 } from "react";
2835
- var createClassNameGenerator = (ids) => {
2836
- const functions = [];
2837
- ids == null ? void 0 : ids.forEach((id) => {
2838
- const fn = getRowClassNameGenerator(id);
2839
- if (fn) {
2840
- functions.push(fn.fn);
2841
- }
2842
- });
2843
- return (row, columnMap) => {
2844
- const classNames = [];
2845
- functions == null ? void 0 : functions.forEach((fn) => {
2846
- const className = fn(row, columnMap);
2847
- if (className) {
2848
- classNames.push(className);
2849
- }
2850
- });
2851
- return classNames.join(" ");
2852
- };
2853
- };
2854
- var useRowClassNameGenerators = ({
2855
- rowClassNameGenerators
2856
- }) => {
2857
- return useMemo7(() => {
2858
- return createClassNameGenerator(rowClassNameGenerators);
2859
- }, [rowClassNameGenerators]);
2860
- };
2861
-
2862
- // src/useTable.ts
2863
- var stripInternalProperties = (tableConfig) => {
2864
- return tableConfig;
2865
- };
2866
- var { KEY, IS_EXPANDED: IS_EXPANDED2, IS_LEAF: IS_LEAF2 } = metadataKeys5;
2867
- var NULL_DRAG_DROP = {
2868
- draggable: void 0,
2869
- onMouseDown: void 0
2870
- };
2871
- var useNullDragDrop = () => NULL_DRAG_DROP;
2872
- var addColumn = (tableConfig, column) => ({
2873
- ...tableConfig,
2874
- columns: tableConfig.columns.concat(column)
2875
- });
2876
- var useTable = ({
2877
- allowDragDrop = false,
2878
- availableColumns,
2879
- config,
2880
- containerRef,
2881
- dataSource,
2882
- disableFocus,
2883
- headerHeight = 25,
2884
- highlightedIndex: highlightedIndexProp,
2885
- id,
2886
- navigationStyle = "cell",
2887
- onAvailableColumnsChange,
2888
- onConfigChange,
2889
- onDragStart,
2890
- onDrop,
2891
- onFeatureInvocation,
2892
- onHighlight,
2893
- onRowClick: onRowClickProp,
2894
- onSelect,
2895
- onSelectionChange,
2896
- renderBufferSize = 0,
2897
- rowHeight = 20,
2898
- scrollingApiRef,
2899
- selectionModel,
2900
- size
2901
- }) => {
2902
- const [rowCount, setRowCount] = useState6(dataSource.size);
2903
- if (dataSource === void 0) {
2904
- throw Error("no data source provided to Vuu Table");
2905
- }
2906
- const rowClassNameGenerator = useRowClassNameGenerators(config);
2907
- const useRowDragDrop = allowDragDrop ? useDragDrop2 : useNullDragDrop;
2908
- const menuBuilder = useMemo8(
2909
- () => buildContextMenuDescriptors(dataSource),
2910
- [dataSource]
2911
- );
2912
- const onDataRowcountChange = useCallback18((size2) => {
2913
- setRowCount(size2);
2914
- }, []);
2915
- const {
2916
- columns,
2917
- dispatchTableModelAction,
2918
- headings,
2919
- tableAttributes,
2920
- tableConfig
2921
- } = useTableModel(config, dataSource);
2922
- useLayoutEffectSkipFirst2(() => {
2923
- dispatchTableModelAction({
2924
- type: "init",
2925
- tableConfig: config,
2926
- dataSource
2927
- });
2928
- }, [config, dataSource, dispatchTableModelAction]);
2929
- const applyTableConfigChange = useCallback18(
2930
- (config2) => {
2931
- dispatchTableModelAction({
2932
- type: "init",
2933
- tableConfig: config2,
2934
- dataSource
2935
- });
2936
- onConfigChange == null ? void 0 : onConfigChange(stripInternalProperties(config2));
2937
- },
2938
- [dataSource, dispatchTableModelAction, onConfigChange]
2939
- );
2940
- const columnMap = useMemo8(
2941
- () => buildColumnMap2(dataSource.columns),
2942
- [dataSource.columns]
2943
- );
2944
- const onSubscribed = useCallback18(
2945
- ({ tableSchema }) => {
2946
- if (tableSchema) {
2947
- dispatchTableModelAction({
2948
- type: "setTableSchema",
2949
- tableSchema
2950
- });
2951
- } else {
2952
- console.log("subscription message with no schema");
2953
- }
2954
- },
2955
- [dispatchTableModelAction]
2956
- );
2957
- const {
2958
- getRowAtPosition,
2959
- getRowOffset,
2960
- setInSituRowOffset: viewportHookSetInSituRowOffset,
2961
- setScrollTop: viewportHookSetScrollTop,
2962
- ...viewportMeasurements
2963
- } = useTableViewport({
2964
- columns,
2965
- headerHeight,
2966
- headings,
2967
- rowCount,
2968
- rowHeight,
2969
- size
2970
- });
2971
- const initialRange = useInitialValue({
2972
- from: 0,
2973
- to: viewportMeasurements.rowCount
2974
- });
2975
- const { data, dataRef, getSelectedRows, range, setRange } = useDataSource({
2976
- dataSource,
2977
- // We need to factor this out of Table
2978
- onFeatureInvocation,
2979
- renderBufferSize,
2980
- onSizeChange: onDataRowcountChange,
2981
- onSubscribed,
2982
- range: initialRange
2983
- });
2984
- const { requestScroll, ...scrollProps } = useTableScroll({
2985
- columns,
2986
- getRowAtPosition,
2987
- rowHeight,
2988
- scrollingApiRef,
2989
- setRange,
2990
- onVerticalScroll: viewportHookSetScrollTop,
2991
- onVerticalScrollInSitu: viewportHookSetInSituRowOffset,
2992
- viewportMeasurements
2993
- });
2994
- const handleConfigEditedInSettingsPanel = useCallback18(
2995
- (tableConfig2) => {
2996
- dispatchTableModelAction({
2997
- type: "init",
2998
- tableConfig: tableConfig2,
2999
- dataSource
3000
- });
3001
- onConfigChange == null ? void 0 : onConfigChange(stripInternalProperties(tableConfig2));
3002
- },
3003
- [dataSource, dispatchTableModelAction, onConfigChange]
3004
- );
3005
- const handleDataSourceConfigChanged = useCallback18(
3006
- (dataSourceConfig) => {
3007
- dataSource.config = {
3008
- ...dataSource.config,
3009
- ...dataSourceConfig
3010
- };
3011
- },
3012
- [dataSource]
3013
- );
3014
- useEffect4(() => {
3015
- dataSource.on("config", (config2, confirmed, changes) => {
3016
- const scrollSensitiveChanges = (changes == null ? void 0 : changes.filterChanged) || (changes == null ? void 0 : changes.groupByChanged);
3017
- if (scrollSensitiveChanges && dataSource.range.from > 0) {
3018
- requestScroll({
3019
- type: "scroll-end",
3020
- direction: "home"
3021
- });
3022
- }
3023
- dispatchTableModelAction({
3024
- type: "tableConfig",
3025
- ...config2,
3026
- confirmed
3027
- });
3028
- });
3029
- }, [dataSource, dispatchTableModelAction, requestScroll]);
3030
- const handleCreateCalculatedColumn = useCallback18(
3031
- (column) => {
3032
- dataSource.columns = dataSource.columns.concat(column.name);
3033
- applyTableConfigChange(addColumn(tableConfig, column));
3034
- },
3035
- [dataSource, tableConfig, applyTableConfigChange]
3036
- );
3037
- const hideColumns2 = useCallback18(
3038
- (action) => {
3039
- const { columns: columns2 } = action;
3040
- const hiddenColumns = columns2.map((c) => c.name);
3041
- const newTableConfig = {
3042
- ...tableConfig,
3043
- columns: tableConfig.columns.map(
3044
- (col) => hiddenColumns.includes(col.name) ? { ...col, hidden: true } : col
3045
- )
3046
- };
3047
- applyTableConfigChange(newTableConfig);
3048
- },
3049
- [tableConfig, applyTableConfigChange]
3050
- );
3051
- const pinColumn3 = useCallback18(
3052
- (action) => {
3053
- applyTableConfigChange({
3054
- ...tableConfig,
3055
- columns: updateColumn(tableConfig.columns, {
3056
- ...action.column,
3057
- pin: action.pin
3058
- })
3059
- });
3060
- },
3061
- [tableConfig, applyTableConfigChange]
3062
- );
3063
- const { showColumnSettingsPanel, showTableSettingsPanel } = useTableAndColumnSettings({
3064
- availableColumns: availableColumns != null ? availableColumns : tableConfig.columns.map(({ name, serverDataType = "string" }) => ({
3065
- name,
3066
- serverDataType
3067
- })),
3068
- onAvailableColumnsChange,
3069
- onConfigChange: handleConfigEditedInSettingsPanel,
3070
- onCreateCalculatedColumn: handleCreateCalculatedColumn,
3071
- onDataSourceConfigChange: handleDataSourceConfigChanged,
3072
- tableConfig
3073
- });
3074
- const onPersistentColumnOperation = useCallback18(
3075
- (action) => {
3076
- if (isShowColumnSettings(action)) {
3077
- showColumnSettingsPanel(action);
3078
- } else if (isShowTableSettings(action)) {
3079
- showTableSettingsPanel();
3080
- } else {
3081
- switch (action.type) {
3082
- case "hideColumns":
3083
- return hideColumns2(action);
3084
- case "pinColumn":
3085
- return pinColumn3(action);
3086
- default:
3087
- dispatchTableModelAction(action);
3088
- }
3089
- }
3090
- },
3091
- [
3092
- dispatchTableModelAction,
3093
- hideColumns2,
3094
- pinColumn3,
3095
- showColumnSettingsPanel,
3096
- showTableSettingsPanel
3097
- ]
3098
- );
3099
- const handleContextMenuAction = useHandleTableContextMenu({
3100
- dataSource,
3101
- onPersistentColumnOperation
3102
- });
3103
- const handleSort = useCallback18(
3104
- (column, extendSort = false, sortType) => {
3105
- if (dataSource) {
3106
- dataSource.sort = toggleOrApplySort(
3107
- dataSource.sort,
3108
- column,
3109
- extendSort,
3110
- sortType
3111
- );
3112
- }
3113
- },
3114
- [dataSource]
3115
- );
3116
- const resizeCells = useRef13();
3117
- const onResizeColumn = useCallback18(
3118
- (phase, columnName, width) => {
3119
- var _a, _b, _c;
3120
- const column = columns.find((column2) => column2.name === columnName);
3121
- if (column) {
3122
- if (phase === "resize") {
3123
- (_a = resizeCells.current) == null ? void 0 : _a.forEach((cell) => {
3124
- cell.style.width = `${width}px`;
3125
- });
3126
- } else if (phase === "end") {
3127
- resizeCells.current = void 0;
3128
- if (isValidNumber(width)) {
3129
- dispatchTableModelAction({
3130
- type: "resizeColumn",
3131
- phase,
3132
- column,
3133
- width
3134
- });
3135
- onConfigChange == null ? void 0 : onConfigChange(
3136
- stripInternalProperties(
3137
- updateTableConfig(tableConfig, {
3138
- type: "col-size",
3139
- column,
3140
- width
3141
- })
3142
- )
3143
- );
3144
- }
3145
- } else {
3146
- const byColIndex = `[aria-colindex='${column.index}']`;
3147
- resizeCells.current = Array.from(
3148
- (_c = (_b = containerRef.current) == null ? void 0 : _b.querySelectorAll(
3149
- `.vuuTableCell${byColIndex},.vuuTableHeaderCell${byColIndex}`
3150
- )) != null ? _c : []
3151
- );
3152
- dispatchTableModelAction({
3153
- type: "resizeColumn",
3154
- phase,
3155
- column,
3156
- width
3157
- });
3158
- }
3159
- } else {
3160
- throw Error(
3161
- `useDataTable.handleColumnResize, column ${columnName} not found`
3162
- );
3163
- }
3164
- },
3165
- [
3166
- columns,
3167
- dispatchTableModelAction,
3168
- onConfigChange,
3169
- tableConfig,
3170
- containerRef
3171
- ]
3172
- );
3173
- const onToggleGroup = useCallback18(
3174
- (row, column) => {
3175
- var _a, _b;
3176
- const isJson = isJsonGroup2(column, row, columnMap);
3177
- const key = row[KEY];
3178
- if (row[IS_EXPANDED2]) {
3179
- dataSource.closeTreeNode(key, true);
3180
- if (isJson) {
3181
- const idx = columns.indexOf(column);
3182
- const rows = (_a = dataSource.getRowsAtDepth) == null ? void 0 : _a.call(dataSource, idx + 1);
3183
- if (rows && !rows.some((row2) => row2[IS_EXPANDED2] || row2[IS_LEAF2])) {
3184
- dispatchTableModelAction({
3185
- type: "hideColumns",
3186
- columns: columns.slice(idx + 2)
3187
- });
3188
- }
3189
- }
3190
- } else {
3191
- dataSource.openTreeNode(key);
3192
- if (isJson) {
3193
- const childRows = (_b = dataSource.getChildRows) == null ? void 0 : _b.call(dataSource, key);
3194
- const idx = columns.indexOf(column) + 1;
3195
- const columnsToShow = [columns[idx]];
3196
- if (childRows && childRows.some((row2) => row2[IS_LEAF2])) {
3197
- columnsToShow.push(columns[idx + 1]);
3198
- }
3199
- if (columnsToShow.some((col) => col.hidden)) {
3200
- dispatchTableModelAction({
3201
- type: "showColumns",
3202
- columns: columnsToShow
3203
- });
3204
- }
3205
- }
3206
- }
3207
- },
3208
- [columnMap, columns, dataSource, dispatchTableModelAction]
3209
- );
3210
- const {
3211
- highlightedIndexRef,
3212
- navigate,
3213
- onFocus: navigationFocus,
3214
- onKeyDown: navigationKeyDown,
3215
- ...containerProps
3216
- } = useKeyboardNavigation({
3217
- columnCount: columns.filter((c) => c.hidden !== true).length,
3218
- containerRef,
3219
- disableFocus,
3220
- highlightedIndex: highlightedIndexProp,
3221
- navigationStyle,
3222
- requestScroll,
3223
- rowCount: dataSource == null ? void 0 : dataSource.size,
3224
- onHighlight,
3225
- viewportRange: range,
3226
- viewportRowCount: viewportMeasurements.rowCount
3227
- });
3228
- const {
3229
- onBlur: editingBlur,
3230
- onDoubleClick: editingDoubleClick,
3231
- onKeyDown: editingKeyDown,
3232
- onFocus: editingFocus
3233
- } = useCellEditing({
3234
- navigate
3235
- });
3236
- const handleFocus = useCallback18(
3237
- (e) => {
3238
- navigationFocus();
3239
- if (!e.defaultPrevented) {
3240
- editingFocus(e);
3241
- }
3242
- },
3243
- [editingFocus, navigationFocus]
3244
- );
3245
- const onContextMenu = useTableContextMenu({
3246
- columns,
3247
- data,
3248
- dataSource,
3249
- getSelectedRows
3250
- });
3251
- const onMoveGroupColumn = useCallback18(
3252
- (columns2) => {
3253
- dataSource.groupBy = columns2.map((col) => col.name);
3254
- },
3255
- [dataSource]
3256
- );
3257
- const onRemoveGroupColumn = useCallback18(
3258
- (column) => {
3259
- if (isGroupColumn4(column)) {
3260
- dataSource.groupBy = [];
3261
- } else {
3262
- if (dataSource && dataSource.groupBy.includes(column.name)) {
3263
- dataSource.groupBy = dataSource.groupBy.filter(
3264
- (columnName) => columnName !== column.name
3265
- );
3266
- }
3267
- }
3268
- },
3269
- [dataSource]
3270
- );
3271
- const handleSelectionChange = useCallback18(
3272
- (selected) => {
3273
- dataSource.select(selected);
3274
- onSelectionChange == null ? void 0 : onSelectionChange(selected);
3275
- },
3276
- [dataSource, onSelectionChange]
3277
- );
3278
- const handleSelect = useCallback18(
3279
- (row) => {
3280
- if (onSelect) {
3281
- onSelect(row === null ? null : asDataSourceRowObject(row, columnMap));
3282
- }
3283
- },
3284
- [columnMap, onSelect]
3285
- );
3286
- const {
3287
- onKeyDown: selectionHookKeyDown,
3288
- onRowClick: selectionHookOnRowClick
3289
- } = useSelection({
3290
- highlightedIndexRef,
3291
- onSelect: handleSelect,
3292
- onSelectionChange: handleSelectionChange,
3293
- selectionModel
3294
- });
3295
- const handleRowClick = useCallback18(
3296
- (evt, row, rangeSelect, keepExistingSelection) => {
3297
- selectionHookOnRowClick(evt, row, rangeSelect, keepExistingSelection);
3298
- onRowClickProp == null ? void 0 : onRowClickProp(evt, asDataSourceRowObject(row, columnMap));
3299
- },
3300
- [columnMap, onRowClickProp, selectionHookOnRowClick]
3301
- );
3302
- const handleKeyDown = useCallback18(
3303
- (e) => {
3304
- navigationKeyDown(e);
3305
- if (!e.defaultPrevented) {
3306
- editingKeyDown(e);
3307
- }
3308
- if (!e.defaultPrevented) {
3309
- selectionHookKeyDown(e);
3310
- }
3311
- },
3312
- [navigationKeyDown, editingKeyDown, selectionHookKeyDown]
3313
- );
3314
- const onMoveColumn = useCallback18(
3315
- (columns2) => {
3316
- const newTableConfig = {
3317
- ...tableConfig,
3318
- columns: columns2
3319
- };
3320
- dispatchTableModelAction({
3321
- type: "init",
3322
- tableConfig: newTableConfig,
3323
- dataSource
3324
- });
3325
- onConfigChange == null ? void 0 : onConfigChange(stripInternalProperties(newTableConfig));
3326
- },
3327
- [dataSource, dispatchTableModelAction, onConfigChange, tableConfig]
3328
- );
3329
- const handleDropRow = useCallback18(
3330
- (dragDropState) => {
3331
- onDrop == null ? void 0 : onDrop(dragDropState);
3332
- },
3333
- [onDrop]
3334
- );
3335
- const handleDataEdited = useCallback18(
3336
- async (row, columnName, value) => dataSource.applyEdit(row, columnName, value),
3337
- [dataSource]
3338
- );
3339
- const handleDragStartRow = useCallback18(
3340
- (dragDropState) => {
3341
- const { initialDragElement } = dragDropState;
3342
- const rowIndex = getIndexFromRowElement3(initialDragElement);
3343
- const row = dataRef.current.find((row2) => row2[0] === rowIndex);
3344
- if (row) {
3345
- dragDropState.setPayload(row);
3346
- } else {
3347
- }
3348
- onDragStart == null ? void 0 : onDragStart(dragDropState);
3349
- },
3350
- [dataRef, onDragStart]
3351
- );
3352
- const { onMouseDown: rowDragMouseDown, draggable: draggableRow } = useRowDragDrop({
3353
- allowDragDrop,
3354
- containerRef,
3355
- draggableClassName: `vuuTable`,
3356
- id,
3357
- onDragStart: handleDragStartRow,
3358
- onDrop: handleDropRow,
3359
- orientation: "vertical",
3360
- itemQuery: ".vuuTableRow"
3361
- });
3362
- return {
3363
- ...containerProps,
3364
- "aria-rowcount": dataSource.size,
3365
- rowClassNameGenerator,
3366
- draggableRow,
3367
- onBlur: editingBlur,
3368
- onDoubleClick: editingDoubleClick,
3369
- onFocus: handleFocus,
3370
- onKeyDown: handleKeyDown,
3371
- onMouseDown: rowDragMouseDown,
3372
- columnMap,
3373
- columns,
3374
- data,
3375
- getRowOffset,
3376
- handleContextMenuAction,
3377
- headings,
3378
- highlightedIndex: highlightedIndexRef.current,
3379
- menuBuilder,
3380
- onContextMenu,
3381
- onDataEdited: handleDataEdited,
3382
- onMoveColumn,
3383
- onMoveGroupColumn,
3384
- onRemoveGroupColumn,
3385
- onRowClick: handleRowClick,
3386
- onSortColumn: handleSort,
3387
- onResizeColumn,
3388
- onToggleGroup,
3389
- scrollProps,
3390
- // TODO don't think we need these ...
3391
- tableAttributes,
3392
- tableConfig,
3393
- viewportMeasurements
3394
- };
3395
- };
3396
-
3397
- // src/useRowHeight.ts
3398
- import { isValidNumber as isValidNumber2 } from "@vuu-ui/vuu-utils";
3399
- import { useCallback as useCallback19, useMemo as useMemo9, useRef as useRef14, useState as useState7 } from "react";
3400
- var useRowHeight = ({
3401
- rowHeight: rowHeightProp = 0
3402
- }) => {
3403
- const [rowHeight, setRowHeight] = useState7(rowHeightProp);
3404
- const heightRef = useRef14(rowHeight);
3405
- const resizeObserver = useMemo9(() => {
3406
- return new ResizeObserver((entries) => {
3407
- for (const entry of entries) {
3408
- const [{ blockSize: measuredSize }] = entry.borderBoxSize;
3409
- const newHeight = Math.round(measuredSize);
3410
- if (isValidNumber2(newHeight) && heightRef.current !== newHeight) {
3411
- heightRef.current = newHeight;
3412
- setRowHeight(newHeight);
3413
- }
3414
- }
3415
- });
3416
- }, []);
3417
- const rowRef = useCallback19(
3418
- (el) => {
3419
- if (el) {
3420
- if (rowHeightProp === 0) {
3421
- const { height } = el.getBoundingClientRect();
3422
- console.log({ boundingClientHeight: height });
3423
- console.log(`measured rowHeight = ${height} (${rowHeightProp})`);
3424
- resizeObserver.observe(el);
3425
- setRowHeight(height);
3426
- }
3427
- } else {
3428
- resizeObserver.disconnect();
3429
- }
3430
- },
3431
- [resizeObserver, rowHeightProp]
3432
- );
3433
- return { rowHeight, rowRef };
3434
- };
3435
-
3436
- // src/Table.tsx
3437
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
3438
- var classBase8 = "vuuTable";
3439
- var { IDX: IDX3, RENDER_IDX } = metadataKeys6;
3440
- var TableCore = ({
3441
- Row: Row2 = Row,
3442
- allowDragDrop,
3443
- availableColumns,
3444
- config,
3445
- containerRef,
3446
- dataSource,
3447
- disableFocus = false,
3448
- highlightedIndex: highlightedIndexProp,
3449
- id: idProp,
3450
- navigationStyle = "cell",
3451
- onAvailableColumnsChange,
3452
- onConfigChange,
3453
- onDragStart,
3454
- onDrop,
3455
- onFeatureInvocation,
3456
- onHighlight,
3457
- onRowClick: onRowClickProp,
3458
- onSelect,
3459
- onSelectionChange,
3460
- renderBufferSize = 5,
3461
- rowHeight,
3462
- scrollingApiRef,
3463
- selectionModel = "extended",
3464
- showColumnHeaders = true,
3465
- showColumnHeaderMenus = true,
3466
- headerHeight = showColumnHeaders ? rowHeight * 1.25 : 0,
3467
- size
3468
- }) => {
3469
- const id = useId(idProp);
3470
- const {
3471
- columnMap,
3472
- columns,
3473
- data,
3474
- draggableRow,
3475
- getRowOffset,
3476
- handleContextMenuAction,
3477
- headings,
3478
- highlightedIndex,
3479
- menuBuilder,
3480
- onDataEdited,
3481
- onMoveColumn,
3482
- onMoveGroupColumn,
3483
- onRemoveGroupColumn,
3484
- onResizeColumn,
3485
- onRowClick,
3486
- onSortColumn,
3487
- onToggleGroup,
3488
- rowClassNameGenerator,
3489
- scrollProps,
3490
- tableAttributes,
3491
- tableConfig,
3492
- viewportMeasurements,
3493
- ...tableProps
3494
- } = useTable({
3495
- allowDragDrop,
3496
- availableColumns,
3497
- config,
3498
- containerRef,
3499
- dataSource,
3500
- disableFocus,
3501
- headerHeight,
3502
- highlightedIndex: highlightedIndexProp,
3503
- id,
3504
- navigationStyle,
3505
- onAvailableColumnsChange,
3506
- onConfigChange,
3507
- onDragStart,
3508
- onDrop,
3509
- onFeatureInvocation,
3510
- onHighlight,
3511
- onRowClick: onRowClickProp,
3512
- onSelect,
3513
- onSelectionChange,
3514
- renderBufferSize: Math.max(5, renderBufferSize),
3515
- rowHeight,
3516
- scrollingApiRef,
3517
- selectionModel,
3518
- size
3519
- });
3520
- const contentContainerClassName = cx9(`${classBase8}-contentContainer`, {
3521
- [`${classBase8}-colLines`]: tableAttributes.columnSeparators,
3522
- [`${classBase8}-rowLines`]: tableAttributes.rowSeparators,
3523
- [`${classBase8}-zebra`]: tableAttributes.zebraStripes
3524
- });
3525
- const cssVariables = {
3526
- "--content-height": `${viewportMeasurements.contentHeight}px`,
3527
- "--content-width": `${viewportMeasurements.contentWidth}px`,
3528
- "--horizontal-scrollbar-height": `${viewportMeasurements.horizontalScrollbarHeight}px`,
3529
- "--pinned-width-left": `${viewportMeasurements.pinnedWidthLeft}px`,
3530
- "--pinned-width-right": `${viewportMeasurements.pinnedWidthRight}px`,
3531
- "--header-height": `${headerHeight}px`,
3532
- "--row-height-prop": `${rowHeight}px`,
3533
- "--total-header-height": `${viewportMeasurements.totalHeaderHeight}px`,
3534
- "--vertical-scrollbar-width": `${viewportMeasurements.verticalScrollbarWidth}px`,
3535
- "--viewport-body-height": `${viewportMeasurements.viewportBodyHeight}px`
3536
- };
3537
- return /* @__PURE__ */ jsxs9(
3538
- ContextMenuProvider,
3539
- {
3540
- menuActionHandler: handleContextMenuAction,
3541
- menuBuilder,
3542
- children: [
3543
- /* @__PURE__ */ jsx12(
3544
- "div",
3545
- {
3546
- className: `${classBase8}-scrollbarContainer`,
3547
- ref: scrollProps.scrollbarContainerRef,
3548
- style: cssVariables,
3549
- children: /* @__PURE__ */ jsx12("div", { className: `${classBase8}-scrollbarContent` })
3550
- }
3551
- ),
3552
- /* @__PURE__ */ jsx12(
3553
- "div",
3554
- {
3555
- className: contentContainerClassName,
3556
- ref: scrollProps.contentContainerRef,
3557
- style: cssVariables,
3558
- children: /* @__PURE__ */ jsxs9(
3559
- "div",
3560
- {
3561
- ...tableProps,
3562
- className: `${classBase8}-table`,
3563
- role: "table",
3564
- tabIndex: disableFocus ? void 0 : -1,
3565
- children: [
3566
- showColumnHeaders ? /* @__PURE__ */ jsx12(
3567
- TableHeader,
3568
- {
3569
- columns: scrollProps.columnsWithinViewport,
3570
- headings,
3571
- onMoveColumn,
3572
- onMoveGroupColumn,
3573
- onRemoveGroupColumn,
3574
- onResizeColumn,
3575
- onSortColumn,
3576
- showColumnHeaderMenus,
3577
- tableConfig,
3578
- tableId: id,
3579
- virtualColSpan: scrollProps.virtualColSpan
3580
- }
3581
- ) : null,
3582
- /* @__PURE__ */ jsx12("div", { className: `${classBase8}-body`, children: data.map((data2) => /* @__PURE__ */ jsx12(
3583
- Row2,
3584
- {
3585
- "aria-rowindex": data2[0] + 1,
3586
- classNameGenerator: rowClassNameGenerator,
3587
- columnMap,
3588
- columns: scrollProps.columnsWithinViewport,
3589
- highlighted: highlightedIndex === data2[IDX3],
3590
- onClick: onRowClick,
3591
- onDataEdited,
3592
- row: data2,
3593
- offset: getRowOffset(data2),
3594
- onToggleGroup,
3595
- virtualColSpan: scrollProps.virtualColSpan,
3596
- zebraStripes: tableAttributes.zebraStripes
3597
- },
3598
- data2[RENDER_IDX]
3599
- )) })
3600
- ]
3601
- }
3602
- )
3603
- }
3604
- ),
3605
- draggableRow
3606
- ]
3607
- }
3608
- );
3609
- };
3610
- var Table = forwardRef2(function TableNext({
3611
- Row: Row2,
3612
- allowDragDrop,
3613
- availableColumns,
3614
- className: classNameProp,
3615
- config,
3616
- dataSource,
3617
- disableFocus,
3618
- highlightedIndex,
3619
- id,
3620
- navigationStyle,
3621
- onAvailableColumnsChange,
3622
- onConfigChange,
3623
- onDragStart,
3624
- onDrop,
3625
- onFeatureInvocation,
3626
- onHighlight,
3627
- onRowClick,
3628
- onSelect,
3629
- onSelectionChange,
3630
- renderBufferSize,
3631
- rowHeight: rowHeightProp,
3632
- scrollingApiRef,
3633
- selectionModel,
3634
- showColumnHeaders,
3635
- showColumnHeaderMenus,
3636
- headerHeight,
3637
- style: styleProp,
3638
- ...htmlAttributes
3639
- }, forwardedRef) {
3640
- const containerRef = useRef15(null);
3641
- const [size, setSize] = useState8();
3642
- const { rowHeight, rowRef } = useRowHeight({ rowHeight: rowHeightProp });
3643
- if (config === void 0) {
3644
- throw Error(
3645
- "vuu Table requires config prop. Minimum config is list of Column Descriptors"
3646
- );
3647
- }
3648
- if (dataSource === void 0) {
3649
- throw Error("vuu Table requires dataSource prop");
3650
- }
3651
- return /* @__PURE__ */ jsxs9(
3652
- MeasuredContainer,
3653
- {
3654
- ...htmlAttributes,
3655
- className: cx9(classBase8, classNameProp),
3656
- id,
3657
- onResize: setSize,
3658
- ref: useForkRef(containerRef, forwardedRef),
3659
- children: [
3660
- /* @__PURE__ */ jsx12(RowProxy, { ref: rowRef, height: rowHeightProp }),
3661
- size && rowHeight ? /* @__PURE__ */ jsx12(
3662
- TableCore,
3663
- {
3664
- Row: Row2,
3665
- allowDragDrop,
3666
- availableColumns,
3667
- config,
3668
- containerRef,
3669
- dataSource,
3670
- disableFocus,
3671
- headerHeight,
3672
- highlightedIndex,
3673
- id,
3674
- navigationStyle,
3675
- onAvailableColumnsChange,
3676
- onConfigChange,
3677
- onDragStart,
3678
- onDrop,
3679
- onFeatureInvocation,
3680
- onHighlight,
3681
- onRowClick,
3682
- onSelect,
3683
- onSelectionChange,
3684
- renderBufferSize,
3685
- rowHeight,
3686
- scrollingApiRef,
3687
- selectionModel,
3688
- showColumnHeaders,
3689
- showColumnHeaderMenus,
3690
- size
3691
- }
3692
- ) : null
3693
- ]
3694
- }
3695
- );
3696
- });
3697
-
3698
- // src/cell-renderers/checkbox-cell/CheckboxCell.tsx
3699
- import { memo as memo3, useCallback as useCallback20 } from "react";
3700
- import { CheckboxIcon, WarnCommit } from "@vuu-ui/vuu-ui-controls";
3701
- import { Checkbox } from "@salt-ds/core";
3702
- import {
3703
- dataColumnAndKeyUnchanged,
3704
- dispatchCustomEvent,
3705
- registerComponent
3706
- } from "@vuu-ui/vuu-utils";
3707
- import { jsx as jsx13 } from "react/jsx-runtime";
3708
- var CheckboxCell = memo3(
3709
- ({ column, columnMap, onCommit = WarnCommit, row }) => {
3710
- const dataIdx = columnMap[column.name];
3711
- const isChecked = !!row[dataIdx];
3712
- const handleCommit = useCallback20(
3713
- (value) => async (evt) => {
3714
- const res = await onCommit(value);
3715
- if (res === true) {
3716
- dispatchCustomEvent(evt.target, "vuu-commit");
3717
- }
3718
- return res;
3719
- },
3720
- [onCommit]
3721
- );
3722
- return column.editable ? /* @__PURE__ */ jsx13(Checkbox, { checked: isChecked, onClick: handleCommit(!isChecked) }) : /* @__PURE__ */ jsx13(CheckboxIcon, { checked: isChecked, disabled: true });
3723
- },
3724
- dataColumnAndKeyUnchanged
3725
- );
3726
- CheckboxCell.displayName = "CheckboxCell";
3727
- registerComponent("checkbox-cell", CheckboxCell, "cell-renderer", {
3728
- serverDataType: "boolean"
3729
- });
3730
-
3731
- // src/cell-renderers/input-cell/InputCell.tsx
3732
- import { registerComponent as registerComponent2 } from "@vuu-ui/vuu-utils";
3733
- import { Input } from "@salt-ds/core";
3734
- import { useEditableText } from "@vuu-ui/vuu-ui-controls";
3735
- import cx10 from "clsx";
3736
- import { jsx as jsx14 } from "react/jsx-runtime";
3737
- var classBase9 = "vuuTableInputCell";
3738
- var WarnCommit2 = () => {
3739
- console.warn(
3740
- "onCommit handler has not been provided to InputCell cell renderer"
3741
- );
3742
- return Promise.resolve(true);
3743
- };
3744
- var InputCell = ({
3745
- column,
3746
- columnMap,
3747
- onCommit = WarnCommit2,
3748
- row
3749
- }) => {
3750
- const dataIdx = columnMap[column.name];
3751
- const dataValue = row[dataIdx];
3752
- const { align = "left", clientSideEditValidationCheck } = column;
3753
- const { warningMessage, ...editProps } = useEditableText({
3754
- initialValue: dataValue,
3755
- onCommit,
3756
- clientSideEditValidationCheck
3757
- });
3758
- const endAdornment = warningMessage && align === "left" ? /* @__PURE__ */ jsx14("span", { className: `${classBase9}-icon`, "data-icon": "error" }) : void 0;
3759
- const startAdornment = warningMessage && align === "right" ? /* @__PURE__ */ jsx14("span", { className: `${classBase9}-icon`, "data-icon": "error" }) : void 0;
3760
- return /* @__PURE__ */ jsx14(
3761
- Input,
3762
- {
3763
- ...editProps,
3764
- className: cx10(classBase9, {
3765
- [`${classBase9}-error`]: warningMessage !== void 0
3766
- }),
3767
- endAdornment,
3768
- startAdornment
3769
- }
3770
- );
3771
- };
3772
- registerComponent2("input-cell", InputCell, "cell-renderer", {
3773
- userCanAssign: false
3774
- });
3775
-
3776
- // src/cell-renderers/toggle-cell/ToggleCell.tsx
3777
- import { WarnCommit as WarnCommit3 } from "@vuu-ui/vuu-ui-controls";
3778
- import {
3779
- dataColumnAndKeyUnchanged as dataColumnAndKeyUnchanged2,
3780
- dispatchCustomEvent as dispatchCustomEvent2,
3781
- isTypeDescriptor,
3782
- isValueListRenderer,
3783
- registerComponent as registerComponent3
3784
- } from "@vuu-ui/vuu-utils";
3785
- import cx11 from "clsx";
3786
- import { memo as memo4, useCallback as useCallback21 } from "react";
3787
- import { CycleStateButton } from "@vuu-ui/vuu-ui-controls";
3788
- import { jsx as jsx15 } from "react/jsx-runtime";
3789
- var classBase10 = "vuuTableToggleCell";
3790
- var getValueList = ({ name, type }) => {
3791
- if (isTypeDescriptor(type) && isValueListRenderer(type.renderer)) {
3792
- return type.renderer.values;
3793
- } else {
3794
- throw Error(
3795
- `useLookupValues column ${name} has not been configured with a values list`
3796
- );
3797
- }
3798
- };
3799
- var ToggleCell = memo4(
3800
- function ToggleCell2({
3801
- column,
3802
- columnMap,
3803
- onCommit = WarnCommit3,
3804
- row
3805
- }) {
3806
- const values = getValueList(column);
3807
- const dataIdx = columnMap[column.name];
3808
- const value = row[dataIdx];
3809
- const handleCommit = useCallback21(
3810
- (evt, value2) => {
3811
- return onCommit(value2).then((response) => {
3812
- if (response === true) {
3813
- dispatchCustomEvent2(evt.target, "vuu-commit");
3814
- }
3815
- return response;
3816
- });
3817
- },
3818
- [onCommit]
3819
- );
3820
- return /* @__PURE__ */ jsx15(
3821
- CycleStateButton,
3822
- {
3823
- className: cx11(classBase10, `${classBase10}-${column.name}`),
3824
- onCommit: handleCommit,
3825
- value,
3826
- values,
3827
- variant: "cta",
3828
- children: value
3829
- }
3830
- );
3831
- },
3832
- dataColumnAndKeyUnchanged2
3833
- );
3834
- registerComponent3("toggle-cell", ToggleCell, "cell-renderer", {
3835
- userCanAssign: false
3836
- });
3837
-
3838
- // src/useControlledTableNavigation.ts
3839
- import { useStateRef } from "@vuu-ui/vuu-ui-controls";
3840
- import { dispatchMouseEvent as dispatchMouseEvent2 } from "@vuu-ui/vuu-utils";
3841
- import { useCallback as useCallback22, useRef as useRef16 } from "react";
3842
- var useControlledTableNavigation = (initialValue, rowCount) => {
3843
- const tableRef = useRef16(null);
3844
- const [highlightedIndexRef, setHighlightedIndex] = useStateRef(initialValue);
3845
- const handleKeyDown = useCallback22(
3846
- (e) => {
3847
- var _a;
3848
- if (e.key === "ArrowDown") {
3849
- setHighlightedIndex((index = -1) => Math.min(rowCount - 1, index + 1));
3850
- } else if (e.key === "ArrowUp") {
3851
- setHighlightedIndex((index = -1) => Math.max(0, index - 1));
3852
- } else if (e.key === "Enter" || e.key === " ") {
3853
- const { current: rowIdx } = highlightedIndexRef;
3854
- const rowEl = (_a = tableRef.current) == null ? void 0 : _a.querySelector(
3855
- `[aria-rowindex="${rowIdx}"]`
3856
- );
3857
- if (rowEl) {
3858
- dispatchMouseEvent2(rowEl, "click");
3859
- }
3860
- }
3861
- },
3862
- [highlightedIndexRef, rowCount, setHighlightedIndex]
3863
- );
3864
- const handleHighlight = useCallback22(
3865
- (idx) => {
3866
- setHighlightedIndex(idx);
3867
- },
3868
- [setHighlightedIndex]
3869
- );
3870
- return {
3871
- highlightedIndexRef,
3872
- onHighlight: handleHighlight,
3873
- onKeyDown: handleKeyDown,
3874
- tableRef
3875
- };
3876
- };
3877
- export {
3878
- CheckboxCell,
3879
- GroupHeaderCell,
3880
- GroupHeaderCell as GroupHeaderCellNext,
3881
- HeaderCell,
3882
- InputCell,
3883
- Table,
3884
- TableCell,
3885
- TableGroupCell,
3886
- ToggleCell,
3887
- isShowColumnSettings,
3888
- isShowTableSettings,
3889
- noScrolling,
3890
- updateTableConfig,
3891
- useControlledTableNavigation,
3892
- useTableModel,
3893
- useTableScroll,
3894
- useTableViewport
3895
- };
1
+ import{OverflowContainer as Hn}from"@vuu-ui/vuu-ui-controls";import{useLayoutEffectSkipFirst as Mn}from"@vuu-ui/vuu-utils";import Pn from"clsx";import{useCallback as En,useRef as Sn,useState as kn}from"react";import dn from"clsx";import{useCallback as pn}from"react";import{jsx as bn,jsxs as fn}from"react/jsx-runtime";var To="vuuColumnHeaderPill",ge=({children:e,className:o,column:t,onRemove:r,removable:n,...l})=>{if(n&&typeof r!="function")throw Error("ColumnHeaderPill onRemove prop must be provided if Pill is removable");let a=pn(i=>{i.preventDefault(),i.stopPropagation(),r==null||r(t)},[t,r]);return fn("div",{...l,className:dn(To,o),children:[e,n?bn("span",{className:`${To}-removeButton`,role:"button","data-icon":"cross",onClick:a}):null]})};import{jsx as Fe,jsxs as gn}from"react/jsx-runtime";var Ro=({column:e,...o})=>{let{name:t,sorted:r}=e,n=typeof r=="number"?r<0?"arrow-down":"arrow-up":r==="A"?"arrow-up":r==="D"?"arrow-down":void 0;return gn(ge,{...o,column:e,children:[Fe("span",{className:"vuuGroupColumnPill-label",children:t}),n!==void 0?Fe("span",{"data-icon":n}):null,typeof r=="number"?Fe("span",{className:"vuuSortPosition",children:Math.abs(r)}):null]})};import{jsx as yo,jsxs as Cn}from"react/jsx-runtime";var Do=({column:e})=>{if(!e.sorted)return null;let o=typeof e.sorted=="number"?e.sorted<0?"arrow-down":"arrow-up":e.sorted==="A"?"arrow-up":"arrow-down";return Cn(ge,{column:e,children:[yo("span",{"data-icon":o}),typeof e.sorted=="number"?yo("span",{className:"vuuSortPosition",children:Math.abs(e.sorted)}):null]})};import{useCallback as Ge,useRef as vn}from"react";import{jsx as wn}from"react/jsx-runtime";var Ho=()=>{},hn="vuuColumnResizer",De=({onDrag:e,onDragEnd:o=Ho,onDragStart:t=Ho})=>{let r=vn({start:0,now:0}),n=Ge(i=>{i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault();let{current:s}=r,u=Math.round(i.clientX),m=u-s.now,c=s.now-s.start;r.current.now=u,m!==0&&e(i,m,c)},[e]),l=Ge(i=>{window.removeEventListener("mouseup",l),window.removeEventListener("mousemove",n);let{current:s}=r,u=s.now-s.start;o(i,u)},[o,n]),a=Ge(i=>{let{current:s}=r;t(i),s.now=s.start=Math.round(i.clientX),window.addEventListener("mouseup",l),window.addEventListener("mousemove",n),i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault()},[t,n,l]);return wn("div",{className:hn,onMouseDown:a})};import{useCallback as Oe,useRef as xn,useState as Tn}from"react";var He=({column:e,onResize:o,rootRef:t})=>{let r=xn({start:0,now:0}),[n,l]=Tn(!1),{name:a}=e,i=Oe(()=>{if(o&&t.current){let{current:m}=r,{width:c}=t.current.getBoundingClientRect();m.start=m.now=Math.round(c),l(!0),o==null||o("begin",a)}},[a,o,t]),s=Oe((m,c,b)=>{if(t.current&&o){let{current:v}=r,w=v.start+b;w!==v.now&&w>0&&(o("resize",a,w),v.now=w)}},[a,o,t]),u=Oe(()=>{if(o){let{current:m}=r;o("end",a,m.now),setTimeout(()=>{l(!1)},80)}},[a,o]);return{isResizing:n,onDrag:s,onDragStart:i,onDragEnd:u}};import{getColumnStyle as Rn}from"@vuu-ui/vuu-utils";import yn from"clsx";import{useMemo as Dn}from"react";var ue=(e,o,t)=>Dn(()=>{let r=yn(o,{vuuPinFloating:e.pin==="floating",vuuPinLeft:e.pin==="left",vuuPinRight:e.pin==="right",vuuEndPin:t&&e.endPin,[`${o}-editable`]:e.editable,[`${o}-right`]:e.align==="right"}),n=Rn(e);return{className:r,style:n}},[e,o,t]);import{jsx as Be,jsxs as In}from"react/jsx-runtime";import{createElement as Ln}from"react";var $e="vuuTableGroupHeaderCell",An=(e,o)=>e===o?e:o,Ve=({column:e,className:o,onMoveColumn:t,onRemoveColumn:r,onResize:n,...l})=>{let a=Sn(null),{isResizing:i,...s}=He({column:e,onResize:n,rootRef:a}),[u,m]=kn(e.columns),{className:c,style:b}=ue(e,$e,!0),v=u.length>1?{removable:!0,onRemove:r}:void 0,w=En((T,d)=>{m(g=>{let h=g.slice(),[H]=h.splice(T,1);if(d===-1){let R=h.concat(H);return t==null||t(R),R}else return h.splice(d,0,H),t==null||t(h),h})},[t]);return Mn(()=>{m(T=>An(T,e.columns))},[e.columns]),In("div",{...l,className:Pn(c,o,{[`${$e}-pending`]:e.groupConfirmed===!1}),ref:a,role:"columnheader",style:b,children:[Be(Hn,{allowDragDrop:!0,className:`${$e}-inner`,onMoveItem:w,overflowPosition:"start",children:u.map(T=>Ln(Ro,{...v,column:T,key:T.name}))}),Be(ge,{column:e,removable:!0,onRemove:r}),e.resizeable!==!1?Be(De,{...s}):null]})};import{useContextMenu as Gn}from"@vuu-ui/vuu-popups";import On from"clsx";import{useCallback as Po,useMemo as Eo,useRef as $n}from"react";import{PopupMenu as zn}from"@vuu-ui/vuu-popups";import Nn from"clsx";import{jsx as Fn}from"react/jsx-runtime";var Kn="vuuColumnMenu",Mo=({className:e,column:o})=>Fn(zn,{className:Nn(Kn,e),"data-embedded":!0,menuLocation:"column-menu",menuOptions:{column:o}});import{jsx as Ce,jsxs as Bn}from"react/jsx-runtime";var xe="vuuTableHeaderCell",So=({className:e,column:o,onClick:t,onResize:r,showMenu:n=!0,...l})=>{let{HeaderCellContentRenderer:a,HeaderCellLabelRenderer:i}=o,s=$n(null),{isResizing:u,...m}=He({column:o,onResize:r,rootRef:s}),[c]=Gn(),b=Eo(()=>{if(!n)return h=>c(h,"column-menu",{column:o})},[o,c,n]),v=Eo(()=>{var D;let h=Ce(Do,{column:o}),H=i?Ce(i,{className:`${xe}-label`,column:o}):Ce("div",{className:`${xe}-label`,children:(D=o.label)!=null?D:o.name}),R=a?[Ce(a,{column:o},"content")]:[];if(n){let k=Ce(Mo,{column:o});return o.align==="right"?[h,H,R,k]:[k,H,h,R]}else return o.align==="right"?[h,H,R]:[H,h,R]},[a,i,o,n]),w=Po(h=>{!u&&(t==null||t(h))},[u,t]),T=Po(h=>{h.key==="Enter"&&(t==null||t(h))},[t]),{className:d,style:g}=ue(o,xe,!0);return Bn("div",{...l,className:On(d,e,{[`${xe}-resizing`]:u,[`${xe}-noMenu`]:n===!1}),onClick:w,onContextMenu:b,onKeyDown:T,ref:s,role:"columnheader",style:g,children:[...v,o.resizeable!==!1?Ce(De,{...m}):null]})};import{ContextMenuProvider as Mi}from"@vuu-ui/vuu-popups";import{MeasuredContainer as Pi}from"@vuu-ui/vuu-ui-controls";import{metadataKeys as Ei,useId as Si}from"@vuu-ui/vuu-utils";import{useForkRef as ki}from"@salt-ds/core";import Kt from"clsx";import{forwardRef as Ai,useRef as Li,useState as Ii}from"react";import{isGroupColumn as zo,isJsonColumn as Yn,isJsonGroup as jn,metadataKeys as qn,isNotHidden as er,RowSelected as or}from"@vuu-ui/vuu-utils";import Ko from"clsx";import{forwardRef as tr,memo as nr,useCallback as No}from"react";import{isNumericColumn as Vn}from"@vuu-ui/vuu-utils";import{useCallback as ko}from"react";import{jsx as Ao}from"react/jsx-runtime";var Wn="vuuTableCell",Lo=({column:e,columnMap:o,onClick:t,onDataEdited:r,row:n})=>{let{className:l,style:a}=ue(e,Wn),{CellRenderer:i,index:s,name:u,valueFormatter:m}=e,c=o[u],b=ko(w=>{if(r){let T=w;return Vn(e)&&typeof w=="string"&&(T=e.serverDataType==="double"?parseFloat(w):parseInt(w)),r==null?void 0:r(n,u,T)}else throw Error("TableCell onDataEdited prop not supplied for an editable cell")},[e,u,r,n]),v=ko(w=>{t==null||t(w,e)},[e,t]);return Ao("div",{"aria-colindex":s,className:l,onClick:t?v:void 0,role:"cell",style:a,children:i?Ao(i,{column:e,columnMap:o,onCommit:b,row:n}):m(n[c])})};import{getGroupValueAndOffset as Un,metadataKeys as _n}from"@vuu-ui/vuu-utils";import{useCallback as Xn}from"react";import Qn from"clsx";import{jsx as Ue,jsxs as Zn}from"react/jsx-runtime";var{IS_LEAF:Jn}=_n,We="vuuTableGroupCell",Io=({column:e,columnMap:o,onClick:t,row:r})=>{let{columns:n}=e,[l,a]=Un(n,r,o),{className:i,style:s}=ue(e,We),u=Xn(b=>{t==null||t(b,e)},[e,t]),m=r[Jn],c=Array(a).fill(0).map((b,v)=>Ue("span",{className:`${We}-spacer`},v));return Zn("div",{className:Qn(i,"vuuTableCell"),role:"cell",style:s,onClick:m?void 0:u,children:[c,m?null:Ue("span",{className:`${We}-toggle`,"data-icon":"triangle-right"}),Ue("span",{children:l})]})};import{jsx as Te,jsxs as ar}from"react/jsx-runtime";var{IDX:rr,IS_EXPANDED:lr,SELECTED:ir}=qn,le="vuuTableRow",Fo=tr(function({height:o},t){return Te("div",{"aria-hidden":!0,className:Ko(le,`${le}-proxy`),ref:t,style:{height:o}})}),_e=nr(({className:e,classNameGenerator:o,columnMap:t,columns:r,highlighted:n,row:l,offset:a,onClick:i,onDataEdited:s,onToggleGroup:u,virtualColSpan:m=0,zebraStripes:c=!1,...b})=>{let{[rr]:v,[lr]:w,[ir]:T}=l,d=No(M=>{let I=M.shiftKey,A=M.ctrlKey||M.metaKey;i==null||i(M,l,I,A)},[i,l]),{True:g,First:h,Last:H}=or,R=Ko(le,e,o==null?void 0:o(l,t),{[`${le}-even`]:c&&v%2===0,[`${le}-expanded`]:w,[`${le}-highlighted`]:n,[`${le}-selected`]:T&g,[`${le}-selectedStart`]:T&h,[`${le}-selectedEnd`]:T&H}),D={transform:`translate3d(0px, ${a}px, 0px)`},k=No((M,I)=>{(zo(I)||jn(I,l,t))&&(M.stopPropagation(),u==null||u(l,I))},[t,u,l]);return ar("div",{...b,role:"row",className:R,onClick:d,style:D,children:[Te("span",{className:`${le}-selectionDecorator vuuStickyLeft`}),m>0?Te("div",{className:"vuuTableCell",style:{width:m}}):null,r.filter(er).map(M=>{let I=zo(M),A=Yn(M);return Te(I?Io:Lo,{column:M,columnMap:t,onClick:I||A?k:void 0,onDataEdited:s,row:l},M.name)}),Te("span",{className:`${le}-selectionDecorator vuuStickyRight`})]})});_e.displayName="Row";import{isGroupColumn as mr,isNotHidden as dr}from"@vuu-ui/vuu-utils";import pr from"clsx";import{memo as br}from"react";import{useDragDrop as sr}from"@vuu-ui/vuu-ui-controls";import{moveColumnTo as Xe,queryClosest as ur,visibleColumnAtIndex as cr}from"@vuu-ui/vuu-utils";import{useCallback as Qe,useRef as Go}from"react";var Oo=({columns:e,onMoveColumn:o,onSortColumn:t,tableConfig:r})=>{let n=Go(null),l=Go(null),a=Qe(b=>{n.current=b,b?l.current=b.closest(".vuuTable-contentContainer"):l.current=null},[]),i=Qe(({fromIndex:b,toIndex:v})=>{let w=e[b],T=Xe(e,w,v),d=({name:R})=>D=>D.name===R,g=T.findIndex(d(w)),h=T[g+1],H=h?r.columns.findIndex(d(h)):-1;v>b&&H!==-1?o(Xe(r.columns,w,H-1)):o(Xe(r.columns,w,H))},[e,o,r.columns]),s=Qe(b=>{var g;let v=ur(b.target,".vuuTableHeaderCell"),w=parseInt((g=v==null?void 0:v.dataset.index)!=null?g:"-1"),T=cr(e,w),d=b.shiftKey;T&&t(T,d)},[e,t]),{onMouseDown:u,draggable:m,...c}=sr({allowDragDrop:!0,containerRef:n,draggableClassName:"vuuTable",itemQuery:".vuuTableHeaderCell",onDrop:i,orientation:"horizontal",scrollingContainerRef:l});return{draggableColumn:m,draggedColumnIndex:c.draggedItemIndex,onClick:s,onMouseDown:u,setContainerRef:a}};import{jsx as Re,jsxs as $o}from"react/jsx-runtime";var Je=br(({classBase:e="vuuTable",columns:o,headings:t,onMoveColumn:r,onMoveGroupColumn:n,onRemoveGroupColumn:l,onResizeColumn:a,onSortColumn:i,showColumnHeaderMenus:s,tableConfig:u,tableId:m,virtualColSpan:c=0})=>{let{draggableColumn:b,draggedColumnIndex:v,onClick:w,onMouseDown:T,setContainerRef:d}=Oo({columns:o,onMoveColumn:r,onSortColumn:i,tableConfig:u});return $o("div",{className:`${e}-col-headings`,ref:d,children:[t.map((g,h)=>Re("div",{className:"vuuTable-heading",children:g.map(({label:H,width:R},D)=>Re("div",{className:"vuuTable-headingCell",style:{width:R},children:H},D))},h)),$o("div",{className:`${e}-col-headers`,role:"row",children:[c>0?Re("div",{role:"cell",className:"vuuTableCell",style:{width:c}}):null,o.filter(dr).map((g,h)=>mr(g)?Re(Ve,{"aria-colindex":g.index,column:g,"data-index":h,onMoveColumn:n,onRemoveColumn:l,onResize:a},g.name):Re(So,{"aria-colindex":g.index,className:pr({"vuuDraggable-dragAway":h===v}),column:g,"data-index":h,id:`${m}-col-${h}`,onClick:w,onMouseDown:T,onResize:a,showMenu:s},g.name)),b]})]})});Je.displayName="TableHeader";import{useDragDrop as li}from"@vuu-ui/vuu-ui-controls";import{toggleOrApplySort as ii,asDataSourceRowObject as kt,buildColumnMap as ai,getIndexFromRowElement as si,isGroupColumn as ui,isJsonGroup as ci,isValidNumber as mi,metadataKeys as di,updateColumn as pi,useLayoutEffectSkipFirst as bi}from"@vuu-ui/vuu-utils";import{useCallback as K,useEffect as fi,useMemo as At,useRef as gi,useState as Ci}from"react";import{isNumericColumn as fr}from"@vuu-ui/vuu-utils";var Bo=e=>(o,t)=>{let r=[];return e===void 0||(o==="header"||o==="column-menu")&&(r.push(...gr(t,e)),r.push(...hr(t,e)),r.push(...Cr(t,e)),r.push(...vr(t)),r.push({action:"column-settings",icon:"cog",label:"Column Settings",options:t}),r.push({action:"table-settings",icon:"cog",label:"DataGrid Settings",options:t})),r};function gr(e,{sort:{sortDefs:o}}){let{column:t}=e,r=[];if(t===void 0)return r;let n=o.length>0;return t.sorted==="A"?r.push({label:"Reverse Sort (DSC)",action:"sort-dsc",options:e}):t.sorted==="D"?r.push({label:"Reverse Sort (ASC)",action:"sort-asc",options:e}):typeof t.sorted=="number"?(t.sorted>0?r.push({label:"Reverse Sort (DSC)",action:"sort-add-dsc",options:e}):r.push({label:"Reverse Sort (ASC)",action:"sort-add-asc",options:e}),n&&Math.abs(t.sorted)<o.length&&r.push({label:"Remove from sort",action:"sort-remove",options:e}),r.push({label:"New Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]})):n?(r.push({label:"Add to sort",children:[{label:"Ascending",action:"sort-add-asc",options:e},{label:"Descending",action:"sort-add-dsc",options:e}]}),r.push({label:"New Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]})):r.push({label:"Sort",children:[{label:"Ascending",action:"sort-asc",options:e},{label:"Descending",action:"sort-dsc",options:e}]}),r}function Cr(e,o){let{column:t}=e;if(t===void 0||o.groupBy.length===0)return[];let{name:r,label:n=r}=t;return[{label:`Aggregate ${n}`,children:[{label:"Count",action:"agg-count",options:e},{label:"Distinct",action:"agg-distinct",options:e}].concat(fr(t)?[{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 qe=(e,o)=>({label:`Pin ${o}`,action:`column-pin-${o}`,options:e}),Ze=e=>qe(e,"left"),Ye=e=>qe(e,"floating"),je=e=>qe(e,"right");function vr(e){let{column:o}=e;if(o===void 0)return[];let{pin:t}=o,r=[{label:"Hide column",action:"column-hide",options:e},{label:"Remove column",action:"column-remove",options:e}];return t===void 0?r.push({label:"Pin column",children:[Ze(e),Ye(e),je(e)]}):t==="left"?r.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[Ye(e),je(e)]}):t==="right"?r.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[Ze(e),Ye(e)]}):t==="floating"&&r.push({label:"Unpin column",action:"column-unpin",options:e},{label:"Pin column",children:[Ze(e),je(e)]}),r}function hr(e,{groupBy:o}){let{column:t}=e,r=[];if(t===void 0)return r;let{name:n,label:l=n}=t;return o.length===0?r.push({label:`Group by ${l}`,action:"group",options:e}):r.push({label:`Add ${l} to group by`,action:"group-add",options:e}),r}import{removeColumnFromFilter as wr}from"@vuu-ui/vuu-utils";import{addGroupColumn as Vo,addSortColumn as Wo,AggregationType as xr,setAggregations as ve,setSortColumn as Uo}from"@vuu-ui/vuu-utils";var Tr=(e,o)=>{if(e.filterStruct&&o){let[t,r]=wr(o,e.filterStruct);return{filter:r,filterStruct:t}}else return e},{Average:Rr,Count:yr,Distinct:Dr,High:Hr,Low:Mr,Sum:Pr}=xr,_o=({dataSource:e,onPersistentColumnOperation:o})=>r=>{let n=r.options;if(n.column&&e){let{column:l}=n;switch(r.menuId){case"sort-asc":return e.sort=Uo(e.sort,l,"A"),!0;case"sort-dsc":return e.sort=Uo(e.sort,l,"D"),!0;case"sort-add-asc":return e.sort=Wo(e.sort,l,"A"),!0;case"sort-add-dsc":return e.sort=Wo(e.sort,l,"D"),!0;case"group":return e.groupBy=Vo(e.groupBy,l),!0;case"group-add":return e.groupBy=Vo(e.groupBy,l),!0;case"column-hide":return o({type:"hideColumns",columns:[l]}),!0;case"column-remove":return e.columns=e.columns.filter(a=>a!==l.name),!0;case"filter-remove-column":return e.filter=Tr(e.filter,l),!0;case"remove-filters":return e.filter={filter:""},!0;case"agg-avg":return e.aggregations=ve(e.aggregations,l,Rr),!0;case"agg-high":return e.aggregations=ve(e.aggregations,l,Hr),!0;case"agg-low":return e.aggregations=ve(e.aggregations,l,Mr),!0;case"agg-count":return e.aggregations=ve(e.aggregations,l,yr),!0;case"agg-distinct":return e.aggregations=ve(e.aggregations,l,Dr),!0;case"agg-sum":return e.aggregations=ve(e.aggregations,l,Pr),!0;case"column-pin-floating":return o({type:"pinColumn",column:l,pin:"floating"}),!0;case"column-pin-left":return o({type:"pinColumn",column:l,pin:"left"}),!0;case"column-pin-right":return o({type:"pinColumn",column:l,pin:"right"}),!0;case"column-unpin":return o({type:"pinColumn",column:l,pin:void 0}),!0;case"column-settings":return o({type:"columnSettings",column:l}),!0;case"table-settings":return o({type:"tableSettings"}),!0;default:}}return!1};var Xo=(e,o)=>{switch(o.type){case"col-size":return{...e,columns:e.columns.map(t=>t.name===o.column.name?{...t,width:o.width}:t)};case"column-prop":return{...e,columns:e.columns.map(t=>t.name===o.column.name?{...t,[o.property]:o.value}:t)};default:return e}};import{isCharacterKey as Lr}from"@vuu-ui/vuu-utils";import{useCallback as de}from"react";var eo=e=>`.vuuTable-col-headers .vuuTableHeaderCell:nth-child(${e})`,oo=(e,o)=>`.vuuTable-body > [aria-rowindex='${e+1}'] > [role='cell']:nth-child(${o+1})`,Qo=(e,[o,t])=>{var l;let r=o===-1?eo(t):oo(o,t),n=(l=e.current)==null?void 0:l.querySelector(r);return Er(n)&&n.querySelector("button")||n},Er=e=>e==null?void 0:e.classList.contains("vuuTableCell-editable"),Jo=e=>e.querySelector(".vuuTableInputCell")!==null;function Sr(e){if(e){let o=e.ariaRowIndex;if(o!==null)return parseInt(o,10)-1}return-1}var kr=e=>e.closest('[role="row"]'),Zo=e=>Sr(kr(e)),Ar=[void 0,void 0],Yo=(e,o,t=e.closest(".vuuTable-contentContainer"))=>{if(t){let r=t==null?void 0:t.getBoundingClientRect(),n=r.top+o,l=e.getBoundingClientRect();if(l)return l.bottom>r.bottom?["down",l.bottom-r.bottom]:l.top<n?["up",l.top-n]:Ar;throw Error("Whats going on, row not found")}else throw Error("Whats going on, scrollbar container not found")};var jo=({navigate:e})=>{let o=de(()=>{e()},[e]),t=de(s=>{let u=s.target,m=u.matches("input")?u:u.querySelector("input");m&&(m.focus(),m.select())},[]),r=de(s=>{let m=s.target.querySelector("input");m&&(m.focus(),m.select())},[]),n=de(s=>{let u=s.target;Jo(u)&&(Lr(s.key)?t(s):s.key==="Enter"&&r(s))},[t,r]),l=de(s=>{let u=s.target;(u.matches("input")||u.querySelector("input"))&&(t(s),s.stopPropagation())},[t]),a=de(s=>{s.target.removeEventListener("vuu-commit",o,!0)},[o]),i=de(s=>{s.target.addEventListener("vuu-commit",o,!0)},[o]);return{onBlur:a,onDoubleClick:l,onFocus:i,onKeyDown:n}};import{getFullRange as no,NULL_RANGE as Kr,rangesAreSame as Fr}from"@vuu-ui/vuu-utils";import{useCallback as Pe,useEffect as qo,useMemo as Gr,useRef as Ee,useState as Or}from"react";import{isRowSelectedLast as Ir,metadataKeys as zr,WindowRange as Nr}from"@vuu-ui/vuu-utils";var{SELECTED:to}=zr,Me=class{constructor({from:o,to:t}){this.rowCount=0;this.setRowCount=o=>{o<this.data.length&&(this.data.length=o),this.rowCount=o};this.range=new Nr(o,t),this.data=new Array(Math.max(0,t-o)),this.rowCount=0}add(o){let[t]=o;if(this.isWithinRange(t)){let r=t-this.range.from;if(this.data[r]=o,o[to]){let n=this.data[r-1];Ir(n)&&(this.data[r-1]=n.slice(),this.data[r-1][to]-=4)}}}getAtIndex(o){return this.range.isWithin(o)&&this.data[o-this.range.from]!=null?this.data[o-this.range.from]:void 0}isWithinRange(o){return this.range.isWithin(o)}setRange({from:o,to:t}){if(o!==this.range.from||t!==this.range.to){let[r,n]=this.range.overlap(o,t),l=new Array(Math.max(0,t-o));for(let a=r;a<n;a++){let i=this.getAtIndex(a);if(i){let s=a-o;l[s]=i}}this.data=l,this.range.from=o,this.range.to=t}}getSelectedRows(){return this.data.filter(o=>o[to]!==0)}};var $r=e=>e.type==="vuu-link-created"||e.type==="vuu-link-removed",et=({dataSource:e,onFeatureInvocation:o,onSizeChange:t,onSubscribed:r,range:n=Kr,renderBufferSize:l=0})=>{let[,a]=Or(null),i=Ee([]),s=Ee(!0),u=Ee(!1),m=Ee(n),c=Gr(()=>new Me(no(n,l)),[]),b=Pe(d=>{for(let g of d)c.add(g);i.current=c.data,s.current&&a({})},[c]),v=Pe(d=>{d.type==="subscribed"?r==null||r(d):d.type==="viewport-update"?(typeof d.size=="number"&&(t==null||t(d.size),c.setRowCount(d.size)),d.rows?b(d.rows):typeof d.size=="number"&&(i.current=c.data,u.current=!0)):$r(d)?o==null||o(d):console.log(`useDataSource unexpected message ${d.type}`)},[c,o,t,r,b]),w=Pe(()=>c.getSelectedRows(),[c]);qo(()=>{var d;return s.current=!0,(d=e.resume)==null||d.call(e),()=>{var g;s.current=!1,(g=e.suspend)==null||g.call(e)}},[e]),qo(()=>{var d;e.status==="disabled"?(d=e.enable)==null||d.call(e,v):e==null||e.subscribe({range:no(n,l)},v)},[e,v,n,l]);let T=Pe(d=>{if(!Fr(d,m.current)){let g=no(d,l);c.setRange(g),e.range=m.current=g,e.emit("range",d)}},[e,c,l]);return{data:i.current,dataRef:i,getSelectedRows:w,range:m.current,setRange:T}};import{useMemo as Br,useRef as Vr}from"react";var ot=e=>{let o=Vr(e);return Br(()=>o.current,[])};import{getIndexFromRowElement as Wr}from"@vuu-ui/vuu-utils";import{useControlled as Ur}from"@salt-ds/core";import{useCallback as j,useEffect as tt,useRef as Se}from"react";var lt=new Set(["Home","End","PageUp","PageDown","ArrowDown","ArrowUp"]),ro=new Set(lt);ro.add("ArrowLeft");ro.add("ArrowRight");var _r=(e,o)=>{switch(o){case"cell":return ro.has(e);case"row":return lt.has(e);default:return!1}},Xr=["Home","End","PageUp","PageDown"],nt=e=>Xr.includes(e),Qr=[-1,-1];function rt(e,[o,t],r,n){return e==="ArrowUp"?o>-1?[o-1,t]:[o,t]:e==="ArrowDown"?o===-1?[0,t]:o===n-1?[o,t]:[o+1,t]:e==="ArrowRight"?t<r?[o,t+1]:[o,t]:e==="ArrowLeft"?t>1?[o,t-1]:[o,t]:[o,t]}var it=({columnCount:e=0,containerRef:o,disableFocus:t=!1,defaultHighlightedIndex:r,disableHighlightOnFocus:n,highlightedIndex:l,navigationStyle:a,requestScroll:i,onHighlight:s,rowCount:u=0,viewportRowCount:m})=>{var ne;let c=Se([-1,-1]),b=Se(),v=Se([-1,0]),w=Se(),[T,d]=Ur({controlled:l,default:r,name:"UseKeyboardNavigation"});w.current=T;let g=j((f,x=!1)=>{s==null||s(f),d(f)},[s,d]),h=f=>f==null?void 0:f.closest("[role='columnHeader'],[role='cell']"),H=f=>{var x;if(f.role==="columnHeader")return[-1,parseInt((x=f.dataset.idx)!=null?x:"-1",10)];{let y=f.closest("[role='row']");if(y){let G=Wr(y),C=Array.from(y.childNodes).indexOf(f);return[G,C]}}return Qr},R=j(f=>{var x;if(o.current){let y=Qo(o,f);y&&(y!==b.current&&((x=b.current)==null||x.removeAttribute("tabindex"),b.current=y,y.setAttribute("tabindex","0")),i==null||i({type:"scroll-row",rowIndex:f[0]}),y.focus({preventScroll:!0}))}},[o,i]),D=j((f,x,y=!1)=>{let G=[f,x];v.current=G,a==="row"?d(f):R(G),y&&(c.current=G)},[R,a,d]),k=j((f,[x,y])=>new Promise(G=>{let C=x;switch(f){case"PageDown":{C=Math.min(u-1,x+m),C!==x&&(i==null||i({type:"scroll-page",direction:"down"}));break}case"PageUp":{C=Math.max(0,x-m),C!==x&&(i==null||i({type:"scroll-page",direction:"up"}));break}case"Home":{C=0,C!==x&&(i==null||i({type:"scroll-end",direction:"home"}));break}case"End":{C=u-1,C!==x&&(i==null||i({type:"scroll-end",direction:"end"}));break}}setTimeout(()=>{G([C,y])},35)}),[i,u,m]),M=j(()=>{var f;if(n!==!0&&(f=o.current)!=null&&f.contains(document.activeElement)){let x=h(document.activeElement);x&&(c.current=H(x),a==="row"&&d(c.current[0]))}},[n,o,a,d]),I=j(async f=>{let[x,y]=nt(f)?await k(f,v.current):rt(f,v.current,e,u),[G,C]=v.current;(x!==G||y!==C)&&D(x,y,!0)},[e,k,u,D]),A=j(f=>{i==null||i({type:"scroll-row",rowIndex:f})},[i]),W=j(async f=>{let{current:x}=w,[y]=nt(f)?await k(f,[x!=null?x:-1,0]):rt(f,[x!=null?x:-1,0],e,u);y!==x&&(g(y),A(y))},[e,k,u,A,g]);tt(()=>{l!==void 0&&l!==-1&&A(l)},[l,A]);let J=j(f=>{u>0&&_r(f.key,a)&&(f.preventDefault(),f.stopPropagation(),a==="row"?W(f.key):I(f.key))},[u,a,W,I]),_=j(f=>{let x=f.target,y=h(x);if(y){let[G,C]=H(y);D(G,C)}},[D]),Z=j(()=>{g(-1)},[g]),z=j(f=>{let x=Zo(f.target);x!==-1&&x!==w.current&&g(x)},[g]),E=j(()=>{I("ArrowDown")},[I]),te=((ne=o.current)==null?void 0:ne.firstChild)!=null;return tt(()=>{if(te&&b.current===void 0&&!t){let{current:f}=o,x=(f==null?void 0:f.querySelector(eo(0)))||(f==null?void 0:f.querySelector(oo(0,0)));x&&(x.setAttribute("tabindex","0"),b.current=x)}},[o,t,te]),{highlightedIndexRef:w,navigate:E,onClick:_,onFocus:M,onKeyDown:J,onMouseLeave:a==="row"?Z:void 0,onMouseMove:a==="row"?z:void 0}};import{deselectItem as Jr,dispatchMouseEvent as Zr,getRowElementAtIndex as Yr,isRowSelected as jr,metadataKeys as qr,selectItem as at}from"@vuu-ui/vuu-utils";import{useCallback as lo,useRef as st}from"react";var{IDX:el}=qr,ol=[],tl=["Enter"," "],ut=({highlightedIndexRef:e,selectionKeys:o=tl,selectionModel:t,onSelect:r,onSelectionChange:n})=>{let l=st(-1),a=st(ol),i=lo(m=>o.includes(m.key),[o]),s=lo((m,c,b,v)=>{let{[el]:w}=c,{current:T}=l,{current:d}=a,g=jr(c)?Jr:at,h=g(t,d,w,b,v,T);a.current=h,l.current=w,r==null||r(g===at?c:null),n==null||n(h)},[r,n,t]);return{onKeyDown:lo(m=>{if(i(m)){let{current:c}=e;if(c!==void 0&&c!==-1){let b=Yr(m.target,c);b&&Zr(b,"click")}}},[e,i]),onRowClick:s}};import{useContextMenu as nl}from"@vuu-ui/vuu-popups";import{buildColumnMap as rl,getIndexFromRowElement as ll}from"@vuu-ui/vuu-utils";import{useCallback as il}from"react";var al=[],ct=({columns:e,data:o,dataSource:t,getSelectedRows:r})=>{let[n]=nl();return il(a=>{let i=a.target,s=i==null?void 0:i.closest("div[role='cell']"),u=i==null?void 0:i.closest("div[role='row']");if(s&&u){let{selectedRowsCount:m}=t,c=rl(e),b=ll(u),v=Array.from(u.childNodes).indexOf(s),w=o.find(([d])=>d===b),T=e[v];n(a,"grid",{columnMap:c,columnName:T,row:w,selectedRows:m===0?al:r(),viewport:t.viewport})}},[e,o,t,r,n])};import{applyFilterToColumns as sl,applyGroupByToColumns as ul,applySortToColumns as cl,existingSort as ml,getCellRenderer as dl,getColumnHeaderContentRenderer as pl,getColumnHeaderLabelRenderer as bl,getColumnLabel as fl,getTableHeadings as gl,getValueFormatter as Cl,hasValidationRules as vl,isFilteredColumn as hl,isGroupColumn as wl,isPinned as xl,logger as Tl,removeSort as Rl,replaceColumn as pe,sortPinnedColumns as mt,stripFilterFromColumns as yl,subscribedOnly as Dl}from"@vuu-ui/vuu-utils";import{buildValidationChecker as Hl}from"@vuu-ui/vuu-ui-controls";import{useReducer as Ml}from"react";var{info:io}=Tl("useTableModel"),Pl=100,El=({serverDataType:e})=>e===void 0,dt=(e,o)=>{let t=o==null?void 0:o.columns.find(({name:r})=>r===e.name);return t?t.serverDataType:e.serverDataType},Sl=["int","long","double"],pt=e=>e===void 0?void 0:Sl.includes(e)?"right":"left",bt=e=>e.type==="columnSettings",ft=e=>e.type==="tableSettings",kl=(e,o)=>{switch(io==null||io(`TableModelReducer ${o.type}`),o.type){case"init":return Ct(o);case"moveColumn":return Ll(e,o);case"resizeColumn":return Nl(e,o);case"setTableSchema":return Kl(e,o);case"hideColumns":return Il(e,o);case"showColumns":return zl(e,o);case"pinColumn":return Fl(e,o);case"updateColumnProp":return he(e,o);case"tableConfig":return ht(e,o);default:return console.log(`unhandled action ${o.type}`),e}},gt=(e,o)=>{let[t,r]=Ml(kl,{tableConfig:e,dataSource:o},Ct),{columns:n,headings:l,tableConfig:a,...i}=t;return{columns:n,dispatchTableModelAction:r,headings:l,tableAttributes:i,tableConfig:a}};function Ct({dataSource:e,tableConfig:o}){let{columns:t,...r}=o,{config:n,tableSchema:l}=e,a=t.filter(Dl(n==null?void 0:n.columns)).map(vt(r,l)),i=a.some(xl)?mt(a):a,s={columns:i,headings:gl(i),tableConfig:o,...r};if(n){let{columns:u,...m}=n;s=ht(s,{type:"tableConfig",...m})}return s}var Al=(e,o)=>o==="uppercase"?e.toUpperCase():o==="capitalize"?e[0].toUpperCase()+e.slice(1).toLowerCase():e,vt=(e,o)=>(t,r)=>{let{columnDefaultWidth:n=Pl,columnFormatHeader:l}=e,a=dt(t,o),{align:i=pt(a),name:s,label:u=fl(t),width:m=n,...c}=t,b={...c,align:i,CellRenderer:dl(t),HeaderCellContentRenderer:pl(t),HeaderCellLabelRenderer:bl(t),clientSideEditValidationCheck:vl(t.type)?Hl(t.type.renderer.rules):void 0,index:r+1,label:Al(u,l),name:s,originalIdx:r,serverDataType:a,valueFormatter:Cl(t,a),width:m};return wl(b)&&(b.columns=b.columns.map(v=>vt(e)(v,r))),b};function Ll(e,{column:o,moveBy:t}){let{columns:r}=e;if(typeof t=="number"){let n=r.indexOf(o),l=r.slice(),[a]=l.splice(n,1);return l.splice(n+t,0,a),{...e,columns:l}}return e}function Il(e,{columns:o}){return o.some(t=>t.hidden!==!0)?o.reduce((t,r)=>r.hidden!==!0?he(t,{type:"updateColumnProp",column:r,hidden:!0}):t,e):e}function zl(e,{columns:o}){return o.some(t=>t.hidden)?o.reduce((t,r)=>r.hidden?he(t,{type:"updateColumnProp",column:r,hidden:!1}):t,e):e}function Nl(e,{column:o,phase:t,width:r}){let n="updateColumnProp",l=t!=="end";switch(t){case"begin":return he(e,{type:n,column:o,resizing:l});case"end":return he(e,{type:n,column:o,resizing:l,width:r});case"resize":return he(e,{type:n,column:o,width:r});default:throw Error(`useTableModel.resizeColumn, invalid resizePhase ${t}`)}}function Kl(e,{tableSchema:o}){let{columns:t}=e;if(t.some(El)){let r=t.map(n=>{var a;let l=dt(n,o);return{...n,align:(a=n.align)!=null?a:pt(l),serverDataType:l}});return{...e,columns:r}}else return e}function Fl(e,o){let{columns:t}=e,{column:r,pin:n}=o,l=t.find(a=>a.name===r.name);return l?(t=pe(t,{...l,pin:n}),t=mt(t),{...e,columns:t}):e}function he(e,o){let{columns:t,tableConfig:r}=e,{align:n,column:l,hidden:a,label:i,resizing:s,width:u}=o,m=t.find(c=>c.name===l.name);if(m&&((n==="left"||n==="right")&&(t=pe(t,{...m,align:n})),typeof i=="string"&&(t=pe(t,{...m,label:i})),typeof s=="boolean"&&(t=pe(t,{...m,resizing:s})),typeof a=="boolean"&&(t=pe(t,{...m,hidden:a})),typeof u=="number")){t=pe(t,{...m,width:u});let c=r.columns.find(b=>b.name===l.name);c&&(r={...r,columns:pe(r.columns,{...c,width:u})})}return{...e,columns:t,tableConfig:r}}function ht(e,{confirmed:o,filter:t,groupBy:r,sort:n}){let l=r!==void 0,a=typeof(t==null?void 0:t.filter)=="string",i=n&&n.sortDefs.length>0,s=e;return l&&(s={...e,columns:ul(s.columns,r,o)}),i?s={...e,columns:cl(s.columns,n)}:ml(s.columns)&&(s={...e,columns:Rl(s.columns)}),a?s={...e,columns:sl(s.columns,t)}:s.columns.some(hl)&&(s={...e,columns:yl(s.columns)}),s}import{getColumnsInViewport as wt,getRowElementAtIndex as Gl,itemsChanged as Ol}from"@vuu-ui/vuu-utils";import{useCallback as ie,useEffect as $l,useImperativeHandle as Bl,useMemo as xt,useRef as oe,useState as Vl}from"react";var Wl=100,Tt=200,Rt=e=>{let{clientHeight:o,clientWidth:t,scrollHeight:r,scrollWidth:n}=e;return[n-t,r-o]},Ul=(e,o)=>{if(e!==void 0){let{scrollTop:t}=e;return o>t?"fwd":"bwd"}},yt=(e,o)=>{let{clientHeight:t,clientWidth:r,scrollHeight:n,scrollLeft:l,scrollTop:a,scrollWidth:i}=e,s=i-r,u=l/(i-r),m=n-t,c=a/(n-t),b=Ul(o,a);return b==="fwd"&&c>.99?c=1:b==="bwd"&&c<.02&&(c=0),[l,u,s,a,c,m]},_l={scrollToIndex:()=>{},scrollToKey:()=>{}},Dt=({onAttach:e,onDetach:o})=>{let t=oe(null);return ie(n=>{if(n)t.current=n,e==null||e(n);else if(t.current){let{current:l}=t;t.current=n,o==null||o(l)}},[e,o])},Ht=({columns:e,getRowAtPosition:o,onHorizontalScroll:t,onVerticalScroll:r,onVerticalScrollInSitu:n,rowHeight:l,scrollingApiRef:a,setRange:i,viewportMeasurements:s})=>{let u=oe(0),m=oe(l),c=oe(!1),b=oe({scrollTop:0,scrollLeft:0}),v=oe(!1),w=oe({scrollTop:0,scrollLeft:0}),T=oe(null),d=oe(null),g=oe(0),{appliedPageSize:h,isVirtualScroll:H,rowCount:R,totalHeaderHeight:D,viewportWidth:k}=s,M=oe([]),[,I]=Vl({}),A=oe(0);xt(()=>{let[C,P]=wt(e,b.current.scrollLeft,b.current.scrollLeft+k+Tt);A.current=P,M.current=C},[k,e]);let W=ie(C=>{if(b.current.scrollLeft=C,t==null||t(C),Math.abs(C-g.current)>Wl){g.current=C;let[P,O]=wt(e,C,C+k+Tt);Ol(M.current,P)&&(A.current=O,M.current=P,I({}))}},[e,t,k]),J=ie((C,P)=>{b.current.scrollTop=C,r==null||r(C,P);let O=o(C);O!==u.current&&(u.current=O,i({from:O,to:O+R})),n==null||n(0)},[o,r,n,i,R]),_=ie(()=>{let{current:C}=d,{current:P}=T,{current:O}=c,{current:X}=w;if(O)c.current=!1;else if(C&&P){v.current=!0;let[U,re,,B,F]=yt(P,X);X.scrollLeft=U,X.scrollTop=B;let[N,V]=Rt(P),q=Math.round(re*N),Q=F*V;C.scrollTo({left:q,top:Q,behavior:"auto"})}n==null||n(0)},[n]),Z=ie(()=>{let{current:C}=v,{current:P}=d,{current:O}=T,{current:X}=b;if(P&&O){let[U,re,B,F,N,V]=yt(P);c.current=!0,C?v.current=!1:(O.scrollLeft=Math.round(re*B),O.scrollTop=N*V),X.scrollTop!==F&&J(F,N),X.scrollLeft!==U&&W(U)}},[J,W]),z=ie(C=>{T.current=C,C.addEventListener("scroll",_,{passive:!0})},[_]),E=ie(C=>{T.current=null,C.removeEventListener("scroll",_)},[_]),te=ie(C=>{d.current=C,C.addEventListener("scroll",Z,{passive:!0})},[Z]),ne=ie(C=>{d.current=null,C.removeEventListener("scroll",Z)},[Z]),f=Dt({onAttach:te,onDetach:ne}),x=Dt({onAttach:z,onDetach:E}),y=ie(C=>{let{current:P}=d;if(P){let[O,X]=Rt(P),{scrollLeft:U,scrollTop:re}=P;if(c.current=!1,C.type==="scroll-row"){let B=Gl(P,C.rowIndex);if(B!==null){let[F,N]=Yo(B,D);if(console.log(`outside viewport ? ${F} ${N}`),F&&N)if(H){let V=F==="down"?1:-1;n==null||n(V);let q=u.current+V;u.current=q,i({from:q,to:q+R})}else{let V=U,q=re;F==="up"||F==="down"?q=Math.min(Math.max(0,re+N),X):V=Math.min(Math.max(0,U+N),O),P.scrollTo({top:q,left:V,behavior:"smooth"})}}}else if(C.type==="scroll-page"){let{direction:B}=C;if(H){let F=B==="down"?R:-R;n==null||n(F);let N=u.current+F;u.current=N,i({from:N,to:N+R})}else{let F=B==="down"?h:-h,N=Math.min(Math.max(0,re+F),X);P.scrollTo({top:N,left:U,behavior:"auto"})}}else if(C.type==="scroll-end"){let{direction:B}=C,F=B==="end"?X:0;P.scrollTo({top:F,left:P.scrollLeft,behavior:"auto"})}}},[h,H,n,i,D,R]),G=xt(()=>({scrollToIndex:C=>{if(T.current){let P=(C-30)*20;T.current.scrollTop=P}},scrollToKey:C=>{console.log(`scrollToKey ${C}`)}}),[]);return Bl(a,()=>T.current?G:_l,[G]),$l(()=>{if(l!==m.current)m.current=l,b.current.scrollTop>0&&d.current&&(d.current.scrollTop=0);else{let{current:C}=u,P={from:C,to:C+R};i(P)}},[l,i,R]),{columnsWithinViewport:M.current,scrollbarContainerRef:x,contentContainerRef:f,requestScroll:y,virtualColSpan:A.current}};import{actualRowPositioning as Xl,measurePinnedColumns as Ql,virtualRowPositioning as Jl}from"@vuu-ui/vuu-utils";import{useCallback as Mt,useMemo as ke,useRef as ao}from"react";var Zl=1e7,Yl={appliedPageSize:0,contentHeight:0,contentWidth:0,getRowAtPosition:()=>-1,getRowOffset:()=>-1,horizontalScrollbarHeight:0,isVirtualScroll:!1,pinnedWidthLeft:0,pinnedWidthRight:0,rowCount:0,setInSituRowOffset:()=>{},setScrollTop:()=>{},totalHeaderHeight:0,verticalScrollbarWidth:0,viewportBodyHeight:0,viewportWidth:0},Pt=({columns:e,headerHeight:o,headings:t,rowCount:r,rowHeight:n,selectionEndSize:l=4,size:a})=>{let i=ao(0),s=ao(0),u=Math.min(n*r,Zl),m=r*n,c=m-u,{pinnedWidthLeft:b,pinnedWidthRight:v,unpinnedWidth:w}=ke(()=>Ql(e,l),[e,l]),T=ao(o);ke(()=>{T.current=o*(1+t.length)},[o,t.length]);let[d,g,h]=ke(()=>{if(c){let[D,k,M]=Jl(n,c,s);return[A=>D(A,i.current),k,M]}else return Xl(n)},[c,n]),H=Mt((D,k)=>{s.current=k},[]),R=Mt(D=>{D===0?i.current=0:i.current=Math.max(0,i.current+D)},[]);return ke(()=>{if(a){let{current:D}=T,k=15,M=b+w+v,I=M>a.width?k:0,A=(a.height-o)/n,W=Number.isInteger(A)?A:Math.ceil(A),J=a.height-D,_=u>J?k:0,Z=W*n*(u/m),z=a.width;return{appliedPageSize:Z,contentHeight:u,contentWidth:M,getRowAtPosition:g,getRowOffset:d,isVirtualScroll:h,horizontalScrollbarHeight:I,pinnedWidthLeft:b,pinnedWidthRight:v,rowCount:W,setInSituRowOffset:R,setScrollTop:H,totalHeaderHeight:D,verticalScrollbarWidth:_,viewportBodyHeight:J,viewportWidth:z}}else return Yl},[g,d,o,h,b,w,v,u,n,R,H,a,m])};import{useLayoutProviderDispatch as jl}from"@vuu-ui/vuu-layout";import{getCalculatedColumnType as ql}from"@vuu-ui/vuu-utils";import{useCallback as be,useRef as ei,useState as oi}from"react";var Et=({availableColumns:e,onAvailableColumnsChange:o,onConfigChange:t,onCreateCalculatedColumn:r,onDataSourceConfigChange:n,tableConfig:l})=>{let a=jl(),i=ei(),[s,u]=oi(e),m=be((d,g,h)=>{a({type:"set-props",path:"#context-panel",props:{expanded:!0,content:{type:d,props:h},title:g}})},[a]),c=be(()=>{requestAnimationFrame(()=>{var d;(d=i.current)==null||d.call(i)})},[]),b=be(d=>{let g=s.concat({name:d.name,serverDataType:ql(d)});u(g),o==null||o(g),requestAnimationFrame(()=>{var h;(h=i.current)==null||h.call(i)}),r(d)},[s,o,r]),v=be(d=>{m("ColumnSettings","Column Settings",{column:d.column,onCancelCreateColumn:c,onConfigChange:t,onCreateCalculatedColumn:b,tableConfig:l,vuuTable:d.vuuTable})},[c,b,t,m,l]),w=be(()=>{v({column:{name:"::",serverDataType:"string"},type:"columnSettings",vuuTable:{module:"SIMUL",table:"instruments"}})},[v]),T=be(d=>{let g=l.columns.find(h=>h.name===d);g&&v({type:"columnSettings",column:g,vuuTable:{module:"SIMUL",table:"instruments"}})},[v,l.columns]);return i.current=be(()=>{m("TableSettings","DataGrid Settings",{availableColumns:s!=null?s:l.columns.map(({name:d,serverDataType:g})=>({name:d,serverDataType:g})),onAddCalculatedColumn:w,onConfigChange:t,onDataSourceConfigChange:n,onNavigateToColumn:T,tableConfig:l})},[s,w,T,t,n,m,l]),{showColumnSettingsPanel:v,showTableSettingsPanel:i.current}};import{getRowClassNameGenerator as ti}from"@vuu-ui/vuu-utils";import{useMemo as ni}from"react";var ri=e=>{let o=[];return e==null||e.forEach(t=>{let r=ti(t);r&&o.push(r.fn)}),(t,r)=>{let n=[];return o==null||o.forEach(l=>{let a=l(t,r);a&&n.push(a)}),n.join(" ")}},St=({rowClassNameGenerators:e})=>ni(()=>ri(e),[e]);var Ae=e=>e,{KEY:vi,IS_EXPANDED:Lt,IS_LEAF:It}=di,hi={draggable:void 0,onMouseDown:void 0},wi=()=>hi,xi=(e,o)=>({...e,columns:e.columns.concat(o)}),zt=({allowDragDrop:e=!1,availableColumns:o,config:t,containerRef:r,dataSource:n,disableFocus:l,headerHeight:a=25,highlightedIndex:i,id:s,navigationStyle:u="cell",onAvailableColumnsChange:m,onConfigChange:c,onDragStart:b,onDrop:v,onFeatureInvocation:w,onHighlight:T,onRowClick:d,onSelect:g,onSelectionChange:h,renderBufferSize:H=0,rowHeight:R=20,scrollingApiRef:D,selectionModel:k,size:M})=>{let[I,A]=Ci(n.size);if(n===void 0)throw Error("no data source provided to Vuu Table");let W=St(t),J=e?li:wi,_=At(()=>Bo(n),[n]),Z=K(p=>{A(p)},[]),{columns:z,dispatchTableModelAction:E,headings:te,tableAttributes:ne,tableConfig:f}=gt(t,n);bi(()=>{E({type:"init",tableConfig:t,dataSource:n})},[t,n,E]);let x=K(p=>{E({type:"init",tableConfig:p,dataSource:n}),c==null||c(Ae(p))},[n,E,c]),y=At(()=>ai(n.columns),[n.columns]),G=K(({tableSchema:p})=>{p?E({type:"setTableSchema",tableSchema:p}):console.log("subscription message with no schema")},[E]),{getRowAtPosition:C,getRowOffset:P,setInSituRowOffset:O,setScrollTop:X,...U}=Pt({columns:z,headerHeight:a,headings:te,rowCount:I,rowHeight:R,size:M}),re=ot({from:0,to:U.rowCount}),{data:B,dataRef:F,getSelectedRows:N,range:V,setRange:q}=et({dataSource:n,onFeatureInvocation:w,renderBufferSize:H,onSizeChange:Z,onSubscribed:G,range:re}),{requestScroll:Q,...Ie}=Ht({columns:z,getRowAtPosition:C,rowHeight:R,scrollingApiRef:D,setRange:q,onVerticalScroll:X,onVerticalScrollInSitu:O,viewportMeasurements:U}),ze=K(p=>{E({type:"init",tableConfig:p,dataSource:n}),c==null||c(Ae(p))},[n,E,c]),ye=K(p=>{n.config={...n.config,...p}},[n]);fi(()=>{n.on("config",(p,S,L)=>{((L==null?void 0:L.filterChanged)||(L==null?void 0:L.groupByChanged))&&n.range.from>0&&Q({type:"scroll-end",direction:"home"}),E({type:"tableConfig",...p,confirmed:S})})},[n,E,Q]);let me=K(p=>{n.columns=n.columns.concat(p.name),x(xi(f,p))},[n,f,x]),co=K(p=>{let{columns:S}=p,L=S.map(Y=>Y.name),$={...f,columns:f.columns.map(Y=>L.includes(Y.name)?{...Y,hidden:!0}:Y)};x($)},[f,x]),mo=K(p=>{x({...f,columns:pi(f.columns,{...p.column,pin:p.pin})})},[f,x]),{showColumnSettingsPanel:po,showTableSettingsPanel:bo}=Et({availableColumns:o!=null?o:f.columns.map(({name:p,serverDataType:S="string"})=>({name:p,serverDataType:S})),onAvailableColumnsChange:m,onConfigChange:ze,onCreateCalculatedColumn:me,onDataSourceConfigChange:ye,tableConfig:f}),Bt=K(p=>{if(bt(p))po(p);else if(ft(p))bo();else switch(p.type){case"hideColumns":return co(p);case"pinColumn":return mo(p);default:E(p)}},[E,co,mo,po,bo]),Vt=_o({dataSource:n,onPersistentColumnOperation:Bt}),Wt=K((p,S=!1,L)=>{n&&(n.sort=ii(n.sort,p,S,L))},[n]),Ne=gi(),Ut=K((p,S,L)=>{var Y,we,se;let $=z.find(ee=>ee.name===S);if($)if(p==="resize")(Y=Ne.current)==null||Y.forEach(ee=>{ee.style.width=`${L}px`});else if(p==="end")Ne.current=void 0,mi(L)&&(E({type:"resizeColumn",phase:p,column:$,width:L}),c==null||c(Ae(Xo(f,{type:"col-size",column:$,width:L}))));else{let ee=`[aria-colindex='${$.index}']`;Ne.current=Array.from((se=(we=r.current)==null?void 0:we.querySelectorAll(`.vuuTableCell${ee},.vuuTableHeaderCell${ee}`))!=null?se:[]),E({type:"resizeColumn",phase:p,column:$,width:L})}else throw Error(`useDataTable.handleColumnResize, column ${S} not found`)},[z,E,c,f,r]),_t=K((p,S)=>{var Y,we;let L=ci(S,p,y),$=p[vi];if(p[Lt]){if(n.closeTreeNode($,!0),L){let se=z.indexOf(S),ee=(Y=n.getRowsAtDepth)==null?void 0:Y.call(n,se+1);ee&&!ee.some(fe=>fe[Lt]||fe[It])&&E({type:"hideColumns",columns:z.slice(se+2)})}}else if(n.openTreeNode($),L){let se=(we=n.getChildRows)==null?void 0:we.call(n,$),ee=z.indexOf(S)+1,fe=[z[ee]];se&&se.some(Ke=>Ke[It])&&fe.push(z[ee+1]),fe.some(Ke=>Ke.hidden)&&E({type:"showColumns",columns:fe})}},[y,z,n,E]),{highlightedIndexRef:fo,navigate:Xt,onFocus:go,onKeyDown:Co,...Qt}=it({columnCount:z.filter(p=>p.hidden!==!0).length,containerRef:r,disableFocus:l,highlightedIndex:i,navigationStyle:u,requestScroll:Q,rowCount:n==null?void 0:n.size,onHighlight:T,viewportRange:V,viewportRowCount:U.rowCount}),{onBlur:Jt,onDoubleClick:Zt,onKeyDown:vo,onFocus:ho}=jo({navigate:Xt}),Yt=K(p=>{go(),p.defaultPrevented||ho(p)},[ho,go]),jt=ct({columns:z,data:B,dataSource:n,getSelectedRows:N}),qt=K(p=>{n.groupBy=p.map(S=>S.name)},[n]),en=K(p=>{ui(p)?n.groupBy=[]:n&&n.groupBy.includes(p.name)&&(n.groupBy=n.groupBy.filter(S=>S!==p.name))},[n]),on=K(p=>{n.select(p),h==null||h(p)},[n,h]),tn=K(p=>{g&&g(p===null?null:kt(p,y))},[y,g]),{onKeyDown:wo,onRowClick:xo}=ut({highlightedIndexRef:fo,onSelect:tn,onSelectionChange:on,selectionModel:k}),nn=K((p,S,L,$)=>{xo(p,S,L,$),d==null||d(p,kt(S,y))},[y,d,xo]),rn=K(p=>{Co(p),p.defaultPrevented||vo(p),p.defaultPrevented||wo(p)},[Co,vo,wo]),ln=K(p=>{let S={...f,columns:p};E({type:"init",tableConfig:S,dataSource:n}),c==null||c(Ae(S))},[n,E,c,f]),an=K(p=>{v==null||v(p)},[v]),sn=K(async(p,S,L)=>n.applyEdit(p,S,L),[n]),un=K(p=>{let{initialDragElement:S}=p,L=si(S),$=F.current.find(Y=>Y[0]===L);$&&p.setPayload($),b==null||b(p)},[F,b]),{onMouseDown:cn,draggable:mn}=J({allowDragDrop:e,containerRef:r,draggableClassName:"vuuTable",id:s,onDragStart:un,onDrop:an,orientation:"vertical",itemQuery:".vuuTableRow"});return{...Qt,"aria-rowcount":n.size,rowClassNameGenerator:W,draggableRow:mn,onBlur:Jt,onDoubleClick:Zt,onFocus:Yt,onKeyDown:rn,onMouseDown:cn,columnMap:y,columns:z,data:B,getRowOffset:P,handleContextMenuAction:Vt,headings:te,highlightedIndex:fo.current,menuBuilder:_,onContextMenu:jt,onDataEdited:sn,onMoveColumn:ln,onMoveGroupColumn:qt,onRemoveGroupColumn:en,onRowClick:nn,onSortColumn:Wt,onResizeColumn:Ut,onToggleGroup:_t,scrollProps:Ie,tableAttributes:ne,tableConfig:f,viewportMeasurements:U}};import{isValidNumber as Ti}from"@vuu-ui/vuu-utils";import{useCallback as Ri,useMemo as yi,useRef as Di,useState as Hi}from"react";var Nt=({rowHeight:e=0})=>{let[o,t]=Hi(e),r=Di(o),n=yi(()=>new ResizeObserver(a=>{for(let i of a){let[{blockSize:s}]=i.borderBoxSize,u=Math.round(s);Ti(u)&&r.current!==u&&(r.current=u,t(u))}}),[]),l=Ri(a=>{if(a){if(e===0){let{height:i}=a.getBoundingClientRect();console.log({boundingClientHeight:i}),console.log(`measured rowHeight = ${i} (${e})`),n.observe(a),t(i)}}else n.disconnect()},[n,e]);return{rowHeight:o,rowRef:l}};import{jsx as ce,jsxs as so}from"react/jsx-runtime";var ae="vuuTable",{IDX:zi,RENDER_IDX:Ni}=Ei,Ki=({Row:e=_e,allowDragDrop:o,availableColumns:t,config:r,containerRef:n,dataSource:l,disableFocus:a=!1,highlightedIndex:i,id:s,navigationStyle:u="cell",onAvailableColumnsChange:m,onConfigChange:c,onDragStart:b,onDrop:v,onFeatureInvocation:w,onHighlight:T,onRowClick:d,onSelect:g,onSelectionChange:h,renderBufferSize:H=5,rowHeight:R,scrollingApiRef:D,selectionModel:k="extended",showColumnHeaders:M=!0,showColumnHeaderMenus:I=!0,headerHeight:A=M?R*1.25:0,size:W})=>{let J=Si(s),{columnMap:_,columns:Z,data:z,draggableRow:E,getRowOffset:te,handleContextMenuAction:ne,headings:f,highlightedIndex:x,menuBuilder:y,onDataEdited:G,onMoveColumn:C,onMoveGroupColumn:P,onRemoveGroupColumn:O,onResizeColumn:X,onRowClick:U,onSortColumn:re,onToggleGroup:B,rowClassNameGenerator:F,scrollProps:N,tableAttributes:V,tableConfig:q,viewportMeasurements:Q,...Ie}=zt({allowDragDrop:o,availableColumns:t,config:r,containerRef:n,dataSource:l,disableFocus:a,headerHeight:A,highlightedIndex:i,id:J,navigationStyle:u,onAvailableColumnsChange:m,onConfigChange:c,onDragStart:b,onDrop:v,onFeatureInvocation:w,onHighlight:T,onRowClick:d,onSelect:g,onSelectionChange:h,renderBufferSize:Math.max(5,H),rowHeight:R,scrollingApiRef:D,selectionModel:k,size:W}),ze=Kt(`${ae}-contentContainer`,{[`${ae}-colLines`]:V.columnSeparators,[`${ae}-rowLines`]:V.rowSeparators,[`${ae}-zebra`]:V.zebraStripes}),ye={"--content-height":`${Q.contentHeight}px`,"--content-width":`${Q.contentWidth}px`,"--horizontal-scrollbar-height":`${Q.horizontalScrollbarHeight}px`,"--pinned-width-left":`${Q.pinnedWidthLeft}px`,"--pinned-width-right":`${Q.pinnedWidthRight}px`,"--header-height":`${A}px`,"--row-height-prop":`${R}px`,"--total-header-height":`${Q.totalHeaderHeight}px`,"--vertical-scrollbar-width":`${Q.verticalScrollbarWidth}px`,"--viewport-body-height":`${Q.viewportBodyHeight}px`};return so(Mi,{menuActionHandler:ne,menuBuilder:y,children:[ce("div",{className:`${ae}-scrollbarContainer`,ref:N.scrollbarContainerRef,style:ye,children:ce("div",{className:`${ae}-scrollbarContent`})}),ce("div",{className:ze,ref:N.contentContainerRef,style:ye,children:so("div",{...Ie,className:`${ae}-table`,role:"table",tabIndex:a?void 0:-1,children:[M?ce(Je,{columns:N.columnsWithinViewport,headings:f,onMoveColumn:C,onMoveGroupColumn:P,onRemoveGroupColumn:O,onResizeColumn:X,onSortColumn:re,showColumnHeaderMenus:I,tableConfig:q,tableId:J,virtualColSpan:N.virtualColSpan}):null,ce("div",{className:`${ae}-body`,children:z.map(me=>ce(e,{"aria-rowindex":me[0]+1,classNameGenerator:F,columnMap:_,columns:N.columnsWithinViewport,highlighted:x===me[zi],onClick:U,onDataEdited:G,row:me,offset:te(me),onToggleGroup:B,virtualColSpan:N.virtualColSpan,zebraStripes:V.zebraStripes},me[Ni]))})]})}),E]})},Zm=Ai(function({Row:o,allowDragDrop:t,availableColumns:r,className:n,config:l,dataSource:a,disableFocus:i,highlightedIndex:s,id:u,navigationStyle:m,onAvailableColumnsChange:c,onConfigChange:b,onDragStart:v,onDrop:w,onFeatureInvocation:T,onHighlight:d,onRowClick:g,onSelect:h,onSelectionChange:H,renderBufferSize:R,rowHeight:D,scrollingApiRef:k,selectionModel:M,showColumnHeaders:I,showColumnHeaderMenus:A,headerHeight:W,style:J,..._},Z){let z=Li(null),[E,te]=Ii(),{rowHeight:ne,rowRef:f}=Nt({rowHeight:D});if(l===void 0)throw Error("vuu Table requires config prop. Minimum config is list of Column Descriptors");if(a===void 0)throw Error("vuu Table requires dataSource prop");return so(Pi,{..._,className:Kt(ae,n),id:u,onResize:te,ref:ki(z,Z),children:[ce(Fo,{ref:f,height:D}),E&&ne?ce(Ki,{Row:o,allowDragDrop:t,availableColumns:r,config:l,containerRef:z,dataSource:a,disableFocus:i,headerHeight:W,highlightedIndex:s,id:u,navigationStyle:m,onAvailableColumnsChange:c,onConfigChange:b,onDragStart:v,onDrop:w,onFeatureInvocation:T,onHighlight:d,onRowClick:g,onSelect:h,onSelectionChange:H,renderBufferSize:R,rowHeight:ne,scrollingApiRef:k,selectionModel:M,showColumnHeaders:I,showColumnHeaderMenus:A,size:E}):null]})});import{memo as Fi,useCallback as Gi}from"react";import{CheckboxIcon as Oi,WarnCommit as $i}from"@vuu-ui/vuu-ui-controls";import{Checkbox as Bi}from"@salt-ds/core";import{dataColumnAndKeyUnchanged as Vi,dispatchCustomEvent as Wi,registerComponent as Ui}from"@vuu-ui/vuu-utils";import{jsx as Ft}from"react/jsx-runtime";var Gt=Fi(({column:e,columnMap:o,onCommit:t=$i,row:r})=>{let n=o[e.name],l=!!r[n],a=Gi(i=>async s=>{let u=await t(i);return u===!0&&Wi(s.target,"vuu-commit"),u},[t]);return e.editable?Ft(Bi,{checked:l,onClick:a(!l)}):Ft(Oi,{checked:l,disabled:!0})},Vi);Gt.displayName="CheckboxCell";Ui("checkbox-cell",Gt,"cell-renderer",{serverDataType:"boolean"});import{registerComponent as _i}from"@vuu-ui/vuu-utils";import{Input as Xi}from"@salt-ds/core";import{useEditableText as Qi}from"@vuu-ui/vuu-ui-controls";import Ji from"clsx";import{jsx as uo}from"react/jsx-runtime";var Le="vuuTableInputCell",Zi=()=>(console.warn("onCommit handler has not been provided to InputCell cell renderer"),Promise.resolve(!0)),Yi=({column:e,columnMap:o,onCommit:t=Zi,row:r})=>{let n=o[e.name],l=r[n],{align:a="left",clientSideEditValidationCheck:i}=e,{warningMessage:s,...u}=Qi({initialValue:l,onCommit:t,clientSideEditValidationCheck:i}),m=s&&a==="left"?uo("span",{className:`${Le}-icon`,"data-icon":"error"}):void 0,c=s&&a==="right"?uo("span",{className:`${Le}-icon`,"data-icon":"error"}):void 0;return uo(Xi,{...u,className:Ji(Le,{[`${Le}-error`]:s!==void 0}),endAdornment:m,startAdornment:c})};_i("input-cell",Yi,"cell-renderer",{userCanAssign:!1});import{WarnCommit as ji}from"@vuu-ui/vuu-ui-controls";import{dataColumnAndKeyUnchanged as qi,dispatchCustomEvent as ea,isTypeDescriptor as oa,isValueListRenderer as ta,registerComponent as na}from"@vuu-ui/vuu-utils";import ra from"clsx";import{memo as la,useCallback as ia}from"react";import{CycleStateButton as aa}from"@vuu-ui/vuu-ui-controls";import{jsx as ca}from"react/jsx-runtime";var Ot="vuuTableToggleCell",sa=({name:e,type:o})=>{if(oa(o)&&ta(o.renderer))return o.renderer.values;throw Error(`useLookupValues column ${e} has not been configured with a values list`)},ua=la(function({column:o,columnMap:t,onCommit:r=ji,row:n}){let l=sa(o),a=t[o.name],i=n[a],s=ia((u,m)=>r(m).then(c=>(c===!0&&ea(u.target,"vuu-commit"),c)),[r]);return ca(aa,{className:ra(Ot,`${Ot}-${o.name}`),onCommit:s,value:i,values:l,variant:"cta",children:i})},qi);na("toggle-cell",ua,"cell-renderer",{userCanAssign:!1});import{useStateRef as ma}from"@vuu-ui/vuu-ui-controls";import{dispatchMouseEvent as da}from"@vuu-ui/vuu-utils";import{useCallback as $t,useRef as pa}from"react";var Vd=(e,o)=>{let t=pa(null),[r,n]=ma(e),l=$t(i=>{var s;if(i.key==="ArrowDown")n((u=-1)=>Math.min(o-1,u+1));else if(i.key==="ArrowUp")n((u=-1)=>Math.max(0,u-1));else if(i.key==="Enter"||i.key===" "){let{current:u}=r,m=(s=t.current)==null?void 0:s.querySelector(`[aria-rowindex="${u}"]`);m&&da(m,"click")}},[r,o,n]),a=$t(i=>{n(i)},[n]);return{highlightedIndexRef:r,onHighlight:a,onKeyDown:l,tableRef:t}};export{Gt as CheckboxCell,Ve as GroupHeaderCell,Ve as GroupHeaderCellNext,So as HeaderCell,Yi as InputCell,Zm as Table,Lo as TableCell,Io as TableGroupCell,ua as ToggleCell,bt as isShowColumnSettings,ft as isShowTableSettings,_l as noScrolling,Xo as updateTableConfig,Vd as useControlledTableNavigation,gt as useTableModel,Ht as useTableScroll,Pt as useTableViewport};
3896
2
  //# sourceMappingURL=index.js.map