@hzab/list-render 1.10.21-alpha.0 → 1.10.21-alpha.2

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 CHANGED
@@ -1,7 +1,3 @@
1
- # @hzab/list-render@1.10.21
2
-
3
- feat: 增加行内编辑表格时,canEditCallback的回调,从外部控制cell是否能编辑,修复原有的hasEdit逻辑
4
-
5
1
  # @hzab/list-render@1.10.20
6
2
 
7
3
  fix: 修复 PaginationRender 的 全部样式
package/README.md CHANGED
@@ -282,6 +282,26 @@ const Slots = {
282
282
  | onEdit | row | 手动触发编辑按钮相关操作 |
283
283
  | onDel | row | 手动触发删除按钮相关操作 |
284
284
 
285
+ #### cellEditTableProps
286
+
287
+ | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
288
+ | -------------- | -------- | ---- | ------ | ------------------ |
289
+ | reactGridProps | Object | 否 | | reactGrid 相关参数 |
290
+ | onChange | Function | 否 | | 单元格回调 |
291
+ | formulaConfig | Object | 否 | | 运算相关配置 |
292
+ | headerHeight | number | 否 | | 表头高度 |
293
+
294
+ #### reactGridProps
295
+
296
+ | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
297
+ | enableFillHandle | boolean | false | 开启后,选中单元格右下角会出现小方块,可拖拽快速复制 / 序列填充数据(类似 Excel 拖拽填充)|
298
+ | enableRangeSelection | boolean | false | 开启框选单元格区域(批量选中、批量编辑 / 填充必备)|
299
+ | onFocusLocationChanging | (location: CellLocation): boolean | 否 | 焦点 / 进入编辑态前回调,return false 阻止进入编辑)|
300
+ | customCellTemplates | Function | 否 | 注册自定义单元格模板(按钮、下拉、日期等单元格)|
301
+ | onSelectionChanged | Function | 否 | 选择区回调 |
302
+ | headerRowHeight | number | 否 | 表头高度 |
303
+ | rowHeight | number | 否 | 数据行高度 |
304
+
285
305
  - onSearch opt
286
306
  - isSaveQuery 是否保存传入的 query 值
287
307
  - isMergeQuery 是否合并上一次保存的 query 值
@@ -568,6 +588,7 @@ async function test() {
568
588
  ## 命令
569
589
 
570
590
  - Mac 执行该命令,设置 pre-commit 为可执行文件
591
+
571
592
  - npm run mac-chmod
572
593
  - chmod +x .husky && chmod +x .husky/pre-commit
573
594
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/list-render",
3
- "version": "1.10.21-alpha.0",
3
+ "version": "1.10.21-alpha.2",
4
4
  "description": "",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -30,8 +30,8 @@
30
30
  "@hzab/formily-result-utils": "^1.2.0",
31
31
  "@hzab/permissions": "^1.0.0",
32
32
  "@hzab/schema-descriptions": "^1.3.0",
33
- "@hzab/webpack-config": "^0.7.2",
34
33
  "@hzab/utils": "^1.0.7",
34
+ "@hzab/webpack-config": "^0.7.2",
35
35
  "@types/react": "^17.0.62",
36
36
  "@types/react-dom": "^17.0.20",
37
37
  "antd": "^4.24.12",
@@ -66,6 +66,7 @@
66
66
  "lib": "lib"
67
67
  },
68
68
  "dependencies": {
69
+ "@silevis/reactgrid": "^4.1.17",
69
70
  "array-move": "^4.0.0",
70
71
  "react-sortable-hoc": "^2.0.0"
71
72
  }
@@ -95,6 +95,19 @@ export function getDateVal(val, format) {
95
95
  return dayjs(val).format(format);
96
96
  }
97
97
 
