@vuu-ui/vuu-table 0.8.99 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/Table.js +2 -2
- package/cjs/Table.js.map +1 -1
- package/cjs/table-dom-utils.js +42 -13
- package/cjs/table-dom-utils.js.map +1 -1
- package/cjs/table-header/TableHeader.js +105 -66
- package/cjs/table-header/TableHeader.js.map +1 -1
- package/cjs/table-header/useTableHeader.js +9 -1
- package/cjs/table-header/useTableHeader.js.map +1 -1
- package/cjs/useCellFocus.js +3 -3
- package/cjs/useCellFocus.js.map +1 -1
- package/cjs/useKeyboardNavigation.js +21 -21
- package/cjs/useKeyboardNavigation.js.map +1 -1
- package/cjs/useSelection.js +2 -1
- package/cjs/useSelection.js.map +1 -1
- package/cjs/useTable.js +21 -7
- package/cjs/useTable.js.map +1 -1
- package/cjs/useTableScroll.js +2 -2
- package/cjs/useTableScroll.js.map +1 -1
- package/esm/Table.js +2 -2
- package/esm/Table.js.map +1 -1
- package/esm/table-dom-utils.js +39 -14
- package/esm/table-dom-utils.js.map +1 -1
- package/esm/table-header/TableHeader.js +106 -67
- package/esm/table-header/TableHeader.js.map +1 -1
- package/esm/table-header/useTableHeader.js +9 -1
- package/esm/table-header/useTableHeader.js.map +1 -1
- package/esm/useCellFocus.js +3 -3
- package/esm/useCellFocus.js.map +1 -1
- package/esm/useKeyboardNavigation.js +22 -22
- package/esm/useKeyboardNavigation.js.map +1 -1
- package/esm/useSelection.js +3 -2
- package/esm/useSelection.js.map +1 -1
- package/esm/useTable.js +21 -7
- package/esm/useTable.js.map +1 -1
- package/esm/useTableScroll.js +4 -4
- package/esm/useTableScroll.js.map +1 -1
- package/package.json +9 -9
- package/types/table-dom-utils.d.ts +5 -1
- package/types/table-header/TableHeader.d.ts +1 -1
- package/types/table-header/useTableHeader.d.ts +5 -3
- package/types/useKeyboardNavigation.d.ts +2 -1
- package/types/useTable.d.ts +7 -2
package/esm/table-dom-utils.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const NULL_CELL_POS = [-1, -1];
|
|
2
|
-
const headerCellQuery = (colIdx) => `.vuuTable-col-headers .vuuTableHeaderCell[aria-colindex='${colIdx
|
|
3
|
-
const dataCellQuery = (rowIdx, colIdx) => `.vuuTable-
|
|
2
|
+
const headerCellQuery = (colIdx) => `.vuuTable-col-headers .vuuTableHeaderCell[aria-colindex='${colIdx}']`;
|
|
3
|
+
const dataCellQuery = (rowIdx, colIdx) => `.vuuTable-table [aria-rowindex='${rowIdx}'] > [aria-colindex='${colIdx}']`;
|
|
4
4
|
const getTableCell = (containerRef, [rowIdx, colIdx]) => {
|
|
5
|
-
const cssQuery =
|
|
5
|
+
const cssQuery = dataCellQuery(rowIdx, colIdx);
|
|
6
6
|
const cell = containerRef.current?.querySelector(
|
|
7
7
|
cssQuery
|
|
8
8
|
);
|
|
@@ -21,26 +21,47 @@ const cellDropdownShowing = (cell) => {
|
|
|
21
21
|
return false;
|
|
22
22
|
};
|
|
23
23
|
const cellIsTextInput = (cell) => cell.querySelector(".vuuTableInputCell") !== null;
|
|
24
|
-
const
|
|
24
|
+
const getAriaRowIndex = (rowElement) => {
|
|
25
25
|
const rowIndex = rowElement?.ariaRowIndex;
|
|
26
26
|
if (rowIndex != null) {
|
|
27
|
-
const index = parseInt(rowIndex)
|
|
27
|
+
const index = parseInt(rowIndex);
|
|
28
28
|
if (!isNaN(index)) {
|
|
29
29
|
return index;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
return -1;
|
|
33
33
|
};
|
|
34
|
-
const
|
|
35
|
-
const colIndex =
|
|
34
|
+
const getAriaColIndex = (rowElement) => {
|
|
35
|
+
const colIndex = rowElement?.ariaColIndex;
|
|
36
36
|
if (colIndex != null) {
|
|
37
|
-
const index = parseInt(colIndex)
|
|
37
|
+
const index = parseInt(colIndex);
|
|
38
38
|
if (!isNaN(index)) {
|
|
39
39
|
return index;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
return -1;
|
|
43
43
|
};
|
|
44
|
+
const getRowElementByAriaIndex = (container, rowIndex) => {
|
|
45
|
+
if (rowIndex === -1) {
|
|
46
|
+
return null;
|
|
47
|
+
} else {
|
|
48
|
+
const activeRow = container.querySelector(
|
|
49
|
+
`[aria-rowindex="${rowIndex}"]`
|
|
50
|
+
);
|
|
51
|
+
if (activeRow) {
|
|
52
|
+
return activeRow;
|
|
53
|
+
} else {
|
|
54
|
+
throw Error(
|
|
55
|
+
`getRowElementAtIndex no row found for index index ${rowIndex}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const getIndexFromRowElement = (rowElement) => {
|
|
61
|
+
const ariaRowIndex = getAriaRowIndex(rowElement);
|
|
62
|
+
return ariaRowIndex === -1 ? -1 : ariaRowIndex - 1;
|
|
63
|
+
};
|
|
64
|
+
const getIndexFromCellElement = (cellElement) => getAriaColIndex(cellElement);
|
|
44
65
|
const getTableCellPos = (tableCell) => {
|
|
45
66
|
const colIdx = getIndexFromCellElement(tableCell);
|
|
46
67
|
if (tableCell.role === "columnHeader") {
|
|
@@ -53,9 +74,13 @@ const getTableCellPos = (tableCell) => {
|
|
|
53
74
|
}
|
|
54
75
|
return NULL_CELL_POS;
|
|
55
76
|
};
|
|
77
|
+
const getAriaCellPos = (tableCell) => {
|
|
78
|
+
const focusedRow = tableCell.closest("[role='row']");
|
|
79
|
+
return [getAriaRowIndex(focusedRow), getAriaColIndex(tableCell)];
|
|
80
|
+
};
|
|
56
81
|
const closestRow = (el) => el.closest('[role="row"]');
|
|
57
82
|
const closestRowIndex = (el) => getIndexFromRowElement(closestRow(el));
|
|
58
|
-
function getNextCellPos(key, [rowIdx, colIdx], columnCount,
|
|
83
|
+
function getNextCellPos(key, [rowIdx, colIdx], columnCount, maxRowIndex) {
|
|
59
84
|
if (key === "ArrowUp") {
|
|
60
85
|
if (rowIdx > -1) {
|
|
61
86
|
return [rowIdx - 1, colIdx];
|
|
@@ -64,20 +89,20 @@ function getNextCellPos(key, [rowIdx, colIdx], columnCount, rowCount) {
|
|
|
64
89
|
}
|
|
65
90
|
} else if (key === "ArrowDown") {
|
|
66
91
|
if (rowIdx === -1) {
|
|
67
|
-
return [
|
|
68
|
-
} else if (rowIdx ===
|
|
92
|
+
return [1, colIdx];
|
|
93
|
+
} else if (rowIdx === maxRowIndex) {
|
|
69
94
|
return [rowIdx, colIdx];
|
|
70
95
|
} else {
|
|
71
96
|
return [rowIdx + 1, colIdx];
|
|
72
97
|
}
|
|
73
98
|
} else if (key === "ArrowRight") {
|
|
74
|
-
if (colIdx < columnCount
|
|
99
|
+
if (colIdx < columnCount) {
|
|
75
100
|
return [rowIdx, colIdx + 1];
|
|
76
101
|
} else {
|
|
77
102
|
return [rowIdx, colIdx];
|
|
78
103
|
}
|
|
79
104
|
} else if (key === "ArrowLeft") {
|
|
80
|
-
if (colIdx >
|
|
105
|
+
if (colIdx > 1) {
|
|
81
106
|
return [rowIdx, colIdx - 1];
|
|
82
107
|
} else {
|
|
83
108
|
return [rowIdx, colIdx];
|
|
@@ -107,5 +132,5 @@ const howFarIsRowOutsideViewport = (rowEl, totalHeaderHeight, contentContainer =
|
|
|
107
132
|
}
|
|
108
133
|
};
|
|
109
134
|
|
|
110
|
-
export { cellDropdownShowing, cellIsEditable, cellIsTextInput, closestRowIndex, dataCellQuery, getIndexFromCellElement, getIndexFromRowElement, getNextCellPos, getTableCell, getTableCellPos, headerCellQuery, howFarIsRowOutsideViewport };
|
|
135
|
+
export { cellDropdownShowing, cellIsEditable, cellIsTextInput, closestRowIndex, dataCellQuery, getAriaCellPos, getAriaColIndex, getAriaRowIndex, getIndexFromCellElement, getIndexFromRowElement, getNextCellPos, getRowElementByAriaIndex, getTableCell, getTableCellPos, headerCellQuery, howFarIsRowOutsideViewport };
|
|
111
136
|
//# sourceMappingURL=table-dom-utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-dom-utils.js","sources":["../src/table-dom-utils.ts"],"sourcesContent":["import { RefObject } from \"react\";\nimport { ScrollDirection } from \"./useTableScroll\";\nimport type { ArrowKey, PageKey } from \"@vuu-ui/vuu-utils\";\nimport type { CellPos } from \"@vuu-ui/vuu-table-types\";\n\nconst NULL_CELL_POS: CellPos = [-1, -1];\n\nexport type NavigationKey = PageKey | ArrowKey;\n\nexport const headerCellQuery = (colIdx: number) =>\n `.vuuTable-col-headers .vuuTableHeaderCell[aria-colindex='${colIdx + 1}']`;\n\nexport const dataCellQuery = (rowIdx: number, colIdx: number) =>\n `.vuuTable-body > [aria-rowindex='${rowIdx + 1}'] > [aria-colindex='${colIdx + 1}']`;\n\nexport const getTableCell = (\n containerRef: RefObject<HTMLElement>,\n [rowIdx, colIdx]: CellPos,\n) => {\n const cssQuery =\n rowIdx === -1 ? headerCellQuery(colIdx) : dataCellQuery(rowIdx, colIdx);\n const cell = containerRef.current?.querySelector(\n cssQuery,\n ) as HTMLTableCellElement;\n\n if (cellIsEditable(cell)) {\n // Dropdown gets focus, Input does not\n const focusableContent = cell.querySelector(\"button\") as HTMLElement;\n return focusableContent || cell;\n } else {\n return cell;\n }\n};\n\nexport const cellIsEditable = (cell: HTMLDivElement | null) =>\n cell?.classList.contains(\"vuuTableCell-editable\");\n\nexport const cellDropdownShowing = (cell: HTMLDivElement | null) => {\n if (cellIsEditable(cell)) {\n return cell?.querySelector('.saltDropdown[aria-expanded=\"true\"]') !== null;\n }\n return false;\n};\n\nexport const cellIsTextInput = (cell: HTMLElement) =>\n cell.querySelector(\".vuuTableInputCell\") !== null;\n\nexport const getIndexFromRowElement = (rowElement: HTMLElement | null) => {\n const rowIndex = rowElement?.ariaRowIndex;\n if (rowIndex != null) {\n const index = parseInt(rowIndex) - 1;\n if (!isNaN(index)) {\n return index;\n }\n }\n return -1;\n};\n\nexport const getIndexFromCellElement = (cellElement: HTMLElement | null) => {\n const colIndex = cellElement?.ariaColIndex;\n if (colIndex != null) {\n const index = parseInt(colIndex) - 1;\n if (!isNaN(index)) {\n return index;\n }\n }\n return -1;\n};\n\nexport const getTableCellPos = (tableCell: HTMLDivElement): CellPos => {\n const colIdx = getIndexFromCellElement(tableCell);\n if (tableCell.role === \"columnHeader\") {\n return [-1, colIdx];\n } else {\n const focusedRow = tableCell.closest(\"[role='row']\") as HTMLElement;\n if (focusedRow) {\n return [getIndexFromRowElement(focusedRow), colIdx];\n }\n }\n return NULL_CELL_POS;\n};\n\nconst closestRow = (el: HTMLElement) =>\n el.closest('[role=\"row\"]') as HTMLElement;\n\nexport const closestRowIndex = (el: HTMLElement) =>\n getIndexFromRowElement(closestRow(el));\n\nexport function getNextCellPos(\n key: ArrowKey,\n [rowIdx, colIdx]: CellPos,\n columnCount: number,\n rowCount: number,\n): CellPos {\n if (key === \"ArrowUp\") {\n if (rowIdx > -1) {\n return [rowIdx - 1, colIdx];\n } else {\n return [rowIdx, colIdx];\n }\n } else if (key === \"ArrowDown\") {\n if (rowIdx === -1) {\n return [0, colIdx];\n } else if (rowIdx === rowCount - 1) {\n return [rowIdx, colIdx];\n } else {\n return [rowIdx + 1, colIdx];\n }\n } else if (key === \"ArrowRight\") {\n if (colIdx < columnCount - 1) {\n return [rowIdx, colIdx + 1];\n } else {\n return [rowIdx, colIdx];\n }\n } else if (key === \"ArrowLeft\") {\n if (colIdx > 0) {\n return [rowIdx, colIdx - 1];\n } else {\n return [rowIdx, colIdx];\n }\n }\n return [rowIdx, colIdx];\n}\n\nconst NO_SCROLL_NECESSARY = [undefined, undefined] as const;\n\nexport const howFarIsRowOutsideViewport = (\n rowEl: HTMLElement,\n totalHeaderHeight: number,\n contentContainer = rowEl.closest(\".vuuTable-contentContainer\"),\n): readonly [ScrollDirection | undefined, number | undefined] => {\n //TODO lots of scope for optimisation here\n if (contentContainer) {\n // TODO take totalHeaderHeight into consideration\n const viewport = contentContainer?.getBoundingClientRect();\n const upperBoundary = viewport.top + totalHeaderHeight;\n const row = rowEl.getBoundingClientRect();\n if (row) {\n if (row.bottom > viewport.bottom) {\n return [\"down\", row.bottom - viewport.bottom];\n } else if (row.top < upperBoundary) {\n return [\"up\", row.top - upperBoundary];\n } else {\n return NO_SCROLL_NECESSARY;\n }\n } else {\n throw Error(\"Whats going on, row not found\");\n }\n } else {\n throw Error(\"Whats going on, scrollbar container not found\");\n }\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table-dom-utils.js","sources":["../src/table-dom-utils.ts"],"sourcesContent":["import { RefObject } from \"react\";\nimport { ScrollDirection } from \"./useTableScroll\";\nimport type { ArrowKey, PageKey } from \"@vuu-ui/vuu-utils\";\nimport type { CellPos } from \"@vuu-ui/vuu-table-types\";\n\nconst NULL_CELL_POS: CellPos = [-1, -1];\n\nexport type NavigationKey = PageKey | ArrowKey;\n\nexport const headerCellQuery = (colIdx: number) =>\n `.vuuTable-col-headers .vuuTableHeaderCell[aria-colindex='${colIdx}']`;\n\nexport const dataCellQuery = (rowIdx: number, colIdx: number) =>\n `.vuuTable-table [aria-rowindex='${rowIdx}'] > [aria-colindex='${colIdx}']`;\n\nexport const getTableCell = (\n containerRef: RefObject<HTMLElement>,\n [rowIdx, colIdx]: CellPos,\n) => {\n const cssQuery = dataCellQuery(rowIdx, colIdx);\n const cell = containerRef.current?.querySelector(\n cssQuery,\n ) as HTMLTableCellElement;\n\n if (cellIsEditable(cell)) {\n // Dropdown gets focus, Input does not\n const focusableContent = cell.querySelector(\"button\") as HTMLElement;\n return focusableContent || cell;\n } else {\n return cell;\n }\n};\n\nexport const cellIsEditable = (cell: HTMLDivElement | null) =>\n cell?.classList.contains(\"vuuTableCell-editable\");\n\nexport const cellDropdownShowing = (cell: HTMLDivElement | null) => {\n if (cellIsEditable(cell)) {\n return cell?.querySelector('.saltDropdown[aria-expanded=\"true\"]') !== null;\n }\n return false;\n};\n\nexport const cellIsTextInput = (cell: HTMLElement) =>\n cell.querySelector(\".vuuTableInputCell\") !== null;\n\nexport const getAriaRowIndex = (rowElement: HTMLElement | null) => {\n const rowIndex = rowElement?.ariaRowIndex;\n if (rowIndex != null) {\n const index = parseInt(rowIndex);\n if (!isNaN(index)) {\n return index;\n }\n }\n return -1;\n};\n\nexport const getAriaColIndex = (rowElement: HTMLElement | null) => {\n const colIndex = rowElement?.ariaColIndex;\n if (colIndex != null) {\n const index = parseInt(colIndex);\n if (!isNaN(index)) {\n return index;\n }\n }\n return -1;\n};\n\nexport const getRowElementByAriaIndex = (\n container: HTMLDivElement | EventTarget,\n rowIndex: number,\n) => {\n if (rowIndex === -1) {\n return null;\n } else {\n const activeRow = (container as HTMLElement).querySelector(\n `[aria-rowindex=\"${rowIndex}\"]`,\n ) as HTMLElement;\n\n if (activeRow) {\n return activeRow;\n } else {\n throw Error(\n `getRowElementAtIndex no row found for index index ${rowIndex}`,\n );\n }\n }\n};\n\nexport const getIndexFromRowElement = (rowElement: HTMLElement | null) => {\n const ariaRowIndex = getAriaRowIndex(rowElement);\n return ariaRowIndex === -1 ? -1 : ariaRowIndex - 1;\n};\n\nexport const getIndexFromCellElement = (cellElement: HTMLElement | null) =>\n getAriaColIndex(cellElement);\n\nexport const getTableCellPos = (tableCell: HTMLDivElement): CellPos => {\n const colIdx = getIndexFromCellElement(tableCell);\n if (tableCell.role === \"columnHeader\") {\n return [-1, colIdx];\n } else {\n const focusedRow = tableCell.closest(\"[role='row']\") as HTMLElement;\n if (focusedRow) {\n return [getIndexFromRowElement(focusedRow), colIdx];\n }\n }\n return NULL_CELL_POS;\n};\n\nexport const getAriaCellPos = (tableCell: HTMLDivElement): CellPos => {\n const focusedRow = tableCell.closest(\"[role='row']\") as HTMLElement;\n return [getAriaRowIndex(focusedRow), getAriaColIndex(tableCell)];\n};\n\nconst closestRow = (el: HTMLElement) =>\n el.closest('[role=\"row\"]') as HTMLElement;\n\nexport const closestRowIndex = (el: HTMLElement) =>\n getIndexFromRowElement(closestRow(el));\n\nexport function getNextCellPos(\n key: ArrowKey,\n [rowIdx, colIdx]: CellPos,\n columnCount: number,\n maxRowIndex: number,\n): CellPos {\n if (key === \"ArrowUp\") {\n if (rowIdx > -1) {\n return [rowIdx - 1, colIdx];\n } else {\n return [rowIdx, colIdx];\n }\n } else if (key === \"ArrowDown\") {\n if (rowIdx === -1) {\n return [1, colIdx];\n } else if (rowIdx === maxRowIndex) {\n return [rowIdx, colIdx];\n } else {\n return [rowIdx + 1, colIdx];\n }\n } else if (key === \"ArrowRight\") {\n if (colIdx < columnCount) {\n return [rowIdx, colIdx + 1];\n } else {\n return [rowIdx, colIdx];\n }\n } else if (key === \"ArrowLeft\") {\n if (colIdx > 1) {\n return [rowIdx, colIdx - 1];\n } else {\n return [rowIdx, colIdx];\n }\n }\n return [rowIdx, colIdx];\n}\n\nconst NO_SCROLL_NECESSARY = [undefined, undefined] as const;\n\nexport const howFarIsRowOutsideViewport = (\n rowEl: HTMLElement,\n totalHeaderHeight: number,\n contentContainer = rowEl.closest(\".vuuTable-contentContainer\"),\n): readonly [ScrollDirection | undefined, number | undefined] => {\n //TODO lots of scope for optimisation here\n if (contentContainer) {\n // TODO take totalHeaderHeight into consideration\n const viewport = contentContainer?.getBoundingClientRect();\n const upperBoundary = viewport.top + totalHeaderHeight;\n const row = rowEl.getBoundingClientRect();\n if (row) {\n if (row.bottom > viewport.bottom) {\n return [\"down\", row.bottom - viewport.bottom];\n } else if (row.top < upperBoundary) {\n return [\"up\", row.top - upperBoundary];\n } else {\n return NO_SCROLL_NECESSARY;\n }\n } else {\n throw Error(\"Whats going on, row not found\");\n }\n } else {\n throw Error(\"Whats going on, scrollbar container not found\");\n }\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { isNotHidden, isGroupColumn } from '@vuu-ui/vuu-utils';
|
|
3
3
|
import cx from 'clsx';
|
|
4
|
-
import { memo, useMemo, isValidElement } from 'react';
|
|
4
|
+
import { memo, useMemo, isValidElement, cloneElement } from 'react';
|
|
5
5
|
import { GroupHeaderCell } from '../header-cell/GroupHeaderCell.js';
|
|
6
6
|
import { HeaderCell } from '../header-cell/HeaderCell.js';
|
|
7
7
|
import { useTableHeader } from './useTableHeader.js';
|
|
@@ -25,90 +25,129 @@ const TableHeader = memo(
|
|
|
25
25
|
tableId,
|
|
26
26
|
virtualColSpan = 0
|
|
27
27
|
}) => {
|
|
28
|
-
const {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
onClick,
|
|
32
|
-
onMouseDown,
|
|
33
|
-
setContainerRef
|
|
34
|
-
} = useTableHeader({
|
|
35
|
-
allowDragColumnHeader,
|
|
36
|
-
columns,
|
|
37
|
-
onHeightMeasured,
|
|
38
|
-
onMoveColumn,
|
|
39
|
-
onSortColumn,
|
|
40
|
-
tableConfig
|
|
41
|
-
});
|
|
42
|
-
const customHeaders = useMemo(() => {
|
|
43
|
-
const createElement = (Component, key) => /* @__PURE__ */ jsx(
|
|
28
|
+
const [customHeaders, customHeaderCount] = useMemo(() => {
|
|
29
|
+
const offset = headings.length;
|
|
30
|
+
const createElement = (Component, index) => /* @__PURE__ */ jsx(
|
|
44
31
|
Component,
|
|
45
32
|
{
|
|
33
|
+
ariaRowIndex: offset + index + 2,
|
|
34
|
+
ariaRole: "row",
|
|
46
35
|
columns,
|
|
47
36
|
virtualColSpan
|
|
48
37
|
},
|
|
49
|
-
|
|
38
|
+
index
|
|
50
39
|
);
|
|
40
|
+
const enrichElementWithAria = (el, rowIndex) => {
|
|
41
|
+
const offset2 = headings.length;
|
|
42
|
+
return cloneElement(el, {
|
|
43
|
+
"aria-rowindex": rowIndex + offset2 + 2,
|
|
44
|
+
ariaRole: "row"
|
|
45
|
+
});
|
|
46
|
+
};
|
|
51
47
|
if (customHeader === void 0) {
|
|
52
|
-
return null;
|
|
48
|
+
return [null, 0];
|
|
53
49
|
} else if (Array.isArray(customHeader)) {
|
|
54
50
|
if (customHeader.some(isValidElement)) {
|
|
55
|
-
|
|
56
|
-
(
|
|
51
|
+
const header = /* @__PURE__ */ jsx(HeaderProvider, { columns, virtualColSpan, children: customHeader.map(
|
|
52
|
+
(header2, i) => isValidElement(header2) ? enrichElementWithAria(header2, i) : createElement(header2, i)
|
|
57
53
|
) });
|
|
54
|
+
return [header, customHeader.length];
|
|
58
55
|
} else {
|
|
59
|
-
return customHeader.map(createElement);
|
|
56
|
+
return [customHeader.map(createElement), customHeader.length];
|
|
60
57
|
}
|
|
61
58
|
} else if (isValidElement(customHeader)) {
|
|
62
|
-
|
|
59
|
+
const header = /* @__PURE__ */ jsx(HeaderProvider, { columns, virtualColSpan, children: enrichElementWithAria(customHeader, 0) });
|
|
60
|
+
return [header, 1];
|
|
63
61
|
} else {
|
|
64
|
-
return createElement(customHeader);
|
|
62
|
+
return [createElement(customHeader, 0), 1];
|
|
65
63
|
}
|
|
66
|
-
}, [columns, customHeader, virtualColSpan]);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
64
|
+
}, [columns, customHeader, headings.length, virtualColSpan]);
|
|
65
|
+
const {
|
|
66
|
+
draggableColumn,
|
|
67
|
+
draggedColumnIndex,
|
|
68
|
+
onClick,
|
|
69
|
+
onMouseDown,
|
|
70
|
+
setContainerRef
|
|
71
|
+
} = useTableHeader({
|
|
72
|
+
allowDragColumnHeader,
|
|
73
|
+
columns,
|
|
74
|
+
customHeaderCount,
|
|
75
|
+
headings,
|
|
76
|
+
onHeightMeasured,
|
|
77
|
+
onMoveColumn,
|
|
78
|
+
onSortColumn,
|
|
79
|
+
tableConfig
|
|
80
|
+
});
|
|
81
|
+
return /* @__PURE__ */ jsxs(
|
|
82
|
+
"div",
|
|
83
|
+
{
|
|
84
|
+
className: `${classBase}-col-headings`,
|
|
85
|
+
ref: setContainerRef,
|
|
86
|
+
role: "rowgroup",
|
|
87
|
+
children: [
|
|
88
|
+
headings.map((colHeaders, i) => /* @__PURE__ */ jsx(
|
|
89
|
+
"div",
|
|
81
90
|
{
|
|
82
|
-
"
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
onRemoveColumn: onRemoveGroupColumn,
|
|
87
|
-
onResize: onResizeColumn
|
|
91
|
+
className: "vuuTable-heading",
|
|
92
|
+
role: "row",
|
|
93
|
+
"aria-rowindex": i + 1,
|
|
94
|
+
children: colHeaders.map(({ label, width }, j) => /* @__PURE__ */ jsx("div", { className: "vuuTable-headingCell", style: { width }, children: label }, j))
|
|
88
95
|
},
|
|
89
|
-
|
|
90
|
-
)
|
|
91
|
-
|
|
96
|
+
i
|
|
97
|
+
)),
|
|
98
|
+
/* @__PURE__ */ jsxs(
|
|
99
|
+
"div",
|
|
92
100
|
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
className: `${classBase}-col-headers`,
|
|
102
|
+
role: "row",
|
|
103
|
+
"aria-rowindex": headings.length + 1,
|
|
104
|
+
children: [
|
|
105
|
+
virtualColSpan > 0 ? /* @__PURE__ */ jsx(
|
|
106
|
+
"div",
|
|
107
|
+
{
|
|
108
|
+
role: "cell",
|
|
109
|
+
className: "vuuTableCell",
|
|
110
|
+
style: { width: virtualColSpan }
|
|
111
|
+
}
|
|
112
|
+
) : null,
|
|
113
|
+
columns.filter(isNotHidden).map(
|
|
114
|
+
(col, i) => isGroupColumn(col) ? /* @__PURE__ */ jsx(
|
|
115
|
+
GroupHeaderCell,
|
|
116
|
+
{
|
|
117
|
+
"aria-colindex": col.index,
|
|
118
|
+
column: col,
|
|
119
|
+
"data-index": i,
|
|
120
|
+
onMoveColumn: onMoveGroupColumn,
|
|
121
|
+
onRemoveColumn: onRemoveGroupColumn,
|
|
122
|
+
onResize: onResizeColumn
|
|
123
|
+
},
|
|
124
|
+
col.name
|
|
125
|
+
) : /* @__PURE__ */ jsx(
|
|
126
|
+
HeaderCell,
|
|
127
|
+
{
|
|
128
|
+
"aria-colindex": col.index,
|
|
129
|
+
className: cx({
|
|
130
|
+
"vuuDraggable-dragAway": i === draggedColumnIndex
|
|
131
|
+
}),
|
|
132
|
+
column: col,
|
|
133
|
+
"data-index": i,
|
|
134
|
+
id: `${tableId}-col-${i}`,
|
|
135
|
+
onClick,
|
|
136
|
+
onMouseDown,
|
|
137
|
+
onResize: onResizeColumn,
|
|
138
|
+
showMenu: showColumnHeaderMenus
|
|
139
|
+
},
|
|
140
|
+
col.name
|
|
141
|
+
)
|
|
142
|
+
),
|
|
143
|
+
draggableColumn
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
),
|
|
147
|
+
customHeaders
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
);
|
|
112
151
|
}
|
|
113
152
|
);
|
|
114
153
|
TableHeader.displayName = "TableHeader";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableHeader.js","sources":["../../src/table-header/TableHeader.tsx"],"sourcesContent":["import { VuuSortType } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n ColumnDescriptor,\n CustomHeader,\n RuntimeColumnDescriptor,\n TableColumnResizeHandler,\n TableConfig,\n TableHeadings,\n} from \"@vuu-ui/vuu-table-types\";\nimport { isGroupColumn, isNotHidden } from \"@vuu-ui/vuu-utils\";\nimport cx from \"clsx\";\nimport { isValidElement, memo, useMemo } from \"react\";\nimport { GroupHeaderCell, HeaderCell } from \"../header-cell\";\nimport { useTableHeader } from \"./useTableHeader\";\nimport { HeaderProvider } from \"./HeaderProvider\";\n\nexport type ColumnSortHandler = (\n column: ColumnDescriptor,\n addToExistingSort: boolean,\n sortType?: VuuSortType,\n) => void;\n\nexport interface TableHeaderProps {\n allowDragColumnHeader: boolean;\n classBase?: string;\n columns: RuntimeColumnDescriptor[];\n customHeader?: CustomHeader | CustomHeader[];\n headings: TableHeadings;\n onHeightMeasured: (height: number) => void;\n onResizeColumn: TableColumnResizeHandler;\n onMoveColumn: (columns: ColumnDescriptor[]) => void;\n onMoveGroupColumn: (columns: ColumnDescriptor[]) => void;\n onRemoveGroupColumn: (column: RuntimeColumnDescriptor) => void;\n onSortColumn: ColumnSortHandler;\n showColumnHeaderMenus: boolean;\n tableConfig: TableConfig;\n tableId: string;\n virtualColSpan?: number;\n}\n\nexport const TableHeader = memo(\n ({\n allowDragColumnHeader,\n classBase = \"vuuTable\",\n columns,\n customHeader,\n headings,\n onHeightMeasured,\n onMoveColumn,\n onMoveGroupColumn,\n onRemoveGroupColumn,\n onResizeColumn,\n onSortColumn,\n showColumnHeaderMenus,\n tableConfig,\n tableId,\n virtualColSpan = 0,\n }: TableHeaderProps) => {\n const {\n draggableColumn,\n draggedColumnIndex,\n onClick,\n onMouseDown,\n setContainerRef,\n } = useTableHeader({\n allowDragColumnHeader,\n columns,\n onHeightMeasured,\n onMoveColumn,\n onSortColumn,\n tableConfig,\n });\n\n const customHeaders = useMemo(() => {\n const createElement = (Component: CustomHeader, key?: number) => (\n <Component\n columns={columns}\n key={key}\n virtualColSpan={virtualColSpan}\n />\n );\n if (customHeader === undefined) {\n return null;\n } else if (Array.isArray(customHeader)) {\n if (customHeader.some(isValidElement)) {\n return (\n <HeaderProvider columns={columns} virtualColSpan={virtualColSpan}>\n {customHeader.map((header, i) =>\n isValidElement(header) ? header : createElement(header, i),\n )}\n </HeaderProvider>\n );\n } else {\n return customHeader.map(createElement);\n }\n } else if (isValidElement(customHeader)) {\n return (\n <HeaderProvider columns={columns} virtualColSpan={virtualColSpan}>\n {customHeader}\n </HeaderProvider>\n );\n } else {\n return createElement(customHeader);\n }\n }, [columns, customHeader, virtualColSpan]);\n\n return (\n <div className={`${classBase}-col-headings`} ref={setContainerRef}>\n {headings.map((colHeaders, i) => (\n <div className=\"vuuTable-heading\" key={i}>\n {colHeaders.map(({ label, width }, j) => (\n <div key={j} className=\"vuuTable-headingCell\" style={{ width }}>\n {label}\n </div>\n ))}\n </div>\n ))}\n <div className={`${classBase}-col-headers`} role=\"row\">\n {virtualColSpan > 0 ? (\n <div\n role=\"cell\"\n className=\"vuuTableCell\"\n style={{ width: virtualColSpan }}\n />\n ) : null}\n {columns.filter(isNotHidden).map((col, i) =>\n isGroupColumn(col) ? (\n <GroupHeaderCell\n aria-colindex={col.index}\n column={col}\n data-index={i}\n key={col.name}\n onMoveColumn={onMoveGroupColumn}\n onRemoveColumn={onRemoveGroupColumn}\n onResize={onResizeColumn}\n />\n ) : (\n <HeaderCell\n aria-colindex={col.index}\n className={cx({\n \"vuuDraggable-dragAway\": i === draggedColumnIndex,\n })}\n column={col}\n data-index={i}\n id={`${tableId}-col-${i}`}\n key={col.name}\n onClick={onClick}\n onMouseDown={onMouseDown}\n onResize={onResizeColumn}\n showMenu={showColumnHeaderMenus}\n />\n ),\n )}\n {draggableColumn}\n </div>\n {customHeaders}\n </div>\n );\n },\n);\nTableHeader.displayName = \"TableHeader\";\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableHeader.js","sources":["../../src/table-header/TableHeader.tsx"],"sourcesContent":["import { VuuSortType } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n ColumnDescriptor,\n CustomHeader,\n RuntimeColumnDescriptor,\n TableColumnResizeHandler,\n TableConfig,\n TableHeadings,\n} from \"@vuu-ui/vuu-table-types\";\nimport { isGroupColumn, isNotHidden } from \"@vuu-ui/vuu-utils\";\nimport cx from \"clsx\";\nimport { cloneElement, isValidElement, memo, useMemo } from \"react\";\nimport { GroupHeaderCell, HeaderCell } from \"../header-cell\";\nimport { useTableHeader } from \"./useTableHeader\";\nimport { HeaderProvider } from \"./HeaderProvider\";\n\nexport type ColumnSortHandler = (\n column: ColumnDescriptor,\n addToExistingSort: boolean,\n sortType?: VuuSortType,\n) => void;\n\nexport interface TableHeaderProps {\n allowDragColumnHeader: boolean;\n classBase?: string;\n columns: RuntimeColumnDescriptor[];\n customHeader?: CustomHeader | CustomHeader[];\n headings: TableHeadings;\n onHeightMeasured: (height: number, count: number) => void;\n onResizeColumn: TableColumnResizeHandler;\n onMoveColumn: (columns: ColumnDescriptor[]) => void;\n onMoveGroupColumn: (columns: ColumnDescriptor[]) => void;\n onRemoveGroupColumn: (column: RuntimeColumnDescriptor) => void;\n onSortColumn: ColumnSortHandler;\n showColumnHeaderMenus: boolean;\n tableConfig: TableConfig;\n tableId: string;\n virtualColSpan?: number;\n}\n\nexport const TableHeader = memo(\n ({\n allowDragColumnHeader,\n classBase = \"vuuTable\",\n columns,\n customHeader,\n headings,\n onHeightMeasured,\n onMoveColumn,\n onMoveGroupColumn,\n onRemoveGroupColumn,\n onResizeColumn,\n onSortColumn,\n showColumnHeaderMenus,\n tableConfig,\n tableId,\n virtualColSpan = 0,\n }: TableHeaderProps) => {\n const [customHeaders, customHeaderCount] = useMemo<\n [JSX.Element | JSX.Element[] | null, number]\n >(() => {\n const offset = headings.length;\n const createElement = (Component: CustomHeader, index: number) => (\n <Component\n ariaRowIndex={offset + index + 2}\n ariaRole=\"row\"\n columns={columns}\n key={index}\n virtualColSpan={virtualColSpan}\n />\n );\n\n const enrichElementWithAria = (el: JSX.Element, rowIndex: number) => {\n const offset = headings.length;\n return cloneElement(el, {\n \"aria-rowindex\": rowIndex + offset + 2,\n ariaRole: \"row\",\n });\n };\n\n if (customHeader === undefined) {\n return [null, 0];\n } else if (Array.isArray(customHeader)) {\n if (customHeader.some(isValidElement)) {\n const header = (\n <HeaderProvider columns={columns} virtualColSpan={virtualColSpan}>\n {customHeader.map((header, i) =>\n isValidElement(header)\n ? enrichElementWithAria(header, i)\n : createElement(header, i),\n )}\n </HeaderProvider>\n );\n return [header, customHeader.length];\n } else {\n return [customHeader.map(createElement), customHeader.length];\n }\n } else if (isValidElement(customHeader)) {\n // TODO rowIndex and role\n const header = (\n <HeaderProvider columns={columns} virtualColSpan={virtualColSpan}>\n {enrichElementWithAria(customHeader, 0)}\n </HeaderProvider>\n );\n return [header, 1];\n } else {\n return [createElement(customHeader, 0), 1];\n }\n }, [columns, customHeader, headings.length, virtualColSpan]);\n\n const {\n draggableColumn,\n draggedColumnIndex,\n onClick,\n onMouseDown,\n setContainerRef,\n } = useTableHeader({\n allowDragColumnHeader,\n columns,\n customHeaderCount,\n headings,\n onHeightMeasured,\n onMoveColumn,\n onSortColumn,\n tableConfig,\n });\n\n return (\n <div\n className={`${classBase}-col-headings`}\n ref={setContainerRef}\n role=\"rowgroup\"\n >\n {headings.map((colHeaders, i) => (\n <div\n className=\"vuuTable-heading\"\n key={i}\n role=\"row\"\n aria-rowindex={i + 1}\n >\n {colHeaders.map(({ label, width }, j) => (\n <div key={j} className=\"vuuTable-headingCell\" style={{ width }}>\n {label}\n </div>\n ))}\n </div>\n ))}\n <div\n className={`${classBase}-col-headers`}\n role=\"row\"\n aria-rowindex={headings.length + 1}\n >\n {virtualColSpan > 0 ? (\n <div\n role=\"cell\"\n className=\"vuuTableCell\"\n style={{ width: virtualColSpan }}\n />\n ) : null}\n {columns.filter(isNotHidden).map((col, i) =>\n isGroupColumn(col) ? (\n <GroupHeaderCell\n aria-colindex={col.index}\n column={col}\n data-index={i}\n key={col.name}\n onMoveColumn={onMoveGroupColumn}\n onRemoveColumn={onRemoveGroupColumn}\n onResize={onResizeColumn}\n />\n ) : (\n <HeaderCell\n aria-colindex={col.index}\n className={cx({\n \"vuuDraggable-dragAway\": i === draggedColumnIndex,\n })}\n column={col}\n data-index={i}\n id={`${tableId}-col-${i}`}\n key={col.name}\n onClick={onClick}\n onMouseDown={onMouseDown}\n onResize={onResizeColumn}\n showMenu={showColumnHeaderMenus}\n />\n ),\n )}\n {draggableColumn}\n </div>\n {customHeaders}\n </div>\n );\n },\n);\nTableHeader.displayName = \"TableHeader\";\n"],"names":["offset","header"],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ import { useForkRef } from '@salt-ds/core';
|
|
|
7
7
|
const useTableHeader = ({
|
|
8
8
|
allowDragColumnHeader,
|
|
9
9
|
columns,
|
|
10
|
+
customHeaderCount,
|
|
11
|
+
headings,
|
|
10
12
|
onHeightMeasured,
|
|
11
13
|
onMoveColumn,
|
|
12
14
|
onSortColumn,
|
|
@@ -14,8 +16,14 @@ const useTableHeader = ({
|
|
|
14
16
|
}) => {
|
|
15
17
|
const containerRef = useRef(null);
|
|
16
18
|
const scrollingContainerRef = useRef(null);
|
|
19
|
+
const handleHeightMeasured = useCallback(
|
|
20
|
+
(height) => {
|
|
21
|
+
onHeightMeasured(height, customHeaderCount + headings.length + 1);
|
|
22
|
+
},
|
|
23
|
+
[customHeaderCount, headings, onHeightMeasured]
|
|
24
|
+
);
|
|
17
25
|
const { measuredRef: rowRef } = useMeasuredHeight({
|
|
18
|
-
onHeightMeasured
|
|
26
|
+
onHeightMeasured: handleHeightMeasured
|
|
19
27
|
});
|
|
20
28
|
const setContainerRef = useCallback((el) => {
|
|
21
29
|
containerRef.current = el;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableHeader.js","sources":["../../src/table-header/useTableHeader.ts"],"sourcesContent":["import { ColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport {\n DropOptions,\n useDragDrop as useDragDrop,\n} from \"@vuu-ui/vuu-ui-controls\";\nimport {\n moveColumnTo,\n queryClosest,\n visibleColumnAtIndex,\n} from \"@vuu-ui/vuu-utils\";\nimport { RefCallback, useCallback, useRef } from \"react\";\nimport { TableHeaderProps } from \"./TableHeader\";\nimport { useMeasuredHeight } from \"../useMeasuredHeight\";\nimport { useForkRef } from \"@salt-ds/core\";\n\nexport interface TableHeaderHookProps\n extends Pick<\n TableHeaderProps,\n | \"allowDragColumnHeader\"\n | \"columns\"\n | \"onMoveColumn\"\n | \"onSortColumn\"\n | \"tableConfig\"\n > {\n label?: string;\n onHeightMeasured: (height: number) => void;\n onMoveColumn: (columns: ColumnDescriptor[]) => void;\n onSortColumn: (column: ColumnDescriptor, addToExistingSort: boolean) => void;\n}\n\nexport const useTableHeader = ({\n allowDragColumnHeader,\n columns,\n onHeightMeasured,\n onMoveColumn,\n onSortColumn,\n tableConfig,\n}: TableHeaderHookProps) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const scrollingContainerRef = useRef<HTMLDivElement | null>(null);\n const { measuredRef: rowRef } = useMeasuredHeight({\n onHeightMeasured,\n });\n\n const setContainerRef = useCallback<RefCallback<HTMLDivElement>>((el) => {\n containerRef.current = el;\n if (el) {\n scrollingContainerRef.current = el.closest(\".vuuTable-contentContainer\");\n } else {\n scrollingContainerRef.current = null;\n }\n }, []);\n\n const handleDropColumnHeader = useCallback(\n ({ fromIndex: moveFrom, toIndex: moveTo }: DropOptions) => {\n const column = columns[moveFrom];\n // columns are what get rendered, so these are the columns that\n // the drop operation relates to. We must translate these into\n // columns within the table config. Grouping complicates this\n // as the group columns are not present in columns but ARE in\n // config.columns\n const orderedColumns = moveColumnTo(columns, column, moveTo);\n\n const ofColumn =\n ({ name }: ColumnDescriptor) =>\n (col: ColumnDescriptor) =>\n col.name === name;\n\n const targetIndex = orderedColumns.findIndex(ofColumn(column));\n const nextColumn = orderedColumns[targetIndex + 1];\n const insertPos = nextColumn\n ? tableConfig.columns.findIndex(ofColumn(nextColumn))\n : -1;\n\n if (moveTo > moveFrom && insertPos !== -1) {\n onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos - 1));\n } else {\n onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos));\n }\n },\n [columns, onMoveColumn, tableConfig.columns],\n );\n\n const handleColumnHeaderClick = useCallback(\n (evt: React.MouseEvent | React.KeyboardEvent) => {\n const headerCell = queryClosest(evt.target, \".vuuTableHeaderCell\");\n const colIdx = parseInt(headerCell?.dataset.index ?? \"-1\");\n const column = visibleColumnAtIndex(columns, colIdx);\n const isAdditive = evt.shiftKey;\n column && onSortColumn(column, isAdditive);\n },\n [columns, onSortColumn],\n );\n\n // Drag Drop column headers\n const {\n onMouseDown: columnHeaderDragMouseDown,\n draggable: draggableColumn,\n ...dragDropHook\n } = useDragDrop({\n allowDragDrop: allowDragColumnHeader,\n containerRef,\n draggableClassName: `vuuTable`,\n itemQuery: \".vuuTableHeaderCell\",\n onDrop: handleDropColumnHeader,\n orientation: \"horizontal\",\n scrollingContainerRef,\n });\n\n return {\n draggableColumn,\n draggedColumnIndex: dragDropHook.draggedItemIndex,\n onClick: handleColumnHeaderClick,\n onMouseDown: columnHeaderDragMouseDown,\n setContainerRef: useForkRef(setContainerRef, rowRef),\n };\n};\n"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"useTableHeader.js","sources":["../../src/table-header/useTableHeader.ts"],"sourcesContent":["import { ColumnDescriptor, TableHeadings } from \"@vuu-ui/vuu-table-types\";\nimport {\n DropOptions,\n useDragDrop as useDragDrop,\n} from \"@vuu-ui/vuu-ui-controls\";\nimport {\n moveColumnTo,\n queryClosest,\n visibleColumnAtIndex,\n} from \"@vuu-ui/vuu-utils\";\nimport { RefCallback, useCallback, useRef } from \"react\";\nimport { TableHeaderProps } from \"./TableHeader\";\nimport { useMeasuredHeight } from \"../useMeasuredHeight\";\nimport { useForkRef } from \"@salt-ds/core\";\n\nexport interface TableHeaderHookProps\n extends Pick<\n TableHeaderProps,\n | \"allowDragColumnHeader\"\n | \"columns\"\n | \"onMoveColumn\"\n | \"onSortColumn\"\n | \"tableConfig\"\n > {\n customHeaderCount: number;\n headings: TableHeadings;\n label?: string;\n onHeightMeasured: (height: number, customHeaderCount: number) => void;\n onMoveColumn: (columns: ColumnDescriptor[]) => void;\n onSortColumn: (column: ColumnDescriptor, addToExistingSort: boolean) => void;\n}\n\nexport const useTableHeader = ({\n allowDragColumnHeader,\n columns,\n customHeaderCount,\n headings,\n onHeightMeasured,\n onMoveColumn,\n onSortColumn,\n tableConfig,\n}: TableHeaderHookProps) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const scrollingContainerRef = useRef<HTMLDivElement | null>(null);\n\n const handleHeightMeasured = useCallback(\n (height: number) => {\n onHeightMeasured(height, customHeaderCount + headings.length + 1);\n },\n [customHeaderCount, headings, onHeightMeasured],\n );\n\n const { measuredRef: rowRef } = useMeasuredHeight({\n onHeightMeasured: handleHeightMeasured,\n });\n\n const setContainerRef = useCallback<RefCallback<HTMLDivElement>>((el) => {\n containerRef.current = el;\n if (el) {\n scrollingContainerRef.current = el.closest(\".vuuTable-contentContainer\");\n } else {\n scrollingContainerRef.current = null;\n }\n }, []);\n\n const handleDropColumnHeader = useCallback(\n ({ fromIndex: moveFrom, toIndex: moveTo }: DropOptions) => {\n const column = columns[moveFrom];\n // columns are what get rendered, so these are the columns that\n // the drop operation relates to. We must translate these into\n // columns within the table config. Grouping complicates this\n // as the group columns are not present in columns but ARE in\n // config.columns\n const orderedColumns = moveColumnTo(columns, column, moveTo);\n\n const ofColumn =\n ({ name }: ColumnDescriptor) =>\n (col: ColumnDescriptor) =>\n col.name === name;\n\n const targetIndex = orderedColumns.findIndex(ofColumn(column));\n const nextColumn = orderedColumns[targetIndex + 1];\n const insertPos = nextColumn\n ? tableConfig.columns.findIndex(ofColumn(nextColumn))\n : -1;\n\n if (moveTo > moveFrom && insertPos !== -1) {\n onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos - 1));\n } else {\n onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos));\n }\n },\n [columns, onMoveColumn, tableConfig.columns],\n );\n\n const handleColumnHeaderClick = useCallback(\n (evt: React.MouseEvent | React.KeyboardEvent) => {\n const headerCell = queryClosest(evt.target, \".vuuTableHeaderCell\");\n const colIdx = parseInt(headerCell?.dataset.index ?? \"-1\");\n const column = visibleColumnAtIndex(columns, colIdx);\n const isAdditive = evt.shiftKey;\n column && onSortColumn(column, isAdditive);\n },\n [columns, onSortColumn],\n );\n\n // Drag Drop column headers\n const {\n onMouseDown: columnHeaderDragMouseDown,\n draggable: draggableColumn,\n ...dragDropHook\n } = useDragDrop({\n allowDragDrop: allowDragColumnHeader,\n containerRef,\n draggableClassName: `vuuTable`,\n itemQuery: \".vuuTableHeaderCell\",\n onDrop: handleDropColumnHeader,\n orientation: \"horizontal\",\n scrollingContainerRef,\n });\n\n return {\n draggableColumn,\n draggedColumnIndex: dragDropHook.draggedItemIndex,\n onClick: handleColumnHeaderClick,\n onMouseDown: columnHeaderDragMouseDown,\n setContainerRef: useForkRef(setContainerRef, rowRef),\n };\n};\n"],"names":[],"mappings":"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"}
|
package/esm/useCellFocus.js
CHANGED
|
@@ -52,11 +52,11 @@ const useCellFocus = ({
|
|
|
52
52
|
if (table) {
|
|
53
53
|
if (state.el === null && !disableFocus) {
|
|
54
54
|
const headerCell = table.querySelector(
|
|
55
|
-
headerCellQuery(
|
|
55
|
+
headerCellQuery(1)
|
|
56
56
|
);
|
|
57
57
|
if (headerCell) {
|
|
58
58
|
headerCell.setAttribute("tabindex", "0");
|
|
59
|
-
state.cellPos = [
|
|
59
|
+
state.cellPos = [1, 1];
|
|
60
60
|
state.el = headerCell;
|
|
61
61
|
state.pos = { top: -20 };
|
|
62
62
|
if (state.placeholderEl) {
|
|
@@ -68,7 +68,7 @@ const useCellFocus = ({
|
|
|
68
68
|
);
|
|
69
69
|
if (cell) {
|
|
70
70
|
cell.setAttribute("tabindex", "0");
|
|
71
|
-
state.cellPos = [
|
|
71
|
+
state.cellPos = [1, 1];
|
|
72
72
|
state.el = cell;
|
|
73
73
|
state.pos = { top: 0 };
|
|
74
74
|
if (state.placeholderEl) {
|
package/esm/useCellFocus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCellFocus.js","sources":["../src/useCellFocus.ts"],"sourcesContent":["import {\n KeyboardEventHandler,\n MutableRefObject,\n RefCallback,\n RefObject,\n useCallback,\n} from \"react\";\nimport {\n dataCellQuery,\n getTableCell,\n headerCellQuery,\n} from \"./table-dom-utils\";\nimport { ScrollRequestHandler } from \"./useTableScroll\";\nimport { isArrowKey, queryClosest } from \"@vuu-ui/vuu-utils\";\nimport { CellFocusState, CellPos } from \"@vuu-ui/vuu-table-types\";\n\nexport interface CellFocusHookProps {\n cellFocusStateRef: MutableRefObject<CellFocusState>;\n containerRef: RefObject<HTMLElement>;\n disableFocus?: boolean;\n requestScroll?: ScrollRequestHandler;\n}\n\nconst getCellPosition = (el: HTMLElement) => {\n const top = parseInt(el.parentElement?.style.top ?? \"-1\");\n return { top };\n};\n\nexport type FocusCell = (cellPos: CellPos, fromKeyboard?: boolean) => void;\n\nexport const useCellFocus = ({\n cellFocusStateRef,\n containerRef,\n disableFocus = false,\n requestScroll,\n}: CellFocusHookProps) => {\n const focusCellPlaceholderRef = useCallback<RefCallback<HTMLDivElement>>(\n (el) => (cellFocusStateRef.current.placeholderEl = el),\n [cellFocusStateRef],\n );\n\n const focusCell = useCallback<FocusCell>(\n (cellPos, fromKeyboard = false) => {\n if (containerRef.current) {\n const { current: state } = cellFocusStateRef;\n\n if (fromKeyboard && state.outsideViewport) {\n state.cellPos = cellPos;\n } else {\n const activeCell = getTableCell(containerRef, cellPos);\n if (activeCell) {\n if (activeCell !== state.el) {\n state.el?.removeAttribute(\"tabindex\");\n activeCell.setAttribute(\"tabindex\", \"0\");\n\n // TODO no need to measure if we're navigating horizontally\n state.cellPos = cellPos;\n state.el = activeCell;\n state.pos = getCellPosition(activeCell);\n state.outsideViewport = false;\n\n if (state.placeholderEl) {\n state.placeholderEl.style.top = `${state.pos.top}px`;\n }\n }\n // TODO needs to be scroll cell to accommodate horizontal virtualization\n requestScroll?.({ type: \"scroll-row\", rowIndex: cellPos[0] });\n activeCell.focus({ preventScroll: true });\n }\n }\n }\n },\n [cellFocusStateRef, containerRef, requestScroll],\n );\n\n const tableBodyRef = useCallback<RefCallback<HTMLDivElement>>(\n (el) => {\n if (el) {\n const { current: state } = cellFocusStateRef;\n const table = queryClosest<HTMLDivElement>(el, \".vuuTable\");\n if (table) {\n if (state.el === null && !disableFocus) {\n const headerCell = table.querySelector<HTMLDivElement>(\n headerCellQuery(
|
|
1
|
+
{"version":3,"file":"useCellFocus.js","sources":["../src/useCellFocus.ts"],"sourcesContent":["import {\n KeyboardEventHandler,\n MutableRefObject,\n RefCallback,\n RefObject,\n useCallback,\n} from \"react\";\nimport {\n dataCellQuery,\n getTableCell,\n headerCellQuery,\n} from \"./table-dom-utils\";\nimport { ScrollRequestHandler } from \"./useTableScroll\";\nimport { isArrowKey, queryClosest } from \"@vuu-ui/vuu-utils\";\nimport { CellFocusState, CellPos } from \"@vuu-ui/vuu-table-types\";\n\nexport interface CellFocusHookProps {\n cellFocusStateRef: MutableRefObject<CellFocusState>;\n containerRef: RefObject<HTMLElement>;\n disableFocus?: boolean;\n requestScroll?: ScrollRequestHandler;\n}\n\nconst getCellPosition = (el: HTMLElement) => {\n const top = parseInt(el.parentElement?.style.top ?? \"-1\");\n return { top };\n};\n\nexport type FocusCell = (cellPos: CellPos, fromKeyboard?: boolean) => void;\n\nexport const useCellFocus = ({\n cellFocusStateRef,\n containerRef,\n disableFocus = false,\n requestScroll,\n}: CellFocusHookProps) => {\n const focusCellPlaceholderRef = useCallback<RefCallback<HTMLDivElement>>(\n (el) => (cellFocusStateRef.current.placeholderEl = el),\n [cellFocusStateRef],\n );\n\n const focusCell = useCallback<FocusCell>(\n (cellPos, fromKeyboard = false) => {\n if (containerRef.current) {\n const { current: state } = cellFocusStateRef;\n\n if (fromKeyboard && state.outsideViewport) {\n state.cellPos = cellPos;\n } else {\n const activeCell = getTableCell(containerRef, cellPos);\n if (activeCell) {\n if (activeCell !== state.el) {\n state.el?.removeAttribute(\"tabindex\");\n activeCell.setAttribute(\"tabindex\", \"0\");\n\n // TODO no need to measure if we're navigating horizontally\n state.cellPos = cellPos;\n state.el = activeCell;\n state.pos = getCellPosition(activeCell);\n state.outsideViewport = false;\n\n if (state.placeholderEl) {\n state.placeholderEl.style.top = `${state.pos.top}px`;\n }\n }\n // TODO needs to be scroll cell to accommodate horizontal virtualization\n requestScroll?.({ type: \"scroll-row\", rowIndex: cellPos[0] });\n activeCell.focus({ preventScroll: true });\n }\n }\n }\n },\n [cellFocusStateRef, containerRef, requestScroll],\n );\n\n const tableBodyRef = useCallback<RefCallback<HTMLDivElement>>(\n (el) => {\n if (el) {\n const { current: state } = cellFocusStateRef;\n const table = queryClosest<HTMLDivElement>(el, \".vuuTable\");\n if (table) {\n if (state.el === null && !disableFocus) {\n const headerCell = table.querySelector<HTMLDivElement>(\n headerCellQuery(1),\n );\n if (headerCell) {\n headerCell.setAttribute(\"tabindex\", \"0\");\n state.cellPos = [1, 1];\n state.el = headerCell;\n state.pos = { top: -20 };\n if (state.placeholderEl) {\n state.placeholderEl.style.top = `-20px`;\n }\n } else {\n const cell = table.querySelector<HTMLDivElement>(\n dataCellQuery(0, 0),\n );\n if (cell) {\n cell.setAttribute(\"tabindex\", \"0\");\n state.cellPos = [1, 1];\n state.el = cell;\n state.pos = { top: 0 };\n if (state.placeholderEl) {\n state.placeholderEl.style.top = `0px`;\n }\n }\n }\n }\n }\n }\n },\n [cellFocusStateRef, disableFocus],\n );\n\n const focusCellPlaceholderKeyDown = useCallback<KeyboardEventHandler>(\n (evt) => {\n const { outsideViewport, pos } = cellFocusStateRef.current;\n if (pos && isArrowKey(evt.key)) {\n // TODO depends on whether we're scrolling up or down\n if (outsideViewport === \"above\") {\n requestScroll?.({ type: \"scroll-top\", scrollPos: pos.top });\n } else if (outsideViewport === \"below\") {\n requestScroll?.({ type: \"scroll-bottom\", scrollPos: pos.top });\n } else {\n throw Error(\n `cellFocusPlaceholder should not have focus if inside viewport`,\n );\n }\n }\n },\n [cellFocusStateRef, requestScroll],\n );\n\n return {\n focusCell,\n focusCellPlaceholderKeyDown,\n focusCellPlaceholderRef,\n tableBodyRef,\n };\n};\n"],"names":[],"mappings":"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"}
|