mirror of
https://github.com/docmost/docmost.git
synced 2026-07-24 15:13:17 +10:00
103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
import { memo, useCallback, useMemo } from "react";
|
|
import { Checkbox } from "@mantine/core";
|
|
import { IconGripVertical } from "@tabler/icons-react";
|
|
import { useAtomValue, useSetAtom, type PrimitiveAtom } from "jotai";
|
|
import { selectAtom } from "jotai/utils";
|
|
import { useRowSelection } from "@/ee/base/hooks/use-row-selection";
|
|
import { focusedCellAtomFamily } from "@/ee/base/atoms/base-atoms";
|
|
import { FocusedCell } from "@/ee/base/types/base.types";
|
|
import { useBaseEditable } from "@/ee/base/context/base-editable";
|
|
import { useGridRowOrder } from "@/ee/base/context/grid-row-order";
|
|
import classes from "@/ee/base/styles/grid.module.css";
|
|
|
|
type RowNumberCellProps = {
|
|
rowId: string;
|
|
rowIndex: number;
|
|
isPinned: boolean;
|
|
pinOffset?: number;
|
|
pageId: string;
|
|
};
|
|
|
|
export const RowNumberCell = memo(function RowNumberCell({
|
|
rowId,
|
|
rowIndex,
|
|
isPinned,
|
|
pinOffset,
|
|
pageId,
|
|
}: RowNumberCellProps) {
|
|
const { isSelected, toggle } = useRowSelection(pageId);
|
|
const selected = isSelected(rowId);
|
|
const editable = useBaseEditable();
|
|
const getOrderedRowIds = useGridRowOrder();
|
|
|
|
const setFocusedCell = useSetAtom(
|
|
focusedCellAtomFamily(pageId) as PrimitiveAtom<FocusedCell>,
|
|
);
|
|
const isFocused = useAtomValue(
|
|
useMemo(
|
|
() =>
|
|
selectAtom(
|
|
focusedCellAtomFamily(pageId),
|
|
(fc) => fc?.rowId === rowId && fc?.propertyId === "__row_number",
|
|
),
|
|
[pageId, rowId],
|
|
),
|
|
);
|
|
|
|
const handleCellClick = useCallback(
|
|
(e: React.MouseEvent<HTMLDivElement>) => {
|
|
setFocusedCell({ rowId, propertyId: "__row_number" });
|
|
(e.currentTarget.closest('[role="grid"]') as HTMLElement | null)?.focus({
|
|
preventScroll: true,
|
|
});
|
|
},
|
|
[rowId, setFocusedCell],
|
|
);
|
|
|
|
const handleCheckboxChange = useCallback(
|
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const nativeEvent = e.nativeEvent as MouseEvent;
|
|
toggle(rowId, {
|
|
shiftKey: nativeEvent.shiftKey === true,
|
|
rowIndex,
|
|
orderedRowIds: getOrderedRowIds(),
|
|
});
|
|
},
|
|
[rowId, rowIndex, getOrderedRowIds, toggle],
|
|
);
|
|
|
|
return (
|
|
<div
|
|
id={`base-cell-${rowId}-__row_number`}
|
|
role="gridcell"
|
|
className={`${classes.cell} ${classes.rowNumberCell} ${isPinned ? classes.cellPinned : ""} ${isFocused ? classes.cellFocused : ""}`}
|
|
style={
|
|
isPinned
|
|
? ({ "--pin-offset": `${pinOffset ?? 0}px` } as React.CSSProperties)
|
|
: undefined
|
|
}
|
|
onClick={handleCellClick}
|
|
>
|
|
<div className={classes.rowNumberCellInner}>
|
|
{editable && (
|
|
<span className={classes.rowNumberDragHandle} aria-label="Drag row">
|
|
<IconGripVertical size={12} />
|
|
</span>
|
|
)}
|
|
{editable && (
|
|
<span className={classes.rowNumberCheckbox}>
|
|
<Checkbox
|
|
size="xs"
|
|
checked={selected}
|
|
onChange={handleCheckboxChange}
|
|
aria-label="Select row"
|
|
tabIndex={-1}
|
|
/>
|
|
</span>
|
|
)}
|
|
<span className={classes.rowNumberIndex}>{rowIndex + 1}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|