98
+ /** 递归生成children数据 */
99
+
100
+ const handleSchema = (arr) => {
101
+ arr?.forEach((item) => {
102
+ if (item?.type == "object" && !item?.["x-component"]) {
103
+ item.children = Schema.getOrderProperties(item)?.map((it) => it?.schema);
104
+ if (item.children?.length > 0) {
105
+ handleSchema(item.children);
106
+ }
107
+ }
108
+ });
109
+ };
110
+
98
111
  export function getFieldList(_schema, fieldList = [], opt = {}, isTableSortXIdex = false) {
99
112
  const schema = cloneSchema(_schema?.schema || _schema);
100
113
 
@@ -142,7 +155,14 @@ export function getFieldList(_schema, fieldList = [], opt = {}, isTableSortXIdex
142
155
  } else {
143
156
  fieldList.push(field);
144
157
  }
158
+ if (field?.type == "object" && !field?.["x-component"]) {
159
+ field.children = Schema.getOrderProperties(field)?.map((it) => it?.schema);
160
+ if (field.children?.length > 0) {
161
+ handleSchema(field.children);
162
+ }
163
+ }
145
164
  });
165
+
146
166
  isTableSortXIdex && fieldList.sort((a, b) => a["x-index"] - b["x-index"]);
147
167
  return fieldList;
148
168
  }
