@hzab/edit-table 0.1.1 → 0.1.3-alpha.0
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/CHANGELOG.md +8 -0
- package/package.json +6 -4
- package/src/Template/NumberCellTemplate/index.less +5 -0
- package/src/Template/NumberCellTemplate/index.tsx +24 -0
- package/src/Template/TextCellTemplate/index.less +5 -0
- package/src/Template/TextCellTemplate/index.tsx +22 -0
- package/src/common/WidthWrapHoc.tsx +89 -61
- package/src/common/childAntdComponent.ts +2 -0
- package/src/index.less +30 -0
- package/src/index.tsx +87 -34
- package/src/Template/NumberCellTemplate.tsx +0 -168
- package/src/Template/TextCellTemplate.tsx +0 -123
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hzab/edit-table",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-alpha.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src",
|
|
6
6
|
"scripts": {
|
|
@@ -41,10 +41,12 @@
|
|
|
41
41
|
"react-router-dom": "6.14.1",
|
|
42
42
|
"typedoc": "0.24.8",
|
|
43
43
|
"typescript": "4.9.4",
|
|
44
|
-
"webpack": "5.75.0"
|
|
44
|
+
"webpack": "5.75.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@silevis/reactgrid": "^4.1.17",
|
|
45
48
|
"@hzab/form-render": "^1.7.17",
|
|
46
|
-
"@hzab/list-render": "^1.11.0"
|
|
47
|
-
"@silevis/reactgrid": "^4.1.17"
|
|
49
|
+
"@hzab/list-render": "^1.11.0"
|
|
48
50
|
},
|
|
49
51
|
"directories": {
|
|
50
52
|
"src": "src"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Input } from "antd";
|
|
2
|
+
import "./index.less"
|
|
3
|
+
const NumberCellTemplate = (props: any) => {
|
|
4
|
+
const { pattern, cell, componentProps } = props;
|
|
5
|
+
return (
|
|
6
|
+
<div className="number-cell-template">
|
|
7
|
+
{pattern == "readPretty" ? (
|
|
8
|
+
<div>{cell?.text}</div>
|
|
9
|
+
) : (
|
|
10
|
+
<Input
|
|
11
|
+
className="rg-input"
|
|
12
|
+
type="number"
|
|
13
|
+
ref={(input) => {
|
|
14
|
+
if (input) {
|
|
15
|
+
input.focus();
|
|
16
|
+
}
|
|
17
|
+
}}
|
|
18
|
+
{...componentProps}
|
|
19
|
+
/>
|
|
20
|
+
)}
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
export default NumberCellTemplate
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "./index.less"
|
|
2
|
+
const TextCellTemplate = (props: any) => {
|
|
3
|
+
const { pattern, cell, componentProps } = props;
|
|
4
|
+
return (
|
|
5
|
+
<div className="text-cell-template">
|
|
6
|
+
{pattern == "readPretty" ? (
|
|
7
|
+
<div>{cell?.text}</div>
|
|
8
|
+
) : (
|
|
9
|
+
<input
|
|
10
|
+
className="rg-input"
|
|
11
|
+
ref={(input) => {
|
|
12
|
+
if (input) {
|
|
13
|
+
input.focus();
|
|
14
|
+
}
|
|
15
|
+
}}
|
|
16
|
+
{...componentProps}
|
|
17
|
+
/>
|
|
18
|
+
)}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
export default TextCellTemplate
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "@silevis/reactgrid";
|
|
15
15
|
import { InfoCircleOutlined } from "@ant-design/icons";
|
|
16
16
|
import { Popover } from "antd";
|
|
17
|
-
|
|
17
|
+
import { isTriggerBlur } from "./childAntdComponent";
|
|
18
18
|
export type OptionType = {
|
|
19
19
|
label: string;
|
|
20
20
|
value: string | number;
|
|
@@ -26,7 +26,6 @@ export interface BaseCell extends Cell {
|
|
|
26
26
|
value: string | number;
|
|
27
27
|
values: OptionType[];
|
|
28
28
|
isDisabled?: boolean;
|
|
29
|
-
commit?: string;
|
|
30
29
|
}
|
|
31
30
|
interface DIProps {
|
|
32
31
|
onCellChanged: (...args: any[]) => void;
|
|
@@ -37,42 +36,22 @@ interface DIProps {
|
|
|
37
36
|
export const WidthWrapHoc = (WrapComponent: any) => {
|
|
38
37
|
class createBaseCellTemplate implements CellTemplate<BaseCell> {
|
|
39
38
|
getCompatibleCell(uncertainCell: Uncertain<BaseCell>): Compatible<BaseCell> {
|
|
40
|
-
let selectedValue: string | undefined;
|
|
41
|
-
try {
|
|
42
|
-
selectedValue = getCellProperty(uncertainCell, "selectedValue", "number");
|
|
43
|
-
} catch {
|
|
44
|
-
selectedValue = undefined;
|
|
45
|
-
}
|
|
46
|
-
if (!selectedValue) {
|
|
47
|
-
try {
|
|
48
|
-
selectedValue = getCellProperty(uncertainCell, "selectedValue", "string");
|
|
49
|
-
} catch {
|
|
50
|
-
selectedValue = undefined;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
let commit: string;
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
commit = getCellProperty(uncertainCell, "commit", "string");
|
|
57
|
-
} catch {
|
|
58
|
-
commit = "submit";
|
|
59
|
-
}
|
|
60
|
-
|
|
61
39
|
let values: any;
|
|
62
40
|
try {
|
|
63
41
|
values = getCellProperty(uncertainCell, "values", "object");
|
|
64
42
|
} catch {
|
|
65
43
|
values = [];
|
|
66
44
|
}
|
|
67
|
-
const value = selectedValue ? parseFloat(selectedValue) : NaN;
|
|
45
|
+
const value = uncertainCell.selectedValue ? parseFloat(uncertainCell.selectedValue) : NaN;
|
|
68
46
|
let isDisabled = true;
|
|
69
47
|
try {
|
|
70
48
|
isDisabled = getCellProperty(uncertainCell, "isDisabled", "boolean");
|
|
71
49
|
} catch {
|
|
72
50
|
isDisabled = false;
|
|
73
51
|
}
|
|
52
|
+
const selectedValue = uncertainCell.selectedValue;
|
|
74
53
|
const text = selectedValue || "";
|
|
75
|
-
return { ...uncertainCell, selectedValue, text, value, values, isDisabled
|
|
54
|
+
return { ...uncertainCell, selectedValue, text, value, values, isDisabled };
|
|
76
55
|
}
|
|
77
56
|
|
|
78
57
|
update(cell: Compatible<BaseCell>, cellToMerge: UncertainCompatible<BaseCell>): Compatible<BaseCell> {
|
|
@@ -83,7 +62,6 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
83
62
|
return this.getCompatibleCell({
|
|
84
63
|
...cell,
|
|
85
64
|
selectedValue: selectedValueFromText,
|
|
86
|
-
commit: cellToMerge?.commit,
|
|
87
65
|
});
|
|
88
66
|
}
|
|
89
67
|
|
|
@@ -104,10 +82,13 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
104
82
|
}
|
|
105
83
|
/** render 不能抽出来组件,否则点击会失效 */
|
|
106
84
|
render(cell: any, isInEditMode: boolean, onCellChanged: (cell: any, commit: boolean) => void): React.ReactNode {
|
|
107
|
-
const [
|
|
85
|
+
const [edit, setEdit] = useState<boolean>(false);
|
|
86
|
+
const [open, setOpen] = useState<boolean>(false);
|
|
108
87
|
const datatypeId = cell?.columnId + cell?.rowId;
|
|
109
88
|
const [comValue, setComValue] = useState(cell?.text);
|
|
89
|
+
const [isValidator, setIsValidator] = useState(false);
|
|
110
90
|
const comValueInit = useRef<any>(cell?.text);
|
|
91
|
+
const openTimerRef = useRef<any>();
|
|
111
92
|
useEffect(() => {
|
|
112
93
|
setComValue(cell?.text);
|
|
113
94
|
comValueInit.current = cell?.text;
|
|
@@ -115,9 +96,9 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
115
96
|
|
|
116
97
|
useEffect(() => {
|
|
117
98
|
// 处理下拉选项弹层失焦逻辑
|
|
118
|
-
function onClick() {
|
|
99
|
+
function onClick(e) {
|
|
119
100
|
if ((window as any).gridEditId != datatypeId) {
|
|
120
|
-
|
|
101
|
+
setEdit(false);
|
|
121
102
|
}
|
|
122
103
|
}
|
|
123
104
|
document.addEventListener("click", onClick);
|
|
@@ -126,65 +107,111 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
126
107
|
};
|
|
127
108
|
}, []);
|
|
128
109
|
|
|
129
|
-
|
|
110
|
+
/** 校验触发器 */
|
|
111
|
+
const onValidator = (val) => {
|
|
130
112
|
let flag = false;
|
|
131
113
|
let isVerify = false;
|
|
132
114
|
for (let it of cell?.validatorList || []) {
|
|
133
|
-
if (it?.pattern?.test(
|
|
115
|
+
if (it?.pattern?.test(val)) {
|
|
134
116
|
flag = true;
|
|
135
117
|
}
|
|
136
118
|
break;
|
|
137
119
|
}
|
|
138
|
-
isVerify = !flag && cell?.validatorList?.length > 0;
|
|
120
|
+
isVerify = !flag && Array.isArray(cell?.validatorList) && cell?.validatorList?.length > 0;
|
|
121
|
+
setIsValidator(isVerify);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (!open) return;
|
|
126
|
+
// 等下一帧,弹窗DOM渲染完成
|
|
127
|
+
const timer = setTimeout(() => {
|
|
128
|
+
const popup: any = document.querySelector(".ant-picker-dropdown");
|
|
129
|
+
if (!popup) return;
|
|
130
|
+
|
|
131
|
+
const stopPointer = (e: PointerEvent) => {
|
|
132
|
+
// 阻断事件往上冒泡到document
|
|
133
|
+
e.stopPropagation();
|
|
134
|
+
};
|
|
135
|
+
// 捕获阶段监听 pointerdown!!必须是pointerdown不是mousedown
|
|
136
|
+
popup.addEventListener("pointerdown", stopPointer, true);
|
|
137
|
+
|
|
138
|
+
// 清理函数
|
|
139
|
+
return () => {
|
|
140
|
+
popup.removeEventListener("pointerdown", stopPointer, true);
|
|
141
|
+
};
|
|
142
|
+
}, 0);
|
|
143
|
+
|
|
144
|
+
return () => clearTimeout(timer);
|
|
145
|
+
}, [open]);
|
|
146
|
+
|
|
147
|
+
/** 失焦提交 */
|
|
148
|
+
const onBlurSubmit = () => {
|
|
149
|
+
let targetValue = comValueInit.current;
|
|
150
|
+
onCellChanged(
|
|
151
|
+
this.getCompatibleCell({
|
|
152
|
+
...cell,
|
|
153
|
+
text: targetValue,
|
|
154
|
+
selectedValue: targetValue,
|
|
155
|
+
}),
|
|
156
|
+
true,
|
|
157
|
+
);
|
|
158
|
+
};
|
|
139
159
|
|
|
140
|
-
|
|
141
|
-
|
|
160
|
+
const dataPickerProps = useMemo(() => {
|
|
161
|
+
if (isTriggerBlur?.includes(cell?.type)) {
|
|
162
|
+
return {
|
|
163
|
+
open: open,
|
|
164
|
+
/** 兼容datapicker 闪烁问题 */
|
|
165
|
+
onOpenChange: (isOpen) => {
|
|
166
|
+
if (openTimerRef.current) {
|
|
167
|
+
clearTimeout(openTimerRef.current);
|
|
168
|
+
}
|
|
169
|
+
openTimerRef.current = setTimeout(() => {
|
|
170
|
+
setOpen(isOpen);
|
|
171
|
+
}, 80);
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return {};
|
|
176
|
+
}, [cell]);
|
|
177
|
+
/** 监听上传组件失焦回调 */
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (!edit && cell.type == "Upload" && (window as any).uploadEdit && (window as any).uploadEdit == datatypeId) {
|
|
180
|
+
(window as any).uploadEdit = null;
|
|
181
|
+
onBlurSubmit();
|
|
182
|
+
}
|
|
183
|
+
}, [edit, comValue]);
|
|
142
184
|
|
|
143
185
|
return (
|
|
144
186
|
<div
|
|
145
|
-
className="base-hoc"
|
|
187
|
+
className={`base-hoc ${edit ? "base-hoc-edit" : ""}`}
|
|
146
188
|
onDoubleClick={(e) => {
|
|
147
189
|
if (cell?.nonEditable) {
|
|
148
190
|
return;
|
|
149
191
|
}
|
|
150
|
-
|
|
192
|
+
if (cell.type === "Upload") {
|
|
193
|
+
(window as any).uploadEdit = datatypeId;
|
|
194
|
+
}
|
|
195
|
+
setEdit(true);
|
|
151
196
|
}}
|
|
152
197
|
>
|
|
153
198
|
<WrapComponent
|
|
199
|
+
onPointerDown={(e) => e.stopPropagation()}
|
|
154
200
|
componentProps={{
|
|
155
201
|
style: { width: "100%", display: "flex", alignItems: "center" },
|
|
156
202
|
value: comValue,
|
|
157
203
|
options: cell.values,
|
|
158
204
|
onChange: (e) => {
|
|
159
|
-
|
|
160
|
-
const targetValue = e?.target?.value ?? e;
|
|
205
|
+
let targetValue = e?.target?.value ?? e;
|
|
161
206
|
setComValue(targetValue);
|
|
162
207
|
comValueInit.current = targetValue;
|
|
163
|
-
|
|
164
|
-
onCellChanged(
|
|
165
|
-
this.getCompatibleCell({
|
|
166
|
-
...cell,
|
|
167
|
-
text: targetValue,
|
|
168
|
-
selectedValue: targetValue,
|
|
169
|
-
}),
|
|
170
|
-
true,
|
|
171
|
-
);
|
|
208
|
+
onValidator(targetValue);
|
|
172
209
|
},
|
|
173
210
|
onBlur: (e) => {
|
|
174
|
-
|
|
175
|
-
if (
|
|
176
|
-
|
|
211
|
+
onBlurSubmit();
|
|
212
|
+
if (!isTriggerBlur?.includes(cell?.type)) {
|
|
213
|
+
setEdit(false);
|
|
177
214
|
}
|
|
178
|
-
const targetValue = comValueInit.current;
|
|
179
|
-
onCellChanged(
|
|
180
|
-
this.getCompatibleCell({
|
|
181
|
-
...cell,
|
|
182
|
-
text: targetValue,
|
|
183
|
-
selectedValue: targetValue,
|
|
184
|
-
}),
|
|
185
|
-
true,
|
|
186
|
-
);
|
|
187
|
-
setIsOpen(false);
|
|
188
215
|
},
|
|
189
216
|
|
|
190
217
|
onPointerDown: (e) => {
|
|
@@ -193,9 +220,10 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
193
220
|
onKeyDown: (e) => {
|
|
194
221
|
if (isAlphaNumericKey(e.keyCode) || isNavigationKey(e.keyCode)) e.stopPropagation();
|
|
195
222
|
},
|
|
223
|
+
...dataPickerProps,
|
|
196
224
|
...((cell?.getField && cell?.getField()["x-component-props"]) || {}),
|
|
197
225
|
}}
|
|
198
|
-
pattern={
|
|
226
|
+
pattern={edit ? "" : "readPretty"}
|
|
199
227
|
cell={cell}
|
|
200
228
|
></WrapComponent>
|
|
201
229
|
{isValidator && (
|
|
@@ -12,3 +12,5 @@ export const childAntdComponent = {
|
|
|
12
12
|
"Input.TextArea": Input.TextArea,
|
|
13
13
|
"TimePicker.RangePicker": TimePicker.RangePicker,
|
|
14
14
|
}
|
|
15
|
+
export const isTriggerBlur = ["DatePicker", "DatePicker.MonthPicker", "DatePicker.QuarterPicker", "DatePicker.RangePicker", "DatePicker.TimePicker", "DatePicker.WeekPicker", "DatePicker.YearPicker", "TimePicker.RangePicker"];
|
|
16
|
+
|
package/src/index.less
CHANGED
|
@@ -18,6 +18,24 @@
|
|
|
18
18
|
display: flex;
|
|
19
19
|
align-items: center;
|
|
20
20
|
justify-content: center;
|
|
21
|
+
z-index: 2;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.rg-partial-area {
|
|
25
|
+
z-index: 3;
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.rg-cell {
|
|
30
|
+
padding: 0px !important;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.rg-cell-focus {
|
|
34
|
+
z-index: 2;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.rg-fill-handle {
|
|
38
|
+
z-index: 2;
|
|
21
39
|
}
|
|
22
40
|
}
|
|
23
41
|
|
|
@@ -27,6 +45,13 @@
|
|
|
27
45
|
display: flex;
|
|
28
46
|
align-items: center;
|
|
29
47
|
justify-content: center;
|
|
48
|
+
z-index: 1;
|
|
49
|
+
padding: 4px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.base-hoc-edit {
|
|
53
|
+
background-color: #fff;
|
|
54
|
+
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
.validator-icon {
|
|
@@ -46,4 +71,9 @@
|
|
|
46
71
|
display: flex;
|
|
47
72
|
align-items: center;
|
|
48
73
|
justify-content: center;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.rg-pane-left,
|
|
77
|
+
.rg-pane-right {
|
|
78
|
+
z-index: 10 !important;
|
|
49
79
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
1
|
+
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Checkbox, Empty, Spin } from "antd";
|
|
3
3
|
import { ReactGrid } from "@silevis/reactgrid";
|
|
4
|
-
import
|
|
4
|
+
import TextTemplate from "./Template/TextCellTemplate";
|
|
5
5
|
import { antdComponents, customComponents } from "@hzab/form-render/src/index";
|
|
6
6
|
import { WidthWrapHoc } from "./common/WidthWrapHoc";
|
|
7
|
-
import
|
|
7
|
+
import NumberTemplate from "./Template/NumberCellTemplate";
|
|
8
8
|
import { ExpandListTemplate } from "./Template/ExpandListTemplate";
|
|
9
9
|
import { convertColumnsToRows, flattenColumns, isReactElement } from "./common/utils";
|
|
10
10
|
import { childAntdComponent } from "./common/childAntdComponent";
|
|
@@ -33,7 +33,7 @@ interface CellEditTableProps {
|
|
|
33
33
|
onRow?: (v: any, ri: number, ci: number) => void;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
37
37
|
const {
|
|
38
38
|
columns,
|
|
39
39
|
dataSource,
|
|
@@ -57,16 +57,22 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
57
57
|
|
|
58
58
|
const [headerList, setHeaderList] = useState<any>([]);
|
|
59
59
|
const [rows, setRows] = useState<any>([]);
|
|
60
|
-
/** 初始行数据 */
|
|
61
60
|
const initRowsRef = useRef<any>([]);
|
|
62
|
-
|
|
61
|
+
/** 初始行数据 */
|
|
63
62
|
const [tableColumns, setTableColumns] = useState<any>([]);
|
|
64
63
|
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
|
|
65
64
|
const [newDataSource, setNewDataSource] = useState<any>([]);
|
|
66
65
|
const [expandKeys, setExpandKeys] = useState<any>([]);
|
|
67
66
|
const [headerCustomTemplate, setHeaderCustomTemplate] = useState<any>([]);
|
|
67
|
+
const [highlights, setHighlights] = useState([]);
|
|
68
68
|
const gridRef = useRef<any>();
|
|
69
|
+
const currentCell = useRef<any>();
|
|
69
70
|
|
|
71
|
+
useImperativeHandle(ref, () => {
|
|
72
|
+
return {
|
|
73
|
+
rows,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
70
76
|
/** 递归处理子节点数据 */
|
|
71
77
|
const handleDataSource = (arr, level = 0) => {
|
|
72
78
|
arr?.forEach((el) => {
|
|
@@ -92,6 +98,9 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
92
98
|
item?.cells?.forEach((el) => {
|
|
93
99
|
if (el?.columnId && !fieldList?.includes(el?.columnId)) {
|
|
94
100
|
obj[el?.columnId] = el?.text || el?.value || el?.selectedValue || "";
|
|
101
|
+
if (el?.type == "Number") {
|
|
102
|
+
obj[el?.columnId] = el?.value;
|
|
103
|
+
}
|
|
95
104
|
}
|
|
96
105
|
});
|
|
97
106
|
|
|
@@ -108,6 +117,7 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
108
117
|
type: "ExpandListTemplate",
|
|
109
118
|
width: 14,
|
|
110
119
|
key: "ExpandListTemplate",
|
|
120
|
+
nonEditable: true,
|
|
111
121
|
style: rowSelection?.style || {
|
|
112
122
|
background: "rgba(128, 128, 128, 0.1)",
|
|
113
123
|
},
|
|
@@ -116,6 +126,7 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
116
126
|
if (rowSelection) {
|
|
117
127
|
columns.unshift({
|
|
118
128
|
type: "rowSelection",
|
|
129
|
+
nonEditable: true,
|
|
119
130
|
width: rowSelection?.width || 30,
|
|
120
131
|
key: "rowSelection",
|
|
121
132
|
style: rowSelection?.style || {
|
|
@@ -192,7 +203,10 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
192
203
|
text: String(cellItem || ""),
|
|
193
204
|
value: cellItem,
|
|
194
205
|
selectedValue: cellItem || "",
|
|
195
|
-
style:
|
|
206
|
+
style:
|
|
207
|
+
columnsItem?.type == "rowSelection"
|
|
208
|
+
? { display: "flex", justifyContent: "center" }
|
|
209
|
+
: { color: cellItem == 0 ? "#CACDD7" : "" },
|
|
196
210
|
...((onRow && onRow(item, index, ind)) || {}),
|
|
197
211
|
...((columnsItem?.onCell && columnsItem?.onCell(item, index, ind)) || {}),
|
|
198
212
|
...(columnsItem?.cellProps || {}),
|
|
@@ -206,13 +220,17 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
206
220
|
}),
|
|
207
221
|
};
|
|
208
222
|
});
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
firstRender.current = false;
|
|
212
|
-
}
|
|
213
|
-
setRows([...headerList, ...tempDataSource]);
|
|
223
|
+
const mergerList = [...headerList, ...tempDataSource];
|
|
224
|
+
setRows(mergerList);
|
|
214
225
|
}, [newDataSource, tableColumns, headerList]);
|
|
215
|
-
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
if (loading) {
|
|
228
|
+
const item = rows?.find((el) => el?.rowId == currentCell.current?.rowId);
|
|
229
|
+
let newItem = item?.cells?.find((it) => it?.columnId == currentCell.current?.columnId);
|
|
230
|
+
newItem = { ...currentCell.current };
|
|
231
|
+
initRowsRef.current = rows;
|
|
232
|
+
}
|
|
233
|
+
}, [loading, rows]);
|
|
216
234
|
// 单元格编辑回调
|
|
217
235
|
const handleCellsChanged = async (changes) => {
|
|
218
236
|
const batchQuery: any = [];
|
|
@@ -225,11 +243,10 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
225
243
|
|
|
226
244
|
setRows((prevRows) => {
|
|
227
245
|
changes.forEach(async (change) => {
|
|
228
|
-
// const hasDiff = JSON.stringify( change?.newCell?.text) != JSON.stringify(change.previousCell?.text);
|
|
229
|
-
// if (hasDiff) return;
|
|
230
246
|
const changeRowIdx = prevRows.findIndex((el) => el.rowId == change.rowId);
|
|
231
247
|
const changeColumnIdx = tableColumns.findIndex((el) => el.columnId == change.columnId);
|
|
232
248
|
prevRows[changeRowIdx].cells[changeColumnIdx] = { ...change.newCell };
|
|
249
|
+
currentCell.current = { ...change.newCell };
|
|
233
250
|
batchQuery.push(handleArrayToObj(prevRows[changeRowIdx]));
|
|
234
251
|
if (formulaConfig) {
|
|
235
252
|
for (let key in formulaConfig) {
|
|
@@ -248,18 +265,15 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
248
265
|
prevRows[changeRowIdx].cells[resultColumnIdx] = newCell;
|
|
249
266
|
}
|
|
250
267
|
}
|
|
251
|
-
|
|
252
|
-
if (change?.newCell?.commit == "submit" && onEditSubmit && !isBatchSubmit) {
|
|
268
|
+
if (onEditSubmit && !isBatchSubmit) {
|
|
253
269
|
try {
|
|
254
270
|
await onEditSubmit(batchQuery);
|
|
255
271
|
} catch (err) {
|
|
256
272
|
getList && getList();
|
|
257
273
|
}
|
|
258
274
|
}
|
|
259
|
-
|
|
260
275
|
onChange && onChange(prevRows[changeRowIdx]);
|
|
261
276
|
});
|
|
262
|
-
initRowsRef.current = prevRows;
|
|
263
277
|
return [...prevRows];
|
|
264
278
|
});
|
|
265
279
|
|
|
@@ -271,6 +285,7 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
271
285
|
}
|
|
272
286
|
}
|
|
273
287
|
};
|
|
288
|
+
|
|
274
289
|
/** 自定义组件注册 */
|
|
275
290
|
const baseTemplate = useMemo(() => {
|
|
276
291
|
const mergeTemplate: any = { ...(antdComponents || {}), ...(customComponents || {}), ...childAntdComponent };
|
|
@@ -285,50 +300,64 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
285
300
|
}, [antdComponents, customComponents]);
|
|
286
301
|
|
|
287
302
|
const ActionDom = (props) => {
|
|
303
|
+
const rowData = rows?.find((el) => el?.rowId == props?.cell?.rowId);
|
|
288
304
|
return (
|
|
289
305
|
<div onPointerDown={(e) => e.stopPropagation()}>
|
|
290
|
-
{Slots?.tableActionsSlot && <Slots.tableActionsSlot {...props?.cell} />}
|
|
291
|
-
{Slots?.actionPrefixSlot && <Slots.actionPrefixSlot {...props?.cell} />}
|
|
292
|
-
{Slots?.actionCenterSlot && <Slots.actionCenterSlot {...props?.cell} />}
|
|
293
|
-
{Slots?.actionSuffixSlot && <Slots.actionSuffixSlot {...props?.cell} />}
|
|
306
|
+
{Slots?.tableActionsSlot && <Slots.tableActionsSlot {...props?.cell} rowData={rowData} />}
|
|
307
|
+
{Slots?.actionPrefixSlot && <Slots.actionPrefixSlot {...props?.cell} rowData={rowData} />}
|
|
308
|
+
{Slots?.actionCenterSlot && <Slots.actionCenterSlot {...props?.cell} rowData={rowData} />}
|
|
309
|
+
{Slots?.actionSuffixSlot && <Slots.actionSuffixSlot {...props?.cell} rowData={rowData} />}
|
|
294
310
|
</div>
|
|
295
311
|
);
|
|
296
312
|
};
|
|
297
|
-
|
|
313
|
+
function flattenDataSource(arr: any) {
|
|
314
|
+
const result: any = [];
|
|
315
|
+
function loop(list: any) {
|
|
316
|
+
for (const item of list) {
|
|
317
|
+
result.push(item);
|
|
318
|
+
if (item.children && item.children.length) {
|
|
319
|
+
loop(item.children);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
loop(arr);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
298
326
|
const CheckBoxDom = (props) => {
|
|
299
327
|
const { record, rowId } = props?.cell;
|
|
328
|
+
const newDataSource = flattenDataSource(dataSource);
|
|
300
329
|
return (
|
|
301
330
|
<Checkbox
|
|
302
331
|
{...props?.componentProps}
|
|
303
332
|
checked={
|
|
304
333
|
rowSelection?.selectedRowKeys?.includes((record && record[rowKey]) || "") ||
|
|
305
|
-
(rowSelection?.selectedRowKeys?.length ==
|
|
334
|
+
(rowSelection?.selectedRowKeys?.length == newDataSource?.length && newDataSource?.length > 0)
|
|
306
335
|
}
|
|
307
336
|
indeterminate={
|
|
308
337
|
!rowId &&
|
|
309
338
|
rowSelection?.selectedRowKeys?.length > 0 &&
|
|
310
|
-
rowSelection?.selectedRowKeys?.length <
|
|
339
|
+
rowSelection?.selectedRowKeys?.length < newDataSource?.length
|
|
311
340
|
}
|
|
312
341
|
onChange={(e) => {
|
|
313
342
|
if (e.target.checked && rowId) {
|
|
314
343
|
const newSelectedRowKeys = [...rowSelection?.selectedRowKeys, record[rowKey]];
|
|
315
|
-
const rows =
|
|
344
|
+
const rows = newDataSource?.filter((el) => newSelectedRowKeys?.includes(el[rowKey]));
|
|
316
345
|
|
|
317
346
|
rowSelection?.onChange(newSelectedRowKeys, rows);
|
|
318
347
|
} else if (!e.target.checked && rowId) {
|
|
319
348
|
const newSelectedRowKeys = rowSelection?.selectedRowKeys?.filter((el) => el != record[rowKey]);
|
|
320
|
-
const rows =
|
|
349
|
+
const rows = newDataSource?.filter((el) => newSelectedRowKeys?.includes(el[rowKey]));
|
|
321
350
|
|
|
322
351
|
rowSelection?.onChange(
|
|
323
352
|
rowSelection?.selectedRowKeys?.filter((el) => el != record[rowKey]),
|
|
324
353
|
rows,
|
|
325
354
|
);
|
|
326
355
|
} else if (e.target.checked && !rowId) {
|
|
327
|
-
const newSelectedRowKeys =
|
|
328
|
-
const rows =
|
|
356
|
+
const newSelectedRowKeys = newDataSource?.map((el) => el[rowKey]);
|
|
357
|
+
const rows = newDataSource?.filter((el) => newSelectedRowKeys?.includes(el[rowKey]));
|
|
329
358
|
|
|
330
359
|
rowSelection?.onChange(
|
|
331
|
-
|
|
360
|
+
newDataSource?.map((el) => el[rowKey]),
|
|
332
361
|
rows,
|
|
333
362
|
);
|
|
334
363
|
} else if (!e.target.checked && !rowId) {
|
|
@@ -340,7 +369,8 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
340
369
|
};
|
|
341
370
|
useEffect(() => {
|
|
342
371
|
if (rowSelection) {
|
|
343
|
-
const
|
|
372
|
+
const newDataSource = flattenDataSource(dataSource);
|
|
373
|
+
const rows = newDataSource?.filter((el) => selectedRowKeys?.includes(el[rowKey]));
|
|
344
374
|
rowSelection?.onChange(selectedRowKeys, rows);
|
|
345
375
|
}
|
|
346
376
|
}, [selectedRowKeys, dataSource]);
|
|
@@ -357,6 +387,19 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
357
387
|
return templatesObj;
|
|
358
388
|
}, [reactGridProps?.customCellTemplates]);
|
|
359
389
|
|
|
390
|
+
/** 选中高亮整行 */
|
|
391
|
+
const onHightsRow = (cell: any, rows: any) => {
|
|
392
|
+
const list = rows
|
|
393
|
+
?.find((el) => el?.rowId == cell?.rowId)
|
|
394
|
+
?.cells?.map((item) => ({
|
|
395
|
+
columnId: item?.columnId,
|
|
396
|
+
rowId: cell?.rowId,
|
|
397
|
+
className: "custom-highlights-row",
|
|
398
|
+
borderColor: "transparent",
|
|
399
|
+
}));
|
|
400
|
+
setHighlights(list);
|
|
401
|
+
};
|
|
402
|
+
|
|
360
403
|
return (
|
|
361
404
|
<Spin spinning={loading}>
|
|
362
405
|
<div className={`grid-container ${className}`} style={reactGridStyle}>
|
|
@@ -370,15 +413,23 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
370
413
|
enableRangeSelection={true}
|
|
371
414
|
horizontalStickyBreakpoint={120}
|
|
372
415
|
{...reactGridProps}
|
|
416
|
+
highlights={reactGridProps?.highlights ?? highlights}
|
|
373
417
|
onFocusLocationChanging={(cell: any) => {
|
|
374
418
|
const datatypeId = cell?.columnId + cell?.rowId;
|
|
375
419
|
(window as any).gridEditId = datatypeId;
|
|
376
420
|
if (["_$actions", "rowSelection", "ExpandListTemplate"]?.includes(cell?.columnId)) {
|
|
377
421
|
return false;
|
|
378
422
|
}
|
|
423
|
+
if (typeof cell?.rowId == "string" && cell?.rowId?.indexOf("header-") > -1) {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
if (reactGridProps?.isRowHighlights && cell?.columnId) {
|
|
427
|
+
onHightsRow(cell, rows);
|
|
428
|
+
}
|
|
379
429
|
if (reactGridProps?.onFocusLocationChanging) {
|
|
380
430
|
return reactGridProps?.onFocusLocationChanging(cell, rows);
|
|
381
431
|
}
|
|
432
|
+
|
|
382
433
|
return cell;
|
|
383
434
|
}}
|
|
384
435
|
customCellTemplates={{
|
|
@@ -388,8 +439,8 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
388
439
|
...headerCustomTemplate,
|
|
389
440
|
_$actions: WidthWrapHoc(ActionDom),
|
|
390
441
|
rowSelection: WidthWrapHoc(CheckBoxDom),
|
|
391
|
-
Input: TextTemplate,
|
|
392
|
-
Number: NumberTemplate,
|
|
442
|
+
Input: WidthWrapHoc(TextTemplate),
|
|
443
|
+
Number: WidthWrapHoc(NumberTemplate),
|
|
393
444
|
}}
|
|
394
445
|
/>
|
|
395
446
|
{dataSource?.length <= 0 && (
|
|
@@ -401,3 +452,5 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
401
452
|
</Spin>
|
|
402
453
|
);
|
|
403
454
|
}
|
|
455
|
+
|
|
456
|
+
export default forwardRef(CellEditTable);
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Cell,
|
|
3
|
-
CellTemplate,
|
|
4
|
-
Compatible,
|
|
5
|
-
getCellProperty,
|
|
6
|
-
getCharFromKey,
|
|
7
|
-
inNumericKey,
|
|
8
|
-
isAllowedOnNumberTypingKey,
|
|
9
|
-
isCharAllowedOnNumberInput,
|
|
10
|
-
isFunctionKey,
|
|
11
|
-
isNavigationKey,
|
|
12
|
-
isNumpadNumericKey,
|
|
13
|
-
keyCodes,
|
|
14
|
-
Uncertain,
|
|
15
|
-
UncertainCompatible,
|
|
16
|
-
} from "@silevis/reactgrid";
|
|
17
|
-
import * as React from "react";
|
|
18
|
-
import { parseLocaleNumber } from "../common/utils";
|
|
19
|
-
|
|
20
|
-
// NOTE: all modules imported below may be imported from '@silevis/reactgrid'
|
|
21
|
-
|
|
22
|
-
export interface NumberCell extends Cell {
|
|
23
|
-
type: "number";
|
|
24
|
-
value: number;
|
|
25
|
-
format?: Intl.NumberFormat;
|
|
26
|
-
validator?: (value: number) => boolean;
|
|
27
|
-
nanToZero?: boolean;
|
|
28
|
-
hideZero?: boolean;
|
|
29
|
-
errorMessage?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export class NumberCellTemplate implements CellTemplate<NumberCell> {
|
|
33
|
-
private wasEscKeyPressed = false;
|
|
34
|
-
|
|
35
|
-
getCompatibleCell(uncertainCell: Uncertain<NumberCell>): Compatible<NumberCell> {
|
|
36
|
-
let value: number;
|
|
37
|
-
try {
|
|
38
|
-
value = getCellProperty(uncertainCell, "value", "number");
|
|
39
|
-
} catch (error) {
|
|
40
|
-
value = NaN;
|
|
41
|
-
}
|
|
42
|
-
const numberFormat = uncertainCell.format || new Intl.NumberFormat(window.navigator.language);
|
|
43
|
-
const displayValue = uncertainCell.nanToZero && Number.isNaN(value) ? 0 : value;
|
|
44
|
-
const text =
|
|
45
|
-
Number.isNaN(displayValue) || (uncertainCell.hideZero && displayValue === 0)
|
|
46
|
-
? ""
|
|
47
|
-
: numberFormat.format(displayValue);
|
|
48
|
-
return { ...uncertainCell, value: displayValue, text };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
handleKeyDown(
|
|
52
|
-
cell: Compatible<NumberCell>,
|
|
53
|
-
keyCode: number,
|
|
54
|
-
ctrl: boolean,
|
|
55
|
-
shift: boolean,
|
|
56
|
-
alt: boolean,
|
|
57
|
-
key: string,
|
|
58
|
-
capsLock: boolean,
|
|
59
|
-
): { cell: Compatible<NumberCell>; enableEditMode: boolean } {
|
|
60
|
-
if (isNumpadNumericKey(keyCode)) keyCode -= 48;
|
|
61
|
-
if (isFunctionKey(keyCode)) {
|
|
62
|
-
if (keyCode === keyCodes.F2) return { cell, enableEditMode: true };
|
|
63
|
-
return { cell, enableEditMode: false };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const char = getCharFromKey(key);
|
|
67
|
-
|
|
68
|
-
if (!ctrl && isCharAllowedOnNumberInput(char)) {
|
|
69
|
-
const value = Number(char);
|
|
70
|
-
|
|
71
|
-
if (Number.isNaN(value) && isCharAllowedOnNumberInput(char))
|
|
72
|
-
return { cell: { ...this.getCompatibleCell({ ...cell, value }), text: char }, enableEditMode: true };
|
|
73
|
-
return { cell: this.getCompatibleCell({ ...cell, value }), enableEditMode: true };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
cell,
|
|
78
|
-
enableEditMode: keyCode === keyCodes.POINTER || keyCode === keyCodes.ENTER,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
update(cell: Compatible<NumberCell>, cellToMerge: UncertainCompatible<NumberCell>): Compatible<NumberCell> {
|
|
83
|
-
return this.getCompatibleCell({ ...cell, value: cellToMerge.value });
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
private getTextFromCharCode = (cellText: string): string => {
|
|
87
|
-
switch (cellText.charCodeAt(0)) {
|
|
88
|
-
case keyCodes.DASH:
|
|
89
|
-
case keyCodes.FIREFOX_DASH:
|
|
90
|
-
case keyCodes.SUBTRACT:
|
|
91
|
-
return "-";
|
|
92
|
-
case keyCodes.COMMA:
|
|
93
|
-
return ",";
|
|
94
|
-
case keyCodes.PERIOD:
|
|
95
|
-
case keyCodes.DECIMAL:
|
|
96
|
-
return ".";
|
|
97
|
-
default:
|
|
98
|
-
return cellText;
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
getClassName(cell: Compatible<NumberCell>, isInEditMode: boolean): string {
|
|
103
|
-
const isValid = cell.validator?.(cell.value) ?? true;
|
|
104
|
-
const className = cell.className || "";
|
|
105
|
-
return `${!isValid ? "rg-invalid" : ""} ${className}`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
render(
|
|
109
|
-
cell: Compatible<NumberCell>,
|
|
110
|
-
isInEditMode: boolean,
|
|
111
|
-
onCellChanged: (cell: Compatible<NumberCell>, commit: boolean) => void,
|
|
112
|
-
): React.ReactNode {
|
|
113
|
-
if (!isInEditMode) {
|
|
114
|
-
const isValid = cell.validator?.(cell.value) ?? true;
|
|
115
|
-
const textToDisplay = !isValid && cell.errorMessage ? cell.errorMessage : cell.text;
|
|
116
|
-
return textToDisplay;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const locale = cell.format ? cell.format.resolvedOptions().locale : window.navigator.languages[0];
|
|
120
|
-
const format = new Intl.NumberFormat(locale, { useGrouping: false, maximumFractionDigits: 20 });
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<input
|
|
124
|
-
className="rg-input"
|
|
125
|
-
inputMode="decimal"
|
|
126
|
-
ref={(input) => {
|
|
127
|
-
if (input) {
|
|
128
|
-
input.focus();
|
|
129
|
-
input.setSelectionRange(input.value.length, input.value.length);
|
|
130
|
-
}
|
|
131
|
-
}}
|
|
132
|
-
defaultValue={Number.isNaN(cell.value) ? this.getTextFromCharCode(cell.text) : format.format(cell.value)}
|
|
133
|
-
onChange={(e) =>
|
|
134
|
-
onCellChanged(this.getCompatibleCell({ ...cell, value: parseLocaleNumber(e.currentTarget.value) }), false)
|
|
135
|
-
}
|
|
136
|
-
onBlur={(e) => {
|
|
137
|
-
onCellChanged(
|
|
138
|
-
this.getCompatibleCell({ ...cell, value: parseLocaleNumber(e.currentTarget.value) }),
|
|
139
|
-
!this.wasEscKeyPressed,
|
|
140
|
-
);
|
|
141
|
-
this.wasEscKeyPressed = false;
|
|
142
|
-
}}
|
|
143
|
-
onKeyDown={(e) => {
|
|
144
|
-
if (
|
|
145
|
-
inNumericKey(e.keyCode) ||
|
|
146
|
-
isNavigationKey(e.keyCode) ||
|
|
147
|
-
isAllowedOnNumberTypingKey(e.keyCode) ||
|
|
148
|
-
((e.ctrlKey || e.metaKey) && e.keyCode === keyCodes.KEY_A)
|
|
149
|
-
)
|
|
150
|
-
e.stopPropagation();
|
|
151
|
-
if (
|
|
152
|
-
!inNumericKey(e.keyCode) &&
|
|
153
|
-
!isNavigationKey(e.keyCode) &&
|
|
154
|
-
!isCharAllowedOnNumberInput(getCharFromKey(e.key))
|
|
155
|
-
)
|
|
156
|
-
e.preventDefault();
|
|
157
|
-
if (e.keyCode === keyCodes.ESCAPE) this.wasEscKeyPressed = true;
|
|
158
|
-
}}
|
|
159
|
-
onCopy={(e) => e.stopPropagation()}
|
|
160
|
-
onCut={(e) => e.stopPropagation()}
|
|
161
|
-
onPaste={(e) => e.stopPropagation()}
|
|
162
|
-
onPointerDown={(e) => e.stopPropagation()}
|
|
163
|
-
/>
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export const NumberTemplate = new NumberCellTemplate();
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Cell,
|
|
3
|
-
CellTemplate,
|
|
4
|
-
Compatible,
|
|
5
|
-
getCellProperty,
|
|
6
|
-
getCharFromKey,
|
|
7
|
-
isAlphaNumericKey,
|
|
8
|
-
isFunctionKey,
|
|
9
|
-
keyCodes,
|
|
10
|
-
Uncertain,
|
|
11
|
-
UncertainCompatible,
|
|
12
|
-
} from "@silevis/reactgrid";
|
|
13
|
-
import * as React from "react";
|
|
14
|
-
|
|
15
|
-
export interface TextCell extends Cell {
|
|
16
|
-
type: "Input";
|
|
17
|
-
text: string;
|
|
18
|
-
placeholder?: string;
|
|
19
|
-
validator?: (text: string) => boolean;
|
|
20
|
-
renderer?: (text: string) => React.ReactNode;
|
|
21
|
-
errorMessage?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export class TextCellTemplate implements CellTemplate<TextCell> {
|
|
25
|
-
private wasEscKeyPressed = false;
|
|
26
|
-
|
|
27
|
-
getCompatibleCell(uncertainCell: Uncertain<TextCell>): Compatible<TextCell> {
|
|
28
|
-
const text = getCellProperty(uncertainCell, "text", "string");
|
|
29
|
-
let placeholder: string | undefined;
|
|
30
|
-
try {
|
|
31
|
-
placeholder = getCellProperty(uncertainCell, "placeholder", "string");
|
|
32
|
-
} catch {
|
|
33
|
-
placeholder = "";
|
|
34
|
-
}
|
|
35
|
-
const value = parseFloat(text); // TODO more advanced parsing for all text based cells
|
|
36
|
-
return { ...uncertainCell, text, value, placeholder };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
update(cell: Compatible<TextCell>, cellToMerge: UncertainCompatible<TextCell>): Compatible<TextCell> {
|
|
40
|
-
return this.getCompatibleCell({ ...cell, text: cellToMerge.text, placeholder: cellToMerge.placeholder });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
handleKeyDown(
|
|
44
|
-
cell: Compatible<TextCell>,
|
|
45
|
-
keyCode: number,
|
|
46
|
-
ctrl: boolean,
|
|
47
|
-
shift: boolean,
|
|
48
|
-
alt: boolean,
|
|
49
|
-
key: string,
|
|
50
|
-
capsLock: boolean,
|
|
51
|
-
): { cell: Compatible<TextCell>; enableEditMode: boolean } {
|
|
52
|
-
if (isFunctionKey(keyCode)) {
|
|
53
|
-
if (keyCode === keyCodes.F2) return { cell, enableEditMode: true };
|
|
54
|
-
return { cell, enableEditMode: false };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const char = getCharFromKey(key, shift, capsLock);
|
|
58
|
-
|
|
59
|
-
if (!ctrl && !alt && isAlphaNumericKey(keyCode) && !(shift && keyCode === keyCodes.SPACE))
|
|
60
|
-
return { cell: this.getCompatibleCell({ ...cell, text: char }), enableEditMode: true };
|
|
61
|
-
return {
|
|
62
|
-
cell,
|
|
63
|
-
enableEditMode: keyCode === keyCodes.POINTER || keyCode === keyCodes.ENTER,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
handleCompositionEnd(
|
|
68
|
-
cell: Compatible<TextCell>,
|
|
69
|
-
eventData: any,
|
|
70
|
-
): { cell: Compatible<TextCell>; enableEditMode: boolean } {
|
|
71
|
-
return { cell: { ...cell, text: eventData }, enableEditMode: true };
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
getClassName(cell: Compatible<TextCell>, isInEditMode: boolean): string {
|
|
75
|
-
const isValid = cell.validator ? cell.validator(cell.text) : true;
|
|
76
|
-
const className = cell.className ? cell.className : "";
|
|
77
|
-
return `${isValid ? "valid" : "rg-invalid"} ${
|
|
78
|
-
cell.placeholder && cell.text === "" ? "placeholder" : ""
|
|
79
|
-
} ${className}`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
render(
|
|
83
|
-
cell: Compatible<TextCell>,
|
|
84
|
-
isInEditMode: boolean,
|
|
85
|
-
onCellChanged: (cell: Compatible<TextCell>, commit: boolean) => void,
|
|
86
|
-
): React.ReactNode {
|
|
87
|
-
if (!isInEditMode) {
|
|
88
|
-
const isValid = cell.validator ? cell.validator(cell.text) : true;
|
|
89
|
-
const cellText = cell.text || cell.placeholder || "";
|
|
90
|
-
const textToDisplay = !isValid && cell.errorMessage ? cell.errorMessage : cellText;
|
|
91
|
-
return cell.renderer ? cell.renderer(textToDisplay) : textToDisplay;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<input
|
|
96
|
-
className="rg-input"
|
|
97
|
-
ref={(input) => {
|
|
98
|
-
if (input) {
|
|
99
|
-
input.focus();
|
|
100
|
-
// input.setSelectionRange(input.value.length, input.value.length);
|
|
101
|
-
}
|
|
102
|
-
}}
|
|
103
|
-
defaultValue={cell.text}
|
|
104
|
-
onChange={(e) => onCellChanged(this.getCompatibleCell({ ...cell, text: e.currentTarget.value }), false)}
|
|
105
|
-
onBlur={(e) => {
|
|
106
|
-
onCellChanged(this.getCompatibleCell({ ...cell, text: e.currentTarget.value }), !this.wasEscKeyPressed);
|
|
107
|
-
this.wasEscKeyPressed = false;
|
|
108
|
-
}}
|
|
109
|
-
onCopy={(e) => e.stopPropagation()}
|
|
110
|
-
onCut={(e) => e.stopPropagation()}
|
|
111
|
-
onPaste={(e) => e.stopPropagation()}
|
|
112
|
-
onPointerDown={(e) => e.stopPropagation()}
|
|
113
|
-
placeholder={cell.placeholder}
|
|
114
|
-
onKeyDown={(e) => {
|
|
115
|
-
// if (isAlphaNumericKey(e.keyCode) || isNavigationKey(e.keyCode)) e.stopPropagation();
|
|
116
|
-
// if (e.keyCode === keyCodes.ESCAPE) this.wasEscKeyPressed = true;
|
|
117
|
-
}}
|
|
118
|
-
/>
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export const TextTemplate = new TextCellTemplate();
|