@hzab/edit-table 0.1.2 → 0.1.3-alpha.1
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 +4 -0
- package/package.json +6 -4
- package/src/Template/GetBaseTemplate.tsx +6 -1
- package/src/Template/NumberCellTemplate/index.less +5 -0
- package/src/Template/NumberCellTemplate/index.tsx +16 -0
- package/src/Template/TextCellTemplate/index.less +5 -0
- package/src/Template/TextCellTemplate/index.tsx +8 -0
- package/src/common/WidthWrapHoc.tsx +91 -62
- package/src/common/childAntdComponent.ts +2 -0
- package/src/index.less +55 -0
- package/src/index.tsx +72 -26
- 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.1",
|
|
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"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
import { getVal } from "@hzab/list-render/src/common/utils";
|
|
3
3
|
export const GetBaseTemplate = (props) => {
|
|
4
|
-
const { pattern, cell, componentProps, Com } = props;
|
|
4
|
+
const { pattern, cell, componentProps, Com, cellRender } = props;
|
|
5
5
|
|
|
6
6
|
const echoValue = useMemo(() => {
|
|
7
7
|
if (!cell?.getField) {
|
|
@@ -12,6 +12,11 @@ export const GetBaseTemplate = (props) => {
|
|
|
12
12
|
{ [cell?.getField && cell?.getField().name]: cell.text },
|
|
13
13
|
);
|
|
14
14
|
}, [cell]);
|
|
15
|
+
if (cellRender && cellRender(props)) {
|
|
16
|
+
const Slot = cellRender;
|
|
17
|
+
return <Slot {...props}></Slot>;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
return (
|
|
16
21
|
<div className="base-hoc">
|
|
17
22
|
{pattern == "readPretty" ? (
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Input } from "antd";
|
|
2
|
+
import { GetBaseTemplate } from "../GetBaseTemplate";
|
|
3
|
+
import "./index.less";
|
|
4
|
+
const NumberCellTemplate = (props: any) => {
|
|
5
|
+
return (
|
|
6
|
+
<GetBaseTemplate
|
|
7
|
+
{...props}
|
|
8
|
+
componentProps={{
|
|
9
|
+
...props?.componentProps,
|
|
10
|
+
type: "number",
|
|
11
|
+
}}
|
|
12
|
+
Com={Input}
|
|
13
|
+
></GetBaseTemplate>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
export default NumberCellTemplate;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Input } from "antd";
|
|
2
|
+
import { GetBaseTemplate } from "../GetBaseTemplate";
|
|
3
|
+
import "./index.less";
|
|
4
|
+
|
|
5
|
+
const TextCellTemplate = (props: any) => {
|
|
6
|
+
return <GetBaseTemplate {...props} Com={Input}></GetBaseTemplate>;
|
|
7
|
+
};
|
|
8
|
+
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;
|
|
@@ -34,45 +33,25 @@ interface DIProps {
|
|
|
34
33
|
isInEditMode?: boolean;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
export const WidthWrapHoc = (WrapComponent: any) => {
|
|
36
|
+
export const WidthWrapHoc = (WrapComponent: any, props = {}) => {
|
|
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,112 @@ 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
|
+
{...props}
|
|
200
|
+
onPointerDown={(e) => e.stopPropagation()}
|
|
154
201
|
componentProps={{
|
|
155
202
|
style: { width: "100%", display: "flex", alignItems: "center" },
|
|
156
203
|
value: comValue,
|
|
157
204
|
options: cell.values,
|
|
158
205
|
onChange: (e) => {
|
|
159
|
-
|
|
160
|
-
const targetValue = e?.target?.value ?? e;
|
|
206
|
+
let targetValue = e?.target?.value ?? e;
|
|
161
207
|
setComValue(targetValue);
|
|
162
208
|
comValueInit.current = targetValue;
|
|
163
|
-
|
|
164
|
-
onCellChanged(
|
|
165
|
-
this.getCompatibleCell({
|
|
166
|
-
...cell,
|
|
167
|
-
text: targetValue,
|
|
168
|
-
selectedValue: targetValue,
|
|
169
|
-
}),
|
|
170
|
-
true,
|
|
171
|
-
);
|
|
209
|
+
onValidator(targetValue);
|
|
172
210
|
},
|
|
173
211
|
onBlur: (e) => {
|
|
174
|
-
|
|
175
|
-
if (
|
|
176
|
-
|
|
212
|
+
onBlurSubmit();
|
|
213
|
+
if (!isTriggerBlur?.includes(cell?.type)) {
|
|
214
|
+
setEdit(false);
|
|
177
215
|
}
|
|
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
216
|
},
|
|
189
217
|
|
|
190
218
|
onPointerDown: (e) => {
|
|
@@ -193,9 +221,10 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
193
221
|
onKeyDown: (e) => {
|
|
194
222
|
if (isAlphaNumericKey(e.keyCode) || isNavigationKey(e.keyCode)) e.stopPropagation();
|
|
195
223
|
},
|
|
224
|
+
...dataPickerProps,
|
|
196
225
|
...((cell?.getField && cell?.getField()["x-component-props"]) || {}),
|
|
197
226
|
}}
|
|
198
|
-
pattern={
|
|
227
|
+
pattern={edit ? "" : "readPretty"}
|
|
199
228
|
cell={cell}
|
|
200
229
|
></WrapComponent>
|
|
201
230
|
{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
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
max-height: 100vh;
|
|
5
5
|
padding-bottom: 16px;
|
|
6
6
|
|
|
7
|
+
.ant-input-affix-wrapper-focused,
|
|
8
|
+
.ant-input-affix-wrapper:focus {
|
|
9
|
+
box-shadow: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.rg-input {
|
|
13
|
+
border: none;
|
|
14
|
+
}
|
|
7
15
|
|
|
8
16
|
|
|
9
17
|
|
|
@@ -18,6 +26,28 @@
|
|
|
18
26
|
display: flex;
|
|
19
27
|
align-items: center;
|
|
20
28
|
justify-content: center;
|
|
29
|
+
z-index: 2;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// .rg-header-cell {
|
|
33
|
+
// z-index: 99;
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
.rg-partial-area {
|
|
37
|
+
z-index: 3;
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.rg-cell {
|
|
42
|
+
padding: 0px !important;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.rg-cell-focus {
|
|
46
|
+
z-index: 2;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.rg-fill-handle {
|
|
50
|
+
z-index: 2;
|
|
21
51
|
}
|
|
22
52
|
}
|
|
23
53
|
|
|
@@ -27,6 +57,13 @@
|
|
|
27
57
|
display: flex;
|
|
28
58
|
align-items: center;
|
|
29
59
|
justify-content: center;
|
|
60
|
+
z-index: 1;
|
|
61
|
+
padding: 4px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.base-hoc-edit {
|
|
65
|
+
background-color: #fff;
|
|
66
|
+
|
|
30
67
|
}
|
|
31
68
|
|
|
32
69
|
.validator-icon {
|
|
@@ -46,4 +83,22 @@
|
|
|
46
83
|
display: flex;
|
|
47
84
|
align-items: center;
|
|
48
85
|
justify-content: center;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.rg-pane-left,
|
|
89
|
+
.rg-pane-right {
|
|
90
|
+
z-index: 10 !important;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.custom-highlights-row {
|
|
94
|
+
background: #E9F8FF;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.rg-pane-top {
|
|
98
|
+
z-index: 9 !important;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.shadow-top-left-corner,
|
|
102
|
+
.shadow-top-right-corner {
|
|
103
|
+
z-index: 11 !important;
|
|
49
104
|
}
|
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,24 @@ 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
|
+
const highlightsRowIdRef = useRef();
|
|
69
|
+
|
|
68
70
|
const gridRef = useRef<any>();
|
|
71
|
+
const currentCell = useRef<any>();
|
|
69
72
|
|
|
73
|
+
useImperativeHandle(ref, () => {
|
|
74
|
+
return {
|
|
75
|
+
rows,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
70
78
|
/** 递归处理子节点数据 */
|
|
71
79
|
const handleDataSource = (arr, level = 0) => {
|
|
72
80
|
arr?.forEach((el) => {
|
|
@@ -82,6 +90,14 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
82
90
|
setNewDataSource(dataSource);
|
|
83
91
|
}, [dataSource]);
|
|
84
92
|
|
|
93
|
+
/** 判断当前选中行是否还存在 */
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
const validRowIds = rows.map((r) => r.rowId);
|
|
96
|
+
if (!validRowIds?.includes(highlightsRowIdRef.current)) {
|
|
97
|
+
setHighlights([]);
|
|
98
|
+
}
|
|
99
|
+
}, [rows]);
|
|
100
|
+
|
|
85
101
|
/**将数组转为对象 */
|
|
86
102
|
const handleArrayToObj = (item) => {
|
|
87
103
|
const record = item?.cells?.[0]?.record;
|
|
@@ -92,6 +108,9 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
92
108
|
item?.cells?.forEach((el) => {
|
|
93
109
|
if (el?.columnId && !fieldList?.includes(el?.columnId)) {
|
|
94
110
|
obj[el?.columnId] = el?.text || el?.value || el?.selectedValue || "";
|
|
111
|
+
if (el?.type == "Number") {
|
|
112
|
+
obj[el?.columnId] = el?.value;
|
|
113
|
+
}
|
|
95
114
|
}
|
|
96
115
|
});
|
|
97
116
|
|
|
@@ -108,6 +127,7 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
108
127
|
type: "ExpandListTemplate",
|
|
109
128
|
width: 14,
|
|
110
129
|
key: "ExpandListTemplate",
|
|
130
|
+
nonEditable: true,
|
|
111
131
|
style: rowSelection?.style || {
|
|
112
132
|
background: "rgba(128, 128, 128, 0.1)",
|
|
113
133
|
},
|
|
@@ -116,6 +136,7 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
116
136
|
if (rowSelection) {
|
|
117
137
|
columns.unshift({
|
|
118
138
|
type: "rowSelection",
|
|
139
|
+
nonEditable: true,
|
|
119
140
|
width: rowSelection?.width || 30,
|
|
120
141
|
key: "rowSelection",
|
|
121
142
|
style: rowSelection?.style || {
|
|
@@ -207,13 +228,16 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
207
228
|
};
|
|
208
229
|
});
|
|
209
230
|
const mergerList = [...headerList, ...tempDataSource];
|
|
210
|
-
if (firstRender.current && tempDataSource?.length > 0) {
|
|
211
|
-
initRowsRef.current = mergerList;
|
|
212
|
-
firstRender.current = false;
|
|
213
|
-
}
|
|
214
231
|
setRows(mergerList);
|
|
215
232
|
}, [newDataSource, tableColumns, headerList]);
|
|
216
|
-
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
if (loading) {
|
|
235
|
+
const item = rows?.find((el) => el?.rowId == currentCell.current?.rowId);
|
|
236
|
+
let newItem = item?.cells?.find((it) => it?.columnId == currentCell.current?.columnId);
|
|
237
|
+
newItem = { ...currentCell.current };
|
|
238
|
+
initRowsRef.current = rows;
|
|
239
|
+
}
|
|
240
|
+
}, [loading, rows]);
|
|
217
241
|
// 单元格编辑回调
|
|
218
242
|
const handleCellsChanged = async (changes) => {
|
|
219
243
|
const batchQuery: any = [];
|
|
@@ -226,11 +250,10 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
226
250
|
|
|
227
251
|
setRows((prevRows) => {
|
|
228
252
|
changes.forEach(async (change) => {
|
|
229
|
-
// const hasDiff = JSON.stringify( change?.newCell?.text) != JSON.stringify(change.previousCell?.text);
|
|
230
|
-
// if (hasDiff) return;
|
|
231
253
|
const changeRowIdx = prevRows.findIndex((el) => el.rowId == change.rowId);
|
|
232
254
|
const changeColumnIdx = tableColumns.findIndex((el) => el.columnId == change.columnId);
|
|
233
255
|
prevRows[changeRowIdx].cells[changeColumnIdx] = { ...change.newCell };
|
|
256
|
+
currentCell.current = { ...change.newCell };
|
|
234
257
|
batchQuery.push(handleArrayToObj(prevRows[changeRowIdx]));
|
|
235
258
|
if (formulaConfig) {
|
|
236
259
|
for (let key in formulaConfig) {
|
|
@@ -249,18 +272,15 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
249
272
|
prevRows[changeRowIdx].cells[resultColumnIdx] = newCell;
|
|
250
273
|
}
|
|
251
274
|
}
|
|
252
|
-
|
|
253
|
-
if (change?.newCell?.commit == "submit" && onEditSubmit && !isBatchSubmit) {
|
|
275
|
+
if (onEditSubmit && !isBatchSubmit) {
|
|
254
276
|
try {
|
|
255
277
|
await onEditSubmit(batchQuery);
|
|
256
278
|
} catch (err) {
|
|
257
279
|
getList && getList();
|
|
258
280
|
}
|
|
259
281
|
}
|
|
260
|
-
|
|
261
282
|
onChange && onChange(prevRows[changeRowIdx]);
|
|
262
283
|
});
|
|
263
|
-
initRowsRef.current = prevRows;
|
|
264
284
|
return [...prevRows];
|
|
265
285
|
});
|
|
266
286
|
|
|
@@ -272,13 +292,14 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
272
292
|
}
|
|
273
293
|
}
|
|
274
294
|
};
|
|
295
|
+
|
|
275
296
|
/** 自定义组件注册 */
|
|
276
297
|
const baseTemplate = useMemo(() => {
|
|
277
298
|
const mergeTemplate: any = { ...(antdComponents || {}), ...(customComponents || {}), ...childAntdComponent };
|
|
278
299
|
const newMergeTemplate: any = {};
|
|
279
300
|
for (let key in mergeTemplate) {
|
|
280
|
-
const NewCom = (
|
|
281
|
-
return <GetBaseTemplate {...props} Com={mergeTemplate[key]} />;
|
|
301
|
+
const NewCom = (newComProps) => {
|
|
302
|
+
return <GetBaseTemplate {...newComProps} {...props} Com={mergeTemplate[key]} />;
|
|
282
303
|
};
|
|
283
304
|
newMergeTemplate[key] = WidthWrapHoc(NewCom);
|
|
284
305
|
}
|
|
@@ -286,12 +307,13 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
286
307
|
}, [antdComponents, customComponents]);
|
|
287
308
|
|
|
288
309
|
const ActionDom = (props) => {
|
|
310
|
+
const rowData = rows?.find((el) => el?.rowId == props?.cell?.rowId);
|
|
289
311
|
return (
|
|
290
312
|
<div onPointerDown={(e) => e.stopPropagation()}>
|
|
291
|
-
{Slots?.tableActionsSlot && <Slots.tableActionsSlot {...props?.cell} />}
|
|
292
|
-
{Slots?.actionPrefixSlot && <Slots.actionPrefixSlot {...props?.cell} />}
|
|
293
|
-
{Slots?.actionCenterSlot && <Slots.actionCenterSlot {...props?.cell} />}
|
|
294
|
-
{Slots?.actionSuffixSlot && <Slots.actionSuffixSlot {...props?.cell} />}
|
|
313
|
+
{Slots?.tableActionsSlot && <Slots.tableActionsSlot {...props?.cell} rowData={rowData} />}
|
|
314
|
+
{Slots?.actionPrefixSlot && <Slots.actionPrefixSlot {...props?.cell} rowData={rowData} />}
|
|
315
|
+
{Slots?.actionCenterSlot && <Slots.actionCenterSlot {...props?.cell} rowData={rowData} />}
|
|
316
|
+
{Slots?.actionSuffixSlot && <Slots.actionSuffixSlot {...props?.cell} rowData={rowData} />}
|
|
295
317
|
</div>
|
|
296
318
|
);
|
|
297
319
|
};
|
|
@@ -372,12 +394,26 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
372
394
|
return templatesObj;
|
|
373
395
|
}, [reactGridProps?.customCellTemplates]);
|
|
374
396
|
|
|
397
|
+
/** 选中高亮整行 */
|
|
398
|
+
const onHightsRow = (cell: any, rows: any) => {
|
|
399
|
+
const list = rows
|
|
400
|
+
?.find((el) => el?.rowId == cell?.rowId)
|
|
401
|
+
?.cells?.map((item) => ({
|
|
402
|
+
columnId: item?.columnId,
|
|
403
|
+
rowId: cell?.rowId,
|
|
404
|
+
className: "custom-highlights-row",
|
|
405
|
+
borderColor: "transparent",
|
|
406
|
+
}));
|
|
407
|
+
highlightsRowIdRef.current = cell?.rowId;
|
|
408
|
+
setHighlights(list);
|
|
409
|
+
};
|
|
410
|
+
|
|
375
411
|
return (
|
|
376
412
|
<Spin spinning={loading}>
|
|
377
413
|
<div className={`grid-container ${className}`} style={reactGridStyle}>
|
|
378
414
|
<ReactGrid
|
|
379
415
|
ref={gridRef}
|
|
380
|
-
rows={rows}
|
|
416
|
+
rows={loading ? initRowsRef.current : rows}
|
|
381
417
|
key={dataSource?.length == 0 ? 0 : 1}
|
|
382
418
|
columns={tableColumns}
|
|
383
419
|
onCellsChanged={handleCellsChanged}
|
|
@@ -385,15 +421,23 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
385
421
|
enableRangeSelection={true}
|
|
386
422
|
horizontalStickyBreakpoint={120}
|
|
387
423
|
{...reactGridProps}
|
|
424
|
+
highlights={reactGridProps?.highlights ?? highlights}
|
|
388
425
|
onFocusLocationChanging={(cell: any) => {
|
|
389
426
|
const datatypeId = cell?.columnId + cell?.rowId;
|
|
390
427
|
(window as any).gridEditId = datatypeId;
|
|
428
|
+
if (typeof cell?.rowId == "string" && cell?.rowId?.indexOf("header-") > -1) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
if (reactGridProps?.isRowHighlights && cell?.columnId) {
|
|
432
|
+
onHightsRow(cell, rows);
|
|
433
|
+
}
|
|
391
434
|
if (["_$actions", "rowSelection", "ExpandListTemplate"]?.includes(cell?.columnId)) {
|
|
392
435
|
return false;
|
|
393
436
|
}
|
|
394
437
|
if (reactGridProps?.onFocusLocationChanging) {
|
|
395
438
|
return reactGridProps?.onFocusLocationChanging(cell, rows);
|
|
396
439
|
}
|
|
440
|
+
|
|
397
441
|
return cell;
|
|
398
442
|
}}
|
|
399
443
|
customCellTemplates={{
|
|
@@ -403,8 +447,8 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
403
447
|
...headerCustomTemplate,
|
|
404
448
|
_$actions: WidthWrapHoc(ActionDom),
|
|
405
449
|
rowSelection: WidthWrapHoc(CheckBoxDom),
|
|
406
|
-
Input: TextTemplate,
|
|
407
|
-
Number: NumberTemplate,
|
|
450
|
+
// Input: WidthWrapHoc(TextTemplate,props),
|
|
451
|
+
Number: WidthWrapHoc(NumberTemplate, props),
|
|
408
452
|
}}
|
|
409
453
|
/>
|
|
410
454
|
{dataSource?.length <= 0 && (
|
|
@@ -416,3 +460,5 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
416
460
|
</Spin>
|
|
417
461
|
);
|
|
418
462
|
}
|
|
463
|
+
|
|
464
|
+
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();
|