@vuu-ui/vuu-table 2.1.19-beta.1 → 2.1.19-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/package.json +12 -13
  2. package/src/CellFocusState.mjs +25 -0
  3. package/src/Row.mjs +83 -0
  4. package/src/Table.css.js +441 -0
  5. package/src/Table.mjs +297 -0
  6. package/src/VirtualColSpan.mjs +12 -0
  7. package/src/applyHighlighting.mjs +28 -0
  8. package/src/bulk-edit/BulkEditPanel.css.js +27 -0
  9. package/src/bulk-edit/BulkEditPanel.mjs +77 -0
  10. package/src/bulk-edit/ColumnCascadingUpdateEditor.css.js +86 -0
  11. package/src/bulk-edit/ColumnCascadingUpdateEditor.mjs +59 -0
  12. package/src/bulk-edit/InsertNewRowEditor.css.js +86 -0
  13. package/src/bulk-edit/InsertNewRowEditor.mjs +59 -0
  14. package/src/bulk-edit/useBulkEditPanel.mjs +61 -0
  15. package/src/bulk-edit/useColumnCascadingEditor.mjs +124 -0
  16. package/src/cell-block/CellBlock.css.js +95 -0
  17. package/src/cell-block/CellBlock.mjs +32 -0
  18. package/src/cell-block/cellblock-utils.mjs +114 -0
  19. package/src/cell-block/useCellBlockSelection.mjs +245 -0
  20. package/src/cell-renderers/checkbox-cell/CheckboxCell.css.js +16 -0
  21. package/src/cell-renderers/checkbox-cell/CheckboxCell.mjs +56 -0
  22. package/src/cell-renderers/checkbox-cell/index.mjs +1 -0
  23. package/src/cell-renderers/checkbox-row-selector/CheckboxRowSelectorCell.css.js +19 -0
  24. package/src/cell-renderers/checkbox-row-selector/CheckboxRowSelectorCell.mjs +34 -0
  25. package/src/cell-renderers/checkbox-row-selector/index.mjs +1 -0
  26. package/src/cell-renderers/index.mjs +4 -0
  27. package/src/cell-renderers/input-cell/InputCell.css.js +81 -0
  28. package/src/cell-renderers/input-cell/InputCell.mjs +73 -0
  29. package/src/cell-renderers/input-cell/index.mjs +1 -0
  30. package/src/cell-renderers/input-cell/useInputCell.mjs +199 -0
  31. package/src/cell-renderers/toggle-cell/ToggleCell.css.js +31 -0
  32. package/src/cell-renderers/toggle-cell/ToggleCell.mjs +47 -0
  33. package/src/cell-renderers/toggle-cell/index.mjs +1 -0
  34. package/src/column-header-pill/ColumnHeaderPill.css.js +34 -0
  35. package/src/column-header-pill/ColumnHeaderPill.mjs +39 -0
  36. package/src/column-header-pill/GroupColumnPill.css.js +10 -0
  37. package/src/column-header-pill/GroupColumnPill.mjs +33 -0
  38. package/src/column-header-pill/SortIndicator.css.js +15 -0
  39. package/src/column-header-pill/SortIndicator.mjs +29 -0
  40. package/src/column-header-pill/index.mjs +3 -0
  41. package/src/column-resizing/ColumnResizer.css.js +32 -0
  42. package/src/column-resizing/ColumnResizer.mjs +69 -0
  43. package/src/column-resizing/index.mjs +2 -0
  44. package/src/column-resizing/useTableColumnResize.mjs +57 -0
  45. package/src/data-row/DataRow.mjs +298 -0
  46. package/src/header-cell/GroupHeaderCell.css.js +91 -0
  47. package/src/header-cell/GroupHeaderCell.mjs +98 -0
  48. package/src/header-cell/HeaderCell.css.js +182 -0
  49. package/src/header-cell/HeaderCell.mjs +126 -0
  50. package/src/header-cell/index.mjs +2 -0
  51. package/src/index.mjs +20 -0
  52. package/src/pagination/PaginationControl.css.js +18 -0
  53. package/src/pagination/PaginationControl.mjs +34 -0
  54. package/src/pagination/index.mjs +1 -0
  55. package/src/pagination/usePagination.mjs +29 -0
  56. package/src/table-cell/TableCell.css.js +67 -0
  57. package/src/table-cell/TableCell.mjs +54 -0
  58. package/src/table-cell/TableGroupCell.css.js +91 -0
  59. package/src/table-cell/TableGroupCell.mjs +61 -0
  60. package/src/table-cell/index.mjs +2 -0
  61. package/src/table-config/useTableConfig.mjs +49 -0
  62. package/src/table-config.mjs +38 -0
  63. package/src/table-data-source/DataRowMovingWindow.mjs +66 -0
  64. package/src/table-data-source/useDataSource.mjs +177 -0
  65. package/src/table-dom-utils.mjs +162 -0
  66. package/src/table-header/HeaderProvider.mjs +14 -0
  67. package/src/table-header/TableHeader.mjs +182 -0
  68. package/src/table-header/index.mjs +2 -0
  69. package/src/table-header/useTableHeader.mjs +69 -0
  70. package/src/useCell.mjs +22 -0
  71. package/src/useCellEditing.mjs +58 -0
  72. package/src/useCellFocus.mjs +112 -0
  73. package/src/useControlledTableNavigation.mjs +34 -0
  74. package/src/useEditableCell.mjs +18 -0
  75. package/src/useInitialValue.mjs +6 -0
  76. package/src/useKeyboardNavigation.mjs +275 -0
  77. package/src/useMeasuredHeight.mjs +44 -0
  78. package/src/useResizeObserver.mjs +118 -0
  79. package/src/useRowClassNameGenerators.mjs +21 -0
  80. package/src/useSelection.mjs +101 -0
  81. package/src/useTable.mjs +588 -0
  82. package/src/useTableContextMenu.mjs +54 -0
  83. package/src/useTableModel.mjs +344 -0
  84. package/src/useTableScroll.mjs +382 -0
  85. package/src/useTableViewport.mjs +120 -0