@@ -0,0 +1,18 @@
1
+ .expandList-template {
2
+ display: flex;
3
+ align-items: center;
4
+
5
+
6
+
7
+ .expandList-template-icon {
8
+ cursor: pointer;
9
+ }
10
+
11
+ .expandList-template-name {
12
+ margin-left: 8px;
13
+ }
14
+
15
+ .expandList-template-indent {
16
+ margin-left: 26px;
17
+ }
18
+ }
@@ -0,0 +1,80 @@
1
+ import { MinusSquareOutlined, PlusCircleOutlined } from "@ant-design/icons";
2
+ import { useEffect, useState } from "react";
3
+ import "./index.less";
4
+ export const ExpandListTemplate = (props) => {
5
+ const [expand, setExpand] = useState<boolean>(false);
6
+ const { record, item } = props;
7
+ const { Slots, setExpandKeys, expandKeys }: any = item;
8
+ const onExpand = (isExpand) => {
9
+ item?.setNewDataSource((pre) => {
10
+ if (isExpand) {
11
+ const findIndex = pre?.findIndex((el) => el?.groupId == props?.record?.groupId);
12
+ pre.splice(findIndex + 1, 0, ...(props?.record?.children || []));
13
+ return [...pre];
14
+ }
15
+ const childrenIds = props?.record?.children?.map((el) => el?.groupId);
16
+
17
+ return pre?.filter((el) => !childrenIds?.includes(el?.groupId));
18
+ });
19
+ };
20
+ useEffect(() => {
21
+ if (expandKeys?.includes(props?.record?.groupId)) {
22
+ setExpand(true);
23
+ onExpand(true);
24
+ } else {
25
+ setExpand(false);
26
+ onExpand(false);
27
+ }
28
+
29
+ // setExpand(props?.record?.expand);
30
+ }, [props?.record]);
31
+
32
+ // console.log(props,"propspropsprops2",Slots[item?.columnId]);
33
+ const colRender = function (text, record) {
34
+ const Slot = Slots[item?.columnId];
35
+ const slotProps = {
36
+ text,
37
+ record,
38
+ // field: { ...field, ...fieldSchemas?.[name] },
39
+ // fieldSchema: fieldSchemas?.[name],
40
+ };
41
+ return <Slot {...slotProps} />;
42
+ };
43
+ return (
44
+ <div className="expandList-template">
45
+ {props?.record?.children && (
46
+ <>
47
+ {!expand ? (
48
+ <PlusCircleOutlined
49
+ className="expandList-template-icon"
50
+ onClick={() => {
51
+ props.record["expand"] = !expand;
52
+ setExpandKeys((preExpandKeys) => {
53
+ if (preExpandKeys?.includes(props?.record?.groupId)) {
54
+ return preExpandKeys?.filter((el) => el?.groupId != props?.record?.groupId);
55
+ }
56
+ return [...preExpandKeys, props?.record?.groupId];
57
+ });
58
+ setExpand(!expand);
59
+ onExpand(!expand);
60
+ }}
61
+ />
62
+ ) : (
63
+ <MinusSquareOutlined
64
+ className="expandList-template-icon"
65
+ onClick={() => {
66
+ props.record["expand"] = !expand;
67
+ setExpand(!expand);
68
+ onExpand(!expand);
69
+ }}
70
+ />
71
+ )}
72
+ </>
73
+ )}
74
+
75
+ <div className={`expandList-template-name ${props?.record?.children ? "" : "expandList-template-indent"}`}>
76
+ {Slots?.[item?.columnId] ? colRender("", record) : record[item?.columnId]}
77
+ </div>
78
+ </div>
79
+ );
80
+ };
@@ -0,0 +1,168 @@
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 "./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();
@@ -0,0 +1,202 @@
1
+ // import * as React from "react";
2
+
3
+ // import {
4
+ // Cell,
5
+ // CellTemplate,
6
+ // Compatible,
7
+ // getCellProperty,
8
+ // getCharFromKey,
9
+ // isAlphaNumericKey,
10
+ // keyCodes,
11
+ // Uncertain,
12
+ // UncertainCompatible,
13
+ // } from "@silevis/reactgrid";
14
+ // import { getVal } from "../../../common/utils";
15
+
16
+ // import { Select } from "antd";
17
+ // import { WidthWrap } from "./widthWrap";
18
+
19
+ // export type OptionType = {
20
+ // label: string;
21
+ // value: string;
22
+ // isDisabled?: boolean;
23
+ // };
24
+
25
+ // export interface SelectCell extends Cell {
26
+ // type: "Select";
27
+ // selectedValue?: string;
28
+ // value: string | number;
29
+ // values: OptionType[];
30
+ // isDisabled?: boolean;
31
+ // isOpen?: boolean;
32
+ // inputValue?: string;
33
+ // }
34
+
35
+ // export class createSelectCellTemplate implements CellTemplate<SelectCell> {
36
+ // getCompatibleCell(uncertainCell: Uncertain<SelectCell>): Compatible<SelectCell> {
37
+ // let selectedValue: string | undefined;
38
+ // try {
39
+ // selectedValue = getCellProperty(uncertainCell, "selectedValue", "number");
40
+ // } catch {
41
+ // selectedValue = undefined;
42
+ // }
43
+ // const values = getCellProperty(uncertainCell, "values", "object");
44
+ // const value = selectedValue ? parseFloat(selectedValue) : NaN;
45
+
46
+ // let isDisabled = true;
47
+ // try {
48
+ // isDisabled = getCellProperty(uncertainCell, "isDisabled", "boolean");
49
+ // } catch {
50
+ // isDisabled = false;
51
+ // }
52
+
53
+ // let inputValue: string | undefined;
54
+ // try {
55
+ // inputValue = getCellProperty(uncertainCell, "inputValue", "string");
56
+ // } catch {
57
+ // inputValue = undefined;
58
+ // }
59
+
60
+ // let isOpen: boolean;
61
+ // try {
62
+ // isOpen = getCellProperty(uncertainCell, "isOpen", "boolean");
63
+ // } catch {
64
+ // isOpen = false;
65
+ // }
66
+
67
+ // const text = selectedValue || "";
68
+
69
+ // return { ...uncertainCell, selectedValue, text, value, isOpen, values, isDisabled, inputValue };
70
+ // }
71
+
72
+ // update(cell: Compatible<SelectCell>, cellToMerge: UncertainCompatible<SelectCell>): Compatible<SelectCell> {
73
+ // const selectedValueFromText = cell.values.some((val: any) => val.value === cellToMerge.text)
74
+ // ? cellToMerge.text
75
+ // : undefined;
76
+ // return this.getCompatibleCell({
77
+ // ...cell,
78
+ // selectedValue: selectedValueFromText,
79
+ // isOpen: cellToMerge?.isOpen,
80
+ // inputValue: cellToMerge.inputValue,
81
+ // });
82
+ // }
83
+
84
+ // getClassName(cell: Compatible<SelectCell>, isInEditMode: boolean): string {
85
+ // const isOpen = cell.isOpen ? "open" : "closed";
86
+ // return `${cell.className ? cell.className : ""}${isOpen}`;
87
+ // }
88
+
89
+ // handleKeyDown(
90
+ // cell: Compatible<SelectCell>,
91
+ // keyCode: number,
92
+ // ctrl: boolean,
93
+ // shift: boolean,
94
+ // alt: boolean,
95
+ // key: string,
96
+ // capsLock: boolean,
97
+ // ): { cell: Compatible<SelectCell>; enableEditMode: boolean } {
98
+ // if ((keyCode === keyCodes.SPACE || keyCode === keyCodes.ENTER) && !shift) {
99
+ // return {
100
+ // cell: this.getCompatibleCell({
101
+ // ...cell,
102
+ // isOpen: !cell.isOpen,
103
+ // }),
104
+ // enableEditMode: false,
105
+ // };
106
+ // }
107
+
108
+ // const char = getCharFromKey(key, shift, capsLock);
109
+
110
+ // if (!ctrl && !alt && isAlphaNumericKey(keyCode) && !(shift && keyCode === keyCodes.SPACE))
111
+ // return {
112
+ // cell: this.getCompatibleCell({
113
+ // ...cell,
114
+ // inputValue: char,
115
+ // isOpen: !cell.isOpen,
116
+ // }),
117
+ // enableEditMode: false,
118
+ // };
119
+
120
+ // return { cell, enableEditMode: false };
121
+ // }
122
+
123
+ // handleCompositionEnd(
124
+ // cell: Compatible<SelectCell>,
125
+ // eventData: any,
126
+ // ): { cell: Compatible<SelectCell>; enableEditMode: boolean } {
127
+ // return {
128
+ // cell: {
129
+ // ...cell,
130
+ // inputValue: eventData,
131
+ // isOpen: !cell.isOpen,
132
+ // },
133
+ // enableEditMode: false,
134
+ // };
135
+ // }
136
+
137
+ // render(
138
+ // cell: Compatible<SelectCell>,
139
+ // isInEditMode: boolean,
140
+ // onCellChanged: (cell: Compatible<SelectCell>, commit: boolean) => void,
141
+ // ): React.ReactNode {
142
+ // return (
143
+ // <SelectInput
144
+ // onCellChanged={(cell) => onCellChanged(this.getCompatibleCell(cell), true)}
145
+ // cell={cell}
146
+ // isInEditMode={isInEditMode}
147
+ // />
148
+ // );
149
+ // }
150
+ // }
151
+
152
+ // interface DIProps {
153
+ // onCellChanged: (...args: any[]) => void;
154
+ // cell: Record<string, any>;
155
+ // isInEditMode?: boolean;
156
+ // }
157
+
158
+ // const SelectInput: React.FC<DIProps> = ({ onCellChanged, cell, isInEditMode }) => {
159
+ // const [isOpen, setIsOpen] = React.useState<boolean>(false);
160
+ // const datatypeId = cell?.columnId + cell?.rowId;
161
+ // React.useEffect(() => {
162
+ // // 处理下拉选项弹层失焦逻辑
163
+ // function onClick() {
164
+ // if (window.gridEditId != datatypeId) {
165
+ // setIsOpen(false);
166
+ // }
167
+ // }
168
+ // document.addEventListener("click", onClick);
169
+ // return () => {
170
+ // document.removeEventListener("click", onClick);
171
+ // };
172
+ // }, []);
173
+
174
+ // return (
175
+ // <div
176
+ // style={{ width: "100%", height: "100%" }}
177
+ // onDoubleClick={(e) => {
178
+ // setIsOpen(true);
179
+ // }}
180
+ // >
181
+ // {isOpen ? (
182
+ // <div onPointerDown={(e) => e.stopPropagation()}>
183
+ // <Select
184
+ // open={isOpen}
185
+ // style={{ width: "100%" }}
186
+ // value={cell?.selectedValue}
187
+ // options={cell.values}
188
+ // onChange={(e) => {
189
+ // onCellChanged({ ...cell, selectedValue: e });
190
+ // }}
191
+ // ></Select>
192
+ // </div>
193
+ // ) : (
194
+ // <div style={{ height: "100%" }}>
195
+ // {getVal(cell?.getField(), { [cell?.getField().name]: cell?.selectedValue })}
196
+ // </div>
197
+ // )}
198
+ // </div>
199
+ // );
200
+ // };
201
+
202
+ // export const SelectTemplate = WidthWrap(Select);
@@ -0,0 +1,123 @@
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();