-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
Cell.tsx
128 lines (114 loc) · 3.44 KB
/
Cell.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import React, { forwardRef, memo, useLayoutEffect, useRef } from 'react';
import clsx from 'clsx';
import { EditorContainer, EditorPortal } from './editors';
import { CellRendererProps } from './common/types';
import { wrapEvent } from './utils';
import { useCombinedRefs } from './hooks';
function Cell<R, SR>({
className,
column,
isCopied,
isDraggedOver,
isRowSelected,
lastFrozenColumnIndex,
row,
rowIdx,
eventBus,
selectedCellProps,
onRowClick,
onKeyDown,
onClick,
onDoubleClick,
onContextMenu,
...props
}: CellRendererProps<R, SR>, ref: React.Ref<HTMLDivElement>) {
const cellRef = useRef<HTMLDivElement>(null);
const isSelected = selectedCellProps !== undefined;
const isEditing = selectedCellProps?.mode === 'EDIT';
const shouldFocus = isSelected && !isEditing;
const { cellClass } = column;
className = clsx(
'rdg-cell',
{
'rdg-cell-frozen': column.frozen,
'rdg-cell-frozen-last': column.idx === lastFrozenColumnIndex,
'rdg-cell-selected': isSelected,
'rdg-cell-copied': isCopied,
'rdg-cell-dragged-over': isDraggedOver
},
typeof cellClass === 'function' ? cellClass(row) : cellClass,
className
);
useLayoutEffect(() => {
if (shouldFocus) {
cellRef.current?.focus();
}
}, [shouldFocus]);
function selectCell(openEditor?: boolean) {
eventBus.dispatch('SELECT_CELL', { idx: column.idx, rowIdx }, openEditor);
}
function handleClick() {
selectCell();
onRowClick?.(rowIdx, row, column);
}
function handleContextMenu() {
selectCell();
}
function handleDoubleClick() {
selectCell(true);
}
function onRowSelectionChange(checked: boolean, isShiftClick: boolean) {
eventBus.dispatch('SELECT_ROW', { rowIdx, checked, isShiftClick });
}
function getCellContent() {
if (selectedCellProps && selectedCellProps.mode === 'EDIT') {
const { editorPortalTarget, ...editorProps } = selectedCellProps.editorContainerProps;
const { left, top } = cellRef.current!.getBoundingClientRect();
return (
<EditorPortal target={editorPortalTarget}>
<EditorContainer<R, SR>
{...editorProps}
rowIdx={rowIdx}
row={row}
column={column}
left={left}
top={top}
/>
</EditorPortal>
);
}
return (
<>
<column.formatter
column={column}
rowIdx={rowIdx}
row={row}
isRowSelected={isRowSelected}
onRowSelectionChange={onRowSelectionChange}
/>
{selectedCellProps?.dragHandleProps && (
<div className="rdg-cell-drag-handle" {...selectedCellProps.dragHandleProps} />
)}
</>
);
}
return (
<div
ref={useCombinedRefs(cellRef, ref)}
className={className}
tabIndex={isSelected ? -1 : undefined}
style={{
width: column.width,
left: column.left
}}
onKeyDown={selectedCellProps?.onKeyDown ? wrapEvent(selectedCellProps.onKeyDown, onKeyDown) : onKeyDown}
onClick={isEditing ? onClick : wrapEvent(handleClick, onClick)}
onDoubleClick={isEditing ? onDoubleClick : wrapEvent(handleDoubleClick, onDoubleClick)}
onContextMenu={isEditing ? onContextMenu : wrapEvent(handleContextMenu, onContextMenu)}
{...props}
>
{getCellContent()}
</div>
);
}
export default memo(forwardRef(Cell)) as <R, SR = unknown>(props: CellRendererProps<R, SR>) => JSX.Element;