@@ -0,0 +1,126 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Checkbox, useForkRef } from "@salt-ds/core";
3
+ import { ColumnMenu } from "@vuu-ui/vuu-table-extras";
4
+ import { isTypeDescriptor, useSortable } from "@vuu-ui/vuu-utils";
5
+ import clsx from "clsx";
6
+ import { useCallback, useMemo, useRef } from "react";
7
+ import { SortIndicator } from "../column-header-pill/index.mjs";
8
+ import { ColumnResizer, useTableColumnResize } from "../column-resizing/index.mjs";
9
+ import { useCell } from "../useCell.mjs";
10
+ const classBase = "vuuTableHeaderCell";
11
+ const doNothing = ()=>({
12
+ ref: {
13
+ current: null
14
+ }
15
+ });
16
+ const HeaderCell = ({ allowDragColumnHeader = true, allowSelectAll, allRowsSelected, className: classNameProp, column, id, index, onCheckBoxColumnHeaderClick, onClick, onResize, showColumnHeaderMenus = true, ...htmlAttributes })=>{
17
+ const dragDropSortHook = allowDragColumnHeader ? useSortable : doNothing;
18
+ const { ref: sortableRef } = dragDropSortHook({
19
+ id,
20
+ index
21
+ });
22
+ const { allowColumnHeaderMenu = true, HeaderCellContentRenderer, HeaderCellLabelRenderer } = column;
23
+ const rootRef = useRef(null);
24
+ const { isResizing, ...resizeProps } = useTableColumnResize({
25
+ column,
26
+ onResize,
27
+ rootRef
28
+ });
29
+ const handleCheckBoxClick = useCallback((e)=>{
30
+ e.stopPropagation();
31
+ onCheckBoxColumnHeaderClick?.();
32
+ }, [
33
+ onCheckBoxColumnHeaderClick
34
+ ]);
35
+ const headerItems = useMemo(()=>{
36
+ const renderCheckbox = allowSelectAll && column.isSystemColumn && isTypeDescriptor(column.type) && "checkbox" === column.type.name;
37
+ if (renderCheckbox) return [
38
+ /*#__PURE__*/ jsx(Checkbox, {
39
+ checked: allRowsSelected,
40
+ className: "vuuCheckboxRowSelector",
41
+ onClick: handleCheckBoxClick
42
+ }, "checkbox")
43
+ ];
44
+ {
45
+ const sortIndicator = /*#__PURE__*/ jsx(SortIndicator, {
46
+ column: column
47
+ });
48
+ const columnLabel = HeaderCellLabelRenderer ? /*#__PURE__*/ jsx(HeaderCellLabelRenderer, {
49
+ className: `${classBase}-label`,
50
+ column: column
51
+ }) : /*#__PURE__*/ jsx("div", {
52
+ className: `${classBase}-label`,
53
+ children: column.label ?? column.name
54
+ });
55
+ const columnContent = HeaderCellContentRenderer ? [
56
+ /*#__PURE__*/ jsx(HeaderCellContentRenderer, {
57
+ column: column
58
+ }, "content")
59
+ ] : [];
60
+ if (!showColumnHeaderMenus || !allowColumnHeaderMenu) return [
61
+ columnLabel,
62
+ sortIndicator,
63
+ columnContent
64
+ ];
65
+ {
66
+ const menuPermissions = true === showColumnHeaderMenus ? void 0 : showColumnHeaderMenus;
67
+ const columnMenu = /*#__PURE__*/ jsx(ColumnMenu, {
68
+ column: column,
69
+ menuPermissions: menuPermissions
70
+ });
71
+ return [
72
+ columnLabel,
73
+ columnContent,
74
+ sortIndicator,
75
+ columnMenu
76
+ ];
77
+ }
78
+ }
79
+ }, [
80
+ HeaderCellContentRenderer,
81
+ HeaderCellLabelRenderer,
82
+ allRowsSelected,
83
+ allowColumnHeaderMenu,
84
+ allowSelectAll,
85
+ column,
86
+ handleCheckBoxClick,
87
+ showColumnHeaderMenus
88
+ ]);
89
+ const handleClick = useCallback((evt)=>{
90
+ isResizing || onClick?.(evt);
91
+ }, [
92
+ isResizing,
93
+ onClick
94
+ ]);
95
+ const handleKeyDown = useCallback((evt)=>{
96
+ if ("Enter" === evt.key) onClick?.(evt);
97
+ }, [
98
+ onClick
99
+ ]);
100
+ const { className, style } = useCell(column, classBase, true);
101
+ return /*#__PURE__*/ jsxs("div", {
102
+ ...htmlAttributes,
103
+ "aria-colindex": column.ariaColIndex,
104
+ "aria-label": `${column.label ?? column.name} column header`,
105
+ className: clsx(className, classNameProp, column.status, {
106
+ [`${classBase}-resizing`]: isResizing,
107
+ [`${classBase}-selected`]: column.selected,
108
+ [`${classBase}-noMenu`]: false === showColumnHeaderMenus
109
+ }),
110
+ "data-column-name": column.name,
111
+ "data-index": index,
112
+ id: id,
113
+ onClick: handleClick,
114
+ onKeyDown: handleKeyDown,
115
+ ref: useForkRef(rootRef, sortableRef),
116
+ role: "columnheader",
117
+ style: style,
118
+ children: [
119
+ ...headerItems,
120
+ false !== column.resizeable ? /*#__PURE__*/ jsx(ColumnResizer, {
121
+ ...resizeProps
122
+ }) : null
123
+ ]
124
+ });
125
+ };
126
+ export { HeaderCell };
@@ -0,0 +1,2 @@
1
+ export * from "./GroupHeaderCell.mjs";
2
+ export * from "./HeaderCell.mjs";
package/src/index.mjs ADDED
@@ -0,0 +1,20 @@
1
+ export * from "./cell-renderers/index.mjs";
2
+ export * from "./header-cell/index.mjs";
3
+ export * from "./pagination/index.mjs";
4
+ export * from "./Table.mjs";
5
+ export * from "./table-cell/index.mjs";
6
+ export * from "./table-config.mjs";
7
+ export * from "./table-header/index.mjs";
8
+ export * from "./useControlledTableNavigation.mjs";
9
+ export * from "./useEditableCell.mjs";
10
+ export * from "./applyHighlighting.mjs";
11
+ export * from "./useKeyboardNavigation.mjs";
12
+ export * from "./useTableContextMenu.mjs";
13
+ export * from "./useTableModel.mjs";
14
+ export * from "./useTableScroll.mjs";
15
+ export * from "./useTableViewport.mjs";
16
+ export * from "./VirtualColSpan.mjs";
17
+ export { BulkEditPanel } from "./bulk-edit/BulkEditPanel.mjs";
18
+ export { dataRowFactory } from "./data-row/DataRow.mjs";
19
+ export { Row } from "./Row.mjs";
20
+ export { useTableConfig } from "./table-config/useTableConfig.mjs";
@@ -0,0 +1,18 @@
1
+ const css = `
2
+ .vuuPaginationControl {
3
+ height: var(--vuuPaginationControl-height, auto);
4
+ padding: 0 var(--salt-spacing-100);
5
+ justify-content: flex-end;
6
+ align-items: center;
7
+ display: flex;
8
+
9
+ & .saltButton {
10
+ & .saltIcon {
11
+ display: block !important;
12
+ }
13
+ }
14
+ }
15
+
16
+
17
+ `;
18
+ export default css;
@@ -0,0 +1,34 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useComponentCssInjection } from "@salt-ds/styles";
3
+ import { useWindow } from "@salt-ds/window";
4
+ import { GoToInput, Pagination, Paginator } from "@salt-ds/core";
5
+ import clsx from "clsx";
6
+ import { usePagination } from "./usePagination.mjs";
7
+ import PaginationControl_0 from "./PaginationControl.css";
8
+ import { forwardRef } from "react";
9
+ const classBase = "vuuPaginationControl";
10
+ const PaginationControl_PaginationControl = /*#__PURE__*/ forwardRef(function({ className, dataSource, ...htmlAttributes }, forwardedRef) {
11
+ const targetWindow = useWindow();
12
+ useComponentCssInjection({
13
+ testId: "vuu-table",
14
+ css: PaginationControl_0,
15
+ window: targetWindow
16
+ });
17
+ const { onPageChange, pageCount } = usePagination({
18
+ dataSource
19
+ });
20
+ return /*#__PURE__*/ jsx("div", {
21
+ ...htmlAttributes,
22
+ className: clsx(classBase, className),
23
+ ref: forwardedRef,
24
+ children: /*#__PURE__*/ jsxs(Pagination, {
25
+ count: pageCount,
26
+ onPageChange: onPageChange,
27
+ children: [
28
+ /*#__PURE__*/ jsx(GoToInput, {}),
29
+ /*#__PURE__*/ jsx(Paginator, {})
30
+ ]
31
+ })
32
+ });
33
+ });
34
+ export { PaginationControl_PaginationControl as PaginationControl };
@@ -0,0 +1 @@
1
+ export * from "./PaginationControl.mjs";
@@ -0,0 +1,29 @@
1
+ import { useCallback, useMemo, useState } from "react";
2
+ import { Range } from "@vuu-ui/vuu-utils";
3
+ const getPageCount = (dataSource)=>{
4
+ const { range, size } = dataSource;
5
+ const pageSize = range.to - range.from;
6
+ if (pageSize > 0) return Math.ceil(size / pageSize);
7
+ return 0;
8
+ };
9
+ const usePagination = ({ dataSource })=>{
10
+ const [pageCount, setPageCount] = useState(getPageCount(dataSource));
11
+ useMemo(()=>{
12
+ dataSource.on("page-count", (n)=>setPageCount(n));
13
+ }, [
14
+ dataSource
15
+ ]);
16
+ const handlePageChange = useCallback((_evt, page)=>{
17
+ const { range } = dataSource;
18
+ const pageSize = range.to - range.from;
19
+ const firstRow = pageSize * (page - 1);
20
+ dataSource.range = Range(firstRow, firstRow + pageSize);
21
+ }, [
22
+ dataSource
23
+ ]);
24
+ return {
25
+ onPageChange: handlePageChange,
26
+ pageCount
27
+ };
28
+ };
29
+ export { usePagination };
@@ -0,0 +1,67 @@
1
+ const css = `
2
+ .vuuTableCell {
3
+ border-right-color: var(--cell-borderColor);
4
+ white-space: nowrap;
5
+ outline-offset: -2px;
6
+ height: 100%;
7
+ padding: var(--vuuTableCell-padding, 0 11px 0 8px);
8
+ text-overflow: ellipsis;
9
+ vertical-align: top;
10
+ border-right-style: solid;
11
+ border-right-width: 1px;
12
+ display: inline-block;
13
+ overflow: hidden;
14
+
15
+ &:has(.vuuCheckboxRowSelector) {
16
+ text-overflow: unset;
17
+ }
18
+ }
19
+
20
+ .vuuTableCell-right {
21
+ text-align: right;
22
+ }
23
+
24
+ .vuuTableCell-editable {
25
+ padding: var(--vuuTableCell-padding-editable, 0px 1px 0 2px);
26
+ align-items: center;
27
+ display: inline-flex;
28
+ }
29
+
30
+ .vuuTableCell:focus-visible {
31
+ outline: none;
32
+ }
33
+
34
+ .vuuTableCell-editable:focus-within, .vuuTableCell:focus {
35
+ border-bottom: none;
36
+
37
+ & .saltInput-bordered {
38
+ outline: solid var(--salt-editable-borderColor-active) 2px;
39
+ outline-offset: -1px;
40
+ border-color: #0000;
41
+ }
42
+
43
+ & .saltInput-bordered.vuuEditing {
44
+ outline: dashed var(--salt-editable-borderColor-active) 2px;
45
+ outline-offset: -1px;
46
+ }
47
+
48
+ & .vuuTableInputCell-error.saltInput-bordered {
49
+ outline: dashed var(--salt-status-error-borderColor) 2px;
50
+ }
51
+ }
52
+
53
+ .vuuTableRow-selected .vuuTableCell:not(.vuuTableCell-editable):focus {
54
+ outline: var(--vuuTableCell-outline, solid var(--salt-focused-outlineColor) 2px);
55
+
56
+ &:has(.vuuCheckboxRowSelector) {
57
+ outline: none;
58
+ }
59
+ }
60
+
61
+ .vuuTableCell.ContextOpen {
62
+ outline: var(--vuuTableCell-outline, solid var(--vuuTableCell-contextOpen-outlineColor, var(--salt-focused-outlineColor)) 2px);
63
+ }
64
+
65
+
66
+ `;
67
+ export default css;
@@ -0,0 +1,54 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useComponentCssInjection } from "@salt-ds/styles";
3
+ import { useWindow } from "@salt-ds/window";
4
+ import { useEditSession } from "@vuu-ui/vuu-utils";
5
+ import { useCallback, useState } from "react";
6
+ import { applyHighlighting } from "../applyHighlighting.mjs";
7
+ import { useCell } from "../useCell.mjs";
8
+ import TableCell from "./TableCell.css";
9
+ const classBase = "vuuTableCell";
10
+ const TableCell_TableCell = ({ column, dataRow, onClick, searchPattern = "" })=>{
11
+ const targetWindow = useWindow();
12
+ useComponentCssInjection({
13
+ testId: "vuu-table-cell",
14
+ css: TableCell,
15
+ window: targetWindow
16
+ });
17
+ const editSession = useEditSession();
18
+ const { className, style } = useCell(column, classBase, false);
19
+ const { ariaColIndex, CellRenderer, name, valueFormatter } = column;
20
+ const [editedDuringCurrentSession, setEditingDuringCurrentSession] = useState(void 0);
21
+ const handleDataItemEdited = useCallback(async (editState, editPhase)=>{
22
+ const { isValid = true, previousValue = "", value } = editState;
23
+ if ("commit" === editPhase && editSession) {
24
+ const { editedDuringCurrentSession, ...response } = await editSession.commit(dataRow.key, name, previousValue, value, isValid);
25
+ setEditingDuringCurrentSession(editedDuringCurrentSession);
26
+ return response;
27
+ }
28
+ }, [
29
+ dataRow.key,
30
+ editSession,
31
+ name
32
+ ]);
33
+ const handleClick = useCallback((evt)=>{
34
+ onClick?.(evt, column);
35
+ }, [
36
+ column,
37
+ onClick
38
+ ]);
39
+ return /*#__PURE__*/ jsx("div", {
40
+ "aria-colindex": ariaColIndex,
41
+ className: className,
42
+ onClick: onClick ? handleClick : void 0,
43
+ role: "cell",
44
+ style: style,
45
+ children: CellRenderer ? /*#__PURE__*/ jsx(CellRenderer, {
46
+ column: column,
47
+ dataRow: dataRow,
48
+ editedDuringCurrentSession: editedDuringCurrentSession,
49
+ onEdit: handleDataItemEdited,
50
+ searchPattern: searchPattern
51
+ }) : applyHighlighting(valueFormatter(dataRow[column.name]), searchPattern)
52
+ });
53
+ };
54
+ export { TableCell_TableCell as TableCell };
@@ -0,0 +1,91 @@
1
+ const css = `
2
+ .vuuTableGroupCell.vuuTableCell {
3
+ --group-cell-spacer-width: 20px;
4
+ border-right-color: var(--vuuTableGroupCell-borderColor, var(--salt-separable-tertiary-borderColor));
5
+ cursor: pointer;
6
+ border-right-style: solid;
7
+ border-right-width: 1px;
8
+ align-items: center;
9
+ line-height: 16px;
10
+ display: inline-flex;
11
+
12
+ & .vuuIcon {
13
+ --vuu-icon-height: 20px;
14
+ --vuu-icon-width: 20px;
15
+ margin-right: var(--salt-spacing-100);
16
+ min-width: 20px;
17
+ }
18
+
19
+ & .vuuToggleIconButton.saltButton {
20
+ --saltButton-height: 20px;
21
+ --saltButton-width: 20px;
22
+ }
23
+
24
+ & .vuuTableGroupCell-label {
25
+ text-overflow: ellipsis;
26
+ overflow: hidden;
27
+ }
28
+ }
29
+
30
+ [aria-level="2"] {
31
+ --indent: 1;
32
+
33
+ &:not([aria-expanded]) {
34
+ --indent: 2;
35
+ }
36
+ }
37
+
38
+ [aria-level="3"] {
39
+ --indent: 2;
40
+
41
+ &:not([aria-expanded]) {
42
+ --indent: 3;
43
+ }
44
+ }
45
+
46
+ [aria-level="4"] {
47
+ --indent: 3;
48
+
49
+ &:not([aria-expanded]) {
50
+ --indent: 4;
51
+ }
52
+ }
53
+
54
+ [aria-level="5"] {
55
+ --indent: 4;
56
+ }
57
+
58
+ [aria-level="6"] {
59
+ --indent: 5;
60
+ }
61
+
62
+ [aria-level="7"] {
63
+ --indent: 6;
64
+ }
65
+
66
+ [aria-level="8"] {
67
+ --indent: 7;
68
+ }
69
+
70
+ [aria-level="9"] {
71
+ --indent: 8;
72
+ }
73
+
74
+ [aria-level="10"] {
75
+ --indent: 9;
76
+ }
77
+
78
+ .vuuTableGroupCell-spacer {
79
+ min-width: calc(var(--indent, 0) * var(--group-cell-spacer-width));
80
+ display: inline-block;
81
+ }
82
+
83
+ .vuuTreeTable {
84
+ & .vuuTableGroupCell.vuuTableCell {
85
+ border-right: none;
86
+ }
87
+ }
88
+
89
+
90
+ `;
91
+ export default css;
@@ -0,0 +1,61 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Icon, ToggleIconButton } from "@vuu-ui/vuu-ui-controls";
3
+ import { getGroupIcon, getGroupValue } from "@vuu-ui/vuu-utils";
4
+ import { useComponentCssInjection } from "@salt-ds/styles";
5
+ import { useWindow } from "@salt-ds/window";
6
+ import clsx from "clsx";
7
+ import { useCallback } from "react";
8
+ import { useCell } from "../useCell.mjs";
9
+ import TableCell from "./TableCell.css";
10
+ import TableGroupCell from "./TableGroupCell.css";
11
+ import { applyHighlighting } from "../applyHighlighting.mjs";
12
+ const classBase = "vuuTableGroupCell";
13
+ const TableGroupCell_TableGroupCell = ({ column, dataRow, onClick, searchPattern = "" })=>{
14
+ const targetWindow = useWindow();
15
+ useComponentCssInjection({
16
+ testId: "vuu-table-cell",
17
+ css: TableCell,
18
+ window: targetWindow
19
+ });
20
+ useComponentCssInjection({
21
+ testId: "vuu-table-group-cell",
22
+ css: TableGroupCell,
23
+ window: targetWindow
24
+ });
25
+ const { columns } = column;
26
+ const value = getGroupValue(columns, dataRow);
27
+ const valueWithHighlighting = applyHighlighting(value || "", searchPattern);
28
+ const icon = getGroupIcon(columns, dataRow);
29
+ const { className, style } = useCell(column, classBase);
30
+ const handleClick = useCallback((evt)=>{
31
+ onClick?.(evt, column);
32
+ }, [
33
+ column,
34
+ onClick
35
+ ]);
36
+ const { childCount, isExpanded, isLeaf } = dataRow;
37
+ const isLeafNode = isLeaf || 0 == childCount;
38
+ return /*#__PURE__*/ jsxs("div", {
39
+ "aria-colindex": 1,
40
+ className: clsx(className, "vuuTableCell"),
41
+ role: "cell",
42
+ style: style,
43
+ onClick: isLeafNode ? void 0 : handleClick,
44
+ children: [
45
+ /*#__PURE__*/ jsx("span", {
46
+ className: `${classBase}-spacer`
47
+ }),
48
+ isLeafNode ? null : /*#__PURE__*/ jsx(ToggleIconButton, {
49
+ isExpanded: isExpanded
50
+ }),
51
+ icon ? /*#__PURE__*/ jsx(Icon, {
52
+ name: icon
53
+ }) : null,
54
+ /*#__PURE__*/ jsx("span", {
55
+ className: `${classBase}-label`,
56
+ children: valueWithHighlighting
57
+ })
58
+ ]
59
+ });
60
+ };
61
+ export { TableGroupCell_TableGroupCell as TableGroupCell };
@@ -0,0 +1,2 @@
1
+ export * from "./TableCell.mjs";
2
+ export * from "./TableGroupCell.mjs";
@@ -0,0 +1,49 @@
1
+ import { ColumnModel } from "@vuu-ui/vuu-table-extras";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ const useTableConfig = ({ availableColumns, config: initialTableConfig, dataSource, onTableConfigChange })=>{
4
+ const [tableConfig, setTableConfig] = useState(initialTableConfig);
5
+ const handleColumnModelChange = useCallback((columns, changeSource, changeDescriptor)=>{
6
+ if ("column-picker" === changeSource || "column-settings" === changeSource) {
7
+ if (changeDescriptor?.type === "calculated-column-added" || changeDescriptor?.type === "column-added") dataSource.columns = dataSource.columns.concat(changeDescriptor.column.name);
8
+ else if (changeDescriptor?.type === "column-removed") dataSource.columns = dataSource.columns.filter((name)=>name !== changeDescriptor.column.name);
9
+ let newConfig;
10
+ setTableConfig((config)=>newConfig = {
11
+ ...config,
12
+ columns
13
+ });
14
+ if (changeDescriptor?.type === "column-removed" || changeDescriptor?.type === "column-added" || changeDescriptor?.type === "calculated-column-added") {
15
+ if (newConfig) onTableConfigChange?.(newConfig, changeDescriptor);
16
+ }
17
+ }
18
+ }, [
19
+ dataSource,
20
+ onTableConfigChange
21
+ ]);
22
+ const columnModel = useMemo(()=>{
23
+ const model = new ColumnModel(availableColumns, tableConfig.columns);
24
+ model.on("change", handleColumnModelChange);
25
+ return model;
26
+ }, [
27
+ availableColumns,
28
+ handleColumnModelChange,
29
+ tableConfig.columns
30
+ ]);
31
+ const handleTableConfigChange = useCallback((_config, changeType)=>{
32
+ if ("column-removed" === changeType.type) columnModel.removeItemFromSelectedColumns(changeType.column.name, "table");
33
+ }, [
34
+ columnModel
35
+ ]);
36
+ const handleTableDisplayAttributeChange = useCallback((displayAttributes)=>{
37
+ setTableConfig((config)=>({
38
+ ...config,
39
+ ...displayAttributes
40
+ }));
41
+ }, []);
42
+ return {
43
+ columnModel,
44
+ onTableDisplayAttributeChange: handleTableDisplayAttributeChange,
45
+ onTableConfigChange: handleTableConfigChange,
46
+ tableConfig
47
+ };
48
+ };
49
+ export { useTableConfig };
@@ -0,0 +1,38 @@
1
+ import { getRuntimeColumnWidth } from "@vuu-ui/vuu-utils";
2
+ const updateTableConfig = (config, action)=>{
3
+ switch(action.type){
4
+ case "col-size":
5
+ {
6
+ const { columns: runtimeColumns, width } = action;
7
+ const isFit = "fit" === config.columnLayout;
8
+ return {
9
+ ...config,
10
+ columnLayout: isFit ? "manual" : config.columnLayout,
11
+ columns: config.columns.map((col)=>{
12
+ if (isFit) return col.name === action.column.name ? {
13
+ ...col,
14
+ width
15
+ } : col.width ? col : {
16
+ ...col,
17
+ width: getRuntimeColumnWidth(col, runtimeColumns)
18
+ };
19
+ return col.name === action.column.name ? {
20
+ ...col,
21
+ width: action.width
22
+ } : col;
23
+ })
24
+ };
25
+ }
26
+ case "column-prop":
27
+ return {
28
+ ...config,
29
+ columns: config.columns.map((col)=>col.name === action.column.name ? {
30
+ ...col,
31
+ [action.property]: action.value
32
+ } : col)
33
+ };
34
+ default:
35
+ return config;
36
+ }
37
+ };
38
+ export { updateTableConfig };
@@ -0,0 +1,66 @@
1
+ import { WindowRange } from "@vuu-ui/vuu-utils";
2
+ class DataRowMovingWindow {
3
+ data;
4
+ rowCount = 0;
5
+ #range;
6
+ constructor({ from, to }){
7
+ this.#range = new WindowRange(from, to);
8
+ this.data = new Array(Math.max(0, to - from));
9
+ this.rowCount = 0;
10
+ }
11
+ setRowCount = (rowCount)=>{
12
+ if (rowCount < this.data.length) this.data.length = rowCount;
13
+ this.rowCount = rowCount;
14
+ };
15
+ add(data) {
16
+ const { index } = data;
17
+ if (this.isWithinRange(index)) {
18
+ const internalIndex = index - this.#range.from;
19
+ this.data[internalIndex] = data;
20
+ }
21
+ }
22
+ getAtIndex(index) {
23
+ return this.#range.isWithin(index) && null != this.data[index - this.#range.from] ? this.data[index - this.#range.from] : void 0;
24
+ }
25
+ getByKey(key) {
26
+ return this.data.find((row)=>row.key === key);
27
+ }
28
+ isWithinRange(index) {
29
+ return index < this.rowCount && this.#range.isWithin(index);
30
+ }
31
+ setRange({ from, to }) {
32
+ if (from !== this.#range.from || to !== this.#range.to) {
33
+ const [overlapFrom, overlapTo] = this.#range.overlap(from, to);
34
+ const newData = new Array(Math.max(0, to - from));
35
+ for(let i = overlapFrom; i < overlapTo; i++){
36
+ const data = this.getAtIndex(i);
37
+ if (data) {
38
+ const index = i - from;
39
+ newData[index] = data;
40
+ }
41
+ }
42
+ this.data = newData;
43
+ this.#range.from = from;
44
+ this.#range.to = to;
45
+ }
46
+ }
47
+ getSelectedRows() {
48
+ return this.data.filter((dataRow)=>dataRow.isSelected);
49
+ }
50
+ get hasData() {
51
+ return this.data.some((d)=>void 0 !== d);
52
+ }
53
+ get firstRow() {
54
+ for(let i = 0; i < this.data.length; i++)if (this.data[i]) return this.data[i];
55
+ throw Error("[DataRowMovingWinddow] firstRow, no data");
56
+ }
57
+ get range() {
58
+ return this.#range;
59
+ }
60
+ get hasAllRowsWithinRange() {
61
+ const { from, to } = this.#range;
62
+ for(let i = from; i < to; i++)if (void 0 === this.getAtIndex(i)) return false;
63
+ return true;
64
+ }
65
+ }
66
+ export { DataRowMovingWindow };