@trail-ui/react
Version:
246 lines (243 loc) • 10.1 kB
JavaScript
import {
useTableContext
} from "./chunk-A4IWBDSQ.mjs";
// src/editable-table/focus-handler/focus-handler-provider.tsx
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { jsx } from "react/jsx-runtime";
var FocusDataContext = createContext({
columnIndex: 0,
rowId: null,
cellType: "headerCell" /* headerCell */,
groupId: null,
rowIndex: 0
});
var FocusDispatchContext = createContext(() => {
});
function FocusHandlerContextProvider(props) {
const [focusedCell, setFocusedCell] = useState({
columnIndex: 0,
rowId: null,
cellType: "headerCell" /* headerCell */,
groupId: null,
rowIndex: 0
});
const { tableRef, allowBulkGroupSelection, hasFooter } = useTableContext();
function updateData(data) {
setFocusedCell(data);
}
useEffect(() => {
const handleKeyDown = (e) => {
var _a, _b, _c, _d, _e, _f;
if (!tableRef.current || !tableRef.current.contains(e.target)) {
return;
}
const activeElement = document.activeElement;
const isInsideCustomSelect = (el) => {
return el && (el.closest('[role="listbox"]') || el.closest('[role="combobox"]'));
};
if ((activeElement == null ? void 0 : activeElement.tagName) === "SELECT" || (activeElement == null ? void 0 : activeElement.tagName) === "INPUT" || isInsideCustomSelect(activeElement)) {
return;
}
const { rowId, columnIndex, cellType, groupId, rowIndex } = focusedCell;
const rows = props.table.getRowModel().rows;
const tableHeaders = ((_a = props.table.getHeaderGroups()[0]) == null ? void 0 : _a.headers) || [];
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
e.preventDefault();
let newrowId = rowId;
let newColumnIndex = columnIndex;
let newCellType = cellType;
let newGroupId = groupId;
let newRowIndex = rowIndex;
const isGroupView = props.groupData.length > 0;
switch (e.key) {
case "ArrowUp":
if (cellType === "headerCell" /* headerCell */) {
return;
}
if (hasFooter && cellType === "footerCell" /* footerCell */) {
newCellType = "dataCell" /* dataCell */;
newGroupId = null;
newRowIndex = rows.length - 1;
newrowId = rows[rows.length - 1].id;
} else if (cellType === "groupHeaderCell" /* groupHeaderCell */) {
const index = rows.findIndex(
({ original }) => original.editableTableGroupId === groupId
);
if (index === 0) {
newCellType = "headerCell" /* headerCell */;
newrowId = null;
newGroupId = null;
newRowIndex = -1;
} else {
newCellType = "dataCell" /* dataCell */;
newrowId = rows[index - 1].id;
newGroupId = null;
newRowIndex = index - 1;
}
} else if (cellType === "dataCell" /* dataCell */) {
const index = rows.findIndex((row) => row.id === rowId);
if (isGroupView) {
if (index === 0 || rows[index].original.editableTableGroupId !== ((_c = (_b = rows[index - 1]) == null ? void 0 : _b.original) == null ? void 0 : _c.editableTableGroupId)) {
newGroupId = rows[index].original.editableTableGroupId;
newrowId = null;
newCellType = "groupHeaderCell" /* groupHeaderCell */;
newRowIndex = -1;
} else {
newrowId = rows[Math.min(rows.length - 1, index - 1)].id;
newRowIndex = Math.min(rows.length - 1, index - 1);
}
} else {
if (index === 0) {
newCellType = "headerCell" /* headerCell */;
newGroupId = null;
newrowId = null;
newRowIndex = -1;
} else {
newCellType = "dataCell" /* dataCell */;
newGroupId = null;
newrowId = rows[Math.max(0, index - 1)].id;
newRowIndex = index - 1;
}
}
}
break;
case "ArrowDown":
if (cellType === "headerCell" /* headerCell */) {
if (isGroupView) {
newCellType = "groupHeaderCell" /* groupHeaderCell */;
newGroupId = rows[0].original.editableTableGroupId;
newrowId = null;
newRowIndex = -1;
} else {
newGroupId = null;
newCellType = "dataCell" /* dataCell */;
newrowId = rows[Math.min(rows.length - 1, 0)].id;
newRowIndex = Math.min(rows.length - 1, 0);
}
} else if (cellType === "groupHeaderCell" /* groupHeaderCell */) {
newCellType = "dataCell" /* dataCell */;
const index = rows.findIndex(
({ original }) => original.editableTableGroupId === groupId
);
newrowId = rows[index].id;
newGroupId = null;
newRowIndex = index;
} else if (cellType === "dataCell" /* dataCell */) {
const index = rows.findIndex((row) => row.id === rowId);
if (hasFooter && index + 1 > rows.length - 1) {
newCellType = "footerCell" /* footerCell */;
newRowIndex = -1;
newGroupId = null;
newrowId = null;
break;
}
if (isGroupView && rows[index].original.editableTableGroupId !== ((_e = (_d = rows[index + 1]) == null ? void 0 : _d.original) == null ? void 0 : _e.editableTableGroupId)) {
newGroupId = rows[index + 1].original.editableTableGroupId;
newrowId = null;
newCellType = "groupHeaderCell" /* groupHeaderCell */;
newRowIndex = -1;
} else {
newrowId = rows[Math.min(rows.length - 1, index + 1)].id;
newRowIndex = Math.min(rows.length - 1, index + 1);
}
} else if (hasFooter && cellType === "footerCell" /* footerCell */) {
return;
}
break;
case "ArrowLeft": {
if (cellType === "groupHeaderCell" /* groupHeaderCell */) {
if (allowBulkGroupSelection && columnIndex > 0) {
newColumnIndex = 0;
}
} else {
newColumnIndex = Math.max(0, newColumnIndex - 1);
}
break;
}
case "ArrowRight": {
if (cellType === "groupHeaderCell" /* groupHeaderCell */) {
if (allowBulkGroupSelection && columnIndex === 0) {
newColumnIndex = 1;
}
} else {
newColumnIndex = Math.min(tableHeaders.length - 1, newColumnIndex + 1);
}
break;
}
}
setFocusedCell({
rowId: newrowId,
columnIndex: newColumnIndex,
cellType: newCellType,
groupId: newGroupId,
rowIndex: newRowIndex
});
}
if (e.key === "Enter" && cellType === "headerCell" /* headerCell */) {
const header = (_f = tableHeaders[columnIndex]) == null ? void 0 : _f.column;
if (header == null ? void 0 : header.getCanSort()) {
header.toggleSorting();
}
}
};
const table = tableRef.current;
table == null ? void 0 : table.addEventListener("keydown", handleKeyDown);
return () => table == null ? void 0 : table.removeEventListener("keydown", handleKeyDown);
}, [focusedCell, props.table]);
return /* @__PURE__ */ jsx(FocusDispatchContext.Provider, { value: updateData, children: /* @__PURE__ */ jsx(FocusDataContext.Provider, { value: focusedCell, children: props.children }) });
}
function useFocusHandler({
cellType,
columnIndex,
groupId,
rowId,
rowIndex
}) {
var _a;
const focusedCell = useContext(FocusDataContext);
const setFocusedCell = useContext(FocusDispatchContext);
const { allowBulkGroupSelection, tableRef, table, serverPagination } = useTableContext();
const filteredRows = (_a = table == null ? void 0 : table.getRowModel().rows) != null ? _a : [];
const localRowIndex = filteredRows.findIndex((row) => row.id === rowId);
const isCurrentCellFocused = useMemo(() => {
var _a2;
const isFocused = ((_a2 = tableRef.current) == null ? void 0 : _a2.contains(document.activeElement)) && focusedCell.cellType === cellType;
switch (cellType) {
case "headerCell" /* headerCell */:
case "footerCell" /* footerCell */:
return isFocused && focusedCell.columnIndex === columnIndex;
case "groupHeaderCell" /* groupHeaderCell */: {
let isGroup = focusedCell.groupId === groupId;
if (allowBulkGroupSelection) {
isGroup && (isGroup = columnIndex === 0 ? focusedCell.columnIndex === 0 : focusedCell.columnIndex > 0);
}
return isFocused && isGroup;
}
case "dataCell" /* dataCell */:
return isFocused && focusedCell.rowIndex === localRowIndex && focusedCell.columnIndex === columnIndex;
default:
return false;
}
}, [focusedCell, columnIndex, cellType, groupId, localRowIndex, allowBulkGroupSelection]);
const focusCurrentCell = useCallback(() => {
setFocusedCell == null ? void 0 : setFocusedCell({ columnIndex, rowId, cellType, groupId, rowIndex });
}, [columnIndex, rowId, cellType, groupId, rowIndex]);
const resetFocus = useCallback(() => {
setFocusedCell == null ? void 0 : setFocusedCell({
cellType: "headerCell" /* headerCell */,
rowId: null,
groupId: null,
rowIndex: -1,
columnIndex: 0
});
}, []);
return {
isCurrentCellFocused,
focusCurrentCell,
resetFocus
};
}
export {
FocusHandlerContextProvider,
useFocusHandler
};