@vuu-ui/vuu-table 0.13.95-alpha.1 → 0.13.95-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/useCellFocus.js +14 -18
- package/cjs/useCellFocus.js.map +1 -1
- package/cjs/useKeyboardNavigation.js +4 -9
- package/cjs/useKeyboardNavigation.js.map +1 -1
- package/cjs/useTableScroll.js.map +1 -1
- package/esm/useCellFocus.js +14 -18
- package/esm/useCellFocus.js.map +1 -1
- package/esm/useKeyboardNavigation.js +4 -9
- package/esm/useKeyboardNavigation.js.map +1 -1
- package/esm/useTableScroll.js.map +1 -1
- package/package.json +10 -10
- package/types/useTableScroll.d.ts +2 -2
package/cjs/useCellFocus.js
CHANGED
|
@@ -27,29 +27,25 @@ const useCellFocus = ({
|
|
|
27
27
|
[cellFocusStateRef]
|
|
28
28
|
);
|
|
29
29
|
const focusCell = react.useCallback(
|
|
30
|
-
(cellPos
|
|
30
|
+
(cellPos) => {
|
|
31
31
|
if (containerRef.current) {
|
|
32
32
|
const { current: state } = cellFocusStateRef;
|
|
33
33
|
if (isDifferentCellPosition(state.cellPos, cellPos)) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
state.
|
|
44
|
-
state.outsideViewport = false;
|
|
45
|
-
if (state.placeholderEl) {
|
|
46
|
-
state.placeholderEl.style.top = `${state.pos.top}px`;
|
|
47
|
-
}
|
|
34
|
+
const activeCell = tableDomUtils.getTableCell(containerRef, cellPos);
|
|
35
|
+
if (activeCell) {
|
|
36
|
+
if (activeCell !== state.el) {
|
|
37
|
+
state.el?.removeAttribute("tabindex");
|
|
38
|
+
activeCell.setAttribute("tabindex", "0");
|
|
39
|
+
state.el = activeCell;
|
|
40
|
+
state.pos = getCellPosition(activeCell);
|
|
41
|
+
state.outsideViewport = false;
|
|
42
|
+
if (state.placeholderEl) {
|
|
43
|
+
state.placeholderEl.style.top = `${state.pos.top}px`;
|
|
48
44
|
}
|
|
49
|
-
state.cellPos = cellPos;
|
|
50
|
-
requestScroll?.({ type: "scroll-row", rowIndex: cellPos[0] });
|
|
51
|
-
activeCell.focus({ preventScroll: true });
|
|
52
45
|
}
|
|
46
|
+
state.cellPos = cellPos;
|
|
47
|
+
requestScroll?.({ type: "scroll-row", rowIndex: cellPos[0] });
|
|
48
|
+
activeCell.focus({ preventScroll: true });
|
|
53
49
|
}
|
|
54
50
|
}
|
|
55
51
|
}
|
package/cjs/useCellFocus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCellFocus.js","sources":["../../../packages/vuu-table/src/useCellFocus.ts"],"sourcesContent":["import {\n KeyboardEventHandler,\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 { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport type { ICellFocusState } from \"./CellFocusState\";\n\nexport interface CellFocusHookProps {\n cellFocusStateRef: RefObject<ICellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\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\nconst isDifferentCellPosition = (\n currentPos: CellPos | undefined,\n newPos: CellPos,\n) => {\n if (currentPos === undefined) {\n return true;\n }\n return currentPos[0] !== newPos[0] || currentPos[1] !== newPos[1];\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) => {\n cellFocusStateRef.current.placeholderEl = el;\n },\n [cellFocusStateRef],\n );\n\n const focusCell = useCallback<FocusCell>(\n (cellPos
|
|
1
|
+
{"version":3,"file":"useCellFocus.js","sources":["../../../packages/vuu-table/src/useCellFocus.ts"],"sourcesContent":["import {\n KeyboardEventHandler,\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 { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport type { ICellFocusState } from \"./CellFocusState\";\n\nexport interface CellFocusHookProps {\n cellFocusStateRef: RefObject<ICellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\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\nconst isDifferentCellPosition = (\n currentPos: CellPos | undefined,\n newPos: CellPos,\n) => {\n if (currentPos === undefined) {\n return true;\n }\n return currentPos[0] !== newPos[0] || currentPos[1] !== newPos[1];\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) => {\n cellFocusStateRef.current.placeholderEl = el;\n },\n [cellFocusStateRef],\n );\n\n const focusCell = useCallback<FocusCell>(\n (cellPos) => {\n if (containerRef.current) {\n const { current: state } = cellFocusStateRef;\n if (isDifferentCellPosition(state.cellPos, cellPos)) {\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 state.cellPos = cellPos;\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 setTableBodyRef = 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 setTableBodyRef,\n };\n};\n"],"names":["useCallback","getTableCell","queryClosest","headerCellQuery","dataCellQuery","isArrowKey"],"mappings":"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"}
|
|
@@ -100,12 +100,12 @@ const useKeyboardNavigation = ({
|
|
|
100
100
|
[onHighlight, setHighlightedIdx]
|
|
101
101
|
);
|
|
102
102
|
const setActiveCell = react.useCallback(
|
|
103
|
-
(rowIdx, colIdx
|
|
103
|
+
(rowIdx, colIdx) => {
|
|
104
104
|
const pos = [rowIdx, colIdx];
|
|
105
105
|
if (navigationStyle === "row") {
|
|
106
106
|
setHighlightedIdx(rowIdx);
|
|
107
107
|
} else {
|
|
108
|
-
focusCell(pos
|
|
108
|
+
focusCell(pos);
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
[focusCell, navigationStyle, setHighlightedIdx]
|
|
@@ -113,12 +113,10 @@ const useKeyboardNavigation = ({
|
|
|
113
113
|
const nextPageItemIdx = react.useCallback(
|
|
114
114
|
(key, [rowIdx, colIdx]) => new Promise((resolve) => {
|
|
115
115
|
let newRowIdx = rowIdx;
|
|
116
|
-
const { current: focusState } = cellFocusStateRef;
|
|
117
116
|
switch (key) {
|
|
118
117
|
case "PageDown": {
|
|
119
118
|
newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);
|
|
120
119
|
if (newRowIdx !== rowIdx) {
|
|
121
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
122
120
|
requestScroll?.({ type: "scroll-page", direction: "down" });
|
|
123
121
|
}
|
|
124
122
|
break;
|
|
@@ -126,7 +124,6 @@ const useKeyboardNavigation = ({
|
|
|
126
124
|
case "PageUp": {
|
|
127
125
|
newRowIdx = Math.max(0, rowIdx - viewportRowCount);
|
|
128
126
|
if (newRowIdx !== rowIdx) {
|
|
129
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
130
127
|
requestScroll?.({ type: "scroll-page", direction: "up" });
|
|
131
128
|
}
|
|
132
129
|
break;
|
|
@@ -134,7 +131,6 @@ const useKeyboardNavigation = ({
|
|
|
134
131
|
case "Home": {
|
|
135
132
|
newRowIdx = headerCount + 1;
|
|
136
133
|
if (newRowIdx !== rowIdx) {
|
|
137
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
138
134
|
requestScroll?.({ type: "scroll-end", direction: "home" });
|
|
139
135
|
}
|
|
140
136
|
break;
|
|
@@ -142,7 +138,6 @@ const useKeyboardNavigation = ({
|
|
|
142
138
|
case "End": {
|
|
143
139
|
newRowIdx = rowCount + headerCount;
|
|
144
140
|
if (newRowIdx !== rowIdx) {
|
|
145
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
146
141
|
requestScroll?.({ type: "scroll-end", direction: "end" });
|
|
147
142
|
}
|
|
148
143
|
break;
|
|
@@ -152,7 +147,7 @@ const useKeyboardNavigation = ({
|
|
|
152
147
|
resolve([newRowIdx, colIdx]);
|
|
153
148
|
}, 35);
|
|
154
149
|
}),
|
|
155
|
-
[
|
|
150
|
+
[headerCount, requestScroll, rowCount, viewportRowCount]
|
|
156
151
|
);
|
|
157
152
|
const handleFocus = react.useCallback(() => {
|
|
158
153
|
if (disableHighlightOnFocus !== true) {
|
|
@@ -205,7 +200,7 @@ const useKeyboardNavigation = ({
|
|
|
205
200
|
}
|
|
206
201
|
}
|
|
207
202
|
if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {
|
|
208
|
-
setActiveCell(nextRowIdx, nextColIdx
|
|
203
|
+
setActiveCell(nextRowIdx, nextColIdx);
|
|
209
204
|
setHighlightedIndex(nextRowIdx);
|
|
210
205
|
}
|
|
211
206
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKeyboardNavigation.js","sources":["../../../packages/vuu-table/src/useKeyboardNavigation.ts"],"sourcesContent":["import { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport { PageKey, queryClosest } from \"@vuu-ui/vuu-utils\";\nimport { useControlled } from \"@salt-ds/core\";\nimport {\n KeyboardEvent,\n MouseEvent,\n RefObject,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport { TableNavigationStyle } from \"./Table\";\nimport {\n NavigationKey,\n cellDropdownShowing,\n closestRowIndex,\n getAriaCellPos,\n getFocusedCell,\n getNextCellPos,\n getTreeNodeOperation,\n getLevelUp as getLevelUp,\n} from \"./table-dom-utils\";\nimport { ScrollRequestHandler } from \"./useTableScroll\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport { CellFocusState } from \"./CellFocusState\";\n\nconst rowNavigationKeys = new Set<NavigationKey>([\n \"Home\",\n \"End\",\n \"PageUp\",\n \"PageDown\",\n \"ArrowDown\",\n \"ArrowUp\",\n]);\n\nconst CellLocator =\n \".vuuTableCell,.vuuTableHeaderCell,.vuuTableGroupHeaderCell\";\n\nconst CellControlLocator = \".vuuColumnMenu,.vuuColumnHeaderPill\";\n\nconst cellNavigationKeys = new Set(rowNavigationKeys);\ncellNavigationKeys.add(\"ArrowLeft\");\ncellNavigationKeys.add(\"ArrowRight\");\n\nexport const isNavigationKey = (\n key: string,\n navigationStyle: TableNavigationStyle,\n): key is NavigationKey => {\n switch (navigationStyle) {\n case \"cell\":\n case \"tree\":\n return cellNavigationKeys.has(key as NavigationKey);\n case \"row\":\n return rowNavigationKeys.has(key as NavigationKey);\n default:\n return false;\n }\n};\n\n// const editCellWithEditInProgress = (el: HTMLElement | null) => {\n// if (el) {\n// const input = el.querySelector(\"input\");\n// return input && document.activeElement === input;\n// }\n// return false;\n// };\n\nconst focusControlWithinCell = (e: KeyboardEvent, el: HTMLElement | null) => {\n if (e.shiftKey && e.key.match(/Arrow(Left|Right)/)) {\n if (el?.classList.contains(\"vuuTableHeaderCell\")) {\n const menuButton = el?.querySelector<HTMLButtonElement>(\".vuuColumnMenu\");\n if (menuButton) {\n menuButton.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuTableGroupHeaderCell\")) {\n const headerPill = el?.querySelector<HTMLButtonElement>(\n \".vuuColumnHeaderPill\",\n );\n if (headerPill) {\n headerPill.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuColumnHeaderPill\")) {\n const nextPill = el.parentElement?.nextElementSibling\n ?.firstChild as HTMLElement;\n if (nextPill?.classList.contains(\"vuuColumnHeaderPill\")) {\n nextPill.focus();\n return true;\n } else {\n const removeButton = queryClosest(\n el,\n \".vuuTableGroupHeaderCell\",\n true,\n ).querySelector(\".vuuTableGroupHeaderCell-removeAll\") as HTMLElement;\n if (removeButton) {\n removeButton.focus();\n return true;\n }\n }\n }\n }\n return false;\n};\n\nconst PageKeys = [\"Home\", \"End\", \"PageUp\", \"PageDown\"];\nexport const isPagingKey = (key: string): key is PageKey =>\n PageKeys.includes(key);\n\nexport type GroupToggleHandler = (\n treeNodeOperation: \"expand\" | \"collapse\",\n rowIndex: number,\n) => void;\n\nexport interface NavigationHookProps {\n cellFocusStateRef: RefObject<CellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\n columnCount?: number;\n headerCount: number;\n defaultHighlightedIndex?: number;\n disableFocus?: boolean;\n disableHighlightOnFocus?: boolean;\n focusCell: FocusCell;\n highlightedIndex?: number;\n label?: string;\n navigationStyle: TableNavigationStyle;\n viewportRange: VuuRange;\n onHighlight?: (idx: number) => void;\n onToggleGroup: GroupToggleHandler;\n requestScroll?: ScrollRequestHandler;\n restoreLastFocus?: boolean;\n rowCount?: number;\n selected?: unknown;\n viewportRowCount: number;\n}\n\nexport const useKeyboardNavigation = ({\n cellFocusStateRef,\n columnCount = 0,\n containerRef,\n defaultHighlightedIndex,\n disableHighlightOnFocus,\n focusCell,\n headerCount,\n highlightedIndex: highlightedIndexProp,\n navigationStyle,\n requestScroll,\n onHighlight,\n onToggleGroup,\n rowCount = 0,\n viewportRowCount,\n}: NavigationHookProps) => {\n // Keep this in sync with state value. This can be used by functions that need\n // to reference highlightedIndex at call time but do not need to be regenerated\n // every time it changes (i.e keep highlightedIndex out of their dependency\n // arrays, as it can update frequently)\n const highlightedIndexRef = useRef<number | undefined>(undefined);\n\n const [highlightedIndex, setHighlightedIdx] = useControlled({\n controlled: highlightedIndexProp,\n default: defaultHighlightedIndex,\n name: \"UseKeyboardNavigation\",\n });\n highlightedIndexRef.current = highlightedIndex;\n\n // We use aria row index for tracking rows\n const maxRowIndex = rowCount + headerCount;\n\n const setHighlightedIndex = useCallback(\n (idx: number) => {\n onHighlight?.(idx);\n setHighlightedIdx(idx);\n highlightedIndexRef.current = idx;\n },\n [onHighlight, setHighlightedIdx],\n );\n\n const setActiveCell = useCallback(\n (rowIdx: number, colIdx: number, fromKeyboard = false) => {\n const pos: CellPos = [rowIdx, colIdx];\n if (navigationStyle === \"row\") {\n setHighlightedIdx(rowIdx);\n } else {\n focusCell(pos, fromKeyboard);\n }\n },\n [focusCell, navigationStyle, setHighlightedIdx],\n );\n\n const nextPageItemIdx = useCallback(\n (\n key: \"PageDown\" | \"PageUp\" | \"Home\" | \"End\",\n [rowIdx, colIdx]: CellPos,\n ): Promise<CellPos> =>\n new Promise((resolve) => {\n let newRowIdx = rowIdx;\n const { current: focusState } = cellFocusStateRef;\n switch (key) {\n case \"PageDown\": {\n newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-page\", direction: \"down\" });\n }\n break;\n }\n case \"PageUp\": {\n newRowIdx = Math.max(0, rowIdx - viewportRowCount);\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-page\", direction: \"up\" });\n }\n break;\n }\n case \"Home\": {\n newRowIdx = headerCount + 1;\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-end\", direction: \"home\" });\n }\n break;\n }\n case \"End\": {\n newRowIdx = rowCount + headerCount;\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-end\", direction: \"end\" });\n }\n break;\n }\n }\n // Introduce a delay to allow the scroll operation to complete,\n // which will trigger a range reset and rerender of rows. We\n // might need to tweak how this works. If we introduce too big\n // a delay, we risk seeing the newly rendered rows, with the focus\n // still on the old cell, which will be apparent as a brief flash\n // of the old cell focus before switching to correct cell. If we were\n // to change the way re assign keys such that we can guarantee that\n // when we page down, rows in same position get same keys, then same\n // cell would be focussed in new page as previous and issue would not\n // arise.\n setTimeout(() => {\n resolve([newRowIdx, colIdx]);\n }, 35);\n }),\n [cellFocusStateRef, headerCount, requestScroll, rowCount, viewportRowCount],\n );\n\n const handleFocus = useCallback(() => {\n // console.log(`[useKeyboardNavigation] handleFocus `);\n if (disableHighlightOnFocus !== true) {\n if (containerRef.current?.contains(document.activeElement)) {\n // IF focus arrives via keyboard, a cell will have received focus,\n // we handle that here. If focus arrives via click on a cell with\n // no tabindex (i.e all cells except one) we leave that to the\n // click handler.\n const focusedCell = getFocusedCell(document.activeElement);\n if (focusedCell) {\n cellFocusStateRef.current.cell = focusedCell;\n if (navigationStyle === \"row\") {\n setHighlightedIdx(cellFocusStateRef.current.cellPos?.[0]);\n }\n }\n }\n }\n }, [\n disableHighlightOnFocus,\n containerRef,\n cellFocusStateRef,\n navigationStyle,\n setHighlightedIdx,\n ]);\n\n const navigateChildItems = useCallback(\n async (\n navigationStyle: \"cell\" | \"tree\" = \"cell\",\n key: NavigationKey,\n shiftKey = false,\n ): Promise<undefined> => {\n const { cellPos } = cellFocusStateRef.current;\n if (cellPos === undefined) {\n throw Error(\"navigateChildItems called before cellPos is set\");\n }\n const [rowIdx, colIdx] = cellPos;\n let nextRowIdx = -1,\n nextColIdx = -1;\n\n if (isPagingKey(key)) {\n [nextRowIdx, nextColIdx] = await nextPageItemIdx(key, cellPos);\n } else {\n const treeNodeOperation = getTreeNodeOperation(\n containerRef,\n navigationStyle,\n cellPos,\n key,\n shiftKey,\n );\n if (\n treeNodeOperation === \"expand\" ||\n treeNodeOperation === \"collapse\"\n ) {\n onToggleGroup(treeNodeOperation, rowIdx - headerCount - 1);\n } else if (treeNodeOperation === \"level-up\") {\n [nextRowIdx, nextColIdx] = getLevelUp(containerRef, cellPos);\n } else {\n [nextRowIdx, nextColIdx] = getNextCellPos(\n key,\n cellPos,\n columnCount,\n maxRowIndex,\n );\n }\n }\n\n if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {\n setActiveCell(nextRowIdx, nextColIdx, true);\n setHighlightedIndex(nextRowIdx);\n }\n },\n [\n cellFocusStateRef,\n nextPageItemIdx,\n containerRef,\n onToggleGroup,\n headerCount,\n columnCount,\n maxRowIndex,\n setActiveCell,\n setHighlightedIndex,\n ],\n );\n\n const scrollRowIntoViewIfNecessary = useCallback(\n (rowIndex: number) => {\n requestScroll?.({ type: \"scroll-row\", rowIndex });\n },\n [requestScroll],\n );\n\n const moveHighlightedRow = useCallback(\n async (key: NavigationKey) => {\n const { current: highlighted } = highlightedIndexRef;\n const [nextRowIdx] = isPagingKey(key)\n ? await nextPageItemIdx(key, [highlighted ?? -1, 0])\n : getNextCellPos(key, [highlighted ?? -1, 0], columnCount, maxRowIndex);\n if (nextRowIdx !== highlighted) {\n setHighlightedIndex(nextRowIdx);\n // TO(DO make this a scroll request)\n scrollRowIntoViewIfNecessary(nextRowIdx);\n }\n },\n [\n columnCount,\n maxRowIndex,\n nextPageItemIdx,\n scrollRowIntoViewIfNecessary,\n setHighlightedIndex,\n ],\n );\n\n useEffect(() => {\n if (highlightedIndexProp !== undefined && highlightedIndexProp !== -1) {\n requestAnimationFrame(() => {\n // deferred call, ensuring table has fully rendered\n scrollRowIntoViewIfNecessary(highlightedIndexProp);\n });\n }\n }, [highlightedIndexProp, scrollRowIntoViewIfNecessary]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n // console.log(`[useKeyboardNavigation] handleKeyDown`);\n\n const cell = queryClosest<HTMLDivElement>(\n e.target,\n `${CellLocator},${CellControlLocator}`,\n );\n if (cellDropdownShowing(cell)) {\n return;\n }\n if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {\n // if (e.key === \"ArrowDown\" && editCellWithEditInProgress(cell)) {\n // // do nothing editCellWithEditInProgress\n // } else {\n // console.log(\n // `[useKeyboardNavigation] handleKeyDown - consume the keydown event`,\n // );\n e.preventDefault();\n e.stopPropagation();\n if (navigationStyle === \"row\") {\n moveHighlightedRow(e.key);\n } else if (navigationStyle !== \"none\") {\n if (!focusControlWithinCell(e, cell)) {\n navigateChildItems(navigationStyle, e.key, e.shiftKey);\n }\n }\n // }\n }\n },\n [rowCount, navigationStyle, moveHighlightedRow, navigateChildItems],\n );\n\n const handleClick = useCallback(\n // Might not be a cell e.g the Settings button\n (evt: MouseEvent) => {\n // console.log(`[useKeyboardNavigation] click`);\n const target = queryClosest<HTMLDivElement>(evt.target, CellLocator);\n const focusedCell = getFocusedCell(target);\n if (focusedCell) {\n const [rowIdx, colIdx] = getAriaCellPos(focusedCell);\n setActiveCell(rowIdx, colIdx);\n }\n },\n [setActiveCell],\n );\n\n const handleMouseLeave = useCallback(() => {\n setHighlightedIndex(-1);\n }, [setHighlightedIndex]);\n\n const handleMouseMove = useCallback(\n (evt: MouseEvent) => {\n const rowIdx = closestRowIndex(evt.target as HTMLElement);\n if (rowIdx !== -1 && rowIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(rowIdx);\n }\n },\n [setHighlightedIndex],\n );\n\n /**\n * used when editing cells\n */\n const navigateCell = useCallback(() => {\n navigateChildItems(\"cell\", \"ArrowDown\");\n }, [navigateChildItems]);\n\n return {\n highlightedIndexRef,\n navigateCell,\n onClick: handleClick,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n onMouseLeave: navigationStyle === \"row\" ? handleMouseLeave : undefined,\n onMouseMove: navigationStyle === \"row\" ? handleMouseMove : undefined,\n };\n};\n"],"names":["queryClosest","useRef","useControlled","useCallback","getFocusedCell","navigationStyle","getTreeNodeOperation","getLevelUp","getNextCellPos","useEffect","cellDropdownShowing","getAriaCellPos","closestRowIndex"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useKeyboardNavigation.js","sources":["../../../packages/vuu-table/src/useKeyboardNavigation.ts"],"sourcesContent":["import { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport { PageKey, queryClosest } from \"@vuu-ui/vuu-utils\";\nimport { useControlled } from \"@salt-ds/core\";\nimport {\n KeyboardEvent,\n MouseEvent,\n RefObject,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport { TableNavigationStyle } from \"./Table\";\nimport {\n NavigationKey,\n cellDropdownShowing,\n closestRowIndex,\n getAriaCellPos,\n getFocusedCell,\n getNextCellPos,\n getTreeNodeOperation,\n getLevelUp as getLevelUp,\n} from \"./table-dom-utils\";\nimport { ScrollRequestHandler } from \"./useTableScroll\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport { CellFocusState } from \"./CellFocusState\";\n\nconst rowNavigationKeys = new Set<NavigationKey>([\n \"Home\",\n \"End\",\n \"PageUp\",\n \"PageDown\",\n \"ArrowDown\",\n \"ArrowUp\",\n]);\n\nconst CellLocator =\n \".vuuTableCell,.vuuTableHeaderCell,.vuuTableGroupHeaderCell\";\n\nconst CellControlLocator = \".vuuColumnMenu,.vuuColumnHeaderPill\";\n\nconst cellNavigationKeys = new Set(rowNavigationKeys);\ncellNavigationKeys.add(\"ArrowLeft\");\ncellNavigationKeys.add(\"ArrowRight\");\n\nexport const isNavigationKey = (\n key: string,\n navigationStyle: TableNavigationStyle,\n): key is NavigationKey => {\n switch (navigationStyle) {\n case \"cell\":\n case \"tree\":\n return cellNavigationKeys.has(key as NavigationKey);\n case \"row\":\n return rowNavigationKeys.has(key as NavigationKey);\n default:\n return false;\n }\n};\n\n// const editCellWithEditInProgress = (el: HTMLElement | null) => {\n// if (el) {\n// const input = el.querySelector(\"input\");\n// return input && document.activeElement === input;\n// }\n// return false;\n// };\n\nconst focusControlWithinCell = (e: KeyboardEvent, el: HTMLElement | null) => {\n if (e.shiftKey && e.key.match(/Arrow(Left|Right)/)) {\n if (el?.classList.contains(\"vuuTableHeaderCell\")) {\n const menuButton = el?.querySelector<HTMLButtonElement>(\".vuuColumnMenu\");\n if (menuButton) {\n menuButton.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuTableGroupHeaderCell\")) {\n const headerPill = el?.querySelector<HTMLButtonElement>(\n \".vuuColumnHeaderPill\",\n );\n if (headerPill) {\n headerPill.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuColumnHeaderPill\")) {\n const nextPill = el.parentElement?.nextElementSibling\n ?.firstChild as HTMLElement;\n if (nextPill?.classList.contains(\"vuuColumnHeaderPill\")) {\n nextPill.focus();\n return true;\n } else {\n const removeButton = queryClosest(\n el,\n \".vuuTableGroupHeaderCell\",\n true,\n ).querySelector(\".vuuTableGroupHeaderCell-removeAll\") as HTMLElement;\n if (removeButton) {\n removeButton.focus();\n return true;\n }\n }\n }\n }\n return false;\n};\n\nconst PageKeys = [\"Home\", \"End\", \"PageUp\", \"PageDown\"];\nexport const isPagingKey = (key: string): key is PageKey =>\n PageKeys.includes(key);\n\nexport type GroupToggleHandler = (\n treeNodeOperation: \"expand\" | \"collapse\",\n rowIndex: number,\n) => void;\n\nexport interface NavigationHookProps {\n cellFocusStateRef: RefObject<CellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\n columnCount?: number;\n headerCount: number;\n defaultHighlightedIndex?: number;\n disableFocus?: boolean;\n disableHighlightOnFocus?: boolean;\n focusCell: FocusCell;\n highlightedIndex?: number;\n label?: string;\n navigationStyle: TableNavigationStyle;\n viewportRange: VuuRange;\n onHighlight?: (idx: number) => void;\n onToggleGroup: GroupToggleHandler;\n requestScroll?: ScrollRequestHandler;\n restoreLastFocus?: boolean;\n rowCount?: number;\n selected?: unknown;\n viewportRowCount: number;\n}\n\nexport const useKeyboardNavigation = ({\n cellFocusStateRef,\n columnCount = 0,\n containerRef,\n defaultHighlightedIndex,\n disableHighlightOnFocus,\n focusCell,\n headerCount,\n highlightedIndex: highlightedIndexProp,\n navigationStyle,\n requestScroll,\n onHighlight,\n onToggleGroup,\n rowCount = 0,\n viewportRowCount,\n}: NavigationHookProps) => {\n // Keep this in sync with state value. This can be used by functions that need\n // to reference highlightedIndex at call time but do not need to be regenerated\n // every time it changes (i.e keep highlightedIndex out of their dependency\n // arrays, as it can update frequently)\n const highlightedIndexRef = useRef<number | undefined>(undefined);\n\n const [highlightedIndex, setHighlightedIdx] = useControlled({\n controlled: highlightedIndexProp,\n default: defaultHighlightedIndex,\n name: \"UseKeyboardNavigation\",\n });\n highlightedIndexRef.current = highlightedIndex;\n\n // We use aria row index for tracking rows\n const maxRowIndex = rowCount + headerCount;\n\n const setHighlightedIndex = useCallback(\n (idx: number) => {\n onHighlight?.(idx);\n setHighlightedIdx(idx);\n highlightedIndexRef.current = idx;\n },\n [onHighlight, setHighlightedIdx],\n );\n\n const setActiveCell = useCallback(\n (rowIdx: number, colIdx: number) => {\n const pos: CellPos = [rowIdx, colIdx];\n if (navigationStyle === \"row\") {\n setHighlightedIdx(rowIdx);\n } else {\n focusCell(pos);\n }\n },\n [focusCell, navigationStyle, setHighlightedIdx],\n );\n\n const nextPageItemIdx = useCallback(\n (\n key: \"PageDown\" | \"PageUp\" | \"Home\" | \"End\",\n [rowIdx, colIdx]: CellPos,\n ): Promise<CellPos> =>\n new Promise((resolve) => {\n let newRowIdx = rowIdx;\n switch (key) {\n case \"PageDown\": {\n newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-page\", direction: \"down\" });\n }\n break;\n }\n case \"PageUp\": {\n newRowIdx = Math.max(0, rowIdx - viewportRowCount);\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-page\", direction: \"up\" });\n }\n break;\n }\n case \"Home\": {\n newRowIdx = headerCount + 1;\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-end\", direction: \"home\" });\n }\n break;\n }\n case \"End\": {\n newRowIdx = rowCount + headerCount;\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-end\", direction: \"end\" });\n }\n break;\n }\n }\n // Introduce a delay to allow the scroll operation to complete,\n // which will trigger a range reset and rerender of rows. We\n // might need to tweak how this works. If we introduce too big\n // a delay, we risk seeing the newly rendered rows, with the focus\n // still on the old cell, which will be apparent as a brief flash\n // of the old cell focus before switching to correct cell. If we were\n // to change the way re assign keys such that we can guarantee that\n // when we page down, rows in same position get same keys, then same\n // cell would be focussed in new page as previous and issue would not\n // arise.\n setTimeout(() => {\n resolve([newRowIdx, colIdx]);\n }, 35);\n }),\n [headerCount, requestScroll, rowCount, viewportRowCount],\n );\n\n const handleFocus = useCallback(() => {\n // console.log(`[useKeyboardNavigation] handleFocus `);\n if (disableHighlightOnFocus !== true) {\n if (containerRef.current?.contains(document.activeElement)) {\n // IF focus arrives via keyboard, a cell will have received focus,\n // we handle that here. If focus arrives via click on a cell with\n // no tabindex (i.e all cells except one) we leave that to the\n // click handler.\n const focusedCell = getFocusedCell(document.activeElement);\n if (focusedCell) {\n cellFocusStateRef.current.cell = focusedCell;\n if (navigationStyle === \"row\") {\n setHighlightedIdx(cellFocusStateRef.current.cellPos?.[0]);\n }\n }\n }\n }\n }, [\n disableHighlightOnFocus,\n containerRef,\n cellFocusStateRef,\n navigationStyle,\n setHighlightedIdx,\n ]);\n\n const navigateChildItems = useCallback(\n async (\n navigationStyle: \"cell\" | \"tree\" = \"cell\",\n key: NavigationKey,\n shiftKey = false,\n ): Promise<undefined> => {\n const { cellPos } = cellFocusStateRef.current;\n if (cellPos === undefined) {\n throw Error(\"navigateChildItems called before cellPos is set\");\n }\n const [rowIdx, colIdx] = cellPos;\n let nextRowIdx = -1,\n nextColIdx = -1;\n\n if (isPagingKey(key)) {\n [nextRowIdx, nextColIdx] = await nextPageItemIdx(key, cellPos);\n } else {\n const treeNodeOperation = getTreeNodeOperation(\n containerRef,\n navigationStyle,\n cellPos,\n key,\n shiftKey,\n );\n if (\n treeNodeOperation === \"expand\" ||\n treeNodeOperation === \"collapse\"\n ) {\n onToggleGroup(treeNodeOperation, rowIdx - headerCount - 1);\n } else if (treeNodeOperation === \"level-up\") {\n [nextRowIdx, nextColIdx] = getLevelUp(containerRef, cellPos);\n } else {\n [nextRowIdx, nextColIdx] = getNextCellPos(\n key,\n cellPos,\n columnCount,\n maxRowIndex,\n );\n }\n }\n\n if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {\n setActiveCell(nextRowIdx, nextColIdx);\n setHighlightedIndex(nextRowIdx);\n }\n },\n [\n cellFocusStateRef,\n nextPageItemIdx,\n containerRef,\n onToggleGroup,\n headerCount,\n columnCount,\n maxRowIndex,\n setActiveCell,\n setHighlightedIndex,\n ],\n );\n\n const scrollRowIntoViewIfNecessary = useCallback(\n (rowIndex: number) => {\n requestScroll?.({ type: \"scroll-row\", rowIndex });\n },\n [requestScroll],\n );\n\n const moveHighlightedRow = useCallback(\n async (key: NavigationKey) => {\n const { current: highlighted } = highlightedIndexRef;\n const [nextRowIdx] = isPagingKey(key)\n ? await nextPageItemIdx(key, [highlighted ?? -1, 0])\n : getNextCellPos(key, [highlighted ?? -1, 0], columnCount, maxRowIndex);\n if (nextRowIdx !== highlighted) {\n setHighlightedIndex(nextRowIdx);\n // TO(DO make this a scroll request)\n scrollRowIntoViewIfNecessary(nextRowIdx);\n }\n },\n [\n columnCount,\n maxRowIndex,\n nextPageItemIdx,\n scrollRowIntoViewIfNecessary,\n setHighlightedIndex,\n ],\n );\n\n useEffect(() => {\n if (highlightedIndexProp !== undefined && highlightedIndexProp !== -1) {\n requestAnimationFrame(() => {\n // deferred call, ensuring table has fully rendered\n scrollRowIntoViewIfNecessary(highlightedIndexProp);\n });\n }\n }, [highlightedIndexProp, scrollRowIntoViewIfNecessary]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n // console.log(`[useKeyboardNavigation] handleKeyDown`);\n\n const cell = queryClosest<HTMLDivElement>(\n e.target,\n `${CellLocator},${CellControlLocator}`,\n );\n if (cellDropdownShowing(cell)) {\n return;\n }\n if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {\n // if (e.key === \"ArrowDown\" && editCellWithEditInProgress(cell)) {\n // // do nothing editCellWithEditInProgress\n // } else {\n // console.log(\n // `[useKeyboardNavigation] handleKeyDown - consume the keydown event`,\n // );\n e.preventDefault();\n e.stopPropagation();\n if (navigationStyle === \"row\") {\n moveHighlightedRow(e.key);\n } else if (navigationStyle !== \"none\") {\n if (!focusControlWithinCell(e, cell)) {\n navigateChildItems(navigationStyle, e.key, e.shiftKey);\n }\n }\n // }\n }\n },\n [rowCount, navigationStyle, moveHighlightedRow, navigateChildItems],\n );\n\n const handleClick = useCallback(\n // Might not be a cell e.g the Settings button\n (evt: MouseEvent) => {\n // console.log(`[useKeyboardNavigation] click`);\n const target = queryClosest<HTMLDivElement>(evt.target, CellLocator);\n const focusedCell = getFocusedCell(target);\n if (focusedCell) {\n const [rowIdx, colIdx] = getAriaCellPos(focusedCell);\n setActiveCell(rowIdx, colIdx);\n }\n },\n [setActiveCell],\n );\n\n const handleMouseLeave = useCallback(() => {\n setHighlightedIndex(-1);\n }, [setHighlightedIndex]);\n\n const handleMouseMove = useCallback(\n (evt: MouseEvent) => {\n const rowIdx = closestRowIndex(evt.target as HTMLElement);\n if (rowIdx !== -1 && rowIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(rowIdx);\n }\n },\n [setHighlightedIndex],\n );\n\n /**\n * used when editing cells\n */\n const navigateCell = useCallback(() => {\n navigateChildItems(\"cell\", \"ArrowDown\");\n }, [navigateChildItems]);\n\n return {\n highlightedIndexRef,\n navigateCell,\n onClick: handleClick,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n onMouseLeave: navigationStyle === \"row\" ? handleMouseLeave : undefined,\n onMouseMove: navigationStyle === \"row\" ? handleMouseMove : undefined,\n };\n};\n"],"names":["queryClosest","useRef","useControlled","useCallback","getFocusedCell","navigationStyle","getTreeNodeOperation","getLevelUp","getNextCellPos","useEffect","cellDropdownShowing","getAriaCellPos","closestRowIndex"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableScroll.js","sources":["../../../packages/vuu-table/src/useTableScroll.ts"],"sourcesContent":["import {\n getColumnsInViewport,\n itemsChanged,\n RowAtPositionFunc,\n} from \"@vuu-ui/vuu-utils\";\nimport type { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n ForwardedRef,\n MutableRefObject,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ViewportMeasurements } from \"./useTableViewport\";\nimport {\n getRowElementByAriaIndex,\n howFarIsRowOutsideViewport,\n} from \"./table-dom-utils\";\nimport type { RuntimeColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { ICellFocusState } from \"./CellFocusState\";\n\nexport type ScrollDirectionVertical = \"up\" | \"down\";\nexport type ScrollDirectionHorizontal = \"left\" | \"right\";\nexport type ScrollDirection =\n | ScrollDirectionVertical\n | ScrollDirectionHorizontal;\n\n/**\n * scroll into view the row at given pixel offset.\n */\nexport interface ScrollRequestPosition {\n scrollPos: number;\n type: \"scroll-top\" | \"scroll-bottom\";\n}\n\n/**\n * scroll into view the row at given row index posiiton.\n */\nexport interface ScrollRequestRow {\n rowIndex: number;\n type: \"scroll-row\";\n}\nexport interface ScrollRequestEnd {\n type: \"scroll-end\";\n direction: \"home\" | \"end\";\n}\n\nexport interface ScrollRequestPage {\n type: \"scroll-page\";\n direction: ScrollDirectionVertical;\n}\n\nexport type ScrollRequest =\n | ScrollRequestPage\n | ScrollRequestEnd\n | ScrollRequestRow\n | ScrollRequestPosition;\n\nexport type ScrollRequestHandler = (request: ScrollRequest) => void;\n\nexport interface ScrollingAPI {\n scrollToIndex: (itemIndex: number) => void;\n scrollToKey: (rowKey: string) => void;\n}\n\n/** How far we allow horizontal scroll movement before we recheck the rendered columns */\nconst SCROLL_MOVE_CHECK_THRESHOLD = 100;\n\n/** The buffer size in pixels that we allow for rendering columns just outside the viewport */\nconst HORIZONTAL_SCROLL_BUFFER = 200;\n\n/**\n * Return the maximum scroll positions for gioven container\n * @param container\n * @returns [maxScrollLeft, maxScrollTop]\n */\nconst getMaxScroll = (container: HTMLElement) => {\n const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;\n return [scrollWidth - clientWidth, scrollHeight - clientHeight];\n};\n\nconst getScrollDirection = (\n prevScrollPositions: ScrollPos | undefined,\n scrollPos: number,\n) => {\n if (prevScrollPositions === undefined) {\n return undefined;\n } else {\n const { scrollTop: prevTop } = prevScrollPositions;\n return scrollPos > prevTop ? \"fwd\" : \"bwd\";\n }\n};\n\nconst getPctScroll = (container: HTMLElement, currentScrollPos?: ScrollPos) => {\n const {\n clientHeight,\n clientWidth,\n scrollHeight,\n scrollLeft,\n scrollTop,\n scrollWidth,\n } = container;\n\n const maxScrollLeft = scrollWidth - clientWidth;\n const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);\n const maxScrollTop = scrollHeight - clientHeight;\n let pctScrollTop = scrollTop / (scrollHeight - clientHeight);\n\n const scrollDirection = getScrollDirection(currentScrollPos, scrollTop);\n\n if (scrollDirection === \"fwd\" && pctScrollTop > 0.99) {\n pctScrollTop = 1;\n } else if (scrollDirection === \"bwd\" && pctScrollTop < 0.02) {\n pctScrollTop = 0;\n }\n\n return [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ];\n};\n\nexport const noScrolling: ScrollingAPI = {\n scrollToIndex: () => undefined,\n scrollToKey: () => undefined,\n};\n\ninterface CallbackRefHookProps<T = HTMLElement> {\n onAttach?: (el: T) => void;\n onDetach: (el: T) => void;\n label?: string;\n}\n\nconst useCallbackRef = <T = HTMLElement>({\n onAttach,\n onDetach,\n}: CallbackRefHookProps<T>) => {\n const ref = useRef<T | null>(null);\n const callbackRef = useCallback(\n (el: T | null) => {\n if (el) {\n ref.current = el;\n onAttach?.(el);\n } else if (ref.current) {\n const { current: originalRef } = ref;\n ref.current = el;\n onDetach?.(originalRef);\n }\n },\n [onAttach, onDetach],\n );\n return callbackRef;\n};\n\ntype ScrollPos = {\n scrollLeft: number;\n scrollTop: number;\n};\n\nexport interface TableScrollHookProps {\n cellFocusStateRef: MutableRefObject<ICellFocusState>;\n columns: RuntimeColumnDescriptor[];\n focusCell?: FocusCell;\n getRowAtPosition: RowAtPositionFunc;\n onHorizontalScroll?: (scrollLeft: number) => void;\n onVerticalScroll?: (scrollTop: number, pctScrollTop: number) => void;\n /**\n * When we have a virtualized scroll container, keyboard navigation is\n * performed `in situ`. We shift the range of rows rendered within the\n * viewport, whithout actually moving the scroll position\n */\n onVerticalScrollInSitu?: (rowIndexOffsetCount: number) => void;\n rowHeight: number;\n scrollingApiRef?: ForwardedRef<ScrollingAPI>;\n setRange: (range: VuuRange) => void;\n showPaginationControls?: boolean;\n viewportMeasurements: ViewportMeasurements;\n}\n\nexport const useTableScroll = ({\n cellFocusStateRef,\n columns,\n focusCell,\n getRowAtPosition,\n onHorizontalScroll,\n onVerticalScroll,\n onVerticalScrollInSitu,\n rowHeight,\n scrollingApiRef,\n setRange,\n viewportMeasurements,\n}: TableScrollHookProps) => {\n const firstRowRef = useRef<number>(0);\n const rowHeightRef = useRef(rowHeight);\n const contentContainerScrolledRef = useRef(false);\n const contentContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerScrolledRef = useRef(false);\n const scrollbarContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerRef = useRef<HTMLDivElement | null>(null);\n const contentContainerRef = useRef<HTMLDivElement | null>(null);\n const lastHorizontalScrollCheckPoint = useRef(0);\n\n const {\n appliedPageSize,\n isVirtualScroll,\n rowCount: viewportRowCount,\n totalHeaderHeight,\n usesMeasuredHeaderHeight,\n viewportBodyHeight,\n viewportWidth,\n } = viewportMeasurements;\n\n const columnsWithinViewportRef = useRef<RuntimeColumnDescriptor[]>([]);\n const [, forceRefresh] = useState({});\n\n const preSpanRef = useRef(0);\n\n useMemo(() => {\n const [visibleColumns, offset] = getColumnsInViewport(\n columns,\n contentContainerPosRef.current.scrollLeft,\n contentContainerPosRef.current.scrollLeft +\n viewportWidth +\n HORIZONTAL_SCROLL_BUFFER,\n );\n preSpanRef.current = offset;\n columnsWithinViewportRef.current = visibleColumns;\n }, [viewportWidth, columns]);\n\n const handleHorizontalScroll = useCallback(\n (scrollLeft: number) => {\n contentContainerPosRef.current.scrollLeft = scrollLeft;\n onHorizontalScroll?.(scrollLeft);\n\n if (\n Math.abs(scrollLeft - lastHorizontalScrollCheckPoint.current) >\n SCROLL_MOVE_CHECK_THRESHOLD\n ) {\n lastHorizontalScrollCheckPoint.current = scrollLeft;\n\n const [visibleColumns, pre] = getColumnsInViewport(\n columns,\n scrollLeft,\n scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER,\n );\n\n if (itemsChanged(columnsWithinViewportRef.current, visibleColumns)) {\n preSpanRef.current = pre;\n columnsWithinViewportRef.current = visibleColumns;\n forceRefresh({});\n }\n }\n },\n [columns, onHorizontalScroll, viewportWidth],\n );\n const handleVerticalScroll = useCallback(\n (scrollTop: number, pctScrollTop: number) => {\n contentContainerPosRef.current.scrollTop = scrollTop;\n const { current: prevFirstRow } = firstRowRef;\n\n onVerticalScroll?.(scrollTop, pctScrollTop);\n const firstRow = getRowAtPosition(scrollTop);\n if (firstRow !== prevFirstRow) {\n firstRowRef.current = firstRow;\n const lastRow = firstRow + viewportRowCount;\n setRange({ from: firstRow, to: lastRow });\n\n // If we've scrolled the focused cell out of view, we need to remove\n // focus from it. The row element will be recycled and used as the\n // render target for a different DataRow, we do not want the focus\n // state of the cell to be preserved.\n // Conversely, if we scroll the focussed cell back into the viewport,\n // we must re-apply focus to it. We use the placeholder cell for this.\n const { current: focusState } = cellFocusStateRef;\n if (focusState.cellPos) {\n const prevLastRow = prevFirstRow + viewportRowCount;\n const [row] = focusState.cellPos;\n const wasInViewport = row >= prevFirstRow && row < prevLastRow;\n const isInViewport = row >= firstRow && row < lastRow;\n\n if (wasInViewport && !isInViewport) {\n focusState.placeholderEl?.focus({ preventScroll: true });\n focusState.outsideViewport = row < firstRow ? \"above\" : \"below\";\n } else if (isInViewport && !wasInViewport) {\n focusState.outsideViewport = false;\n focusCell?.(focusState.cellPos);\n }\n }\n }\n onVerticalScrollInSitu?.(0);\n },\n [\n cellFocusStateRef,\n focusCell,\n getRowAtPosition,\n onVerticalScroll,\n onVerticalScrollInSitu,\n setRange,\n viewportRowCount,\n ],\n );\n\n const handleScrollbarContainerScroll = useCallback(() => {\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: contentContainerScrolled } = contentContainerScrolledRef;\n const { current: scrollPos } = scrollbarContainerPosRef;\n\n if (contentContainerScrolled) {\n contentContainerScrolledRef.current = false;\n } else if (contentContainer && scrollbarContainer) {\n scrollbarContainerScrolledRef.current = true;\n const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] =\n getPctScroll(scrollbarContainer, scrollPos);\n\n scrollPos.scrollLeft = scrollLeft;\n scrollPos.scrollTop = scrollTop;\n\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer);\n const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft);\n const contentScrollTop = pctScrollTop * maxScrollTop;\n\n contentContainer.scrollTo({\n left: contentScrollLeft,\n top: contentScrollTop,\n behavior: \"auto\",\n });\n }\n onVerticalScrollInSitu?.(0);\n }, [onVerticalScrollInSitu]);\n\n const handleContentContainerScroll = useCallback(() => {\n const { current: scrollbarContainerScrolled } =\n scrollbarContainerScrolledRef;\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: scrollPos } = contentContainerPosRef;\n if (contentContainer && scrollbarContainer) {\n const [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ] = getPctScroll(contentContainer);\n\n contentContainerScrolledRef.current = true;\n\n if (scrollbarContainerScrolled) {\n scrollbarContainerScrolledRef.current = false;\n } else {\n scrollbarContainer.scrollLeft = Math.round(\n pctScrollLeft * maxScrollLeft,\n );\n scrollbarContainer.scrollTop = pctScrollTop * maxScrollTop;\n }\n\n if (scrollPos.scrollTop !== scrollTop) {\n handleVerticalScroll(scrollTop, pctScrollTop);\n }\n if (scrollPos.scrollLeft !== scrollLeft) {\n handleHorizontalScroll(scrollLeft);\n }\n }\n }, [handleVerticalScroll, handleHorizontalScroll]);\n\n const handleAttachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = el;\n el.addEventListener(\"scroll\", handleScrollbarContainerScroll, {\n passive: true,\n });\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleDetachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleScrollbarContainerScroll);\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleAttachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = el;\n el.addEventListener(\"scroll\", handleContentContainerScroll, {\n passive: true,\n });\n },\n [handleContentContainerScroll],\n );\n\n const handleDetachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleContentContainerScroll);\n },\n [handleContentContainerScroll],\n );\n\n const contentContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachContentContainer,\n onDetach: handleDetachContentContainer,\n });\n\n const scrollbarContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachScrollbarContainer,\n onDetach: handleDetachScrollbarContainer,\n });\n\n const requestScroll: ScrollRequestHandler = useCallback(\n (scrollRequest) => {\n const { current: contentContainer } = contentContainerRef;\n if (contentContainer) {\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer);\n const { scrollLeft, scrollTop } = contentContainer;\n contentContainerScrolledRef.current = false;\n switch (scrollRequest.type) {\n case \"scroll-top\":\n {\n contentContainer.scrollTo({\n top: scrollRequest.scrollPos,\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-bottom\":\n {\n contentContainer.scrollTo({\n top:\n scrollRequest.scrollPos -\n (viewportBodyHeight - 2 * rowHeight),\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-row\":\n {\n const activeRow = getRowElementByAriaIndex(\n contentContainer,\n scrollRequest.rowIndex,\n );\n\n if (activeRow !== null) {\n const [direction, distance] = howFarIsRowOutsideViewport(\n activeRow,\n totalHeaderHeight,\n );\n if (direction && distance) {\n if (isVirtualScroll) {\n const offset = direction === \"down\" ? 1 : -1;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({\n from: firstRow,\n to: firstRow + viewportRowCount,\n });\n } else {\n let newScrollLeft = scrollLeft;\n let newScrollTop = scrollTop;\n if (direction === \"up\" || direction === \"down\") {\n newScrollTop = Math.min(\n Math.max(0, scrollTop + distance),\n maxScrollTop,\n );\n } else {\n newScrollLeft = Math.min(\n Math.max(0, scrollLeft + distance),\n maxScrollLeft,\n );\n }\n contentContainer.scrollTo({\n top: newScrollTop,\n left: newScrollLeft,\n // avoid behaviour: 'smooth', doesn't work correctly\n behavior: \"instant\",\n });\n }\n }\n }\n }\n break;\n case \"scroll-page\":\n {\n const { direction } = scrollRequest;\n if (isVirtualScroll) {\n const offset =\n direction === \"down\" ? viewportRowCount : -viewportRowCount;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({ from: firstRow, to: firstRow + viewportRowCount });\n } else {\n const scrollBy =\n direction === \"down\" ? appliedPageSize : -appliedPageSize;\n const newScrollTop = Math.min(\n Math.max(0, scrollTop + scrollBy),\n maxScrollTop,\n );\n contentContainer.scrollTo({\n top: newScrollTop,\n left: scrollLeft,\n behavior: \"auto\",\n });\n }\n }\n break;\n case \"scroll-end\":\n {\n const { direction } = scrollRequest;\n const scrollTo = direction === \"end\" ? maxScrollTop : 0;\n contentContainer.scrollTo({\n top: scrollTo,\n left: contentContainer.scrollLeft,\n behavior: \"auto\",\n });\n }\n break;\n default:\n console.warn(`unexpected scroll request ${scrollRequest[\"type\"]}`);\n }\n }\n },\n [\n appliedPageSize,\n isVirtualScroll,\n onVerticalScrollInSitu,\n rowHeight,\n setRange,\n totalHeaderHeight,\n viewportBodyHeight,\n viewportRowCount,\n ],\n );\n\n const scrollHandles: ScrollingAPI = useMemo(\n // TODO not complete yet\n () => ({\n scrollToIndex: (rowIndex: number) => {\n if (scrollbarContainerRef.current) {\n // TODO hardcoded rowHeight\n const scrollPos = (rowIndex - 30) * 20;\n scrollbarContainerRef.current.scrollTop = scrollPos;\n }\n },\n scrollToKey: (rowKey: string) => {\n console.log(`scrollToKey ${rowKey}`);\n },\n }),\n [],\n );\n\n useImperativeHandle(scrollingApiRef, () => {\n if (scrollbarContainerRef.current) {\n return scrollHandles;\n } else {\n return noScrolling;\n }\n }, [scrollHandles]);\n\n useEffect(() => {\n if (rowHeight !== rowHeightRef.current) {\n rowHeightRef.current = rowHeight;\n if (contentContainerPosRef.current.scrollTop > 0) {\n if (contentContainerRef.current) {\n contentContainerRef.current.scrollTop = 0;\n }\n }\n } else if (usesMeasuredHeaderHeight) {\n const { current: from } = firstRowRef;\n const rowRange = { from, to: from + viewportRowCount };\n setRange(rowRange);\n }\n }, [rowHeight, setRange, usesMeasuredHeaderHeight, viewportRowCount]);\n\n return {\n columnsWithinViewport: columnsWithinViewportRef.current,\n /** Ref to be assigned to ScrollbarContainer */\n scrollbarContainerRef: scrollbarContainerCallbackRef,\n /** Ref to be assigned to ContentContainer */\n contentContainerRef: contentContainerCallbackRef,\n /** Scroll the table */\n requestScroll,\n /** number of leading columns not rendered because of virtualization */\n virtualColSpan: preSpanRef.current,\n };\n};\n"],"names":["useRef","useCallback","useState","useMemo","getColumnsInViewport","itemsChanged","getRowElementByAriaIndex","howFarIsRowOutsideViewport","useImperativeHandle","useEffect"],"mappings":";;;;;;AAsEA,MAAM,2BAA8B,GAAA,GAAA;AAGpC,MAAM,wBAA2B,GAAA,GAAA;AAOjC,MAAM,YAAA,GAAe,CAAC,SAA2B,KAAA;AAC/C,EAAA,MAAM,EAAE,YAAA,EAAc,WAAa,EAAA,YAAA,EAAc,aAAgB,GAAA,SAAA;AACjE,EAAA,OAAO,CAAC,WAAA,GAAc,WAAa,EAAA,YAAA,GAAe,YAAY,CAAA;AAChE,CAAA;AAEA,MAAM,kBAAA,GAAqB,CACzB,mBAAA,EACA,SACG,KAAA;AACH,EAAA,IAAI,wBAAwB,KAAW,CAAA,EAAA;AACrC,IAAO,OAAA,KAAA,CAAA;AAAA,GACF,MAAA;AACL,IAAM,MAAA,EAAE,SAAW,EAAA,OAAA,EAAY,GAAA,mBAAA;AAC/B,IAAO,OAAA,SAAA,GAAY,UAAU,KAAQ,GAAA,KAAA;AAAA;AAEzC,CAAA;AAEA,MAAM,YAAA,GAAe,CAAC,SAAA,EAAwB,gBAAiC,KAAA;AAC7E,EAAM,MAAA;AAAA,IACJ,YAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACE,GAAA,SAAA;AAEJ,EAAA,MAAM,gBAAgB,WAAc,GAAA,WAAA;AACpC,EAAM,MAAA,aAAA,GAAgB,cAAc,WAAc,GAAA,WAAA,CAAA;AAClD,EAAA,MAAM,eAAe,YAAe,GAAA,YAAA;AACpC,EAAI,IAAA,YAAA,GAAe,aAAa,YAAe,GAAA,YAAA,CAAA;AAE/C,EAAM,MAAA,eAAA,GAAkB,kBAAmB,CAAA,gBAAA,EAAkB,SAAS,CAAA;AAEtE,EAAI,IAAA,eAAA,KAAoB,KAAS,IAAA,YAAA,GAAe,IAAM,EAAA;AACpD,IAAe,YAAA,GAAA,CAAA;AAAA,GACN,MAAA,IAAA,eAAA,KAAoB,KAAS,IAAA,YAAA,GAAe,IAAM,EAAA;AAC3D,IAAe,YAAA,GAAA,CAAA;AAAA;AAGjB,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;AAEO,MAAM,WAA4B,GAAA;AAAA,EACvC,eAAe,MAAM,KAAA,CAAA;AAAA,EACrB,aAAa,MAAM,KAAA;AACrB;AAQA,MAAM,iBAAiB,CAAkB;AAAA,EACvC,QAAA;AAAA,EACA;AACF,CAA+B,KAAA;AAC7B,EAAM,MAAA,GAAA,GAAMA,aAAiB,IAAI,CAAA;AACjC,EAAA,MAAM,WAAc,GAAAC,iBAAA;AAAA,IAClB,CAAC,EAAiB,KAAA;AAChB,MAAA,IAAI,EAAI,EAAA;AACN,QAAA,GAAA,CAAI,OAAU,GAAA,EAAA;AACd,QAAA,QAAA,GAAW,EAAE,CAAA;AAAA,OACf,MAAA,IAAW,IAAI,OAAS,EAAA;AACtB,QAAM,MAAA,EAAE,OAAS,EAAA,WAAA,EAAgB,GAAA,GAAA;AACjC,QAAA,GAAA,CAAI,OAAU,GAAA,EAAA;AACd,QAAA,QAAA,GAAW,WAAW,CAAA;AAAA;AACxB,KACF;AAAA,IACA,CAAC,UAAU,QAAQ;AAAA,GACrB;AACA,EAAO,OAAA,WAAA;AACT,CAAA;AA2BO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,iBAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,sBAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAA4B,KAAA;AAC1B,EAAM,MAAA,WAAA,GAAcD,aAAe,CAAC,CAAA;AACpC,EAAM,MAAA,YAAA,GAAeA,aAAO,SAAS,CAAA;AACrC,EAAM,MAAA,2BAAA,GAA8BA,aAAO,KAAK,CAAA;AAChD,EAAA,MAAM,yBAAyBA,YAAkB,CAAA;AAAA,IAC/C,SAAW,EAAA,CAAA;AAAA,IACX,UAAY,EAAA;AAAA,GACb,CAAA;AACD,EAAM,MAAA,6BAAA,GAAgCA,aAAO,KAAK,CAAA;AAClD,EAAA,MAAM,2BAA2BA,YAAkB,CAAA;AAAA,IACjD,SAAW,EAAA,CAAA;AAAA,IACX,UAAY,EAAA;AAAA,GACb,CAAA;AACD,EAAM,MAAA,qBAAA,GAAwBA,aAA8B,IAAI,CAAA;AAChE,EAAM,MAAA,mBAAA,GAAsBA,aAA8B,IAAI,CAAA;AAC9D,EAAM,MAAA,8BAAA,GAAiCA,aAAO,CAAC,CAAA;AAE/C,EAAM,MAAA;AAAA,IACJ,eAAA;AAAA,IACA,eAAA;AAAA,IACA,QAAU,EAAA,gBAAA;AAAA,IACV,iBAAA;AAAA,IACA,wBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACE,GAAA,oBAAA;AAEJ,EAAM,MAAA,wBAAA,GAA2BA,YAAkC,CAAA,EAAE,CAAA;AACrE,EAAA,MAAM,GAAG,YAAY,CAAI,GAAAE,cAAA,CAAS,EAAE,CAAA;AAEpC,EAAM,MAAA,UAAA,GAAaF,aAAO,CAAC,CAAA;AAE3B,EAAAG,aAAA,CAAQ,MAAM;AACZ,IAAM,MAAA,CAAC,cAAgB,EAAA,MAAM,CAAI,GAAAC,6BAAA;AAAA,MAC/B,OAAA;AAAA,MACA,uBAAuB,OAAQ,CAAA,UAAA;AAAA,MAC/B,sBAAA,CAAuB,OAAQ,CAAA,UAAA,GAC7B,aACA,GAAA;AAAA,KACJ;AACA,IAAA,UAAA,CAAW,OAAU,GAAA,MAAA;AACrB,IAAA,wBAAA,CAAyB,OAAU,GAAA,cAAA;AAAA,GAClC,EAAA,CAAC,aAAe,EAAA,OAAO,CAAC,CAAA;AAE3B,EAAA,MAAM,sBAAyB,GAAAH,iBAAA;AAAA,IAC7B,CAAC,UAAuB,KAAA;AACtB,MAAA,sBAAA,CAAuB,QAAQ,UAAa,GAAA,UAAA;AAC5C,MAAA,kBAAA,GAAqB,UAAU,CAAA;AAE/B,MAAA,IACE,KAAK,GAAI,CAAA,UAAA,GAAa,8BAA+B,CAAA,OAAO,IAC5D,2BACA,EAAA;AACA,QAAA,8BAAA,CAA+B,OAAU,GAAA,UAAA;AAEzC,QAAM,MAAA,CAAC,cAAgB,EAAA,GAAG,CAAI,GAAAG,6BAAA;AAAA,UAC5B,OAAA;AAAA,UACA,UAAA;AAAA,UACA,aAAa,aAAgB,GAAA;AAAA,SAC/B;AAEA,QAAA,IAAIC,qBAAa,CAAA,wBAAA,CAAyB,OAAS,EAAA,cAAc,CAAG,EAAA;AAClE,UAAA,UAAA,CAAW,OAAU,GAAA,GAAA;AACrB,UAAA,wBAAA,CAAyB,OAAU,GAAA,cAAA;AACnC,UAAA,YAAA,CAAa,EAAE,CAAA;AAAA;AACjB;AACF,KACF;AAAA,IACA,CAAC,OAAS,EAAA,kBAAA,EAAoB,aAAa;AAAA,GAC7C;AACA,EAAA,MAAM,oBAAuB,GAAAJ,iBAAA;AAAA,IAC3B,CAAC,WAAmB,YAAyB,KAAA;AAC3C,MAAA,sBAAA,CAAuB,QAAQ,SAAY,GAAA,SAAA;AAC3C,MAAM,MAAA,EAAE,OAAS,EAAA,YAAA,EAAiB,GAAA,WAAA;AAElC,MAAA,gBAAA,GAAmB,WAAW,YAAY,CAAA;AAC1C,MAAM,MAAA,QAAA,GAAW,iBAAiB,SAAS,CAAA;AAC3C,MAAA,IAAI,aAAa,YAAc,EAAA;AAC7B,QAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AACtB,QAAA,MAAM,UAAU,QAAW,GAAA,gBAAA;AAC3B,QAAA,QAAA,CAAS,EAAE,IAAA,EAAM,QAAU,EAAA,EAAA,EAAI,SAAS,CAAA;AAQxC,QAAM,MAAA,EAAE,OAAS,EAAA,UAAA,EAAe,GAAA,iBAAA;AAChC,QAAA,IAAI,WAAW,OAAS,EAAA;AACtB,UAAA,MAAM,cAAc,YAAe,GAAA,gBAAA;AACnC,UAAM,MAAA,CAAC,GAAG,CAAA,GAAI,UAAW,CAAA,OAAA;AACzB,UAAM,MAAA,aAAA,GAAgB,GAAO,IAAA,YAAA,IAAgB,GAAM,GAAA,WAAA;AACnD,UAAM,MAAA,YAAA,GAAe,GAAO,IAAA,QAAA,IAAY,GAAM,GAAA,OAAA;AAE9C,UAAI,IAAA,aAAA,IAAiB,CAAC,YAAc,EAAA;AAClC,YAAA,UAAA,CAAW,aAAe,EAAA,KAAA,CAAM,EAAE,aAAA,EAAe,MAAM,CAAA;AACvD,YAAW,UAAA,CAAA,eAAA,GAAkB,GAAM,GAAA,QAAA,GAAW,OAAU,GAAA,OAAA;AAAA,WAC1D,MAAA,IAAW,YAAgB,IAAA,CAAC,aAAe,EAAA;AACzC,YAAA,UAAA,CAAW,eAAkB,GAAA,KAAA;AAC7B,YAAA,SAAA,GAAY,WAAW,OAAO,CAAA;AAAA;AAChC;AACF;AAEF,MAAA,sBAAA,GAAyB,CAAC,CAAA;AAAA,KAC5B;AAAA,IACA;AAAA,MACE,iBAAA;AAAA,MACA,SAAA;AAAA,MACA,gBAAA;AAAA,MACA,gBAAA;AAAA,MACA,sBAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAM,MAAA,8BAAA,GAAiCA,kBAAY,MAAM;AACvD,IAAM,MAAA,EAAE,OAAS,EAAA,gBAAA,EAAqB,GAAA,mBAAA;AACtC,IAAM,MAAA,EAAE,OAAS,EAAA,kBAAA,EAAuB,GAAA,qBAAA;AACxC,IAAM,MAAA,EAAE,OAAS,EAAA,wBAAA,EAA6B,GAAA,2BAAA;AAC9C,IAAM,MAAA,EAAE,OAAS,EAAA,SAAA,EAAc,GAAA,wBAAA;AAE/B,IAAA,IAAI,wBAA0B,EAAA;AAC5B,MAAA,2BAAA,CAA4B,OAAU,GAAA,KAAA;AAAA,KACxC,MAAA,IAAW,oBAAoB,kBAAoB,EAAA;AACjD,MAAA,6BAAA,CAA8B,OAAU,GAAA,IAAA;AACxC,MAAM,MAAA,CAAC,YAAY,aAAe,IAAE,WAAW,YAAY,CAAA,GACzD,YAAa,CAAA,kBAAA,EAAoB,SAAS,CAAA;AAE5C,MAAA,SAAA,CAAU,UAAa,GAAA,UAAA;AACvB,MAAA,SAAA,CAAU,SAAY,GAAA,SAAA;AAEtB,MAAA,MAAM,CAAC,aAAA,EAAe,YAAY,CAAA,GAAI,aAAa,kBAAkB,CAAA;AACrE,MAAA,MAAM,iBAAoB,GAAA,IAAA,CAAK,KAAM,CAAA,aAAA,GAAgB,aAAa,CAAA;AAClE,MAAA,MAAM,mBAAmB,YAAe,GAAA,YAAA;AAExC,MAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,QACxB,IAAM,EAAA,iBAAA;AAAA,QACN,GAAK,EAAA,gBAAA;AAAA,QACL,QAAU,EAAA;AAAA,OACX,CAAA;AAAA;AAEH,IAAA,sBAAA,GAAyB,CAAC,CAAA;AAAA,GAC5B,EAAG,CAAC,sBAAsB,CAAC,CAAA;AAE3B,EAAM,MAAA,4BAAA,GAA+BA,kBAAY,MAAM;AACrD,IAAM,MAAA,EAAE,OAAS,EAAA,0BAAA,EACf,GAAA,6BAAA;AACF,IAAM,MAAA,EAAE,OAAS,EAAA,gBAAA,EAAqB,GAAA,mBAAA;AACtC,IAAM,MAAA,EAAE,OAAS,EAAA,kBAAA,EAAuB,GAAA,qBAAA;AACxC,IAAM,MAAA,EAAE,OAAS,EAAA,SAAA,EAAc,GAAA,sBAAA;AAC/B,IAAA,IAAI,oBAAoB,kBAAoB,EAAA;AAC1C,MAAM,MAAA;AAAA,QACJ,UAAA;AAAA,QACA,aAAA;AAAA,QACA,aAAA;AAAA,QACA,SAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACF,GAAI,aAAa,gBAAgB,CAAA;AAEjC,MAAA,2BAAA,CAA4B,OAAU,GAAA,IAAA;AAEtC,MAAA,IAAI,0BAA4B,EAAA;AAC9B,QAAA,6BAAA,CAA8B,OAAU,GAAA,KAAA;AAAA,OACnC,MAAA;AACL,QAAA,kBAAA,CAAmB,aAAa,IAAK,CAAA,KAAA;AAAA,UACnC,aAAgB,GAAA;AAAA,SAClB;AACA,QAAA,kBAAA,CAAmB,YAAY,YAAe,GAAA,YAAA;AAAA;AAGhD,MAAI,IAAA,SAAA,CAAU,cAAc,SAAW,EAAA;AACrC,QAAA,oBAAA,CAAqB,WAAW,YAAY,CAAA;AAAA;AAE9C,MAAI,IAAA,SAAA,CAAU,eAAe,UAAY,EAAA;AACvC,QAAA,sBAAA,CAAuB,UAAU,CAAA;AAAA;AACnC;AACF,GACC,EAAA,CAAC,oBAAsB,EAAA,sBAAsB,CAAC,CAAA;AAEjD,EAAA,MAAM,8BAAiC,GAAAA,iBAAA;AAAA,IACrC,CAAC,EAAuB,KAAA;AACtB,MAAA,qBAAA,CAAsB,OAAU,GAAA,EAAA;AAChC,MAAG,EAAA,CAAA,gBAAA,CAAiB,UAAU,8BAAgC,EAAA;AAAA,QAC5D,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,KACH;AAAA,IACA,CAAC,8BAA8B;AAAA,GACjC;AAEA,EAAA,MAAM,8BAAiC,GAAAA,iBAAA;AAAA,IACrC,CAAC,EAAuB,KAAA;AACtB,MAAA,qBAAA,CAAsB,OAAU,GAAA,IAAA;AAChC,MAAG,EAAA,CAAA,mBAAA,CAAoB,UAAU,8BAA8B,CAAA;AAAA,KACjE;AAAA,IACA,CAAC,8BAA8B;AAAA,GACjC;AAEA,EAAA,MAAM,4BAA+B,GAAAA,iBAAA;AAAA,IACnC,CAAC,EAAuB,KAAA;AACtB,MAAA,mBAAA,CAAoB,OAAU,GAAA,EAAA;AAC9B,MAAG,EAAA,CAAA,gBAAA,CAAiB,UAAU,4BAA8B,EAAA;AAAA,QAC1D,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,KACH;AAAA,IACA,CAAC,4BAA4B;AAAA,GAC/B;AAEA,EAAA,MAAM,4BAA+B,GAAAA,iBAAA;AAAA,IACnC,CAAC,EAAuB,KAAA;AACtB,MAAA,mBAAA,CAAoB,OAAU,GAAA,IAAA;AAC9B,MAAG,EAAA,CAAA,mBAAA,CAAoB,UAAU,4BAA4B,CAAA;AAAA,KAC/D;AAAA,IACA,CAAC,4BAA4B;AAAA,GAC/B;AAEA,EAAA,MAAM,8BAA8B,cAAe,CAAA;AAAA,IACjD,QAAU,EAAA,4BAAA;AAAA,IACV,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAA,MAAM,gCAAgC,cAAe,CAAA;AAAA,IACnD,QAAU,EAAA,8BAAA;AAAA,IACV,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAA,MAAM,aAAsC,GAAAA,iBAAA;AAAA,IAC1C,CAAC,aAAkB,KAAA;AACjB,MAAM,MAAA,EAAE,OAAS,EAAA,gBAAA,EAAqB,GAAA,mBAAA;AACtC,MAAA,IAAI,gBAAkB,EAAA;AACpB,QAAA,MAAM,CAAC,aAAA,EAAe,YAAY,CAAA,GAAI,aAAa,gBAAgB,CAAA;AACnE,QAAM,MAAA,EAAE,UAAY,EAAA,SAAA,EAAc,GAAA,gBAAA;AAClC,QAAA,2BAAA,CAA4B,OAAU,GAAA,KAAA;AACtC,QAAA,QAAQ,cAAc,IAAM;AAAA,UAC1B,KAAK,YAAA;AACH,YAAA;AACE,cAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,gBACxB,KAAK,aAAc,CAAA,SAAA;AAAA,gBACnB,IAAM,EAAA,UAAA;AAAA,gBACN,QAAU,EAAA;AAAA,eACX,CAAA;AAAA;AAEH,YAAA;AAAA,UACF,KAAK,eAAA;AACH,YAAA;AACE,cAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,gBACxB,GACE,EAAA,aAAA,CAAc,SACb,IAAA,kBAAA,GAAqB,CAAI,GAAA,SAAA,CAAA;AAAA,gBAC5B,IAAM,EAAA,UAAA;AAAA,gBACN,QAAU,EAAA;AAAA,eACX,CAAA;AAAA;AAEH,YAAA;AAAA,UACF,KAAK,YAAA;AACH,YAAA;AACE,cAAA,MAAM,SAAY,GAAAK,sCAAA;AAAA,gBAChB,gBAAA;AAAA,gBACA,aAAc,CAAA;AAAA,eAChB;AAEA,cAAA,IAAI,cAAc,IAAM,EAAA;AACtB,gBAAM,MAAA,CAAC,SAAW,EAAA,QAAQ,CAAI,GAAAC,wCAAA;AAAA,kBAC5B,SAAA;AAAA,kBACA;AAAA,iBACF;AACA,gBAAA,IAAI,aAAa,QAAU,EAAA;AACzB,kBAAA,IAAI,eAAiB,EAAA;AACnB,oBAAM,MAAA,MAAA,GAAS,SAAc,KAAA,MAAA,GAAS,CAAI,GAAA,CAAA,CAAA;AAC1C,oBAAA,sBAAA,GAAyB,MAAM,CAAA;AAC/B,oBAAM,MAAA,QAAA,GAAW,YAAY,OAAU,GAAA,MAAA;AACvC,oBAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AACtB,oBAAS,QAAA,CAAA;AAAA,sBACP,IAAM,EAAA,QAAA;AAAA,sBACN,IAAI,QAAW,GAAA;AAAA,qBAChB,CAAA;AAAA,mBACI,MAAA;AACL,oBAAA,IAAI,aAAgB,GAAA,UAAA;AACpB,oBAAA,IAAI,YAAe,GAAA,SAAA;AACnB,oBAAI,IAAA,SAAA,KAAc,IAAQ,IAAA,SAAA,KAAc,MAAQ,EAAA;AAC9C,sBAAA,YAAA,GAAe,IAAK,CAAA,GAAA;AAAA,wBAClB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,SAAA,GAAY,QAAQ,CAAA;AAAA,wBAChC;AAAA,uBACF;AAAA,qBACK,MAAA;AACL,sBAAA,aAAA,GAAgB,IAAK,CAAA,GAAA;AAAA,wBACnB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,UAAA,GAAa,QAAQ,CAAA;AAAA,wBACjC;AAAA,uBACF;AAAA;AAEF,oBAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,sBACxB,GAAK,EAAA,YAAA;AAAA,sBACL,IAAM,EAAA,aAAA;AAAA;AAAA,sBAEN,QAAU,EAAA;AAAA,qBACX,CAAA;AAAA;AACH;AACF;AACF;AAEF,YAAA;AAAA,UACF,KAAK,aAAA;AACH,YAAA;AACE,cAAM,MAAA,EAAE,WAAc,GAAA,aAAA;AACtB,cAAA,IAAI,eAAiB,EAAA;AACnB,gBAAA,MAAM,MACJ,GAAA,SAAA,KAAc,MAAS,GAAA,gBAAA,GAAmB,CAAC,gBAAA;AAC7C,gBAAA,sBAAA,GAAyB,MAAM,CAAA;AAC/B,gBAAM,MAAA,QAAA,GAAW,YAAY,OAAU,GAAA,MAAA;AACvC,gBAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AACtB,gBAAA,QAAA,CAAS,EAAE,IAAM,EAAA,QAAA,EAAU,EAAI,EAAA,QAAA,GAAW,kBAAkB,CAAA;AAAA,eACvD,MAAA;AACL,gBAAA,MAAM,QACJ,GAAA,SAAA,KAAc,MAAS,GAAA,eAAA,GAAkB,CAAC,eAAA;AAC5C,gBAAA,MAAM,eAAe,IAAK,CAAA,GAAA;AAAA,kBACxB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,SAAA,GAAY,QAAQ,CAAA;AAAA,kBAChC;AAAA,iBACF;AACA,gBAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,kBACxB,GAAK,EAAA,YAAA;AAAA,kBACL,IAAM,EAAA,UAAA;AAAA,kBACN,QAAU,EAAA;AAAA,iBACX,CAAA;AAAA;AACH;AAEF,YAAA;AAAA,UACF,KAAK,YAAA;AACH,YAAA;AACE,cAAM,MAAA,EAAE,WAAc,GAAA,aAAA;AACtB,cAAM,MAAA,QAAA,GAAW,SAAc,KAAA,KAAA,GAAQ,YAAe,GAAA,CAAA;AACtD,cAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,gBACxB,GAAK,EAAA,QAAA;AAAA,gBACL,MAAM,gBAAiB,CAAA,UAAA;AAAA,gBACvB,QAAU,EAAA;AAAA,eACX,CAAA;AAAA;AAEH,YAAA;AAAA,UACF;AACE,YAAA,OAAA,CAAQ,IAAK,CAAA,CAAA,0BAAA,EAA6B,aAAc,CAAA,MAAM,CAAC,CAAE,CAAA,CAAA;AAAA;AACrE;AACF,KACF;AAAA,IACA;AAAA,MACE,eAAA;AAAA,MACA,eAAA;AAAA,MACA,sBAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAA;AAAA,MACA,iBAAA;AAAA,MACA,kBAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,MAAM,aAA8B,GAAAJ,aAAA;AAAA;AAAA,IAElC,OAAO;AAAA,MACL,aAAA,EAAe,CAAC,QAAqB,KAAA;AACnC,QAAA,IAAI,sBAAsB,OAAS,EAAA;AAEjC,UAAM,MAAA,SAAA,GAAA,CAAa,WAAW,EAAM,IAAA,EAAA;AACpC,UAAA,qBAAA,CAAsB,QAAQ,SAAY,GAAA,SAAA;AAAA;AAC5C,OACF;AAAA,MACA,WAAA,EAAa,CAAC,MAAmB,KAAA;AAC/B,QAAQ,OAAA,CAAA,GAAA,CAAI,CAAe,YAAA,EAAA,MAAM,CAAE,CAAA,CAAA;AAAA;AACrC,KACF,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAAK,yBAAA,CAAoB,iBAAiB,MAAM;AACzC,IAAA,IAAI,sBAAsB,OAAS,EAAA;AACjC,MAAO,OAAA,aAAA;AAAA,KACF,MAAA;AACL,MAAO,OAAA,WAAA;AAAA;AACT,GACF,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAAC,eAAA,CAAU,MAAM;AACd,IAAI,IAAA,SAAA,KAAc,aAAa,OAAS,EAAA;AACtC,MAAA,YAAA,CAAa,OAAU,GAAA,SAAA;AACvB,MAAI,IAAA,sBAAA,CAAuB,OAAQ,CAAA,SAAA,GAAY,CAAG,EAAA;AAChD,QAAA,IAAI,oBAAoB,OAAS,EAAA;AAC/B,UAAA,mBAAA,CAAoB,QAAQ,SAAY,GAAA,CAAA;AAAA;AAC1C;AACF,eACS,wBAA0B,EAAA;AACnC,MAAM,MAAA,EAAE,OAAS,EAAA,IAAA,EAAS,GAAA,WAAA;AAC1B,MAAA,MAAM,QAAW,GAAA,EAAE,IAAM,EAAA,EAAA,EAAI,OAAO,gBAAiB,EAAA;AACrD,MAAA,QAAA,CAAS,QAAQ,CAAA;AAAA;AACnB,KACC,CAAC,SAAA,EAAW,QAAU,EAAA,wBAAA,EAA0B,gBAAgB,CAAC,CAAA;AAEpE,EAAO,OAAA;AAAA,IACL,uBAAuB,wBAAyB,CAAA,OAAA;AAAA;AAAA,IAEhD,qBAAuB,EAAA,6BAAA;AAAA;AAAA,IAEvB,mBAAqB,EAAA,2BAAA;AAAA;AAAA,IAErB,aAAA;AAAA;AAAA,IAEA,gBAAgB,UAAW,CAAA;AAAA,GAC7B;AACF;;;;;"}
|
|
1
|
+
{"version":3,"file":"useTableScroll.js","sources":["../../../packages/vuu-table/src/useTableScroll.ts"],"sourcesContent":["import {\n getColumnsInViewport,\n itemsChanged,\n RowAtPositionFunc,\n} from \"@vuu-ui/vuu-utils\";\nimport type { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n ForwardedRef,\n RefObject,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ViewportMeasurements } from \"./useTableViewport\";\nimport {\n getRowElementByAriaIndex,\n howFarIsRowOutsideViewport,\n} from \"./table-dom-utils\";\nimport type { RuntimeColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { ICellFocusState } from \"./CellFocusState\";\n\nexport type ScrollDirectionVertical = \"up\" | \"down\";\nexport type ScrollDirectionHorizontal = \"left\" | \"right\";\nexport type ScrollDirection =\n | ScrollDirectionVertical\n | ScrollDirectionHorizontal;\n\n/**\n * scroll into view the row at given pixel offset.\n */\nexport interface ScrollRequestPosition {\n scrollPos: number;\n type: \"scroll-top\" | \"scroll-bottom\";\n}\n\n/**\n * scroll into view the row at given row index posiiton.\n */\nexport interface ScrollRequestRow {\n rowIndex: number;\n type: \"scroll-row\";\n}\nexport interface ScrollRequestEnd {\n type: \"scroll-end\";\n direction: \"home\" | \"end\";\n}\n\nexport interface ScrollRequestPage {\n type: \"scroll-page\";\n direction: ScrollDirectionVertical;\n}\n\nexport type ScrollRequest =\n | ScrollRequestPage\n | ScrollRequestEnd\n | ScrollRequestRow\n | ScrollRequestPosition;\n\nexport type ScrollRequestHandler = (request: ScrollRequest) => void;\n\nexport interface ScrollingAPI {\n scrollToIndex: (itemIndex: number) => void;\n scrollToKey: (rowKey: string) => void;\n}\n\n/** How far we allow horizontal scroll movement before we recheck the rendered columns */\nconst SCROLL_MOVE_CHECK_THRESHOLD = 100;\n\n/** The buffer size in pixels that we allow for rendering columns just outside the viewport */\nconst HORIZONTAL_SCROLL_BUFFER = 200;\n\n/**\n * Return the maximum scroll positions for gioven container\n * @param container\n * @returns [maxScrollLeft, maxScrollTop]\n */\nconst getMaxScroll = (container: HTMLElement) => {\n const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;\n return [scrollWidth - clientWidth, scrollHeight - clientHeight];\n};\n\nconst getScrollDirection = (\n prevScrollPositions: ScrollPos | undefined,\n scrollPos: number,\n) => {\n if (prevScrollPositions === undefined) {\n return undefined;\n } else {\n const { scrollTop: prevTop } = prevScrollPositions;\n return scrollPos > prevTop ? \"fwd\" : \"bwd\";\n }\n};\n\nconst getPctScroll = (container: HTMLElement, currentScrollPos?: ScrollPos) => {\n const {\n clientHeight,\n clientWidth,\n scrollHeight,\n scrollLeft,\n scrollTop,\n scrollWidth,\n } = container;\n\n const maxScrollLeft = scrollWidth - clientWidth;\n const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);\n const maxScrollTop = scrollHeight - clientHeight;\n let pctScrollTop = scrollTop / (scrollHeight - clientHeight);\n\n const scrollDirection = getScrollDirection(currentScrollPos, scrollTop);\n\n if (scrollDirection === \"fwd\" && pctScrollTop > 0.99) {\n pctScrollTop = 1;\n } else if (scrollDirection === \"bwd\" && pctScrollTop < 0.02) {\n pctScrollTop = 0;\n }\n\n return [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ];\n};\n\nexport const noScrolling: ScrollingAPI = {\n scrollToIndex: () => undefined,\n scrollToKey: () => undefined,\n};\n\ninterface CallbackRefHookProps<T = HTMLElement> {\n onAttach?: (el: T) => void;\n onDetach: (el: T) => void;\n label?: string;\n}\n\nconst useCallbackRef = <T = HTMLElement>({\n onAttach,\n onDetach,\n}: CallbackRefHookProps<T>) => {\n const ref = useRef<T | null>(null);\n const callbackRef = useCallback(\n (el: T | null) => {\n if (el) {\n ref.current = el;\n onAttach?.(el);\n } else if (ref.current) {\n const { current: originalRef } = ref;\n ref.current = el;\n onDetach?.(originalRef);\n }\n },\n [onAttach, onDetach],\n );\n return callbackRef;\n};\n\ntype ScrollPos = {\n scrollLeft: number;\n scrollTop: number;\n};\n\nexport interface TableScrollHookProps {\n cellFocusStateRef: RefObject<ICellFocusState>;\n columns: RuntimeColumnDescriptor[];\n focusCell?: FocusCell;\n getRowAtPosition: RowAtPositionFunc;\n onHorizontalScroll?: (scrollLeft: number) => void;\n onVerticalScroll?: (scrollTop: number, pctScrollTop: number) => void;\n /**\n * When we have a virtualized scroll container, keyboard navigation is\n * performed `in situ`. We shift the range of rows rendered within the\n * viewport, whithout actually moving the scroll position\n */\n onVerticalScrollInSitu?: (rowIndexOffsetCount: number) => void;\n rowHeight: number;\n scrollingApiRef?: ForwardedRef<ScrollingAPI>;\n setRange: (range: VuuRange) => void;\n showPaginationControls?: boolean;\n viewportMeasurements: ViewportMeasurements;\n}\n\nexport const useTableScroll = ({\n cellFocusStateRef,\n columns,\n focusCell,\n getRowAtPosition,\n onHorizontalScroll,\n onVerticalScroll,\n onVerticalScrollInSitu,\n rowHeight,\n scrollingApiRef,\n setRange,\n viewportMeasurements,\n}: TableScrollHookProps) => {\n const firstRowRef = useRef<number>(0);\n const rowHeightRef = useRef(rowHeight);\n const contentContainerScrolledRef = useRef(false);\n const contentContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerScrolledRef = useRef(false);\n const scrollbarContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerRef = useRef<HTMLDivElement | null>(null);\n const contentContainerRef = useRef<HTMLDivElement | null>(null);\n const lastHorizontalScrollCheckPoint = useRef(0);\n\n const {\n appliedPageSize,\n isVirtualScroll,\n rowCount: viewportRowCount,\n totalHeaderHeight,\n usesMeasuredHeaderHeight,\n viewportBodyHeight,\n viewportWidth,\n } = viewportMeasurements;\n\n const columnsWithinViewportRef = useRef<RuntimeColumnDescriptor[]>([]);\n const [, forceRefresh] = useState({});\n\n const preSpanRef = useRef(0);\n\n useMemo(() => {\n const [visibleColumns, offset] = getColumnsInViewport(\n columns,\n contentContainerPosRef.current.scrollLeft,\n contentContainerPosRef.current.scrollLeft +\n viewportWidth +\n HORIZONTAL_SCROLL_BUFFER,\n );\n preSpanRef.current = offset;\n columnsWithinViewportRef.current = visibleColumns;\n }, [viewportWidth, columns]);\n\n const handleHorizontalScroll = useCallback(\n (scrollLeft: number) => {\n contentContainerPosRef.current.scrollLeft = scrollLeft;\n onHorizontalScroll?.(scrollLeft);\n\n if (\n Math.abs(scrollLeft - lastHorizontalScrollCheckPoint.current) >\n SCROLL_MOVE_CHECK_THRESHOLD\n ) {\n lastHorizontalScrollCheckPoint.current = scrollLeft;\n\n const [visibleColumns, pre] = getColumnsInViewport(\n columns,\n scrollLeft,\n scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER,\n );\n\n if (itemsChanged(columnsWithinViewportRef.current, visibleColumns)) {\n preSpanRef.current = pre;\n columnsWithinViewportRef.current = visibleColumns;\n forceRefresh({});\n }\n }\n },\n [columns, onHorizontalScroll, viewportWidth],\n );\n const handleVerticalScroll = useCallback(\n (scrollTop: number, pctScrollTop: number) => {\n contentContainerPosRef.current.scrollTop = scrollTop;\n const { current: prevFirstRow } = firstRowRef;\n\n onVerticalScroll?.(scrollTop, pctScrollTop);\n const firstRow = getRowAtPosition(scrollTop);\n if (firstRow !== prevFirstRow) {\n firstRowRef.current = firstRow;\n const lastRow = firstRow + viewportRowCount;\n setRange({ from: firstRow, to: lastRow });\n\n // If we've scrolled the focused cell out of view, we need to remove\n // focus from it. The row element will be recycled and used as the\n // render target for a different DataRow, we do not want the focus\n // state of the cell to be preserved.\n // Conversely, if we scroll the focussed cell back into the viewport,\n // we must re-apply focus to it. We use the placeholder cell for this.\n const { current: focusState } = cellFocusStateRef;\n if (focusState.cellPos) {\n const prevLastRow = prevFirstRow + viewportRowCount;\n const [row] = focusState.cellPos;\n const wasInViewport = row >= prevFirstRow && row < prevLastRow;\n const isInViewport = row >= firstRow && row < lastRow;\n\n if (wasInViewport && !isInViewport) {\n focusState.placeholderEl?.focus({ preventScroll: true });\n focusState.outsideViewport = row < firstRow ? \"above\" : \"below\";\n } else if (isInViewport && !wasInViewport) {\n focusState.outsideViewport = false;\n focusCell?.(focusState.cellPos);\n }\n }\n }\n onVerticalScrollInSitu?.(0);\n },\n [\n cellFocusStateRef,\n focusCell,\n getRowAtPosition,\n onVerticalScroll,\n onVerticalScrollInSitu,\n setRange,\n viewportRowCount,\n ],\n );\n\n const handleScrollbarContainerScroll = useCallback(() => {\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: contentContainerScrolled } = contentContainerScrolledRef;\n const { current: scrollPos } = scrollbarContainerPosRef;\n\n if (contentContainerScrolled) {\n contentContainerScrolledRef.current = false;\n } else if (contentContainer && scrollbarContainer) {\n scrollbarContainerScrolledRef.current = true;\n const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] =\n getPctScroll(scrollbarContainer, scrollPos);\n\n scrollPos.scrollLeft = scrollLeft;\n scrollPos.scrollTop = scrollTop;\n\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer);\n const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft);\n const contentScrollTop = pctScrollTop * maxScrollTop;\n\n contentContainer.scrollTo({\n left: contentScrollLeft,\n top: contentScrollTop,\n behavior: \"auto\",\n });\n }\n onVerticalScrollInSitu?.(0);\n }, [onVerticalScrollInSitu]);\n\n const handleContentContainerScroll = useCallback(() => {\n const { current: scrollbarContainerScrolled } =\n scrollbarContainerScrolledRef;\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: scrollPos } = contentContainerPosRef;\n if (contentContainer && scrollbarContainer) {\n const [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ] = getPctScroll(contentContainer);\n\n contentContainerScrolledRef.current = true;\n\n if (scrollbarContainerScrolled) {\n scrollbarContainerScrolledRef.current = false;\n } else {\n scrollbarContainer.scrollLeft = Math.round(\n pctScrollLeft * maxScrollLeft,\n );\n scrollbarContainer.scrollTop = pctScrollTop * maxScrollTop;\n }\n\n if (scrollPos.scrollTop !== scrollTop) {\n handleVerticalScroll(scrollTop, pctScrollTop);\n }\n if (scrollPos.scrollLeft !== scrollLeft) {\n handleHorizontalScroll(scrollLeft);\n }\n }\n }, [handleVerticalScroll, handleHorizontalScroll]);\n\n const handleAttachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = el;\n el.addEventListener(\"scroll\", handleScrollbarContainerScroll, {\n passive: true,\n });\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleDetachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleScrollbarContainerScroll);\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleAttachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = el;\n el.addEventListener(\"scroll\", handleContentContainerScroll, {\n passive: true,\n });\n },\n [handleContentContainerScroll],\n );\n\n const handleDetachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleContentContainerScroll);\n },\n [handleContentContainerScroll],\n );\n\n const contentContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachContentContainer,\n onDetach: handleDetachContentContainer,\n });\n\n const scrollbarContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachScrollbarContainer,\n onDetach: handleDetachScrollbarContainer,\n });\n\n const requestScroll: ScrollRequestHandler = useCallback(\n (scrollRequest) => {\n const { current: contentContainer } = contentContainerRef;\n if (contentContainer) {\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer);\n const { scrollLeft, scrollTop } = contentContainer;\n contentContainerScrolledRef.current = false;\n switch (scrollRequest.type) {\n case \"scroll-top\":\n {\n contentContainer.scrollTo({\n top: scrollRequest.scrollPos,\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-bottom\":\n {\n contentContainer.scrollTo({\n top:\n scrollRequest.scrollPos -\n (viewportBodyHeight - 2 * rowHeight),\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-row\":\n {\n const activeRow = getRowElementByAriaIndex(\n contentContainer,\n scrollRequest.rowIndex,\n );\n\n if (activeRow !== null) {\n const [direction, distance] = howFarIsRowOutsideViewport(\n activeRow,\n totalHeaderHeight,\n );\n if (direction && distance) {\n if (isVirtualScroll) {\n const offset = direction === \"down\" ? 1 : -1;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({\n from: firstRow,\n to: firstRow + viewportRowCount,\n });\n } else {\n let newScrollLeft = scrollLeft;\n let newScrollTop = scrollTop;\n if (direction === \"up\" || direction === \"down\") {\n newScrollTop = Math.min(\n Math.max(0, scrollTop + distance),\n maxScrollTop,\n );\n } else {\n newScrollLeft = Math.min(\n Math.max(0, scrollLeft + distance),\n maxScrollLeft,\n );\n }\n contentContainer.scrollTo({\n top: newScrollTop,\n left: newScrollLeft,\n // avoid behaviour: 'smooth', doesn't work correctly\n behavior: \"instant\",\n });\n }\n }\n }\n }\n break;\n case \"scroll-page\":\n {\n const { direction } = scrollRequest;\n if (isVirtualScroll) {\n const offset =\n direction === \"down\" ? viewportRowCount : -viewportRowCount;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({ from: firstRow, to: firstRow + viewportRowCount });\n } else {\n const scrollBy =\n direction === \"down\" ? appliedPageSize : -appliedPageSize;\n const newScrollTop = Math.min(\n Math.max(0, scrollTop + scrollBy),\n maxScrollTop,\n );\n contentContainer.scrollTo({\n top: newScrollTop,\n left: scrollLeft,\n behavior: \"auto\",\n });\n }\n }\n break;\n case \"scroll-end\":\n {\n const { direction } = scrollRequest;\n const scrollTo = direction === \"end\" ? maxScrollTop : 0;\n contentContainer.scrollTo({\n top: scrollTo,\n left: contentContainer.scrollLeft,\n behavior: \"auto\",\n });\n }\n break;\n default:\n console.warn(`unexpected scroll request ${scrollRequest[\"type\"]}`);\n }\n }\n },\n [\n appliedPageSize,\n isVirtualScroll,\n onVerticalScrollInSitu,\n rowHeight,\n setRange,\n totalHeaderHeight,\n viewportBodyHeight,\n viewportRowCount,\n ],\n );\n\n const scrollHandles: ScrollingAPI = useMemo(\n // TODO not complete yet\n () => ({\n scrollToIndex: (rowIndex: number) => {\n if (scrollbarContainerRef.current) {\n // TODO hardcoded rowHeight\n const scrollPos = (rowIndex - 30) * 20;\n scrollbarContainerRef.current.scrollTop = scrollPos;\n }\n },\n scrollToKey: (rowKey: string) => {\n console.log(`scrollToKey ${rowKey}`);\n },\n }),\n [],\n );\n\n useImperativeHandle(scrollingApiRef, () => {\n if (scrollbarContainerRef.current) {\n return scrollHandles;\n } else {\n return noScrolling;\n }\n }, [scrollHandles]);\n\n useEffect(() => {\n if (rowHeight !== rowHeightRef.current) {\n rowHeightRef.current = rowHeight;\n if (contentContainerPosRef.current.scrollTop > 0) {\n if (contentContainerRef.current) {\n contentContainerRef.current.scrollTop = 0;\n }\n }\n } else if (usesMeasuredHeaderHeight) {\n const { current: from } = firstRowRef;\n const rowRange = { from, to: from + viewportRowCount };\n setRange(rowRange);\n }\n }, [rowHeight, setRange, usesMeasuredHeaderHeight, viewportRowCount]);\n\n return {\n columnsWithinViewport: columnsWithinViewportRef.current,\n /** Ref to be assigned to ScrollbarContainer */\n scrollbarContainerRef: scrollbarContainerCallbackRef,\n /** Ref to be assigned to ContentContainer */\n contentContainerRef: contentContainerCallbackRef,\n /** Scroll the table */\n requestScroll,\n /** number of leading columns not rendered because of virtualization */\n virtualColSpan: preSpanRef.current,\n };\n};\n"],"names":["useRef","useCallback","useState","useMemo","getColumnsInViewport","itemsChanged","getRowElementByAriaIndex","howFarIsRowOutsideViewport","useImperativeHandle","useEffect"],"mappings":"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"}
|
package/esm/useCellFocus.js
CHANGED
|
@@ -25,29 +25,25 @@ const useCellFocus = ({
|
|
|
25
25
|
[cellFocusStateRef]
|
|
26
26
|
);
|
|
27
27
|
const focusCell = useCallback(
|
|
28
|
-
(cellPos
|
|
28
|
+
(cellPos) => {
|
|
29
29
|
if (containerRef.current) {
|
|
30
30
|
const { current: state } = cellFocusStateRef;
|
|
31
31
|
if (isDifferentCellPosition(state.cellPos, cellPos)) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
state.
|
|
42
|
-
state.outsideViewport = false;
|
|
43
|
-
if (state.placeholderEl) {
|
|
44
|
-
state.placeholderEl.style.top = `${state.pos.top}px`;
|
|
45
|
-
}
|
|
32
|
+
const activeCell = getTableCell(containerRef, cellPos);
|
|
33
|
+
if (activeCell) {
|
|
34
|
+
if (activeCell !== state.el) {
|
|
35
|
+
state.el?.removeAttribute("tabindex");
|
|
36
|
+
activeCell.setAttribute("tabindex", "0");
|
|
37
|
+
state.el = activeCell;
|
|
38
|
+
state.pos = getCellPosition(activeCell);
|
|
39
|
+
state.outsideViewport = false;
|
|
40
|
+
if (state.placeholderEl) {
|
|
41
|
+
state.placeholderEl.style.top = `${state.pos.top}px`;
|
|
46
42
|
}
|
|
47
|
-
state.cellPos = cellPos;
|
|
48
|
-
requestScroll?.({ type: "scroll-row", rowIndex: cellPos[0] });
|
|
49
|
-
activeCell.focus({ preventScroll: true });
|
|
50
43
|
}
|
|
44
|
+
state.cellPos = cellPos;
|
|
45
|
+
requestScroll?.({ type: "scroll-row", rowIndex: cellPos[0] });
|
|
46
|
+
activeCell.focus({ preventScroll: true });
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
}
|
package/esm/useCellFocus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCellFocus.js","sources":["../../../packages/vuu-table/src/useCellFocus.ts"],"sourcesContent":["import {\n KeyboardEventHandler,\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 { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport type { ICellFocusState } from \"./CellFocusState\";\n\nexport interface CellFocusHookProps {\n cellFocusStateRef: RefObject<ICellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\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\nconst isDifferentCellPosition = (\n currentPos: CellPos | undefined,\n newPos: CellPos,\n) => {\n if (currentPos === undefined) {\n return true;\n }\n return currentPos[0] !== newPos[0] || currentPos[1] !== newPos[1];\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) => {\n cellFocusStateRef.current.placeholderEl = el;\n },\n [cellFocusStateRef],\n );\n\n const focusCell = useCallback<FocusCell>(\n (cellPos
|
|
1
|
+
{"version":3,"file":"useCellFocus.js","sources":["../../../packages/vuu-table/src/useCellFocus.ts"],"sourcesContent":["import {\n KeyboardEventHandler,\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 { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport type { ICellFocusState } from \"./CellFocusState\";\n\nexport interface CellFocusHookProps {\n cellFocusStateRef: RefObject<ICellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\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\nconst isDifferentCellPosition = (\n currentPos: CellPos | undefined,\n newPos: CellPos,\n) => {\n if (currentPos === undefined) {\n return true;\n }\n return currentPos[0] !== newPos[0] || currentPos[1] !== newPos[1];\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) => {\n cellFocusStateRef.current.placeholderEl = el;\n },\n [cellFocusStateRef],\n );\n\n const focusCell = useCallback<FocusCell>(\n (cellPos) => {\n if (containerRef.current) {\n const { current: state } = cellFocusStateRef;\n if (isDifferentCellPosition(state.cellPos, cellPos)) {\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 state.cellPos = cellPos;\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 setTableBodyRef = 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 setTableBodyRef,\n };\n};\n"],"names":[],"mappings":";;;;AAuBA,MAAM,eAAA,GAAkB,CAAC,EAAoB,KAAA;AAC3C,EAAA,MAAM,MAAM,QAAS,CAAA,EAAA,CAAG,aAAe,EAAA,KAAA,CAAM,OAAO,IAAI,CAAA;AACxD,EAAA,OAAO,EAAE,GAAI,EAAA;AACf,CAAA;AAEA,MAAM,uBAAA,GAA0B,CAC9B,UAAA,EACA,MACG,KAAA;AACH,EAAA,IAAI,eAAe,KAAW,CAAA,EAAA;AAC5B,IAAO,OAAA,IAAA;AAAA;AAET,EAAO,OAAA,UAAA,CAAW,CAAC,CAAA,KAAM,MAAO,CAAA,CAAC,KAAK,UAAW,CAAA,CAAC,CAAM,KAAA,MAAA,CAAO,CAAC,CAAA;AAClE,CAAA;AAIO,MAAM,eAAe,CAAC;AAAA,EAC3B,iBAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAe,GAAA,KAAA;AAAA,EACf;AACF,CAA0B,KAAA;AACxB,EAAA,MAAM,uBAA0B,GAAA,WAAA;AAAA,IAC9B,CAAC,EAAO,KAAA;AACN,MAAA,iBAAA,CAAkB,QAAQ,aAAgB,GAAA,EAAA;AAAA,KAC5C;AAAA,IACA,CAAC,iBAAiB;AAAA,GACpB;AAEA,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IAChB,CAAC,OAAY,KAAA;AACX,MAAA,IAAI,aAAa,OAAS,EAAA;AACxB,QAAM,MAAA,EAAE,OAAS,EAAA,KAAA,EAAU,GAAA,iBAAA;AAC3B,QAAA,IAAI,uBAAwB,CAAA,KAAA,CAAM,OAAS,EAAA,OAAO,CAAG,EAAA;AACnD,UAAM,MAAA,UAAA,GAAa,YAAa,CAAA,YAAA,EAAc,OAAO,CAAA;AACrD,UAAA,IAAI,UAAY,EAAA;AACd,YAAI,IAAA,UAAA,KAAe,MAAM,EAAI,EAAA;AAC3B,cAAM,KAAA,CAAA,EAAA,EAAI,gBAAgB,UAAU,CAAA;AACpC,cAAW,UAAA,CAAA,YAAA,CAAa,YAAY,GAAG,CAAA;AAIvC,cAAA,KAAA,CAAM,EAAK,GAAA,UAAA;AACX,cAAM,KAAA,CAAA,GAAA,GAAM,gBAAgB,UAAU,CAAA;AACtC,cAAA,KAAA,CAAM,eAAkB,GAAA,KAAA;AAExB,cAAA,IAAI,MAAM,aAAe,EAAA;AACvB,gBAAA,KAAA,CAAM,cAAc,KAAM,CAAA,GAAA,GAAM,CAAG,EAAA,KAAA,CAAM,IAAI,GAAG,CAAA,EAAA,CAAA;AAAA;AAClD;AAEF,YAAA,KAAA,CAAM,OAAU,GAAA,OAAA;AAGhB,YAAA,aAAA,GAAgB,EAAE,IAAM,EAAA,YAAA,EAAc,UAAU,OAAQ,CAAA,CAAC,GAAG,CAAA;AAC5D,YAAA,UAAA,CAAW,KAAM,CAAA,EAAE,aAAe,EAAA,IAAA,EAAM,CAAA;AAAA;AAC1C;AACF;AACF,KACF;AAAA,IACA,CAAC,iBAAmB,EAAA,YAAA,EAAc,aAAa;AAAA,GACjD;AAEA,EAAA,MAAM,eAAkB,GAAA,WAAA;AAAA,IACtB,CAAC,EAAO,KAAA;AACN,MAAA,IAAI,EAAI,EAAA;AACN,QAAM,MAAA,EAAE,OAAS,EAAA,KAAA,EAAU,GAAA,iBAAA;AAC3B,QAAM,MAAA,KAAA,GAAQ,YAA6B,CAAA,EAAA,EAAI,WAAW,CAAA;AAC1D,QAAA,IAAI,KAAO,EAAA;AACT,UAAA,IAAI,KAAM,CAAA,EAAA,KAAO,IAAQ,IAAA,CAAC,YAAc,EAAA;AACtC,YAAA,MAAM,aAAa,KAAM,CAAA,aAAA;AAAA,cACvB,gBAAgB,CAAC;AAAA,aACnB;AACA,YAAA,IAAI,UAAY,EAAA;AACd,cAAW,UAAA,CAAA,YAAA,CAAa,YAAY,GAAG,CAAA;AACvC,cAAM,KAAA,CAAA,OAAA,GAAU,CAAC,CAAA,EAAG,CAAC,CAAA;AACrB,cAAA,KAAA,CAAM,EAAK,GAAA,UAAA;AACX,cAAM,KAAA,CAAA,GAAA,GAAM,EAAE,GAAA,EAAK,CAAI,EAAA,EAAA;AACvB,cAAA,IAAI,MAAM,aAAe,EAAA;AACvB,gBAAM,KAAA,CAAA,aAAA,CAAc,MAAM,GAAM,GAAA,CAAA,KAAA,CAAA;AAAA;AAClC,aACK,MAAA;AACL,cAAA,MAAM,OAAO,KAAM,CAAA,aAAA;AAAA,gBACjB,aAAA,CAAc,GAAG,CAAC;AAAA,eACpB;AACA,cAAA,IAAI,IAAM,EAAA;AACR,gBAAK,IAAA,CAAA,YAAA,CAAa,YAAY,GAAG,CAAA;AACjC,gBAAM,KAAA,CAAA,OAAA,GAAU,CAAC,CAAA,EAAG,CAAC,CAAA;AACrB,gBAAA,KAAA,CAAM,EAAK,GAAA,IAAA;AACX,gBAAM,KAAA,CAAA,GAAA,GAAM,EAAE,GAAA,EAAK,CAAE,EAAA;AACrB,gBAAA,IAAI,MAAM,aAAe,EAAA;AACvB,kBAAM,KAAA,CAAA,aAAA,CAAc,MAAM,GAAM,GAAA,CAAA,GAAA,CAAA;AAAA;AAClC;AACF;AACF;AACF;AACF;AACF,KACF;AAAA,IACA,CAAC,mBAAmB,YAAY;AAAA,GAClC;AAEA,EAAA,MAAM,2BAA8B,GAAA,WAAA;AAAA,IAClC,CAAC,GAAQ,KAAA;AACP,MAAA,MAAM,EAAE,eAAA,EAAiB,GAAI,EAAA,GAAI,iBAAkB,CAAA,OAAA;AACnD,MAAA,IAAI,GAAO,IAAA,UAAA,CAAW,GAAI,CAAA,GAAG,CAAG,EAAA;AAE9B,QAAA,IAAI,oBAAoB,OAAS,EAAA;AAC/B,UAAA,aAAA,GAAgB,EAAE,IAAM,EAAA,YAAA,EAAc,SAAW,EAAA,GAAA,CAAI,KAAK,CAAA;AAAA,SAC5D,MAAA,IAAW,oBAAoB,OAAS,EAAA;AACtC,UAAA,aAAA,GAAgB,EAAE,IAAM,EAAA,eAAA,EAAiB,SAAW,EAAA,GAAA,CAAI,KAAK,CAAA;AAAA,SACxD,MAAA;AACL,UAAM,MAAA,KAAA;AAAA,YACJ,CAAA,6DAAA;AAAA,WACF;AAAA;AACF;AACF,KACF;AAAA,IACA,CAAC,mBAAmB,aAAa;AAAA,GACnC;AAEA,EAAO,OAAA;AAAA,IACL,SAAA;AAAA,IACA,2BAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -98,12 +98,12 @@ const useKeyboardNavigation = ({
|
|
|
98
98
|
[onHighlight, setHighlightedIdx]
|
|
99
99
|
);
|
|
100
100
|
const setActiveCell = useCallback(
|
|
101
|
-
(rowIdx, colIdx
|
|
101
|
+
(rowIdx, colIdx) => {
|
|
102
102
|
const pos = [rowIdx, colIdx];
|
|
103
103
|
if (navigationStyle === "row") {
|
|
104
104
|
setHighlightedIdx(rowIdx);
|
|
105
105
|
} else {
|
|
106
|
-
focusCell(pos
|
|
106
|
+
focusCell(pos);
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
109
|
[focusCell, navigationStyle, setHighlightedIdx]
|
|
@@ -111,12 +111,10 @@ const useKeyboardNavigation = ({
|
|
|
111
111
|
const nextPageItemIdx = useCallback(
|
|
112
112
|
(key, [rowIdx, colIdx]) => new Promise((resolve) => {
|
|
113
113
|
let newRowIdx = rowIdx;
|
|
114
|
-
const { current: focusState } = cellFocusStateRef;
|
|
115
114
|
switch (key) {
|
|
116
115
|
case "PageDown": {
|
|
117
116
|
newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);
|
|
118
117
|
if (newRowIdx !== rowIdx) {
|
|
119
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
120
118
|
requestScroll?.({ type: "scroll-page", direction: "down" });
|
|
121
119
|
}
|
|
122
120
|
break;
|
|
@@ -124,7 +122,6 @@ const useKeyboardNavigation = ({
|
|
|
124
122
|
case "PageUp": {
|
|
125
123
|
newRowIdx = Math.max(0, rowIdx - viewportRowCount);
|
|
126
124
|
if (newRowIdx !== rowIdx) {
|
|
127
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
128
125
|
requestScroll?.({ type: "scroll-page", direction: "up" });
|
|
129
126
|
}
|
|
130
127
|
break;
|
|
@@ -132,7 +129,6 @@ const useKeyboardNavigation = ({
|
|
|
132
129
|
case "Home": {
|
|
133
130
|
newRowIdx = headerCount + 1;
|
|
134
131
|
if (newRowIdx !== rowIdx) {
|
|
135
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
136
132
|
requestScroll?.({ type: "scroll-end", direction: "home" });
|
|
137
133
|
}
|
|
138
134
|
break;
|
|
@@ -140,7 +136,6 @@ const useKeyboardNavigation = ({
|
|
|
140
136
|
case "End": {
|
|
141
137
|
newRowIdx = rowCount + headerCount;
|
|
142
138
|
if (newRowIdx !== rowIdx) {
|
|
143
|
-
focusState.cellPos = [newRowIdx, colIdx];
|
|
144
139
|
requestScroll?.({ type: "scroll-end", direction: "end" });
|
|
145
140
|
}
|
|
146
141
|
break;
|
|
@@ -150,7 +145,7 @@ const useKeyboardNavigation = ({
|
|
|
150
145
|
resolve([newRowIdx, colIdx]);
|
|
151
146
|
}, 35);
|
|
152
147
|
}),
|
|
153
|
-
[
|
|
148
|
+
[headerCount, requestScroll, rowCount, viewportRowCount]
|
|
154
149
|
);
|
|
155
150
|
const handleFocus = useCallback(() => {
|
|
156
151
|
if (disableHighlightOnFocus !== true) {
|
|
@@ -203,7 +198,7 @@ const useKeyboardNavigation = ({
|
|
|
203
198
|
}
|
|
204
199
|
}
|
|
205
200
|
if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {
|
|
206
|
-
setActiveCell(nextRowIdx, nextColIdx
|
|
201
|
+
setActiveCell(nextRowIdx, nextColIdx);
|
|
207
202
|
setHighlightedIndex(nextRowIdx);
|
|
208
203
|
}
|
|
209
204
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKeyboardNavigation.js","sources":["../../../packages/vuu-table/src/useKeyboardNavigation.ts"],"sourcesContent":["import { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport { PageKey, queryClosest } from \"@vuu-ui/vuu-utils\";\nimport { useControlled } from \"@salt-ds/core\";\nimport {\n KeyboardEvent,\n MouseEvent,\n RefObject,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport { TableNavigationStyle } from \"./Table\";\nimport {\n NavigationKey,\n cellDropdownShowing,\n closestRowIndex,\n getAriaCellPos,\n getFocusedCell,\n getNextCellPos,\n getTreeNodeOperation,\n getLevelUp as getLevelUp,\n} from \"./table-dom-utils\";\nimport { ScrollRequestHandler } from \"./useTableScroll\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport { CellFocusState } from \"./CellFocusState\";\n\nconst rowNavigationKeys = new Set<NavigationKey>([\n \"Home\",\n \"End\",\n \"PageUp\",\n \"PageDown\",\n \"ArrowDown\",\n \"ArrowUp\",\n]);\n\nconst CellLocator =\n \".vuuTableCell,.vuuTableHeaderCell,.vuuTableGroupHeaderCell\";\n\nconst CellControlLocator = \".vuuColumnMenu,.vuuColumnHeaderPill\";\n\nconst cellNavigationKeys = new Set(rowNavigationKeys);\ncellNavigationKeys.add(\"ArrowLeft\");\ncellNavigationKeys.add(\"ArrowRight\");\n\nexport const isNavigationKey = (\n key: string,\n navigationStyle: TableNavigationStyle,\n): key is NavigationKey => {\n switch (navigationStyle) {\n case \"cell\":\n case \"tree\":\n return cellNavigationKeys.has(key as NavigationKey);\n case \"row\":\n return rowNavigationKeys.has(key as NavigationKey);\n default:\n return false;\n }\n};\n\n// const editCellWithEditInProgress = (el: HTMLElement | null) => {\n// if (el) {\n// const input = el.querySelector(\"input\");\n// return input && document.activeElement === input;\n// }\n// return false;\n// };\n\nconst focusControlWithinCell = (e: KeyboardEvent, el: HTMLElement | null) => {\n if (e.shiftKey && e.key.match(/Arrow(Left|Right)/)) {\n if (el?.classList.contains(\"vuuTableHeaderCell\")) {\n const menuButton = el?.querySelector<HTMLButtonElement>(\".vuuColumnMenu\");\n if (menuButton) {\n menuButton.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuTableGroupHeaderCell\")) {\n const headerPill = el?.querySelector<HTMLButtonElement>(\n \".vuuColumnHeaderPill\",\n );\n if (headerPill) {\n headerPill.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuColumnHeaderPill\")) {\n const nextPill = el.parentElement?.nextElementSibling\n ?.firstChild as HTMLElement;\n if (nextPill?.classList.contains(\"vuuColumnHeaderPill\")) {\n nextPill.focus();\n return true;\n } else {\n const removeButton = queryClosest(\n el,\n \".vuuTableGroupHeaderCell\",\n true,\n ).querySelector(\".vuuTableGroupHeaderCell-removeAll\") as HTMLElement;\n if (removeButton) {\n removeButton.focus();\n return true;\n }\n }\n }\n }\n return false;\n};\n\nconst PageKeys = [\"Home\", \"End\", \"PageUp\", \"PageDown\"];\nexport const isPagingKey = (key: string): key is PageKey =>\n PageKeys.includes(key);\n\nexport type GroupToggleHandler = (\n treeNodeOperation: \"expand\" | \"collapse\",\n rowIndex: number,\n) => void;\n\nexport interface NavigationHookProps {\n cellFocusStateRef: RefObject<CellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\n columnCount?: number;\n headerCount: number;\n defaultHighlightedIndex?: number;\n disableFocus?: boolean;\n disableHighlightOnFocus?: boolean;\n focusCell: FocusCell;\n highlightedIndex?: number;\n label?: string;\n navigationStyle: TableNavigationStyle;\n viewportRange: VuuRange;\n onHighlight?: (idx: number) => void;\n onToggleGroup: GroupToggleHandler;\n requestScroll?: ScrollRequestHandler;\n restoreLastFocus?: boolean;\n rowCount?: number;\n selected?: unknown;\n viewportRowCount: number;\n}\n\nexport const useKeyboardNavigation = ({\n cellFocusStateRef,\n columnCount = 0,\n containerRef,\n defaultHighlightedIndex,\n disableHighlightOnFocus,\n focusCell,\n headerCount,\n highlightedIndex: highlightedIndexProp,\n navigationStyle,\n requestScroll,\n onHighlight,\n onToggleGroup,\n rowCount = 0,\n viewportRowCount,\n}: NavigationHookProps) => {\n // Keep this in sync with state value. This can be used by functions that need\n // to reference highlightedIndex at call time but do not need to be regenerated\n // every time it changes (i.e keep highlightedIndex out of their dependency\n // arrays, as it can update frequently)\n const highlightedIndexRef = useRef<number | undefined>(undefined);\n\n const [highlightedIndex, setHighlightedIdx] = useControlled({\n controlled: highlightedIndexProp,\n default: defaultHighlightedIndex,\n name: \"UseKeyboardNavigation\",\n });\n highlightedIndexRef.current = highlightedIndex;\n\n // We use aria row index for tracking rows\n const maxRowIndex = rowCount + headerCount;\n\n const setHighlightedIndex = useCallback(\n (idx: number) => {\n onHighlight?.(idx);\n setHighlightedIdx(idx);\n highlightedIndexRef.current = idx;\n },\n [onHighlight, setHighlightedIdx],\n );\n\n const setActiveCell = useCallback(\n (rowIdx: number, colIdx: number, fromKeyboard = false) => {\n const pos: CellPos = [rowIdx, colIdx];\n if (navigationStyle === \"row\") {\n setHighlightedIdx(rowIdx);\n } else {\n focusCell(pos, fromKeyboard);\n }\n },\n [focusCell, navigationStyle, setHighlightedIdx],\n );\n\n const nextPageItemIdx = useCallback(\n (\n key: \"PageDown\" | \"PageUp\" | \"Home\" | \"End\",\n [rowIdx, colIdx]: CellPos,\n ): Promise<CellPos> =>\n new Promise((resolve) => {\n let newRowIdx = rowIdx;\n const { current: focusState } = cellFocusStateRef;\n switch (key) {\n case \"PageDown\": {\n newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-page\", direction: \"down\" });\n }\n break;\n }\n case \"PageUp\": {\n newRowIdx = Math.max(0, rowIdx - viewportRowCount);\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-page\", direction: \"up\" });\n }\n break;\n }\n case \"Home\": {\n newRowIdx = headerCount + 1;\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-end\", direction: \"home\" });\n }\n break;\n }\n case \"End\": {\n newRowIdx = rowCount + headerCount;\n if (newRowIdx !== rowIdx) {\n focusState.cellPos = [newRowIdx, colIdx];\n requestScroll?.({ type: \"scroll-end\", direction: \"end\" });\n }\n break;\n }\n }\n // Introduce a delay to allow the scroll operation to complete,\n // which will trigger a range reset and rerender of rows. We\n // might need to tweak how this works. If we introduce too big\n // a delay, we risk seeing the newly rendered rows, with the focus\n // still on the old cell, which will be apparent as a brief flash\n // of the old cell focus before switching to correct cell. If we were\n // to change the way re assign keys such that we can guarantee that\n // when we page down, rows in same position get same keys, then same\n // cell would be focussed in new page as previous and issue would not\n // arise.\n setTimeout(() => {\n resolve([newRowIdx, colIdx]);\n }, 35);\n }),\n [cellFocusStateRef, headerCount, requestScroll, rowCount, viewportRowCount],\n );\n\n const handleFocus = useCallback(() => {\n // console.log(`[useKeyboardNavigation] handleFocus `);\n if (disableHighlightOnFocus !== true) {\n if (containerRef.current?.contains(document.activeElement)) {\n // IF focus arrives via keyboard, a cell will have received focus,\n // we handle that here. If focus arrives via click on a cell with\n // no tabindex (i.e all cells except one) we leave that to the\n // click handler.\n const focusedCell = getFocusedCell(document.activeElement);\n if (focusedCell) {\n cellFocusStateRef.current.cell = focusedCell;\n if (navigationStyle === \"row\") {\n setHighlightedIdx(cellFocusStateRef.current.cellPos?.[0]);\n }\n }\n }\n }\n }, [\n disableHighlightOnFocus,\n containerRef,\n cellFocusStateRef,\n navigationStyle,\n setHighlightedIdx,\n ]);\n\n const navigateChildItems = useCallback(\n async (\n navigationStyle: \"cell\" | \"tree\" = \"cell\",\n key: NavigationKey,\n shiftKey = false,\n ): Promise<undefined> => {\n const { cellPos } = cellFocusStateRef.current;\n if (cellPos === undefined) {\n throw Error(\"navigateChildItems called before cellPos is set\");\n }\n const [rowIdx, colIdx] = cellPos;\n let nextRowIdx = -1,\n nextColIdx = -1;\n\n if (isPagingKey(key)) {\n [nextRowIdx, nextColIdx] = await nextPageItemIdx(key, cellPos);\n } else {\n const treeNodeOperation = getTreeNodeOperation(\n containerRef,\n navigationStyle,\n cellPos,\n key,\n shiftKey,\n );\n if (\n treeNodeOperation === \"expand\" ||\n treeNodeOperation === \"collapse\"\n ) {\n onToggleGroup(treeNodeOperation, rowIdx - headerCount - 1);\n } else if (treeNodeOperation === \"level-up\") {\n [nextRowIdx, nextColIdx] = getLevelUp(containerRef, cellPos);\n } else {\n [nextRowIdx, nextColIdx] = getNextCellPos(\n key,\n cellPos,\n columnCount,\n maxRowIndex,\n );\n }\n }\n\n if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {\n setActiveCell(nextRowIdx, nextColIdx, true);\n setHighlightedIndex(nextRowIdx);\n }\n },\n [\n cellFocusStateRef,\n nextPageItemIdx,\n containerRef,\n onToggleGroup,\n headerCount,\n columnCount,\n maxRowIndex,\n setActiveCell,\n setHighlightedIndex,\n ],\n );\n\n const scrollRowIntoViewIfNecessary = useCallback(\n (rowIndex: number) => {\n requestScroll?.({ type: \"scroll-row\", rowIndex });\n },\n [requestScroll],\n );\n\n const moveHighlightedRow = useCallback(\n async (key: NavigationKey) => {\n const { current: highlighted } = highlightedIndexRef;\n const [nextRowIdx] = isPagingKey(key)\n ? await nextPageItemIdx(key, [highlighted ?? -1, 0])\n : getNextCellPos(key, [highlighted ?? -1, 0], columnCount, maxRowIndex);\n if (nextRowIdx !== highlighted) {\n setHighlightedIndex(nextRowIdx);\n // TO(DO make this a scroll request)\n scrollRowIntoViewIfNecessary(nextRowIdx);\n }\n },\n [\n columnCount,\n maxRowIndex,\n nextPageItemIdx,\n scrollRowIntoViewIfNecessary,\n setHighlightedIndex,\n ],\n );\n\n useEffect(() => {\n if (highlightedIndexProp !== undefined && highlightedIndexProp !== -1) {\n requestAnimationFrame(() => {\n // deferred call, ensuring table has fully rendered\n scrollRowIntoViewIfNecessary(highlightedIndexProp);\n });\n }\n }, [highlightedIndexProp, scrollRowIntoViewIfNecessary]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n // console.log(`[useKeyboardNavigation] handleKeyDown`);\n\n const cell = queryClosest<HTMLDivElement>(\n e.target,\n `${CellLocator},${CellControlLocator}`,\n );\n if (cellDropdownShowing(cell)) {\n return;\n }\n if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {\n // if (e.key === \"ArrowDown\" && editCellWithEditInProgress(cell)) {\n // // do nothing editCellWithEditInProgress\n // } else {\n // console.log(\n // `[useKeyboardNavigation] handleKeyDown - consume the keydown event`,\n // );\n e.preventDefault();\n e.stopPropagation();\n if (navigationStyle === \"row\") {\n moveHighlightedRow(e.key);\n } else if (navigationStyle !== \"none\") {\n if (!focusControlWithinCell(e, cell)) {\n navigateChildItems(navigationStyle, e.key, e.shiftKey);\n }\n }\n // }\n }\n },\n [rowCount, navigationStyle, moveHighlightedRow, navigateChildItems],\n );\n\n const handleClick = useCallback(\n // Might not be a cell e.g the Settings button\n (evt: MouseEvent) => {\n // console.log(`[useKeyboardNavigation] click`);\n const target = queryClosest<HTMLDivElement>(evt.target, CellLocator);\n const focusedCell = getFocusedCell(target);\n if (focusedCell) {\n const [rowIdx, colIdx] = getAriaCellPos(focusedCell);\n setActiveCell(rowIdx, colIdx);\n }\n },\n [setActiveCell],\n );\n\n const handleMouseLeave = useCallback(() => {\n setHighlightedIndex(-1);\n }, [setHighlightedIndex]);\n\n const handleMouseMove = useCallback(\n (evt: MouseEvent) => {\n const rowIdx = closestRowIndex(evt.target as HTMLElement);\n if (rowIdx !== -1 && rowIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(rowIdx);\n }\n },\n [setHighlightedIndex],\n );\n\n /**\n * used when editing cells\n */\n const navigateCell = useCallback(() => {\n navigateChildItems(\"cell\", \"ArrowDown\");\n }, [navigateChildItems]);\n\n return {\n highlightedIndexRef,\n navigateCell,\n onClick: handleClick,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n onMouseLeave: navigationStyle === \"row\" ? handleMouseLeave : undefined,\n onMouseMove: navigationStyle === \"row\" ? handleMouseMove : undefined,\n };\n};\n"],"names":["navigationStyle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useKeyboardNavigation.js","sources":["../../../packages/vuu-table/src/useKeyboardNavigation.ts"],"sourcesContent":["import { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport { PageKey, queryClosest } from \"@vuu-ui/vuu-utils\";\nimport { useControlled } from \"@salt-ds/core\";\nimport {\n KeyboardEvent,\n MouseEvent,\n RefObject,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport { TableNavigationStyle } from \"./Table\";\nimport {\n NavigationKey,\n cellDropdownShowing,\n closestRowIndex,\n getAriaCellPos,\n getFocusedCell,\n getNextCellPos,\n getTreeNodeOperation,\n getLevelUp as getLevelUp,\n} from \"./table-dom-utils\";\nimport { ScrollRequestHandler } from \"./useTableScroll\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { CellPos } from \"@vuu-ui/vuu-table-types\";\nimport { CellFocusState } from \"./CellFocusState\";\n\nconst rowNavigationKeys = new Set<NavigationKey>([\n \"Home\",\n \"End\",\n \"PageUp\",\n \"PageDown\",\n \"ArrowDown\",\n \"ArrowUp\",\n]);\n\nconst CellLocator =\n \".vuuTableCell,.vuuTableHeaderCell,.vuuTableGroupHeaderCell\";\n\nconst CellControlLocator = \".vuuColumnMenu,.vuuColumnHeaderPill\";\n\nconst cellNavigationKeys = new Set(rowNavigationKeys);\ncellNavigationKeys.add(\"ArrowLeft\");\ncellNavigationKeys.add(\"ArrowRight\");\n\nexport const isNavigationKey = (\n key: string,\n navigationStyle: TableNavigationStyle,\n): key is NavigationKey => {\n switch (navigationStyle) {\n case \"cell\":\n case \"tree\":\n return cellNavigationKeys.has(key as NavigationKey);\n case \"row\":\n return rowNavigationKeys.has(key as NavigationKey);\n default:\n return false;\n }\n};\n\n// const editCellWithEditInProgress = (el: HTMLElement | null) => {\n// if (el) {\n// const input = el.querySelector(\"input\");\n// return input && document.activeElement === input;\n// }\n// return false;\n// };\n\nconst focusControlWithinCell = (e: KeyboardEvent, el: HTMLElement | null) => {\n if (e.shiftKey && e.key.match(/Arrow(Left|Right)/)) {\n if (el?.classList.contains(\"vuuTableHeaderCell\")) {\n const menuButton = el?.querySelector<HTMLButtonElement>(\".vuuColumnMenu\");\n if (menuButton) {\n menuButton.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuTableGroupHeaderCell\")) {\n const headerPill = el?.querySelector<HTMLButtonElement>(\n \".vuuColumnHeaderPill\",\n );\n if (headerPill) {\n headerPill.focus();\n return true;\n }\n } else if (el?.classList.contains(\"vuuColumnHeaderPill\")) {\n const nextPill = el.parentElement?.nextElementSibling\n ?.firstChild as HTMLElement;\n if (nextPill?.classList.contains(\"vuuColumnHeaderPill\")) {\n nextPill.focus();\n return true;\n } else {\n const removeButton = queryClosest(\n el,\n \".vuuTableGroupHeaderCell\",\n true,\n ).querySelector(\".vuuTableGroupHeaderCell-removeAll\") as HTMLElement;\n if (removeButton) {\n removeButton.focus();\n return true;\n }\n }\n }\n }\n return false;\n};\n\nconst PageKeys = [\"Home\", \"End\", \"PageUp\", \"PageDown\"];\nexport const isPagingKey = (key: string): key is PageKey =>\n PageKeys.includes(key);\n\nexport type GroupToggleHandler = (\n treeNodeOperation: \"expand\" | \"collapse\",\n rowIndex: number,\n) => void;\n\nexport interface NavigationHookProps {\n cellFocusStateRef: RefObject<CellFocusState>;\n containerRef: RefObject<HTMLElement | null>;\n columnCount?: number;\n headerCount: number;\n defaultHighlightedIndex?: number;\n disableFocus?: boolean;\n disableHighlightOnFocus?: boolean;\n focusCell: FocusCell;\n highlightedIndex?: number;\n label?: string;\n navigationStyle: TableNavigationStyle;\n viewportRange: VuuRange;\n onHighlight?: (idx: number) => void;\n onToggleGroup: GroupToggleHandler;\n requestScroll?: ScrollRequestHandler;\n restoreLastFocus?: boolean;\n rowCount?: number;\n selected?: unknown;\n viewportRowCount: number;\n}\n\nexport const useKeyboardNavigation = ({\n cellFocusStateRef,\n columnCount = 0,\n containerRef,\n defaultHighlightedIndex,\n disableHighlightOnFocus,\n focusCell,\n headerCount,\n highlightedIndex: highlightedIndexProp,\n navigationStyle,\n requestScroll,\n onHighlight,\n onToggleGroup,\n rowCount = 0,\n viewportRowCount,\n}: NavigationHookProps) => {\n // Keep this in sync with state value. This can be used by functions that need\n // to reference highlightedIndex at call time but do not need to be regenerated\n // every time it changes (i.e keep highlightedIndex out of their dependency\n // arrays, as it can update frequently)\n const highlightedIndexRef = useRef<number | undefined>(undefined);\n\n const [highlightedIndex, setHighlightedIdx] = useControlled({\n controlled: highlightedIndexProp,\n default: defaultHighlightedIndex,\n name: \"UseKeyboardNavigation\",\n });\n highlightedIndexRef.current = highlightedIndex;\n\n // We use aria row index for tracking rows\n const maxRowIndex = rowCount + headerCount;\n\n const setHighlightedIndex = useCallback(\n (idx: number) => {\n onHighlight?.(idx);\n setHighlightedIdx(idx);\n highlightedIndexRef.current = idx;\n },\n [onHighlight, setHighlightedIdx],\n );\n\n const setActiveCell = useCallback(\n (rowIdx: number, colIdx: number) => {\n const pos: CellPos = [rowIdx, colIdx];\n if (navigationStyle === \"row\") {\n setHighlightedIdx(rowIdx);\n } else {\n focusCell(pos);\n }\n },\n [focusCell, navigationStyle, setHighlightedIdx],\n );\n\n const nextPageItemIdx = useCallback(\n (\n key: \"PageDown\" | \"PageUp\" | \"Home\" | \"End\",\n [rowIdx, colIdx]: CellPos,\n ): Promise<CellPos> =>\n new Promise((resolve) => {\n let newRowIdx = rowIdx;\n switch (key) {\n case \"PageDown\": {\n newRowIdx = Math.min(rowCount - 1, rowIdx + viewportRowCount);\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-page\", direction: \"down\" });\n }\n break;\n }\n case \"PageUp\": {\n newRowIdx = Math.max(0, rowIdx - viewportRowCount);\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-page\", direction: \"up\" });\n }\n break;\n }\n case \"Home\": {\n newRowIdx = headerCount + 1;\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-end\", direction: \"home\" });\n }\n break;\n }\n case \"End\": {\n newRowIdx = rowCount + headerCount;\n if (newRowIdx !== rowIdx) {\n requestScroll?.({ type: \"scroll-end\", direction: \"end\" });\n }\n break;\n }\n }\n // Introduce a delay to allow the scroll operation to complete,\n // which will trigger a range reset and rerender of rows. We\n // might need to tweak how this works. If we introduce too big\n // a delay, we risk seeing the newly rendered rows, with the focus\n // still on the old cell, which will be apparent as a brief flash\n // of the old cell focus before switching to correct cell. If we were\n // to change the way re assign keys such that we can guarantee that\n // when we page down, rows in same position get same keys, then same\n // cell would be focussed in new page as previous and issue would not\n // arise.\n setTimeout(() => {\n resolve([newRowIdx, colIdx]);\n }, 35);\n }),\n [headerCount, requestScroll, rowCount, viewportRowCount],\n );\n\n const handleFocus = useCallback(() => {\n // console.log(`[useKeyboardNavigation] handleFocus `);\n if (disableHighlightOnFocus !== true) {\n if (containerRef.current?.contains(document.activeElement)) {\n // IF focus arrives via keyboard, a cell will have received focus,\n // we handle that here. If focus arrives via click on a cell with\n // no tabindex (i.e all cells except one) we leave that to the\n // click handler.\n const focusedCell = getFocusedCell(document.activeElement);\n if (focusedCell) {\n cellFocusStateRef.current.cell = focusedCell;\n if (navigationStyle === \"row\") {\n setHighlightedIdx(cellFocusStateRef.current.cellPos?.[0]);\n }\n }\n }\n }\n }, [\n disableHighlightOnFocus,\n containerRef,\n cellFocusStateRef,\n navigationStyle,\n setHighlightedIdx,\n ]);\n\n const navigateChildItems = useCallback(\n async (\n navigationStyle: \"cell\" | \"tree\" = \"cell\",\n key: NavigationKey,\n shiftKey = false,\n ): Promise<undefined> => {\n const { cellPos } = cellFocusStateRef.current;\n if (cellPos === undefined) {\n throw Error(\"navigateChildItems called before cellPos is set\");\n }\n const [rowIdx, colIdx] = cellPos;\n let nextRowIdx = -1,\n nextColIdx = -1;\n\n if (isPagingKey(key)) {\n [nextRowIdx, nextColIdx] = await nextPageItemIdx(key, cellPos);\n } else {\n const treeNodeOperation = getTreeNodeOperation(\n containerRef,\n navigationStyle,\n cellPos,\n key,\n shiftKey,\n );\n if (\n treeNodeOperation === \"expand\" ||\n treeNodeOperation === \"collapse\"\n ) {\n onToggleGroup(treeNodeOperation, rowIdx - headerCount - 1);\n } else if (treeNodeOperation === \"level-up\") {\n [nextRowIdx, nextColIdx] = getLevelUp(containerRef, cellPos);\n } else {\n [nextRowIdx, nextColIdx] = getNextCellPos(\n key,\n cellPos,\n columnCount,\n maxRowIndex,\n );\n }\n }\n\n if (nextRowIdx !== rowIdx || nextColIdx !== colIdx) {\n setActiveCell(nextRowIdx, nextColIdx);\n setHighlightedIndex(nextRowIdx);\n }\n },\n [\n cellFocusStateRef,\n nextPageItemIdx,\n containerRef,\n onToggleGroup,\n headerCount,\n columnCount,\n maxRowIndex,\n setActiveCell,\n setHighlightedIndex,\n ],\n );\n\n const scrollRowIntoViewIfNecessary = useCallback(\n (rowIndex: number) => {\n requestScroll?.({ type: \"scroll-row\", rowIndex });\n },\n [requestScroll],\n );\n\n const moveHighlightedRow = useCallback(\n async (key: NavigationKey) => {\n const { current: highlighted } = highlightedIndexRef;\n const [nextRowIdx] = isPagingKey(key)\n ? await nextPageItemIdx(key, [highlighted ?? -1, 0])\n : getNextCellPos(key, [highlighted ?? -1, 0], columnCount, maxRowIndex);\n if (nextRowIdx !== highlighted) {\n setHighlightedIndex(nextRowIdx);\n // TO(DO make this a scroll request)\n scrollRowIntoViewIfNecessary(nextRowIdx);\n }\n },\n [\n columnCount,\n maxRowIndex,\n nextPageItemIdx,\n scrollRowIntoViewIfNecessary,\n setHighlightedIndex,\n ],\n );\n\n useEffect(() => {\n if (highlightedIndexProp !== undefined && highlightedIndexProp !== -1) {\n requestAnimationFrame(() => {\n // deferred call, ensuring table has fully rendered\n scrollRowIntoViewIfNecessary(highlightedIndexProp);\n });\n }\n }, [highlightedIndexProp, scrollRowIntoViewIfNecessary]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n // console.log(`[useKeyboardNavigation] handleKeyDown`);\n\n const cell = queryClosest<HTMLDivElement>(\n e.target,\n `${CellLocator},${CellControlLocator}`,\n );\n if (cellDropdownShowing(cell)) {\n return;\n }\n if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {\n // if (e.key === \"ArrowDown\" && editCellWithEditInProgress(cell)) {\n // // do nothing editCellWithEditInProgress\n // } else {\n // console.log(\n // `[useKeyboardNavigation] handleKeyDown - consume the keydown event`,\n // );\n e.preventDefault();\n e.stopPropagation();\n if (navigationStyle === \"row\") {\n moveHighlightedRow(e.key);\n } else if (navigationStyle !== \"none\") {\n if (!focusControlWithinCell(e, cell)) {\n navigateChildItems(navigationStyle, e.key, e.shiftKey);\n }\n }\n // }\n }\n },\n [rowCount, navigationStyle, moveHighlightedRow, navigateChildItems],\n );\n\n const handleClick = useCallback(\n // Might not be a cell e.g the Settings button\n (evt: MouseEvent) => {\n // console.log(`[useKeyboardNavigation] click`);\n const target = queryClosest<HTMLDivElement>(evt.target, CellLocator);\n const focusedCell = getFocusedCell(target);\n if (focusedCell) {\n const [rowIdx, colIdx] = getAriaCellPos(focusedCell);\n setActiveCell(rowIdx, colIdx);\n }\n },\n [setActiveCell],\n );\n\n const handleMouseLeave = useCallback(() => {\n setHighlightedIndex(-1);\n }, [setHighlightedIndex]);\n\n const handleMouseMove = useCallback(\n (evt: MouseEvent) => {\n const rowIdx = closestRowIndex(evt.target as HTMLElement);\n if (rowIdx !== -1 && rowIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(rowIdx);\n }\n },\n [setHighlightedIndex],\n );\n\n /**\n * used when editing cells\n */\n const navigateCell = useCallback(() => {\n navigateChildItems(\"cell\", \"ArrowDown\");\n }, [navigateChildItems]);\n\n return {\n highlightedIndexRef,\n navigateCell,\n onClick: handleClick,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n onMouseLeave: navigationStyle === \"row\" ? handleMouseLeave : undefined,\n onMouseMove: navigationStyle === \"row\" ? handleMouseMove : undefined,\n };\n};\n"],"names":["navigationStyle"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableScroll.js","sources":["../../../packages/vuu-table/src/useTableScroll.ts"],"sourcesContent":["import {\n getColumnsInViewport,\n itemsChanged,\n RowAtPositionFunc,\n} from \"@vuu-ui/vuu-utils\";\nimport type { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n ForwardedRef,\n MutableRefObject,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ViewportMeasurements } from \"./useTableViewport\";\nimport {\n getRowElementByAriaIndex,\n howFarIsRowOutsideViewport,\n} from \"./table-dom-utils\";\nimport type { RuntimeColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { ICellFocusState } from \"./CellFocusState\";\n\nexport type ScrollDirectionVertical = \"up\" | \"down\";\nexport type ScrollDirectionHorizontal = \"left\" | \"right\";\nexport type ScrollDirection =\n | ScrollDirectionVertical\n | ScrollDirectionHorizontal;\n\n/**\n * scroll into view the row at given pixel offset.\n */\nexport interface ScrollRequestPosition {\n scrollPos: number;\n type: \"scroll-top\" | \"scroll-bottom\";\n}\n\n/**\n * scroll into view the row at given row index posiiton.\n */\nexport interface ScrollRequestRow {\n rowIndex: number;\n type: \"scroll-row\";\n}\nexport interface ScrollRequestEnd {\n type: \"scroll-end\";\n direction: \"home\" | \"end\";\n}\n\nexport interface ScrollRequestPage {\n type: \"scroll-page\";\n direction: ScrollDirectionVertical;\n}\n\nexport type ScrollRequest =\n | ScrollRequestPage\n | ScrollRequestEnd\n | ScrollRequestRow\n | ScrollRequestPosition;\n\nexport type ScrollRequestHandler = (request: ScrollRequest) => void;\n\nexport interface ScrollingAPI {\n scrollToIndex: (itemIndex: number) => void;\n scrollToKey: (rowKey: string) => void;\n}\n\n/** How far we allow horizontal scroll movement before we recheck the rendered columns */\nconst SCROLL_MOVE_CHECK_THRESHOLD = 100;\n\n/** The buffer size in pixels that we allow for rendering columns just outside the viewport */\nconst HORIZONTAL_SCROLL_BUFFER = 200;\n\n/**\n * Return the maximum scroll positions for gioven container\n * @param container\n * @returns [maxScrollLeft, maxScrollTop]\n */\nconst getMaxScroll = (container: HTMLElement) => {\n const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;\n return [scrollWidth - clientWidth, scrollHeight - clientHeight];\n};\n\nconst getScrollDirection = (\n prevScrollPositions: ScrollPos | undefined,\n scrollPos: number,\n) => {\n if (prevScrollPositions === undefined) {\n return undefined;\n } else {\n const { scrollTop: prevTop } = prevScrollPositions;\n return scrollPos > prevTop ? \"fwd\" : \"bwd\";\n }\n};\n\nconst getPctScroll = (container: HTMLElement, currentScrollPos?: ScrollPos) => {\n const {\n clientHeight,\n clientWidth,\n scrollHeight,\n scrollLeft,\n scrollTop,\n scrollWidth,\n } = container;\n\n const maxScrollLeft = scrollWidth - clientWidth;\n const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);\n const maxScrollTop = scrollHeight - clientHeight;\n let pctScrollTop = scrollTop / (scrollHeight - clientHeight);\n\n const scrollDirection = getScrollDirection(currentScrollPos, scrollTop);\n\n if (scrollDirection === \"fwd\" && pctScrollTop > 0.99) {\n pctScrollTop = 1;\n } else if (scrollDirection === \"bwd\" && pctScrollTop < 0.02) {\n pctScrollTop = 0;\n }\n\n return [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ];\n};\n\nexport const noScrolling: ScrollingAPI = {\n scrollToIndex: () => undefined,\n scrollToKey: () => undefined,\n};\n\ninterface CallbackRefHookProps<T = HTMLElement> {\n onAttach?: (el: T) => void;\n onDetach: (el: T) => void;\n label?: string;\n}\n\nconst useCallbackRef = <T = HTMLElement>({\n onAttach,\n onDetach,\n}: CallbackRefHookProps<T>) => {\n const ref = useRef<T | null>(null);\n const callbackRef = useCallback(\n (el: T | null) => {\n if (el) {\n ref.current = el;\n onAttach?.(el);\n } else if (ref.current) {\n const { current: originalRef } = ref;\n ref.current = el;\n onDetach?.(originalRef);\n }\n },\n [onAttach, onDetach],\n );\n return callbackRef;\n};\n\ntype ScrollPos = {\n scrollLeft: number;\n scrollTop: number;\n};\n\nexport interface TableScrollHookProps {\n cellFocusStateRef: MutableRefObject<ICellFocusState>;\n columns: RuntimeColumnDescriptor[];\n focusCell?: FocusCell;\n getRowAtPosition: RowAtPositionFunc;\n onHorizontalScroll?: (scrollLeft: number) => void;\n onVerticalScroll?: (scrollTop: number, pctScrollTop: number) => void;\n /**\n * When we have a virtualized scroll container, keyboard navigation is\n * performed `in situ`. We shift the range of rows rendered within the\n * viewport, whithout actually moving the scroll position\n */\n onVerticalScrollInSitu?: (rowIndexOffsetCount: number) => void;\n rowHeight: number;\n scrollingApiRef?: ForwardedRef<ScrollingAPI>;\n setRange: (range: VuuRange) => void;\n showPaginationControls?: boolean;\n viewportMeasurements: ViewportMeasurements;\n}\n\nexport const useTableScroll = ({\n cellFocusStateRef,\n columns,\n focusCell,\n getRowAtPosition,\n onHorizontalScroll,\n onVerticalScroll,\n onVerticalScrollInSitu,\n rowHeight,\n scrollingApiRef,\n setRange,\n viewportMeasurements,\n}: TableScrollHookProps) => {\n const firstRowRef = useRef<number>(0);\n const rowHeightRef = useRef(rowHeight);\n const contentContainerScrolledRef = useRef(false);\n const contentContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerScrolledRef = useRef(false);\n const scrollbarContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerRef = useRef<HTMLDivElement | null>(null);\n const contentContainerRef = useRef<HTMLDivElement | null>(null);\n const lastHorizontalScrollCheckPoint = useRef(0);\n\n const {\n appliedPageSize,\n isVirtualScroll,\n rowCount: viewportRowCount,\n totalHeaderHeight,\n usesMeasuredHeaderHeight,\n viewportBodyHeight,\n viewportWidth,\n } = viewportMeasurements;\n\n const columnsWithinViewportRef = useRef<RuntimeColumnDescriptor[]>([]);\n const [, forceRefresh] = useState({});\n\n const preSpanRef = useRef(0);\n\n useMemo(() => {\n const [visibleColumns, offset] = getColumnsInViewport(\n columns,\n contentContainerPosRef.current.scrollLeft,\n contentContainerPosRef.current.scrollLeft +\n viewportWidth +\n HORIZONTAL_SCROLL_BUFFER,\n );\n preSpanRef.current = offset;\n columnsWithinViewportRef.current = visibleColumns;\n }, [viewportWidth, columns]);\n\n const handleHorizontalScroll = useCallback(\n (scrollLeft: number) => {\n contentContainerPosRef.current.scrollLeft = scrollLeft;\n onHorizontalScroll?.(scrollLeft);\n\n if (\n Math.abs(scrollLeft - lastHorizontalScrollCheckPoint.current) >\n SCROLL_MOVE_CHECK_THRESHOLD\n ) {\n lastHorizontalScrollCheckPoint.current = scrollLeft;\n\n const [visibleColumns, pre] = getColumnsInViewport(\n columns,\n scrollLeft,\n scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER,\n );\n\n if (itemsChanged(columnsWithinViewportRef.current, visibleColumns)) {\n preSpanRef.current = pre;\n columnsWithinViewportRef.current = visibleColumns;\n forceRefresh({});\n }\n }\n },\n [columns, onHorizontalScroll, viewportWidth],\n );\n const handleVerticalScroll = useCallback(\n (scrollTop: number, pctScrollTop: number) => {\n contentContainerPosRef.current.scrollTop = scrollTop;\n const { current: prevFirstRow } = firstRowRef;\n\n onVerticalScroll?.(scrollTop, pctScrollTop);\n const firstRow = getRowAtPosition(scrollTop);\n if (firstRow !== prevFirstRow) {\n firstRowRef.current = firstRow;\n const lastRow = firstRow + viewportRowCount;\n setRange({ from: firstRow, to: lastRow });\n\n // If we've scrolled the focused cell out of view, we need to remove\n // focus from it. The row element will be recycled and used as the\n // render target for a different DataRow, we do not want the focus\n // state of the cell to be preserved.\n // Conversely, if we scroll the focussed cell back into the viewport,\n // we must re-apply focus to it. We use the placeholder cell for this.\n const { current: focusState } = cellFocusStateRef;\n if (focusState.cellPos) {\n const prevLastRow = prevFirstRow + viewportRowCount;\n const [row] = focusState.cellPos;\n const wasInViewport = row >= prevFirstRow && row < prevLastRow;\n const isInViewport = row >= firstRow && row < lastRow;\n\n if (wasInViewport && !isInViewport) {\n focusState.placeholderEl?.focus({ preventScroll: true });\n focusState.outsideViewport = row < firstRow ? \"above\" : \"below\";\n } else if (isInViewport && !wasInViewport) {\n focusState.outsideViewport = false;\n focusCell?.(focusState.cellPos);\n }\n }\n }\n onVerticalScrollInSitu?.(0);\n },\n [\n cellFocusStateRef,\n focusCell,\n getRowAtPosition,\n onVerticalScroll,\n onVerticalScrollInSitu,\n setRange,\n viewportRowCount,\n ],\n );\n\n const handleScrollbarContainerScroll = useCallback(() => {\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: contentContainerScrolled } = contentContainerScrolledRef;\n const { current: scrollPos } = scrollbarContainerPosRef;\n\n if (contentContainerScrolled) {\n contentContainerScrolledRef.current = false;\n } else if (contentContainer && scrollbarContainer) {\n scrollbarContainerScrolledRef.current = true;\n const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] =\n getPctScroll(scrollbarContainer, scrollPos);\n\n scrollPos.scrollLeft = scrollLeft;\n scrollPos.scrollTop = scrollTop;\n\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer);\n const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft);\n const contentScrollTop = pctScrollTop * maxScrollTop;\n\n contentContainer.scrollTo({\n left: contentScrollLeft,\n top: contentScrollTop,\n behavior: \"auto\",\n });\n }\n onVerticalScrollInSitu?.(0);\n }, [onVerticalScrollInSitu]);\n\n const handleContentContainerScroll = useCallback(() => {\n const { current: scrollbarContainerScrolled } =\n scrollbarContainerScrolledRef;\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: scrollPos } = contentContainerPosRef;\n if (contentContainer && scrollbarContainer) {\n const [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ] = getPctScroll(contentContainer);\n\n contentContainerScrolledRef.current = true;\n\n if (scrollbarContainerScrolled) {\n scrollbarContainerScrolledRef.current = false;\n } else {\n scrollbarContainer.scrollLeft = Math.round(\n pctScrollLeft * maxScrollLeft,\n );\n scrollbarContainer.scrollTop = pctScrollTop * maxScrollTop;\n }\n\n if (scrollPos.scrollTop !== scrollTop) {\n handleVerticalScroll(scrollTop, pctScrollTop);\n }\n if (scrollPos.scrollLeft !== scrollLeft) {\n handleHorizontalScroll(scrollLeft);\n }\n }\n }, [handleVerticalScroll, handleHorizontalScroll]);\n\n const handleAttachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = el;\n el.addEventListener(\"scroll\", handleScrollbarContainerScroll, {\n passive: true,\n });\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleDetachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleScrollbarContainerScroll);\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleAttachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = el;\n el.addEventListener(\"scroll\", handleContentContainerScroll, {\n passive: true,\n });\n },\n [handleContentContainerScroll],\n );\n\n const handleDetachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleContentContainerScroll);\n },\n [handleContentContainerScroll],\n );\n\n const contentContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachContentContainer,\n onDetach: handleDetachContentContainer,\n });\n\n const scrollbarContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachScrollbarContainer,\n onDetach: handleDetachScrollbarContainer,\n });\n\n const requestScroll: ScrollRequestHandler = useCallback(\n (scrollRequest) => {\n const { current: contentContainer } = contentContainerRef;\n if (contentContainer) {\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer);\n const { scrollLeft, scrollTop } = contentContainer;\n contentContainerScrolledRef.current = false;\n switch (scrollRequest.type) {\n case \"scroll-top\":\n {\n contentContainer.scrollTo({\n top: scrollRequest.scrollPos,\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-bottom\":\n {\n contentContainer.scrollTo({\n top:\n scrollRequest.scrollPos -\n (viewportBodyHeight - 2 * rowHeight),\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-row\":\n {\n const activeRow = getRowElementByAriaIndex(\n contentContainer,\n scrollRequest.rowIndex,\n );\n\n if (activeRow !== null) {\n const [direction, distance] = howFarIsRowOutsideViewport(\n activeRow,\n totalHeaderHeight,\n );\n if (direction && distance) {\n if (isVirtualScroll) {\n const offset = direction === \"down\" ? 1 : -1;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({\n from: firstRow,\n to: firstRow + viewportRowCount,\n });\n } else {\n let newScrollLeft = scrollLeft;\n let newScrollTop = scrollTop;\n if (direction === \"up\" || direction === \"down\") {\n newScrollTop = Math.min(\n Math.max(0, scrollTop + distance),\n maxScrollTop,\n );\n } else {\n newScrollLeft = Math.min(\n Math.max(0, scrollLeft + distance),\n maxScrollLeft,\n );\n }\n contentContainer.scrollTo({\n top: newScrollTop,\n left: newScrollLeft,\n // avoid behaviour: 'smooth', doesn't work correctly\n behavior: \"instant\",\n });\n }\n }\n }\n }\n break;\n case \"scroll-page\":\n {\n const { direction } = scrollRequest;\n if (isVirtualScroll) {\n const offset =\n direction === \"down\" ? viewportRowCount : -viewportRowCount;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({ from: firstRow, to: firstRow + viewportRowCount });\n } else {\n const scrollBy =\n direction === \"down\" ? appliedPageSize : -appliedPageSize;\n const newScrollTop = Math.min(\n Math.max(0, scrollTop + scrollBy),\n maxScrollTop,\n );\n contentContainer.scrollTo({\n top: newScrollTop,\n left: scrollLeft,\n behavior: \"auto\",\n });\n }\n }\n break;\n case \"scroll-end\":\n {\n const { direction } = scrollRequest;\n const scrollTo = direction === \"end\" ? maxScrollTop : 0;\n contentContainer.scrollTo({\n top: scrollTo,\n left: contentContainer.scrollLeft,\n behavior: \"auto\",\n });\n }\n break;\n default:\n console.warn(`unexpected scroll request ${scrollRequest[\"type\"]}`);\n }\n }\n },\n [\n appliedPageSize,\n isVirtualScroll,\n onVerticalScrollInSitu,\n rowHeight,\n setRange,\n totalHeaderHeight,\n viewportBodyHeight,\n viewportRowCount,\n ],\n );\n\n const scrollHandles: ScrollingAPI = useMemo(\n // TODO not complete yet\n () => ({\n scrollToIndex: (rowIndex: number) => {\n if (scrollbarContainerRef.current) {\n // TODO hardcoded rowHeight\n const scrollPos = (rowIndex - 30) * 20;\n scrollbarContainerRef.current.scrollTop = scrollPos;\n }\n },\n scrollToKey: (rowKey: string) => {\n console.log(`scrollToKey ${rowKey}`);\n },\n }),\n [],\n );\n\n useImperativeHandle(scrollingApiRef, () => {\n if (scrollbarContainerRef.current) {\n return scrollHandles;\n } else {\n return noScrolling;\n }\n }, [scrollHandles]);\n\n useEffect(() => {\n if (rowHeight !== rowHeightRef.current) {\n rowHeightRef.current = rowHeight;\n if (contentContainerPosRef.current.scrollTop > 0) {\n if (contentContainerRef.current) {\n contentContainerRef.current.scrollTop = 0;\n }\n }\n } else if (usesMeasuredHeaderHeight) {\n const { current: from } = firstRowRef;\n const rowRange = { from, to: from + viewportRowCount };\n setRange(rowRange);\n }\n }, [rowHeight, setRange, usesMeasuredHeaderHeight, viewportRowCount]);\n\n return {\n columnsWithinViewport: columnsWithinViewportRef.current,\n /** Ref to be assigned to ScrollbarContainer */\n scrollbarContainerRef: scrollbarContainerCallbackRef,\n /** Ref to be assigned to ContentContainer */\n contentContainerRef: contentContainerCallbackRef,\n /** Scroll the table */\n requestScroll,\n /** number of leading columns not rendered because of virtualization */\n virtualColSpan: preSpanRef.current,\n };\n};\n"],"names":[],"mappings":";;;;AAsEA,MAAM,2BAA8B,GAAA,GAAA;AAGpC,MAAM,wBAA2B,GAAA,GAAA;AAOjC,MAAM,YAAA,GAAe,CAAC,SAA2B,KAAA;AAC/C,EAAA,MAAM,EAAE,YAAA,EAAc,WAAa,EAAA,YAAA,EAAc,aAAgB,GAAA,SAAA;AACjE,EAAA,OAAO,CAAC,WAAA,GAAc,WAAa,EAAA,YAAA,GAAe,YAAY,CAAA;AAChE,CAAA;AAEA,MAAM,kBAAA,GAAqB,CACzB,mBAAA,EACA,SACG,KAAA;AACH,EAAA,IAAI,wBAAwB,KAAW,CAAA,EAAA;AACrC,IAAO,OAAA,KAAA,CAAA;AAAA,GACF,MAAA;AACL,IAAM,MAAA,EAAE,SAAW,EAAA,OAAA,EAAY,GAAA,mBAAA;AAC/B,IAAO,OAAA,SAAA,GAAY,UAAU,KAAQ,GAAA,KAAA;AAAA;AAEzC,CAAA;AAEA,MAAM,YAAA,GAAe,CAAC,SAAA,EAAwB,gBAAiC,KAAA;AAC7E,EAAM,MAAA;AAAA,IACJ,YAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACE,GAAA,SAAA;AAEJ,EAAA,MAAM,gBAAgB,WAAc,GAAA,WAAA;AACpC,EAAM,MAAA,aAAA,GAAgB,cAAc,WAAc,GAAA,WAAA,CAAA;AAClD,EAAA,MAAM,eAAe,YAAe,GAAA,YAAA;AACpC,EAAI,IAAA,YAAA,GAAe,aAAa,YAAe,GAAA,YAAA,CAAA;AAE/C,EAAM,MAAA,eAAA,GAAkB,kBAAmB,CAAA,gBAAA,EAAkB,SAAS,CAAA;AAEtE,EAAI,IAAA,eAAA,KAAoB,KAAS,IAAA,YAAA,GAAe,IAAM,EAAA;AACpD,IAAe,YAAA,GAAA,CAAA;AAAA,GACN,MAAA,IAAA,eAAA,KAAoB,KAAS,IAAA,YAAA,GAAe,IAAM,EAAA;AAC3D,IAAe,YAAA,GAAA,CAAA;AAAA;AAGjB,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;AAEO,MAAM,WAA4B,GAAA;AAAA,EACvC,eAAe,MAAM,KAAA,CAAA;AAAA,EACrB,aAAa,MAAM,KAAA;AACrB;AAQA,MAAM,iBAAiB,CAAkB;AAAA,EACvC,QAAA;AAAA,EACA;AACF,CAA+B,KAAA;AAC7B,EAAM,MAAA,GAAA,GAAM,OAAiB,IAAI,CAAA;AACjC,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,CAAC,EAAiB,KAAA;AAChB,MAAA,IAAI,EAAI,EAAA;AACN,QAAA,GAAA,CAAI,OAAU,GAAA,EAAA;AACd,QAAA,QAAA,GAAW,EAAE,CAAA;AAAA,OACf,MAAA,IAAW,IAAI,OAAS,EAAA;AACtB,QAAM,MAAA,EAAE,OAAS,EAAA,WAAA,EAAgB,GAAA,GAAA;AACjC,QAAA,GAAA,CAAI,OAAU,GAAA,EAAA;AACd,QAAA,QAAA,GAAW,WAAW,CAAA;AAAA;AACxB,KACF;AAAA,IACA,CAAC,UAAU,QAAQ;AAAA,GACrB;AACA,EAAO,OAAA,WAAA;AACT,CAAA;AA2BO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,iBAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,sBAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAA4B,KAAA;AAC1B,EAAM,MAAA,WAAA,GAAc,OAAe,CAAC,CAAA;AACpC,EAAM,MAAA,YAAA,GAAe,OAAO,SAAS,CAAA;AACrC,EAAM,MAAA,2BAAA,GAA8B,OAAO,KAAK,CAAA;AAChD,EAAA,MAAM,yBAAyB,MAAkB,CAAA;AAAA,IAC/C,SAAW,EAAA,CAAA;AAAA,IACX,UAAY,EAAA;AAAA,GACb,CAAA;AACD,EAAM,MAAA,6BAAA,GAAgC,OAAO,KAAK,CAAA;AAClD,EAAA,MAAM,2BAA2B,MAAkB,CAAA;AAAA,IACjD,SAAW,EAAA,CAAA;AAAA,IACX,UAAY,EAAA;AAAA,GACb,CAAA;AACD,EAAM,MAAA,qBAAA,GAAwB,OAA8B,IAAI,CAAA;AAChE,EAAM,MAAA,mBAAA,GAAsB,OAA8B,IAAI,CAAA;AAC9D,EAAM,MAAA,8BAAA,GAAiC,OAAO,CAAC,CAAA;AAE/C,EAAM,MAAA;AAAA,IACJ,eAAA;AAAA,IACA,eAAA;AAAA,IACA,QAAU,EAAA,gBAAA;AAAA,IACV,iBAAA;AAAA,IACA,wBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACE,GAAA,oBAAA;AAEJ,EAAM,MAAA,wBAAA,GAA2B,MAAkC,CAAA,EAAE,CAAA;AACrE,EAAA,MAAM,GAAG,YAAY,CAAI,GAAA,QAAA,CAAS,EAAE,CAAA;AAEpC,EAAM,MAAA,UAAA,GAAa,OAAO,CAAC,CAAA;AAE3B,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAM,MAAA,CAAC,cAAgB,EAAA,MAAM,CAAI,GAAA,oBAAA;AAAA,MAC/B,OAAA;AAAA,MACA,uBAAuB,OAAQ,CAAA,UAAA;AAAA,MAC/B,sBAAA,CAAuB,OAAQ,CAAA,UAAA,GAC7B,aACA,GAAA;AAAA,KACJ;AACA,IAAA,UAAA,CAAW,OAAU,GAAA,MAAA;AACrB,IAAA,wBAAA,CAAyB,OAAU,GAAA,cAAA;AAAA,GAClC,EAAA,CAAC,aAAe,EAAA,OAAO,CAAC,CAAA;AAE3B,EAAA,MAAM,sBAAyB,GAAA,WAAA;AAAA,IAC7B,CAAC,UAAuB,KAAA;AACtB,MAAA,sBAAA,CAAuB,QAAQ,UAAa,GAAA,UAAA;AAC5C,MAAA,kBAAA,GAAqB,UAAU,CAAA;AAE/B,MAAA,IACE,KAAK,GAAI,CAAA,UAAA,GAAa,8BAA+B,CAAA,OAAO,IAC5D,2BACA,EAAA;AACA,QAAA,8BAAA,CAA+B,OAAU,GAAA,UAAA;AAEzC,QAAM,MAAA,CAAC,cAAgB,EAAA,GAAG,CAAI,GAAA,oBAAA;AAAA,UAC5B,OAAA;AAAA,UACA,UAAA;AAAA,UACA,aAAa,aAAgB,GAAA;AAAA,SAC/B;AAEA,QAAA,IAAI,YAAa,CAAA,wBAAA,CAAyB,OAAS,EAAA,cAAc,CAAG,EAAA;AAClE,UAAA,UAAA,CAAW,OAAU,GAAA,GAAA;AACrB,UAAA,wBAAA,CAAyB,OAAU,GAAA,cAAA;AACnC,UAAA,YAAA,CAAa,EAAE,CAAA;AAAA;AACjB;AACF,KACF;AAAA,IACA,CAAC,OAAS,EAAA,kBAAA,EAAoB,aAAa;AAAA,GAC7C;AACA,EAAA,MAAM,oBAAuB,GAAA,WAAA;AAAA,IAC3B,CAAC,WAAmB,YAAyB,KAAA;AAC3C,MAAA,sBAAA,CAAuB,QAAQ,SAAY,GAAA,SAAA;AAC3C,MAAM,MAAA,EAAE,OAAS,EAAA,YAAA,EAAiB,GAAA,WAAA;AAElC,MAAA,gBAAA,GAAmB,WAAW,YAAY,CAAA;AAC1C,MAAM,MAAA,QAAA,GAAW,iBAAiB,SAAS,CAAA;AAC3C,MAAA,IAAI,aAAa,YAAc,EAAA;AAC7B,QAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AACtB,QAAA,MAAM,UAAU,QAAW,GAAA,gBAAA;AAC3B,QAAA,QAAA,CAAS,EAAE,IAAA,EAAM,QAAU,EAAA,EAAA,EAAI,SAAS,CAAA;AAQxC,QAAM,MAAA,EAAE,OAAS,EAAA,UAAA,EAAe,GAAA,iBAAA;AAChC,QAAA,IAAI,WAAW,OAAS,EAAA;AACtB,UAAA,MAAM,cAAc,YAAe,GAAA,gBAAA;AACnC,UAAM,MAAA,CAAC,GAAG,CAAA,GAAI,UAAW,CAAA,OAAA;AACzB,UAAM,MAAA,aAAA,GAAgB,GAAO,IAAA,YAAA,IAAgB,GAAM,GAAA,WAAA;AACnD,UAAM,MAAA,YAAA,GAAe,GAAO,IAAA,QAAA,IAAY,GAAM,GAAA,OAAA;AAE9C,UAAI,IAAA,aAAA,IAAiB,CAAC,YAAc,EAAA;AAClC,YAAA,UAAA,CAAW,aAAe,EAAA,KAAA,CAAM,EAAE,aAAA,EAAe,MAAM,CAAA;AACvD,YAAW,UAAA,CAAA,eAAA,GAAkB,GAAM,GAAA,QAAA,GAAW,OAAU,GAAA,OAAA;AAAA,WAC1D,MAAA,IAAW,YAAgB,IAAA,CAAC,aAAe,EAAA;AACzC,YAAA,UAAA,CAAW,eAAkB,GAAA,KAAA;AAC7B,YAAA,SAAA,GAAY,WAAW,OAAO,CAAA;AAAA;AAChC;AACF;AAEF,MAAA,sBAAA,GAAyB,CAAC,CAAA;AAAA,KAC5B;AAAA,IACA;AAAA,MACE,iBAAA;AAAA,MACA,SAAA;AAAA,MACA,gBAAA;AAAA,MACA,gBAAA;AAAA,MACA,sBAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAM,MAAA,8BAAA,GAAiC,YAAY,MAAM;AACvD,IAAM,MAAA,EAAE,OAAS,EAAA,gBAAA,EAAqB,GAAA,mBAAA;AACtC,IAAM,MAAA,EAAE,OAAS,EAAA,kBAAA,EAAuB,GAAA,qBAAA;AACxC,IAAM,MAAA,EAAE,OAAS,EAAA,wBAAA,EAA6B,GAAA,2BAAA;AAC9C,IAAM,MAAA,EAAE,OAAS,EAAA,SAAA,EAAc,GAAA,wBAAA;AAE/B,IAAA,IAAI,wBAA0B,EAAA;AAC5B,MAAA,2BAAA,CAA4B,OAAU,GAAA,KAAA;AAAA,KACxC,MAAA,IAAW,oBAAoB,kBAAoB,EAAA;AACjD,MAAA,6BAAA,CAA8B,OAAU,GAAA,IAAA;AACxC,MAAM,MAAA,CAAC,YAAY,aAAe,IAAE,WAAW,YAAY,CAAA,GACzD,YAAa,CAAA,kBAAA,EAAoB,SAAS,CAAA;AAE5C,MAAA,SAAA,CAAU,UAAa,GAAA,UAAA;AACvB,MAAA,SAAA,CAAU,SAAY,GAAA,SAAA;AAEtB,MAAA,MAAM,CAAC,aAAA,EAAe,YAAY,CAAA,GAAI,aAAa,kBAAkB,CAAA;AACrE,MAAA,MAAM,iBAAoB,GAAA,IAAA,CAAK,KAAM,CAAA,aAAA,GAAgB,aAAa,CAAA;AAClE,MAAA,MAAM,mBAAmB,YAAe,GAAA,YAAA;AAExC,MAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,QACxB,IAAM,EAAA,iBAAA;AAAA,QACN,GAAK,EAAA,gBAAA;AAAA,QACL,QAAU,EAAA;AAAA,OACX,CAAA;AAAA;AAEH,IAAA,sBAAA,GAAyB,CAAC,CAAA;AAAA,GAC5B,EAAG,CAAC,sBAAsB,CAAC,CAAA;AAE3B,EAAM,MAAA,4BAAA,GAA+B,YAAY,MAAM;AACrD,IAAM,MAAA,EAAE,OAAS,EAAA,0BAAA,EACf,GAAA,6BAAA;AACF,IAAM,MAAA,EAAE,OAAS,EAAA,gBAAA,EAAqB,GAAA,mBAAA;AACtC,IAAM,MAAA,EAAE,OAAS,EAAA,kBAAA,EAAuB,GAAA,qBAAA;AACxC,IAAM,MAAA,EAAE,OAAS,EAAA,SAAA,EAAc,GAAA,sBAAA;AAC/B,IAAA,IAAI,oBAAoB,kBAAoB,EAAA;AAC1C,MAAM,MAAA;AAAA,QACJ,UAAA;AAAA,QACA,aAAA;AAAA,QACA,aAAA;AAAA,QACA,SAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACF,GAAI,aAAa,gBAAgB,CAAA;AAEjC,MAAA,2BAAA,CAA4B,OAAU,GAAA,IAAA;AAEtC,MAAA,IAAI,0BAA4B,EAAA;AAC9B,QAAA,6BAAA,CAA8B,OAAU,GAAA,KAAA;AAAA,OACnC,MAAA;AACL,QAAA,kBAAA,CAAmB,aAAa,IAAK,CAAA,KAAA;AAAA,UACnC,aAAgB,GAAA;AAAA,SAClB;AACA,QAAA,kBAAA,CAAmB,YAAY,YAAe,GAAA,YAAA;AAAA;AAGhD,MAAI,IAAA,SAAA,CAAU,cAAc,SAAW,EAAA;AACrC,QAAA,oBAAA,CAAqB,WAAW,YAAY,CAAA;AAAA;AAE9C,MAAI,IAAA,SAAA,CAAU,eAAe,UAAY,EAAA;AACvC,QAAA,sBAAA,CAAuB,UAAU,CAAA;AAAA;AACnC;AACF,GACC,EAAA,CAAC,oBAAsB,EAAA,sBAAsB,CAAC,CAAA;AAEjD,EAAA,MAAM,8BAAiC,GAAA,WAAA;AAAA,IACrC,CAAC,EAAuB,KAAA;AACtB,MAAA,qBAAA,CAAsB,OAAU,GAAA,EAAA;AAChC,MAAG,EAAA,CAAA,gBAAA,CAAiB,UAAU,8BAAgC,EAAA;AAAA,QAC5D,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,KACH;AAAA,IACA,CAAC,8BAA8B;AAAA,GACjC;AAEA,EAAA,MAAM,8BAAiC,GAAA,WAAA;AAAA,IACrC,CAAC,EAAuB,KAAA;AACtB,MAAA,qBAAA,CAAsB,OAAU,GAAA,IAAA;AAChC,MAAG,EAAA,CAAA,mBAAA,CAAoB,UAAU,8BAA8B,CAAA;AAAA,KACjE;AAAA,IACA,CAAC,8BAA8B;AAAA,GACjC;AAEA,EAAA,MAAM,4BAA+B,GAAA,WAAA;AAAA,IACnC,CAAC,EAAuB,KAAA;AACtB,MAAA,mBAAA,CAAoB,OAAU,GAAA,EAAA;AAC9B,MAAG,EAAA,CAAA,gBAAA,CAAiB,UAAU,4BAA8B,EAAA;AAAA,QAC1D,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,KACH;AAAA,IACA,CAAC,4BAA4B;AAAA,GAC/B;AAEA,EAAA,MAAM,4BAA+B,GAAA,WAAA;AAAA,IACnC,CAAC,EAAuB,KAAA;AACtB,MAAA,mBAAA,CAAoB,OAAU,GAAA,IAAA;AAC9B,MAAG,EAAA,CAAA,mBAAA,CAAoB,UAAU,4BAA4B,CAAA;AAAA,KAC/D;AAAA,IACA,CAAC,4BAA4B;AAAA,GAC/B;AAEA,EAAA,MAAM,8BAA8B,cAAe,CAAA;AAAA,IACjD,QAAU,EAAA,4BAAA;AAAA,IACV,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAA,MAAM,gCAAgC,cAAe,CAAA;AAAA,IACnD,QAAU,EAAA,8BAAA;AAAA,IACV,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAA,MAAM,aAAsC,GAAA,WAAA;AAAA,IAC1C,CAAC,aAAkB,KAAA;AACjB,MAAM,MAAA,EAAE,OAAS,EAAA,gBAAA,EAAqB,GAAA,mBAAA;AACtC,MAAA,IAAI,gBAAkB,EAAA;AACpB,QAAA,MAAM,CAAC,aAAA,EAAe,YAAY,CAAA,GAAI,aAAa,gBAAgB,CAAA;AACnE,QAAM,MAAA,EAAE,UAAY,EAAA,SAAA,EAAc,GAAA,gBAAA;AAClC,QAAA,2BAAA,CAA4B,OAAU,GAAA,KAAA;AACtC,QAAA,QAAQ,cAAc,IAAM;AAAA,UAC1B,KAAK,YAAA;AACH,YAAA;AACE,cAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,gBACxB,KAAK,aAAc,CAAA,SAAA;AAAA,gBACnB,IAAM,EAAA,UAAA;AAAA,gBACN,QAAU,EAAA;AAAA,eACX,CAAA;AAAA;AAEH,YAAA;AAAA,UACF,KAAK,eAAA;AACH,YAAA;AACE,cAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,gBACxB,GACE,EAAA,aAAA,CAAc,SACb,IAAA,kBAAA,GAAqB,CAAI,GAAA,SAAA,CAAA;AAAA,gBAC5B,IAAM,EAAA,UAAA;AAAA,gBACN,QAAU,EAAA;AAAA,eACX,CAAA;AAAA;AAEH,YAAA;AAAA,UACF,KAAK,YAAA;AACH,YAAA;AACE,cAAA,MAAM,SAAY,GAAA,wBAAA;AAAA,gBAChB,gBAAA;AAAA,gBACA,aAAc,CAAA;AAAA,eAChB;AAEA,cAAA,IAAI,cAAc,IAAM,EAAA;AACtB,gBAAM,MAAA,CAAC,SAAW,EAAA,QAAQ,CAAI,GAAA,0BAAA;AAAA,kBAC5B,SAAA;AAAA,kBACA;AAAA,iBACF;AACA,gBAAA,IAAI,aAAa,QAAU,EAAA;AACzB,kBAAA,IAAI,eAAiB,EAAA;AACnB,oBAAM,MAAA,MAAA,GAAS,SAAc,KAAA,MAAA,GAAS,CAAI,GAAA,CAAA,CAAA;AAC1C,oBAAA,sBAAA,GAAyB,MAAM,CAAA;AAC/B,oBAAM,MAAA,QAAA,GAAW,YAAY,OAAU,GAAA,MAAA;AACvC,oBAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AACtB,oBAAS,QAAA,CAAA;AAAA,sBACP,IAAM,EAAA,QAAA;AAAA,sBACN,IAAI,QAAW,GAAA;AAAA,qBAChB,CAAA;AAAA,mBACI,MAAA;AACL,oBAAA,IAAI,aAAgB,GAAA,UAAA;AACpB,oBAAA,IAAI,YAAe,GAAA,SAAA;AACnB,oBAAI,IAAA,SAAA,KAAc,IAAQ,IAAA,SAAA,KAAc,MAAQ,EAAA;AAC9C,sBAAA,YAAA,GAAe,IAAK,CAAA,GAAA;AAAA,wBAClB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,SAAA,GAAY,QAAQ,CAAA;AAAA,wBAChC;AAAA,uBACF;AAAA,qBACK,MAAA;AACL,sBAAA,aAAA,GAAgB,IAAK,CAAA,GAAA;AAAA,wBACnB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,UAAA,GAAa,QAAQ,CAAA;AAAA,wBACjC;AAAA,uBACF;AAAA;AAEF,oBAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,sBACxB,GAAK,EAAA,YAAA;AAAA,sBACL,IAAM,EAAA,aAAA;AAAA;AAAA,sBAEN,QAAU,EAAA;AAAA,qBACX,CAAA;AAAA;AACH;AACF;AACF;AAEF,YAAA;AAAA,UACF,KAAK,aAAA;AACH,YAAA;AACE,cAAM,MAAA,EAAE,WAAc,GAAA,aAAA;AACtB,cAAA,IAAI,eAAiB,EAAA;AACnB,gBAAA,MAAM,MACJ,GAAA,SAAA,KAAc,MAAS,GAAA,gBAAA,GAAmB,CAAC,gBAAA;AAC7C,gBAAA,sBAAA,GAAyB,MAAM,CAAA;AAC/B,gBAAM,MAAA,QAAA,GAAW,YAAY,OAAU,GAAA,MAAA;AACvC,gBAAA,WAAA,CAAY,OAAU,GAAA,QAAA;AACtB,gBAAA,QAAA,CAAS,EAAE,IAAM,EAAA,QAAA,EAAU,EAAI,EAAA,QAAA,GAAW,kBAAkB,CAAA;AAAA,eACvD,MAAA;AACL,gBAAA,MAAM,QACJ,GAAA,SAAA,KAAc,MAAS,GAAA,eAAA,GAAkB,CAAC,eAAA;AAC5C,gBAAA,MAAM,eAAe,IAAK,CAAA,GAAA;AAAA,kBACxB,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,SAAA,GAAY,QAAQ,CAAA;AAAA,kBAChC;AAAA,iBACF;AACA,gBAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,kBACxB,GAAK,EAAA,YAAA;AAAA,kBACL,IAAM,EAAA,UAAA;AAAA,kBACN,QAAU,EAAA;AAAA,iBACX,CAAA;AAAA;AACH;AAEF,YAAA;AAAA,UACF,KAAK,YAAA;AACH,YAAA;AACE,cAAM,MAAA,EAAE,WAAc,GAAA,aAAA;AACtB,cAAM,MAAA,QAAA,GAAW,SAAc,KAAA,KAAA,GAAQ,YAAe,GAAA,CAAA;AACtD,cAAA,gBAAA,CAAiB,QAAS,CAAA;AAAA,gBACxB,GAAK,EAAA,QAAA;AAAA,gBACL,MAAM,gBAAiB,CAAA,UAAA;AAAA,gBACvB,QAAU,EAAA;AAAA,eACX,CAAA;AAAA;AAEH,YAAA;AAAA,UACF;AACE,YAAA,OAAA,CAAQ,IAAK,CAAA,CAAA,0BAAA,EAA6B,aAAc,CAAA,MAAM,CAAC,CAAE,CAAA,CAAA;AAAA;AACrE;AACF,KACF;AAAA,IACA;AAAA,MACE,eAAA;AAAA,MACA,eAAA;AAAA,MACA,sBAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAA;AAAA,MACA,iBAAA;AAAA,MACA,kBAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,MAAM,aAA8B,GAAA,OAAA;AAAA;AAAA,IAElC,OAAO;AAAA,MACL,aAAA,EAAe,CAAC,QAAqB,KAAA;AACnC,QAAA,IAAI,sBAAsB,OAAS,EAAA;AAEjC,UAAM,MAAA,SAAA,GAAA,CAAa,WAAW,EAAM,IAAA,EAAA;AACpC,UAAA,qBAAA,CAAsB,QAAQ,SAAY,GAAA,SAAA;AAAA;AAC5C,OACF;AAAA,MACA,WAAA,EAAa,CAAC,MAAmB,KAAA;AAC/B,QAAQ,OAAA,CAAA,GAAA,CAAI,CAAe,YAAA,EAAA,MAAM,CAAE,CAAA,CAAA;AAAA;AACrC,KACF,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,mBAAA,CAAoB,iBAAiB,MAAM;AACzC,IAAA,IAAI,sBAAsB,OAAS,EAAA;AACjC,MAAO,OAAA,aAAA;AAAA,KACF,MAAA;AACL,MAAO,OAAA,WAAA;AAAA;AACT,GACF,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,SAAA,KAAc,aAAa,OAAS,EAAA;AACtC,MAAA,YAAA,CAAa,OAAU,GAAA,SAAA;AACvB,MAAI,IAAA,sBAAA,CAAuB,OAAQ,CAAA,SAAA,GAAY,CAAG,EAAA;AAChD,QAAA,IAAI,oBAAoB,OAAS,EAAA;AAC/B,UAAA,mBAAA,CAAoB,QAAQ,SAAY,GAAA,CAAA;AAAA;AAC1C;AACF,eACS,wBAA0B,EAAA;AACnC,MAAM,MAAA,EAAE,OAAS,EAAA,IAAA,EAAS,GAAA,WAAA;AAC1B,MAAA,MAAM,QAAW,GAAA,EAAE,IAAM,EAAA,EAAA,EAAI,OAAO,gBAAiB,EAAA;AACrD,MAAA,QAAA,CAAS,QAAQ,CAAA;AAAA;AACnB,KACC,CAAC,SAAA,EAAW,QAAU,EAAA,wBAAA,EAA0B,gBAAgB,CAAC,CAAA;AAEpE,EAAO,OAAA;AAAA,IACL,uBAAuB,wBAAyB,CAAA,OAAA;AAAA;AAAA,IAEhD,qBAAuB,EAAA,6BAAA;AAAA;AAAA,IAEvB,mBAAqB,EAAA,2BAAA;AAAA;AAAA,IAErB,aAAA;AAAA;AAAA,IAEA,gBAAgB,UAAW,CAAA;AAAA,GAC7B;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"useTableScroll.js","sources":["../../../packages/vuu-table/src/useTableScroll.ts"],"sourcesContent":["import {\n getColumnsInViewport,\n itemsChanged,\n RowAtPositionFunc,\n} from \"@vuu-ui/vuu-utils\";\nimport type { VuuRange } from \"@vuu-ui/vuu-protocol-types\";\nimport {\n ForwardedRef,\n RefObject,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ViewportMeasurements } from \"./useTableViewport\";\nimport {\n getRowElementByAriaIndex,\n howFarIsRowOutsideViewport,\n} from \"./table-dom-utils\";\nimport type { RuntimeColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport { FocusCell } from \"./useCellFocus\";\nimport { ICellFocusState } from \"./CellFocusState\";\n\nexport type ScrollDirectionVertical = \"up\" | \"down\";\nexport type ScrollDirectionHorizontal = \"left\" | \"right\";\nexport type ScrollDirection =\n | ScrollDirectionVertical\n | ScrollDirectionHorizontal;\n\n/**\n * scroll into view the row at given pixel offset.\n */\nexport interface ScrollRequestPosition {\n scrollPos: number;\n type: \"scroll-top\" | \"scroll-bottom\";\n}\n\n/**\n * scroll into view the row at given row index posiiton.\n */\nexport interface ScrollRequestRow {\n rowIndex: number;\n type: \"scroll-row\";\n}\nexport interface ScrollRequestEnd {\n type: \"scroll-end\";\n direction: \"home\" | \"end\";\n}\n\nexport interface ScrollRequestPage {\n type: \"scroll-page\";\n direction: ScrollDirectionVertical;\n}\n\nexport type ScrollRequest =\n | ScrollRequestPage\n | ScrollRequestEnd\n | ScrollRequestRow\n | ScrollRequestPosition;\n\nexport type ScrollRequestHandler = (request: ScrollRequest) => void;\n\nexport interface ScrollingAPI {\n scrollToIndex: (itemIndex: number) => void;\n scrollToKey: (rowKey: string) => void;\n}\n\n/** How far we allow horizontal scroll movement before we recheck the rendered columns */\nconst SCROLL_MOVE_CHECK_THRESHOLD = 100;\n\n/** The buffer size in pixels that we allow for rendering columns just outside the viewport */\nconst HORIZONTAL_SCROLL_BUFFER = 200;\n\n/**\n * Return the maximum scroll positions for gioven container\n * @param container\n * @returns [maxScrollLeft, maxScrollTop]\n */\nconst getMaxScroll = (container: HTMLElement) => {\n const { clientHeight, clientWidth, scrollHeight, scrollWidth } = container;\n return [scrollWidth - clientWidth, scrollHeight - clientHeight];\n};\n\nconst getScrollDirection = (\n prevScrollPositions: ScrollPos | undefined,\n scrollPos: number,\n) => {\n if (prevScrollPositions === undefined) {\n return undefined;\n } else {\n const { scrollTop: prevTop } = prevScrollPositions;\n return scrollPos > prevTop ? \"fwd\" : \"bwd\";\n }\n};\n\nconst getPctScroll = (container: HTMLElement, currentScrollPos?: ScrollPos) => {\n const {\n clientHeight,\n clientWidth,\n scrollHeight,\n scrollLeft,\n scrollTop,\n scrollWidth,\n } = container;\n\n const maxScrollLeft = scrollWidth - clientWidth;\n const pctScrollLeft = scrollLeft / (scrollWidth - clientWidth);\n const maxScrollTop = scrollHeight - clientHeight;\n let pctScrollTop = scrollTop / (scrollHeight - clientHeight);\n\n const scrollDirection = getScrollDirection(currentScrollPos, scrollTop);\n\n if (scrollDirection === \"fwd\" && pctScrollTop > 0.99) {\n pctScrollTop = 1;\n } else if (scrollDirection === \"bwd\" && pctScrollTop < 0.02) {\n pctScrollTop = 0;\n }\n\n return [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ];\n};\n\nexport const noScrolling: ScrollingAPI = {\n scrollToIndex: () => undefined,\n scrollToKey: () => undefined,\n};\n\ninterface CallbackRefHookProps<T = HTMLElement> {\n onAttach?: (el: T) => void;\n onDetach: (el: T) => void;\n label?: string;\n}\n\nconst useCallbackRef = <T = HTMLElement>({\n onAttach,\n onDetach,\n}: CallbackRefHookProps<T>) => {\n const ref = useRef<T | null>(null);\n const callbackRef = useCallback(\n (el: T | null) => {\n if (el) {\n ref.current = el;\n onAttach?.(el);\n } else if (ref.current) {\n const { current: originalRef } = ref;\n ref.current = el;\n onDetach?.(originalRef);\n }\n },\n [onAttach, onDetach],\n );\n return callbackRef;\n};\n\ntype ScrollPos = {\n scrollLeft: number;\n scrollTop: number;\n};\n\nexport interface TableScrollHookProps {\n cellFocusStateRef: RefObject<ICellFocusState>;\n columns: RuntimeColumnDescriptor[];\n focusCell?: FocusCell;\n getRowAtPosition: RowAtPositionFunc;\n onHorizontalScroll?: (scrollLeft: number) => void;\n onVerticalScroll?: (scrollTop: number, pctScrollTop: number) => void;\n /**\n * When we have a virtualized scroll container, keyboard navigation is\n * performed `in situ`. We shift the range of rows rendered within the\n * viewport, whithout actually moving the scroll position\n */\n onVerticalScrollInSitu?: (rowIndexOffsetCount: number) => void;\n rowHeight: number;\n scrollingApiRef?: ForwardedRef<ScrollingAPI>;\n setRange: (range: VuuRange) => void;\n showPaginationControls?: boolean;\n viewportMeasurements: ViewportMeasurements;\n}\n\nexport const useTableScroll = ({\n cellFocusStateRef,\n columns,\n focusCell,\n getRowAtPosition,\n onHorizontalScroll,\n onVerticalScroll,\n onVerticalScrollInSitu,\n rowHeight,\n scrollingApiRef,\n setRange,\n viewportMeasurements,\n}: TableScrollHookProps) => {\n const firstRowRef = useRef<number>(0);\n const rowHeightRef = useRef(rowHeight);\n const contentContainerScrolledRef = useRef(false);\n const contentContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerScrolledRef = useRef(false);\n const scrollbarContainerPosRef = useRef<ScrollPos>({\n scrollTop: 0,\n scrollLeft: 0,\n });\n const scrollbarContainerRef = useRef<HTMLDivElement | null>(null);\n const contentContainerRef = useRef<HTMLDivElement | null>(null);\n const lastHorizontalScrollCheckPoint = useRef(0);\n\n const {\n appliedPageSize,\n isVirtualScroll,\n rowCount: viewportRowCount,\n totalHeaderHeight,\n usesMeasuredHeaderHeight,\n viewportBodyHeight,\n viewportWidth,\n } = viewportMeasurements;\n\n const columnsWithinViewportRef = useRef<RuntimeColumnDescriptor[]>([]);\n const [, forceRefresh] = useState({});\n\n const preSpanRef = useRef(0);\n\n useMemo(() => {\n const [visibleColumns, offset] = getColumnsInViewport(\n columns,\n contentContainerPosRef.current.scrollLeft,\n contentContainerPosRef.current.scrollLeft +\n viewportWidth +\n HORIZONTAL_SCROLL_BUFFER,\n );\n preSpanRef.current = offset;\n columnsWithinViewportRef.current = visibleColumns;\n }, [viewportWidth, columns]);\n\n const handleHorizontalScroll = useCallback(\n (scrollLeft: number) => {\n contentContainerPosRef.current.scrollLeft = scrollLeft;\n onHorizontalScroll?.(scrollLeft);\n\n if (\n Math.abs(scrollLeft - lastHorizontalScrollCheckPoint.current) >\n SCROLL_MOVE_CHECK_THRESHOLD\n ) {\n lastHorizontalScrollCheckPoint.current = scrollLeft;\n\n const [visibleColumns, pre] = getColumnsInViewport(\n columns,\n scrollLeft,\n scrollLeft + viewportWidth + HORIZONTAL_SCROLL_BUFFER,\n );\n\n if (itemsChanged(columnsWithinViewportRef.current, visibleColumns)) {\n preSpanRef.current = pre;\n columnsWithinViewportRef.current = visibleColumns;\n forceRefresh({});\n }\n }\n },\n [columns, onHorizontalScroll, viewportWidth],\n );\n const handleVerticalScroll = useCallback(\n (scrollTop: number, pctScrollTop: number) => {\n contentContainerPosRef.current.scrollTop = scrollTop;\n const { current: prevFirstRow } = firstRowRef;\n\n onVerticalScroll?.(scrollTop, pctScrollTop);\n const firstRow = getRowAtPosition(scrollTop);\n if (firstRow !== prevFirstRow) {\n firstRowRef.current = firstRow;\n const lastRow = firstRow + viewportRowCount;\n setRange({ from: firstRow, to: lastRow });\n\n // If we've scrolled the focused cell out of view, we need to remove\n // focus from it. The row element will be recycled and used as the\n // render target for a different DataRow, we do not want the focus\n // state of the cell to be preserved.\n // Conversely, if we scroll the focussed cell back into the viewport,\n // we must re-apply focus to it. We use the placeholder cell for this.\n const { current: focusState } = cellFocusStateRef;\n if (focusState.cellPos) {\n const prevLastRow = prevFirstRow + viewportRowCount;\n const [row] = focusState.cellPos;\n const wasInViewport = row >= prevFirstRow && row < prevLastRow;\n const isInViewport = row >= firstRow && row < lastRow;\n\n if (wasInViewport && !isInViewport) {\n focusState.placeholderEl?.focus({ preventScroll: true });\n focusState.outsideViewport = row < firstRow ? \"above\" : \"below\";\n } else if (isInViewport && !wasInViewport) {\n focusState.outsideViewport = false;\n focusCell?.(focusState.cellPos);\n }\n }\n }\n onVerticalScrollInSitu?.(0);\n },\n [\n cellFocusStateRef,\n focusCell,\n getRowAtPosition,\n onVerticalScroll,\n onVerticalScrollInSitu,\n setRange,\n viewportRowCount,\n ],\n );\n\n const handleScrollbarContainerScroll = useCallback(() => {\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: contentContainerScrolled } = contentContainerScrolledRef;\n const { current: scrollPos } = scrollbarContainerPosRef;\n\n if (contentContainerScrolled) {\n contentContainerScrolledRef.current = false;\n } else if (contentContainer && scrollbarContainer) {\n scrollbarContainerScrolledRef.current = true;\n const [scrollLeft, pctScrollLeft, , scrollTop, pctScrollTop] =\n getPctScroll(scrollbarContainer, scrollPos);\n\n scrollPos.scrollLeft = scrollLeft;\n scrollPos.scrollTop = scrollTop;\n\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(scrollbarContainer);\n const contentScrollLeft = Math.round(pctScrollLeft * maxScrollLeft);\n const contentScrollTop = pctScrollTop * maxScrollTop;\n\n contentContainer.scrollTo({\n left: contentScrollLeft,\n top: contentScrollTop,\n behavior: \"auto\",\n });\n }\n onVerticalScrollInSitu?.(0);\n }, [onVerticalScrollInSitu]);\n\n const handleContentContainerScroll = useCallback(() => {\n const { current: scrollbarContainerScrolled } =\n scrollbarContainerScrolledRef;\n const { current: contentContainer } = contentContainerRef;\n const { current: scrollbarContainer } = scrollbarContainerRef;\n const { current: scrollPos } = contentContainerPosRef;\n if (contentContainer && scrollbarContainer) {\n const [\n scrollLeft,\n pctScrollLeft,\n maxScrollLeft,\n scrollTop,\n pctScrollTop,\n maxScrollTop,\n ] = getPctScroll(contentContainer);\n\n contentContainerScrolledRef.current = true;\n\n if (scrollbarContainerScrolled) {\n scrollbarContainerScrolledRef.current = false;\n } else {\n scrollbarContainer.scrollLeft = Math.round(\n pctScrollLeft * maxScrollLeft,\n );\n scrollbarContainer.scrollTop = pctScrollTop * maxScrollTop;\n }\n\n if (scrollPos.scrollTop !== scrollTop) {\n handleVerticalScroll(scrollTop, pctScrollTop);\n }\n if (scrollPos.scrollLeft !== scrollLeft) {\n handleHorizontalScroll(scrollLeft);\n }\n }\n }, [handleVerticalScroll, handleHorizontalScroll]);\n\n const handleAttachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = el;\n el.addEventListener(\"scroll\", handleScrollbarContainerScroll, {\n passive: true,\n });\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleDetachScrollbarContainer = useCallback(\n (el: HTMLDivElement) => {\n scrollbarContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleScrollbarContainerScroll);\n },\n [handleScrollbarContainerScroll],\n );\n\n const handleAttachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = el;\n el.addEventListener(\"scroll\", handleContentContainerScroll, {\n passive: true,\n });\n },\n [handleContentContainerScroll],\n );\n\n const handleDetachContentContainer = useCallback(\n (el: HTMLDivElement) => {\n contentContainerRef.current = null;\n el.removeEventListener(\"scroll\", handleContentContainerScroll);\n },\n [handleContentContainerScroll],\n );\n\n const contentContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachContentContainer,\n onDetach: handleDetachContentContainer,\n });\n\n const scrollbarContainerCallbackRef = useCallbackRef({\n onAttach: handleAttachScrollbarContainer,\n onDetach: handleDetachScrollbarContainer,\n });\n\n const requestScroll: ScrollRequestHandler = useCallback(\n (scrollRequest) => {\n const { current: contentContainer } = contentContainerRef;\n if (contentContainer) {\n const [maxScrollLeft, maxScrollTop] = getMaxScroll(contentContainer);\n const { scrollLeft, scrollTop } = contentContainer;\n contentContainerScrolledRef.current = false;\n switch (scrollRequest.type) {\n case \"scroll-top\":\n {\n contentContainer.scrollTo({\n top: scrollRequest.scrollPos,\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-bottom\":\n {\n contentContainer.scrollTo({\n top:\n scrollRequest.scrollPos -\n (viewportBodyHeight - 2 * rowHeight),\n left: scrollLeft,\n behavior: \"instant\",\n });\n }\n break;\n case \"scroll-row\":\n {\n const activeRow = getRowElementByAriaIndex(\n contentContainer,\n scrollRequest.rowIndex,\n );\n\n if (activeRow !== null) {\n const [direction, distance] = howFarIsRowOutsideViewport(\n activeRow,\n totalHeaderHeight,\n );\n if (direction && distance) {\n if (isVirtualScroll) {\n const offset = direction === \"down\" ? 1 : -1;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({\n from: firstRow,\n to: firstRow + viewportRowCount,\n });\n } else {\n let newScrollLeft = scrollLeft;\n let newScrollTop = scrollTop;\n if (direction === \"up\" || direction === \"down\") {\n newScrollTop = Math.min(\n Math.max(0, scrollTop + distance),\n maxScrollTop,\n );\n } else {\n newScrollLeft = Math.min(\n Math.max(0, scrollLeft + distance),\n maxScrollLeft,\n );\n }\n contentContainer.scrollTo({\n top: newScrollTop,\n left: newScrollLeft,\n // avoid behaviour: 'smooth', doesn't work correctly\n behavior: \"instant\",\n });\n }\n }\n }\n }\n break;\n case \"scroll-page\":\n {\n const { direction } = scrollRequest;\n if (isVirtualScroll) {\n const offset =\n direction === \"down\" ? viewportRowCount : -viewportRowCount;\n onVerticalScrollInSitu?.(offset);\n const firstRow = firstRowRef.current + offset;\n firstRowRef.current = firstRow;\n setRange({ from: firstRow, to: firstRow + viewportRowCount });\n } else {\n const scrollBy =\n direction === \"down\" ? appliedPageSize : -appliedPageSize;\n const newScrollTop = Math.min(\n Math.max(0, scrollTop + scrollBy),\n maxScrollTop,\n );\n contentContainer.scrollTo({\n top: newScrollTop,\n left: scrollLeft,\n behavior: \"auto\",\n });\n }\n }\n break;\n case \"scroll-end\":\n {\n const { direction } = scrollRequest;\n const scrollTo = direction === \"end\" ? maxScrollTop : 0;\n contentContainer.scrollTo({\n top: scrollTo,\n left: contentContainer.scrollLeft,\n behavior: \"auto\",\n });\n }\n break;\n default:\n console.warn(`unexpected scroll request ${scrollRequest[\"type\"]}`);\n }\n }\n },\n [\n appliedPageSize,\n isVirtualScroll,\n onVerticalScrollInSitu,\n rowHeight,\n setRange,\n totalHeaderHeight,\n viewportBodyHeight,\n viewportRowCount,\n ],\n );\n\n const scrollHandles: ScrollingAPI = useMemo(\n // TODO not complete yet\n () => ({\n scrollToIndex: (rowIndex: number) => {\n if (scrollbarContainerRef.current) {\n // TODO hardcoded rowHeight\n const scrollPos = (rowIndex - 30) * 20;\n scrollbarContainerRef.current.scrollTop = scrollPos;\n }\n },\n scrollToKey: (rowKey: string) => {\n console.log(`scrollToKey ${rowKey}`);\n },\n }),\n [],\n );\n\n useImperativeHandle(scrollingApiRef, () => {\n if (scrollbarContainerRef.current) {\n return scrollHandles;\n } else {\n return noScrolling;\n }\n }, [scrollHandles]);\n\n useEffect(() => {\n if (rowHeight !== rowHeightRef.current) {\n rowHeightRef.current = rowHeight;\n if (contentContainerPosRef.current.scrollTop > 0) {\n if (contentContainerRef.current) {\n contentContainerRef.current.scrollTop = 0;\n }\n }\n } else if (usesMeasuredHeaderHeight) {\n const { current: from } = firstRowRef;\n const rowRange = { from, to: from + viewportRowCount };\n setRange(rowRange);\n }\n }, [rowHeight, setRange, usesMeasuredHeaderHeight, viewportRowCount]);\n\n return {\n columnsWithinViewport: columnsWithinViewportRef.current,\n /** Ref to be assigned to ScrollbarContainer */\n scrollbarContainerRef: scrollbarContainerCallbackRef,\n /** Ref to be assigned to ContentContainer */\n contentContainerRef: contentContainerCallbackRef,\n /** Scroll the table */\n requestScroll,\n /** number of leading columns not rendered because of virtualization */\n virtualColSpan: preSpanRef.current,\n };\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.13.95-alpha.
|
|
2
|
+
"version": "0.13.95-alpha.2",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"devDependencies": {
|
|
6
|
-
"@vuu-ui/vuu-data-types": "0.13.95-alpha.
|
|
7
|
-
"@vuu-ui/vuu-table-types": "0.13.95-alpha.
|
|
8
|
-
"@vuu-ui/vuu-protocol-types": "0.13.95-alpha.
|
|
6
|
+
"@vuu-ui/vuu-data-types": "0.13.95-alpha.2",
|
|
7
|
+
"@vuu-ui/vuu-table-types": "0.13.95-alpha.2",
|
|
8
|
+
"@vuu-ui/vuu-protocol-types": "0.13.95-alpha.2"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@salt-ds/core": "1.54.1",
|
|
12
12
|
"@salt-ds/styles": "0.2.1",
|
|
13
13
|
"@salt-ds/window": "0.1.1",
|
|
14
|
-
"@vuu-ui/vuu-context-menu": "0.13.95-alpha.
|
|
15
|
-
"@vuu-ui/vuu-data-react": "0.13.95-alpha.
|
|
16
|
-
"@vuu-ui/vuu-popups": "0.13.95-alpha.
|
|
17
|
-
"@vuu-ui/vuu-table-extras": "0.13.95-alpha.
|
|
18
|
-
"@vuu-ui/vuu-ui-controls": "0.13.95-alpha.
|
|
19
|
-
"@vuu-ui/vuu-utils": "0.13.95-alpha.
|
|
14
|
+
"@vuu-ui/vuu-context-menu": "0.13.95-alpha.2",
|
|
15
|
+
"@vuu-ui/vuu-data-react": "0.13.95-alpha.2",
|
|
16
|
+
"@vuu-ui/vuu-popups": "0.13.95-alpha.2",
|
|
17
|
+
"@vuu-ui/vuu-table-extras": "0.13.95-alpha.2",
|
|
18
|
+
"@vuu-ui/vuu-ui-controls": "0.13.95-alpha.2",
|
|
19
|
+
"@vuu-ui/vuu-utils": "0.13.95-alpha.2"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"clsx": "^2.0.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RowAtPositionFunc } from "@vuu-ui/vuu-utils";
|
|
2
2
|
import type { VuuRange } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
-
import { ForwardedRef,
|
|
3
|
+
import { ForwardedRef, RefObject } from "react";
|
|
4
4
|
import type { ViewportMeasurements } from "./useTableViewport";
|
|
5
5
|
import type { RuntimeColumnDescriptor } from "@vuu-ui/vuu-table-types";
|
|
6
6
|
import { FocusCell } from "./useCellFocus";
|
|
@@ -38,7 +38,7 @@ export interface ScrollingAPI {
|
|
|
38
38
|
}
|
|
39
39
|
export declare const noScrolling: ScrollingAPI;
|
|
40
40
|
export interface TableScrollHookProps {
|
|
41
|
-
cellFocusStateRef:
|
|
41
|
+
cellFocusStateRef: RefObject<ICellFocusState>;
|
|
42
42
|
columns: RuntimeColumnDescriptor[];
|
|
43
43
|
focusCell?: FocusCell;
|
|
44
44
|
getRowAtPosition: RowAtPositionFunc;
|