2022-10-25 15:49:38 +11:00
|
|
|
|
import { useMemo, useRef, useState, useEffect, useCallback } from "react";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
import { useAtom, useSetAtom } from "jotai";
|
2022-10-24 15:59:56 +11:00
|
|
|
|
import { useThrottledCallback } from "use-debounce";
|
2022-10-14 16:15:41 +11:00
|
|
|
|
import {
|
|
|
|
|
|
createColumnHelper,
|
|
|
|
|
|
flexRender,
|
|
|
|
|
|
getCoreRowModel,
|
|
|
|
|
|
useReactTable,
|
|
|
|
|
|
} from "@tanstack/react-table";
|
2022-10-31 17:04:18 +11:00
|
|
|
|
import {
|
|
|
|
|
|
DragDropContext,
|
|
|
|
|
|
DropResult,
|
|
|
|
|
|
Droppable,
|
|
|
|
|
|
Draggable,
|
|
|
|
|
|
} from "react-beautiful-dnd";
|
|
|
|
|
|
import { Portal } from "@mui/material";
|
2022-10-14 16:15:41 +11:00
|
|
|
|
|
2022-10-31 17:04:18 +11:00
|
|
|
|
import StyledTable from "./Styled/StyledTable";
|
|
|
|
|
|
import StyledRow from "./Styled/StyledRow";
|
|
|
|
|
|
import ColumnHeader from "./ColumnHeader";
|
|
|
|
|
|
import StyledResizer from "./Styled/StyledResizer";
|
2022-10-31 17:56:54 +11:00
|
|
|
|
import FinalColumnHeader from "./FinalColumn/FinalColumnHeader";
|
|
|
|
|
|
import FinalColumn from "./FinalColumn/FinalColumn";
|
2022-10-24 15:38:35 +11:00
|
|
|
|
import OutOfOrderIndicator from "./OutOfOrderIndicator";
|
2022-10-31 17:04:18 +11:00
|
|
|
|
import ContextMenu from "./ContextMenu";
|
2022-10-14 16:15:41 +11:00
|
|
|
|
|
2022-05-27 15:10:06 +10:00
|
|
|
|
import EmptyState from "@src/components/EmptyState";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
// import BulkActions from "./BulkActions";
|
2022-05-27 15:10:06 +10:00
|
|
|
|
import AddRow from "@src/components/TableToolbar/AddRow";
|
2022-06-02 14:55:47 +10:00
|
|
|
|
import { AddRow as AddRowIcon } from "@src/assets/icons";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
|
|
|
|
|
import {
|
2022-07-18 14:40:46 +10:00
|
|
|
|
projectScope,
|
2022-05-19 16:37:56 +10:00
|
|
|
|
userRolesAtom,
|
|
|
|
|
|
userSettingsAtom,
|
2022-07-18 14:40:46 +10:00
|
|
|
|
} from "@src/atoms/projectScope";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
import {
|
|
|
|
|
|
tableScope,
|
|
|
|
|
|
tableIdAtom,
|
|
|
|
|
|
tableSettingsAtom,
|
|
|
|
|
|
tableSchemaAtom,
|
|
|
|
|
|
tableColumnsOrderedAtom,
|
|
|
|
|
|
tableRowsAtom,
|
2022-05-30 12:48:27 +10:00
|
|
|
|
tableNextPageAtom,
|
2022-05-19 16:37:56 +10:00
|
|
|
|
tablePageAtom,
|
|
|
|
|
|
updateColumnAtom,
|
|
|
|
|
|
updateFieldAtom,
|
2022-06-02 17:36:30 +10:00
|
|
|
|
selectedCellAtom,
|
2022-10-31 16:17:21 +11:00
|
|
|
|
contextMenuTargetAtom,
|
2022-05-19 16:37:56 +10:00
|
|
|
|
} from "@src/atoms/tableScope";
|
2022-10-17 17:57:26 +11:00
|
|
|
|
import { COLLECTION_PAGE_SIZE } from "@src/config/db";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
2022-05-24 20:34:28 +10:00
|
|
|
|
import { getFieldType, getFieldProp } from "@src/components/fields";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
import { FieldType } from "@src/constants/fields";
|
|
|
|
|
|
import { formatSubTableName } from "@src/utils/table";
|
2022-10-14 16:15:41 +11:00
|
|
|
|
import { TableRow, ColumnConfig } from "@src/types/table";
|
|
|
|
|
|
import { StyledCell } from "./Styled/StyledCell";
|
2022-10-18 17:53:47 +11:00
|
|
|
|
import { useKeyboardNavigation } from "./useKeyboardNavigation";
|
2022-10-24 14:59:29 +11:00
|
|
|
|
import { useSaveColumnSizing } from "./useSaveColumnSizing";
|
2022-10-24 15:59:56 +11:00
|
|
|
|
import useVirtualization from "./useVirtualization";
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
|
|
|
|
|
export const DEFAULT_ROW_HEIGHT = 41;
|
2022-06-13 16:02:38 +10:00
|
|
|
|
export const DEFAULT_COL_WIDTH = 150;
|
2022-10-24 14:59:29 +11:00
|
|
|
|
export const MIN_COL_WIDTH = 80;
|
2022-10-21 14:58:25 +11:00
|
|
|
|
export const TABLE_PADDING = 16;
|
2022-10-24 15:19:28 +11:00
|
|
|
|
export const OUT_OF_ORDER_MARGIN = 8;
|
2022-10-24 13:12:53 +11:00
|
|
|
|
export const DEBOUNCE_DELAY = 500;
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
2022-10-14 16:15:41 +11:00
|
|
|
|
declare module "@tanstack/table-core" {
|
|
|
|
|
|
interface ColumnMeta<TData, TValue> extends ColumnConfig {}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const columnHelper = createColumnHelper<TableRow>();
|
|
|
|
|
|
const getRowId = (row: TableRow) => row._rowy_ref.path || row._rowy_ref.id;
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
2022-10-14 16:15:41 +11:00
|
|
|
|
export default function TableComponent() {
|
2022-07-18 14:40:46 +10:00
|
|
|
|
const [userRoles] = useAtom(userRolesAtom, projectScope);
|
|
|
|
|
|
const [userSettings] = useAtom(userSettingsAtom, projectScope);
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
|
|
|
|
|
const [tableId] = useAtom(tableIdAtom, tableScope);
|
|
|
|
|
|
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
|
|
|
|
|
|
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
|
|
|
|
|
|
const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope);
|
|
|
|
|
|
const [tableRows] = useAtom(tableRowsAtom, tableScope);
|
2022-05-30 12:48:27 +10:00
|
|
|
|
const [tableNextPage] = useAtom(tableNextPageAtom, tableScope);
|
2022-10-24 13:22:46 +11:00
|
|
|
|
const [tablePage, setTablePage] = useAtom(tablePageAtom, tableScope);
|
2022-06-03 18:17:27 +10:00
|
|
|
|
const [selectedCell, setSelectedCell] = useAtom(selectedCellAtom, tableScope);
|
2022-10-31 16:17:21 +11:00
|
|
|
|
const setContextMenuTarget = useSetAtom(contextMenuTargetAtom, tableScope);
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
|
|
|
|
|
const updateColumn = useSetAtom(updateColumnAtom, tableScope);
|
|
|
|
|
|
const updateField = useSetAtom(updateFieldAtom, tableScope);
|
|
|
|
|
|
|
2022-10-18 17:53:47 +11:00
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
2022-10-17 17:57:26 +11:00
|
|
|
|
const gridRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
2022-10-14 16:15:41 +11:00
|
|
|
|
const canAddColumn = userRoles.includes("ADMIN");
|
2022-10-17 17:57:26 +11:00
|
|
|
|
const canEditColumn = userRoles.includes("ADMIN");
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
2022-10-14 16:15:41 +11:00
|
|
|
|
// Get column defs from table schema
|
|
|
|
|
|
// Also add end column for admins
|
2022-05-19 16:37:56 +10:00
|
|
|
|
const columns = useMemo(() => {
|
2022-10-14 16:15:41 +11:00
|
|
|
|
const _columns = tableColumnsOrdered
|
2022-10-19 12:41:20 +11:00
|
|
|
|
// Hide column for all users using table schema
|
|
|
|
|
|
.filter((column) => !column.hidden)
|
2022-10-14 16:15:41 +11:00
|
|
|
|
.map((columnConfig) =>
|
|
|
|
|
|
columnHelper.accessor(columnConfig.fieldName, {
|
2022-10-17 17:57:26 +11:00
|
|
|
|
id: columnConfig.fieldName,
|
2022-10-14 16:15:41 +11:00
|
|
|
|
meta: columnConfig,
|
2022-10-24 13:12:53 +11:00
|
|
|
|
size: columnConfig.width,
|
|
|
|
|
|
enableResizing: columnConfig.resizable !== false,
|
|
|
|
|
|
minSize: MIN_COL_WIDTH,
|
2022-10-14 16:15:41 +11:00
|
|
|
|
// formatter:
|
|
|
|
|
|
// getFieldProp("TableCell", getFieldType(columnConfig)) ??
|
|
|
|
|
|
// function InDev() {
|
|
|
|
|
|
// return null;
|
|
|
|
|
|
// },
|
|
|
|
|
|
// editor:
|
|
|
|
|
|
// getFieldProp("TableEditor", getFieldType(columnConfig)) ??
|
|
|
|
|
|
// function InDev() {
|
|
|
|
|
|
// return null;
|
|
|
|
|
|
// },
|
|
|
|
|
|
// ...columnConfig,
|
|
|
|
|
|
// editable:
|
|
|
|
|
|
// tableSettings.readOnly && !userRoles.includes("ADMIN")
|
|
|
|
|
|
// ? false
|
|
|
|
|
|
// : columnConfig.editable ?? true,
|
|
|
|
|
|
// width: columnConfig.width ?? DEFAULT_COL_WIDTH,
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2022-10-19 12:41:20 +11:00
|
|
|
|
if (canAddColumn || !tableSettings.readOnly) {
|
|
|
|
|
|
_columns.push(
|
|
|
|
|
|
columnHelper.display({
|
|
|
|
|
|
id: "_rowy_column_actions",
|
2022-10-31 17:56:54 +11:00
|
|
|
|
cell: FinalColumn as any,
|
2022-10-25 12:33:29 +11:00
|
|
|
|
// cell: () => (
|
|
|
|
|
|
// <>
|
|
|
|
|
|
// <IconButton>M</IconButton>
|
|
|
|
|
|
// <IconButton>D</IconButton>
|
|
|
|
|
|
// <IconButton>X</IconButton>
|
|
|
|
|
|
// </>
|
|
|
|
|
|
// ),
|
2022-10-19 12:41:20 +11:00
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
|
|
|
|
|
return _columns;
|
2022-10-19 12:41:20 +11:00
|
|
|
|
}, [tableColumnsOrdered, canAddColumn, tableSettings.readOnly]);
|
|
|
|
|
|
|
|
|
|
|
|
// Get user’s hidden columns from user document
|
|
|
|
|
|
const userDocHiddenFields =
|
|
|
|
|
|
userSettings.tables?.[formatSubTableName(tableId)]?.hiddenFields;
|
|
|
|
|
|
// Memoize into a VisibilityState
|
|
|
|
|
|
const columnVisibility = useMemo(() => {
|
|
|
|
|
|
if (!Array.isArray(userDocHiddenFields)) return {};
|
|
|
|
|
|
return userDocHiddenFields.reduce((a, c) => ({ ...a, [c]: false }), {});
|
|
|
|
|
|
}, [userDocHiddenFields]);
|
2022-06-03 18:17:27 +10:00
|
|
|
|
|
2022-10-21 14:58:25 +11:00
|
|
|
|
// Get frozen columns
|
|
|
|
|
|
const columnPinning = useMemo(
|
|
|
|
|
|
() => ({
|
|
|
|
|
|
left: columns.filter((c) => c.meta?.fixed && c.id).map((c) => c.id!),
|
|
|
|
|
|
}),
|
|
|
|
|
|
[columns]
|
|
|
|
|
|
);
|
|
|
|
|
|
const lastFrozen: string | undefined =
|
|
|
|
|
|
columnPinning.left[columnPinning.left.length - 1];
|
|
|
|
|
|
|
2022-10-24 13:12:53 +11:00
|
|
|
|
// Call TanStack Table
|
2022-10-14 16:15:41 +11:00
|
|
|
|
const table = useReactTable({
|
|
|
|
|
|
data: tableRows,
|
|
|
|
|
|
columns,
|
|
|
|
|
|
getCoreRowModel: getCoreRowModel(),
|
|
|
|
|
|
getRowId,
|
|
|
|
|
|
columnResizeMode: "onChange",
|
|
|
|
|
|
});
|
2022-10-24 13:12:53 +11:00
|
|
|
|
|
2022-10-25 15:49:38 +11:00
|
|
|
|
// Store local columnSizing state so we can save it to table schema
|
|
|
|
|
|
// in `useSaveColumnSizing`. This could be generalized by storing the
|
|
|
|
|
|
// entire table state.
|
2022-10-24 13:12:53 +11:00
|
|
|
|
const [columnSizing, setColumnSizing] = useState(
|
|
|
|
|
|
table.initialState.columnSizing
|
|
|
|
|
|
);
|
|
|
|
|
|
table.setOptions((prev) => ({
|
|
|
|
|
|
...prev,
|
|
|
|
|
|
state: { ...prev.state, columnVisibility, columnPinning, columnSizing },
|
|
|
|
|
|
onColumnSizingChange: setColumnSizing,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2022-10-18 17:53:47 +11:00
|
|
|
|
const { rows } = table.getRowModel();
|
2022-10-19 12:41:20 +11:00
|
|
|
|
const leafColumns = table.getVisibleLeafColumns();
|
2022-10-17 17:57:26 +11:00
|
|
|
|
|
2022-10-18 17:53:47 +11:00
|
|
|
|
const { handleKeyDown, focusInsideCell } = useKeyboardNavigation({
|
|
|
|
|
|
gridRef,
|
|
|
|
|
|
tableRows,
|
2022-10-19 12:41:20 +11:00
|
|
|
|
leafColumns,
|
2022-10-18 17:53:47 +11:00
|
|
|
|
});
|
2022-10-24 15:59:56 +11:00
|
|
|
|
const {
|
|
|
|
|
|
virtualRows,
|
|
|
|
|
|
// totalHeight,
|
|
|
|
|
|
// scrollToRowIndex,
|
|
|
|
|
|
virtualCols,
|
|
|
|
|
|
// totalWidth,
|
|
|
|
|
|
// scrollToColIndex,
|
|
|
|
|
|
paddingTop,
|
|
|
|
|
|
paddingBottom,
|
|
|
|
|
|
paddingLeft,
|
|
|
|
|
|
paddingRight,
|
|
|
|
|
|
} = useVirtualization(containerRef, leafColumns);
|
|
|
|
|
|
useSaveColumnSizing(columnSizing, canEditColumn);
|
2022-10-18 17:53:47 +11:00
|
|
|
|
|
2022-10-25 15:49:38 +11:00
|
|
|
|
const handleDropColumn = useCallback(
|
|
|
|
|
|
(result: DropResult) => {
|
|
|
|
|
|
if (result.destination?.index === undefined || !result.draggableId)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
console.log(result.draggableId, result.destination.index);
|
|
|
|
|
|
|
|
|
|
|
|
updateColumn({
|
|
|
|
|
|
key: result.draggableId,
|
|
|
|
|
|
index: result.destination.index,
|
|
|
|
|
|
config: {},
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
[updateColumn]
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2022-10-18 17:53:47 +11:00
|
|
|
|
const fetchMoreOnBottomReached = useThrottledCallback(
|
|
|
|
|
|
(containerElement?: HTMLDivElement | null) => {
|
|
|
|
|
|
if (!containerElement) return;
|
|
|
|
|
|
|
|
|
|
|
|
const { scrollHeight, scrollTop, clientHeight } = containerElement;
|
|
|
|
|
|
if (scrollHeight - scrollTop - clientHeight < 300) {
|
|
|
|
|
|
setTablePage((p) => p + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2022-10-24 13:12:53 +11:00
|
|
|
|
DEBOUNCE_DELAY
|
2022-10-18 17:53:47 +11:00
|
|
|
|
);
|
2022-10-24 13:22:46 +11:00
|
|
|
|
// Check on mount and after fetch to see if the table is at the bottom
|
|
|
|
|
|
// for large screen heights
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
fetchMoreOnBottomReached(containerRef.current);
|
|
|
|
|
|
}, [fetchMoreOnBottomReached, tablePage, tableNextPage.loading]);
|
2022-05-19 16:37:56 +10:00
|
|
|
|
|
|
|
|
|
|
return (
|
2022-10-18 17:53:47 +11:00
|
|
|
|
<div
|
|
|
|
|
|
ref={containerRef}
|
2022-10-19 12:54:31 +11:00
|
|
|
|
onScroll={(e) => fetchMoreOnBottomReached(e.target as HTMLDivElement)}
|
2022-10-18 17:53:47 +11:00
|
|
|
|
style={{ overflow: "auto", width: "100%", height: "100%" }}
|
|
|
|
|
|
>
|
2022-10-14 16:15:41 +11:00
|
|
|
|
<StyledTable
|
2022-10-17 17:57:26 +11:00
|
|
|
|
ref={gridRef}
|
2022-10-14 16:15:41 +11:00
|
|
|
|
role="grid"
|
2022-10-17 17:57:26 +11:00
|
|
|
|
aria-readonly={tableSettings.readOnly}
|
|
|
|
|
|
aria-colcount={columns.length}
|
|
|
|
|
|
aria-rowcount={tableRows.length + 1}
|
2022-10-24 15:38:35 +11:00
|
|
|
|
style={
|
|
|
|
|
|
{
|
|
|
|
|
|
width: table.getTotalSize(),
|
|
|
|
|
|
userSelect: "none",
|
|
|
|
|
|
"--row-height": `${tableSchema.rowHeight || DEFAULT_ROW_HEIGHT}px`,
|
|
|
|
|
|
} as any
|
|
|
|
|
|
}
|
2022-10-14 16:15:41 +11:00
|
|
|
|
onKeyDown={handleKeyDown}
|
|
|
|
|
|
>
|
2022-10-17 17:57:26 +11:00
|
|
|
|
<div
|
|
|
|
|
|
className="thead"
|
|
|
|
|
|
role="rowgroup"
|
2022-10-21 14:58:25 +11:00
|
|
|
|
style={{
|
|
|
|
|
|
position: "sticky",
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
zIndex: 10,
|
|
|
|
|
|
padding: `0 ${TABLE_PADDING}px`,
|
|
|
|
|
|
}}
|
2022-10-17 17:57:26 +11:00
|
|
|
|
>
|
2022-10-25 15:49:38 +11:00
|
|
|
|
<DragDropContext onDragEnd={handleDropColumn}>
|
|
|
|
|
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
|
|
|
|
<Droppable droppableId="droppable-column" direction="horizontal">
|
|
|
|
|
|
{(provided) => (
|
|
|
|
|
|
<StyledRow
|
|
|
|
|
|
key={headerGroup.id}
|
|
|
|
|
|
role="row"
|
|
|
|
|
|
aria-rowindex={1}
|
|
|
|
|
|
style={{ height: DEFAULT_ROW_HEIGHT + 1 }}
|
|
|
|
|
|
{...provided.droppableProps}
|
|
|
|
|
|
ref={provided.innerRef}
|
2022-10-17 17:57:26 +11:00
|
|
|
|
>
|
2022-10-25 15:49:38 +11:00
|
|
|
|
{headerGroup.headers.map((header) => {
|
|
|
|
|
|
const isSelectedCell =
|
|
|
|
|
|
(!selectedCell && header.index === 0) ||
|
|
|
|
|
|
(selectedCell?.path === "_rowy_header" &&
|
|
|
|
|
|
selectedCell?.columnKey === header.id);
|
|
|
|
|
|
|
2022-10-31 17:56:54 +11:00
|
|
|
|
if (header.id === "_rowy_column_actions")
|
|
|
|
|
|
return (
|
|
|
|
|
|
<FinalColumnHeader
|
|
|
|
|
|
key={header.id}
|
|
|
|
|
|
data-row-id={"_rowy_header"}
|
|
|
|
|
|
data-col-id={header.id}
|
|
|
|
|
|
tabIndex={isSelectedCell ? 0 : -1}
|
|
|
|
|
|
focusInsideCell={isSelectedCell && focusInsideCell}
|
|
|
|
|
|
aria-colindex={header.index + 1}
|
|
|
|
|
|
aria-readonly={!canEditColumn}
|
|
|
|
|
|
aria-selected={isSelectedCell}
|
|
|
|
|
|
/>
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!header.column.columnDef.meta) return null;
|
|
|
|
|
|
|
2022-10-25 15:49:38 +11:00
|
|
|
|
return (
|
|
|
|
|
|
<Draggable
|
|
|
|
|
|
key={header.id}
|
|
|
|
|
|
draggableId={header.id}
|
|
|
|
|
|
index={header.index}
|
|
|
|
|
|
isDragDisabled={!canEditColumn}
|
|
|
|
|
|
disableInteractiveElementBlocking
|
|
|
|
|
|
>
|
|
|
|
|
|
{(provided, snapshot) => (
|
2022-10-31 17:04:18 +11:00
|
|
|
|
<ColumnHeader
|
2022-10-25 15:49:38 +11:00
|
|
|
|
key={header.id}
|
|
|
|
|
|
data-row-id={"_rowy_header"}
|
|
|
|
|
|
data-col-id={header.id}
|
|
|
|
|
|
data-frozen={
|
|
|
|
|
|
header.column.getIsPinned() || undefined
|
|
|
|
|
|
}
|
|
|
|
|
|
data-frozen-last={
|
|
|
|
|
|
lastFrozen === header.id || undefined
|
|
|
|
|
|
}
|
|
|
|
|
|
ref={provided.innerRef}
|
|
|
|
|
|
{...provided.draggableProps}
|
|
|
|
|
|
tabIndex={isSelectedCell ? 0 : -1}
|
|
|
|
|
|
aria-colindex={header.index + 1}
|
|
|
|
|
|
aria-readonly={!canEditColumn}
|
|
|
|
|
|
aria-selected={isSelectedCell}
|
2022-10-31 17:04:18 +11:00
|
|
|
|
column={header.column.columnDef.meta!}
|
2022-10-25 15:49:38 +11:00
|
|
|
|
style={{
|
|
|
|
|
|
width: header.getSize(),
|
|
|
|
|
|
left: header.column.getIsPinned()
|
|
|
|
|
|
? virtualCols[header.index].start -
|
|
|
|
|
|
TABLE_PADDING
|
|
|
|
|
|
: undefined,
|
|
|
|
|
|
...provided.draggableProps.style,
|
2022-10-31 18:17:33 +11:00
|
|
|
|
zIndex: header.column.getIsPinned() ? 11 : 10,
|
2022-10-25 15:49:38 +11:00
|
|
|
|
}}
|
2022-10-31 17:04:18 +11:00
|
|
|
|
width={header.getSize()}
|
2022-10-25 15:49:38 +11:00
|
|
|
|
sx={[
|
|
|
|
|
|
snapshot.isDragging
|
|
|
|
|
|
? {}
|
|
|
|
|
|
: { "& + &": { borderLeft: "none" } },
|
|
|
|
|
|
]}
|
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
|
setSelectedCell({
|
|
|
|
|
|
path: "_rowy_header",
|
|
|
|
|
|
columnKey: header.id,
|
|
|
|
|
|
});
|
|
|
|
|
|
(e.target as HTMLDivElement).focus();
|
|
|
|
|
|
}}
|
2022-10-31 17:04:18 +11:00
|
|
|
|
focusInsideCell={
|
|
|
|
|
|
isSelectedCell && focusInsideCell
|
|
|
|
|
|
}
|
2022-10-25 15:49:38 +11:00
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
{...provided.dragHandleProps}
|
|
|
|
|
|
tabIndex={
|
|
|
|
|
|
isSelectedCell && focusInsideCell ? 0 : -1
|
|
|
|
|
|
}
|
|
|
|
|
|
aria-describedby={
|
|
|
|
|
|
isSelectedCell && focusInsideCell
|
|
|
|
|
|
? provided.dragHandleProps?.[
|
|
|
|
|
|
"aria-describedby"
|
|
|
|
|
|
]
|
|
|
|
|
|
: undefined
|
|
|
|
|
|
}
|
2022-10-31 17:04:18 +11:00
|
|
|
|
style={{
|
|
|
|
|
|
position: "absolute",
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
zIndex: 0,
|
|
|
|
|
|
}}
|
2022-10-25 15:49:38 +11:00
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{header.column.getCanResize() && (
|
|
|
|
|
|
<StyledResizer
|
|
|
|
|
|
isResizing={header.column.getIsResizing()}
|
|
|
|
|
|
onMouseDown={header.getResizeHandler()}
|
|
|
|
|
|
onTouchStart={header.getResizeHandler()}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
2022-10-31 17:04:18 +11:00
|
|
|
|
</ColumnHeader>
|
2022-10-25 15:49:38 +11:00
|
|
|
|
)}
|
|
|
|
|
|
</Draggable>
|
|
|
|
|
|
);
|
|
|
|
|
|
})}
|
|
|
|
|
|
{provided.placeholder}
|
|
|
|
|
|
</StyledRow>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Droppable>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</DragDropContext>
|
2022-10-14 16:15:41 +11:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2022-10-17 17:57:26 +11:00
|
|
|
|
<div className="tbody" role="rowgroup">
|
2022-10-18 17:53:47 +11:00
|
|
|
|
{paddingTop > 0 && (
|
|
|
|
|
|
<div role="presentation" style={{ height: `${paddingTop}px` }} />
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{virtualRows.map((virtualRow) => {
|
|
|
|
|
|
const row = rows[virtualRow.index];
|
2022-10-24 15:38:35 +11:00
|
|
|
|
const outOfOrder = row.original._rowy_outOfOrder;
|
2022-10-18 17:53:47 +11:00
|
|
|
|
|
|
|
|
|
|
return (
|
2022-10-19 12:54:31 +11:00
|
|
|
|
<StyledRow
|
|
|
|
|
|
key={row.id}
|
|
|
|
|
|
role="row"
|
|
|
|
|
|
aria-rowindex={row.index + 2}
|
2022-10-24 15:19:28 +11:00
|
|
|
|
style={{
|
2022-10-24 15:38:35 +11:00
|
|
|
|
height: "auto",
|
|
|
|
|
|
marginBottom: outOfOrder ? OUT_OF_ORDER_MARGIN : 0,
|
2022-10-24 15:19:28 +11:00
|
|
|
|
}}
|
2022-10-24 15:38:35 +11:00
|
|
|
|
data-out-of-order={outOfOrder || undefined}
|
2022-10-19 12:54:31 +11:00
|
|
|
|
>
|
2022-10-18 17:53:47 +11:00
|
|
|
|
{paddingLeft > 0 && (
|
|
|
|
|
|
<div
|
|
|
|
|
|
role="presentation"
|
|
|
|
|
|
style={{ width: `${paddingLeft}px` }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
2022-10-24 15:38:35 +11:00
|
|
|
|
{outOfOrder && <OutOfOrderIndicator />}
|
|
|
|
|
|
|
2022-10-18 17:53:47 +11:00
|
|
|
|
{virtualCols.map((virtualCell) => {
|
|
|
|
|
|
const cellIndex = virtualCell.index;
|
|
|
|
|
|
const cell = row.getVisibleCells()[cellIndex];
|
|
|
|
|
|
|
|
|
|
|
|
const isSelectedCell =
|
|
|
|
|
|
selectedCell?.path === row.original._rowy_ref.path &&
|
|
|
|
|
|
selectedCell?.columnKey === cell.column.id;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<StyledCell
|
|
|
|
|
|
key={cell.id}
|
2022-10-21 14:58:25 +11:00
|
|
|
|
data-row-id={row.id}
|
|
|
|
|
|
data-col-id={cell.column.id}
|
|
|
|
|
|
data-frozen={cell.column.getIsPinned() || undefined}
|
|
|
|
|
|
data-frozen-last={
|
|
|
|
|
|
lastFrozen === cell.column.id || undefined
|
|
|
|
|
|
}
|
2022-10-18 17:53:47 +11:00
|
|
|
|
role="gridcell"
|
|
|
|
|
|
tabIndex={isSelectedCell && !focusInsideCell ? 0 : -1}
|
|
|
|
|
|
aria-colindex={cellIndex + 1}
|
|
|
|
|
|
aria-readonly={
|
|
|
|
|
|
cell.column.columnDef.meta?.editable === false
|
|
|
|
|
|
}
|
|
|
|
|
|
aria-selected={isSelectedCell}
|
2022-10-25 15:49:38 +11:00
|
|
|
|
aria-describedby="rowy-table-cell-description"
|
2022-10-21 14:58:25 +11:00
|
|
|
|
style={{
|
|
|
|
|
|
width: cell.column.getSize(),
|
|
|
|
|
|
left: cell.column.getIsPinned()
|
|
|
|
|
|
? virtualCell.start - TABLE_PADDING
|
|
|
|
|
|
: undefined,
|
|
|
|
|
|
backgroundColor:
|
|
|
|
|
|
cell.column.id === "_rowy_column_actions"
|
|
|
|
|
|
? "transparent"
|
|
|
|
|
|
: undefined,
|
|
|
|
|
|
borderBottomWidth:
|
|
|
|
|
|
cell.column.id === "_rowy_column_actions"
|
|
|
|
|
|
? 0
|
|
|
|
|
|
: undefined,
|
|
|
|
|
|
borderRightWidth:
|
|
|
|
|
|
cell.column.id === "_rowy_column_actions"
|
|
|
|
|
|
? 0
|
|
|
|
|
|
: undefined,
|
|
|
|
|
|
}}
|
2022-10-18 17:53:47 +11:00
|
|
|
|
onClick={(e) => {
|
|
|
|
|
|
setSelectedCell({
|
|
|
|
|
|
path: row.original._rowy_ref.path,
|
|
|
|
|
|
columnKey: cell.column.id,
|
|
|
|
|
|
});
|
|
|
|
|
|
(e.target as HTMLDivElement).focus();
|
|
|
|
|
|
}}
|
2022-10-31 16:17:21 +11:00
|
|
|
|
onContextMenu={(e) => {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
setSelectedCell({
|
|
|
|
|
|
path: row.original._rowy_ref.path,
|
|
|
|
|
|
columnKey: cell.column.id,
|
|
|
|
|
|
});
|
|
|
|
|
|
(e.target as HTMLDivElement).focus();
|
|
|
|
|
|
setContextMenuTarget(e.target as HTMLElement);
|
|
|
|
|
|
}}
|
2022-10-18 14:49:17 +11:00
|
|
|
|
>
|
2022-10-24 15:38:35 +11:00
|
|
|
|
<div
|
|
|
|
|
|
className="cell-contents"
|
|
|
|
|
|
style={{ height: tableSchema.rowHeight }}
|
|
|
|
|
|
>
|
2022-10-31 17:56:54 +11:00
|
|
|
|
{flexRender(cell.column.columnDef.cell, {
|
|
|
|
|
|
...cell.getContext(),
|
|
|
|
|
|
focusInsideCell: isSelectedCell && focusInsideCell,
|
|
|
|
|
|
})}
|
2022-10-24 15:38:35 +11:00
|
|
|
|
</div>
|
2022-10-19 12:54:31 +11:00
|
|
|
|
{/* <button
|
2022-10-18 17:53:47 +11:00
|
|
|
|
tabIndex={isSelectedCell && focusInsideCell ? 0 : -1}
|
|
|
|
|
|
>
|
|
|
|
|
|
{isSelectedCell ? "f" : "x"}
|
2022-10-19 12:54:31 +11:00
|
|
|
|
</button> */}
|
2022-10-18 17:53:47 +11:00
|
|
|
|
</StyledCell>
|
|
|
|
|
|
);
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
|
|
|
|
{paddingRight > 0 && (
|
|
|
|
|
|
<div
|
|
|
|
|
|
role="presentation"
|
|
|
|
|
|
style={{ width: `${paddingRight}px` }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</StyledRow>
|
|
|
|
|
|
);
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
|
|
|
|
{paddingBottom > 0 && (
|
|
|
|
|
|
<div role="presentation" style={{ height: `${paddingBottom}px` }} />
|
|
|
|
|
|
)}
|
2022-10-14 16:15:41 +11:00
|
|
|
|
</div>
|
|
|
|
|
|
</StyledTable>
|
2022-10-25 15:49:38 +11:00
|
|
|
|
|
|
|
|
|
|
<Portal>
|
|
|
|
|
|
<div id="rowy-table-cell-description" style={{ display: "none" }}>
|
|
|
|
|
|
Press Enter to edit.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Portal>
|
2022-10-31 16:17:21 +11:00
|
|
|
|
|
|
|
|
|
|
<ContextMenu />
|
2022-10-18 17:53:47 +11:00
|
|
|
|
</div>
|
2022-05-19 16:37:56 +10:00
|
|
|
|
);
|
|
|
|
|
|
}
|