funda-ui 4.7.222 → 4.7.252
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/Date/index.js +51 -0
- package/EventCalendar/index.js +30 -13
- package/EventCalendarTimeline/index.js +30 -13
- package/ModalDialog/index.d.ts +8 -4
- package/ModalDialog/index.js +30 -13
- package/Table/index.js +304 -183
- package/lib/cjs/Date/index.js +51 -0
- package/lib/cjs/EventCalendar/index.js +30 -13
- package/lib/cjs/EventCalendarTimeline/index.js +30 -13
- package/lib/cjs/ModalDialog/index.d.ts +8 -4
- package/lib/cjs/ModalDialog/index.js +30 -13
- package/lib/cjs/Table/index.js +304 -183
- package/lib/esm/Date/index.tsx +47 -18
- package/lib/esm/Input/index.tsx +1 -0
- package/lib/esm/ModalDialog/index.tsx +39 -20
- package/lib/esm/Table/Table.tsx +74 -15
- package/lib/esm/Table/TableCell.tsx +7 -3
- package/lib/esm/Table/utils/func.ts +12 -1
- package/lib/esm/Table/utils/hooks/useTableKeyPress.tsx +152 -72
- package/package.json +1 -1
package/lib/esm/Date/index.tsx
CHANGED
|
@@ -29,7 +29,6 @@ import { isNumeric } from 'funda-utils/dist/cjs/math';
|
|
|
29
29
|
import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
import Calendar from './Calendar';
|
|
34
33
|
|
|
35
34
|
|
|
@@ -644,6 +643,11 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
644
643
|
|
|
645
644
|
resetDefauleValueExist();
|
|
646
645
|
|
|
646
|
+
// Automatically pop up a pop-up window
|
|
647
|
+
if (enableEntireAreaPopup) {
|
|
648
|
+
handleShow();
|
|
649
|
+
}
|
|
650
|
+
|
|
647
651
|
// If there is no valid default value in the input field,
|
|
648
652
|
// onChange should be triggered only after the resetDefauleValueExist() function is processed
|
|
649
653
|
if (!dateDefaultValueExist) {
|
|
@@ -1093,12 +1097,9 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1093
1097
|
if (_val !== '' && !isValidYear(_val) && isNumeric(_val) && Number(_val) > 9999) _val = '9999';
|
|
1094
1098
|
if (_val !== '' && !isValidYear(_val) && !isNumeric(_val)) _val = `${getCurrentYear()}`;
|
|
1095
1099
|
|
|
1096
|
-
|
|
1097
1100
|
const _date = `${_val}-${splitVals[1]}-${splitVals[2]}`;
|
|
1098
1101
|
const _full = `${_date} ${splitVals[3]}:${splitVals[4]}:${splitVals[5]}`;
|
|
1099
1102
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
1103
|
onChange?.(inputRef.current, valueResConverter(_full), isValidDate(_full), getAllSplittingInputs());
|
|
1103
1104
|
setSplitVals((prevState: string[]) => {
|
|
1104
1105
|
return [_val, prevState[1], prevState[2], prevState[3], prevState[4], prevState[5]];
|
|
@@ -1109,7 +1110,14 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1109
1110
|
setChangedVal(_full);
|
|
1110
1111
|
setTimeVal([splitVals[3], splitVals[4], splitVals[5]]);
|
|
1111
1112
|
|
|
1112
|
-
|
|
1113
|
+
// Auto focus to next input if year is 4 digits
|
|
1114
|
+
if (_val.length === 4) {
|
|
1115
|
+
const nextInput = splitInputs.current.get(splitInputsIds[1]);
|
|
1116
|
+
if (nextInput) {
|
|
1117
|
+
(nextInput as HTMLInputElement).focus();
|
|
1118
|
+
(nextInput as HTMLInputElement).select();
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1113
1121
|
}}
|
|
1114
1122
|
{...attributes}
|
|
1115
1123
|
/>
|
|
@@ -1142,13 +1150,9 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1142
1150
|
}
|
|
1143
1151
|
if (_val !== '' && !isValidMonth(_val) && !isNumeric(_val)) _val = `${getCurrentMonth()}`;
|
|
1144
1152
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
1153
|
const _date = `${splitVals[0]}-${_val}-${splitVals[2]}`;
|
|
1148
1154
|
const _full = `${_date} ${splitVals[3]}:${splitVals[4]}:${splitVals[5]}`;
|
|
1149
1155
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
1156
|
onChange?.(inputRef.current, valueResConverter(_full), isValidDate(_full), getAllSplittingInputs());
|
|
1153
1157
|
setSplitVals((prevState: string[]) => {
|
|
1154
1158
|
return [prevState[0], _val, prevState[2], prevState[3], prevState[4], prevState[5]];
|
|
@@ -1158,7 +1162,15 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1158
1162
|
setDateVal(_date);
|
|
1159
1163
|
setChangedVal(_full);
|
|
1160
1164
|
setTimeVal([splitVals[3], splitVals[4], splitVals[5]]);
|
|
1161
|
-
|
|
1165
|
+
|
|
1166
|
+
// Auto focus to next input if month is 2 digits
|
|
1167
|
+
if (_val.length === 2) {
|
|
1168
|
+
const nextInput = splitInputs.current.get(splitInputsIds[2]);
|
|
1169
|
+
if (nextInput) {
|
|
1170
|
+
(nextInput as HTMLInputElement).focus();
|
|
1171
|
+
(nextInput as HTMLInputElement).select();
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1162
1174
|
}}
|
|
1163
1175
|
{...attributes}
|
|
1164
1176
|
/>
|
|
@@ -1199,13 +1211,9 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1199
1211
|
}
|
|
1200
1212
|
if (_val !== '' && !isValidDay(_val) && !isNumeric(_val)) _val = `${getCurrentDay()}`;
|
|
1201
1213
|
|
|
1202
|
-
|
|
1203
1214
|
const _date = `${splitVals[0]}-${splitVals[1]}-${_val}`;
|
|
1204
1215
|
const _full = `${_date} ${splitVals[3]}:${splitVals[4]}:${splitVals[5]}`;
|
|
1205
1216
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
1217
|
onChange?.(inputRef.current, valueResConverter(_full), isValidDate(_full), getAllSplittingInputs());
|
|
1210
1218
|
setSplitVals((prevState: string[]) => {
|
|
1211
1219
|
return [prevState[0], prevState[1], _val, prevState[3], prevState[4], prevState[5]];
|
|
@@ -1216,7 +1224,14 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1216
1224
|
setChangedVal(_full);
|
|
1217
1225
|
setTimeVal([splitVals[3], splitVals[4], splitVals[5]]);
|
|
1218
1226
|
|
|
1219
|
-
|
|
1227
|
+
// Auto focus to next input if day is 2 digits
|
|
1228
|
+
if (_val.length === 2) {
|
|
1229
|
+
const nextInput = splitInputs.current.get(splitInputsIds[3]);
|
|
1230
|
+
if (nextInput) {
|
|
1231
|
+
(nextInput as HTMLInputElement).focus();
|
|
1232
|
+
(nextInput as HTMLInputElement).select();
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1220
1235
|
}}
|
|
1221
1236
|
{...attributes}
|
|
1222
1237
|
/>
|
|
@@ -1266,7 +1281,14 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1266
1281
|
setChangedVal(_full);
|
|
1267
1282
|
setTimeVal([_val, splitVals[4], splitVals[5]]);
|
|
1268
1283
|
|
|
1269
|
-
|
|
1284
|
+
// Auto focus to next input if hour is 2 digits
|
|
1285
|
+
if (_val.length === 2) {
|
|
1286
|
+
const nextInput = splitInputs.current.get(splitInputsIds[4]);
|
|
1287
|
+
if (nextInput) {
|
|
1288
|
+
(nextInput as HTMLInputElement).focus();
|
|
1289
|
+
(nextInput as HTMLInputElement).select();
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1270
1292
|
}}
|
|
1271
1293
|
{...attributes}
|
|
1272
1294
|
/>
|
|
@@ -1314,7 +1336,14 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1314
1336
|
setChangedVal(_full);
|
|
1315
1337
|
setTimeVal([splitVals[3], _val, splitVals[5]]);
|
|
1316
1338
|
|
|
1317
|
-
|
|
1339
|
+
// Auto focus to next input if minute is 2 digits
|
|
1340
|
+
if (_val.length === 2) {
|
|
1341
|
+
const nextInput = splitInputs.current.get(splitInputsIds[5]);
|
|
1342
|
+
if (nextInput) {
|
|
1343
|
+
(nextInput as HTMLInputElement).focus();
|
|
1344
|
+
(nextInput as HTMLInputElement).select();
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1318
1347
|
}}
|
|
1319
1348
|
{...attributes}
|
|
1320
1349
|
/>
|
|
@@ -1364,7 +1393,7 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
|
|
|
1364
1393
|
setDateVal(_date);
|
|
1365
1394
|
setChangedVal(_full);
|
|
1366
1395
|
setTimeVal([splitVals[3], splitVals[4], _val]);
|
|
1367
|
-
|
|
1396
|
+
// No auto focus for the last input (seconds)
|
|
1368
1397
|
}}
|
|
1369
1398
|
{...attributes}
|
|
1370
1399
|
/>
|
package/lib/esm/Input/index.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from 'funda-utils/dist/cjs/bodyScrollLock';
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
|
|
16
17
|
declare global {
|
|
17
18
|
interface Window {
|
|
18
19
|
curVideo?: any;
|
|
@@ -90,10 +91,14 @@ export type ModalDialogProps = {
|
|
|
90
91
|
/** This function is called whenever the data is updated.
|
|
91
92
|
* Exposes the JSON format data about the option as an argument.
|
|
92
93
|
*/
|
|
93
|
-
onLoad?: (openFunc:
|
|
94
|
-
onOpen?: (e:
|
|
95
|
-
onClose?: (e:
|
|
96
|
-
onSubmit?: (e:
|
|
94
|
+
onLoad?: (openFunc: () => void, closeFunc: () => void) => void;
|
|
95
|
+
onOpen?: (e: React.MouseEvent<HTMLElement> | null, callback: () => void) => void;
|
|
96
|
+
onClose?: (e: React.MouseEvent<HTMLElement> | null) => void;
|
|
97
|
+
onSubmit?: (e: React.MouseEvent<HTMLButtonElement>, callback: () => void, incomingData: string | null | undefined) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Called when Enter key is pressed while modal is open
|
|
100
|
+
*/
|
|
101
|
+
onPressEnter?: (callback: () => void) => void;
|
|
97
102
|
};
|
|
98
103
|
|
|
99
104
|
const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.ForwardedRef<ModalDialogRef>) => {
|
|
@@ -132,7 +137,8 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
132
137
|
onClose,
|
|
133
138
|
onSubmit,
|
|
134
139
|
id,
|
|
135
|
-
children
|
|
140
|
+
children,
|
|
141
|
+
onPressEnter
|
|
136
142
|
} = props;
|
|
137
143
|
|
|
138
144
|
|
|
@@ -186,7 +192,7 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
186
192
|
|
|
187
193
|
|
|
188
194
|
//
|
|
189
|
-
function handleCloseWin(e:
|
|
195
|
+
function handleCloseWin(e: React.MouseEvent<HTMLElement> | null) {
|
|
190
196
|
if (typeof e !== 'undefined' && e !== null) {
|
|
191
197
|
e.preventDefault();
|
|
192
198
|
|
|
@@ -206,7 +212,7 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
206
212
|
}
|
|
207
213
|
|
|
208
214
|
|
|
209
|
-
function handleOpenWin(e:
|
|
215
|
+
function handleOpenWin(e: React.MouseEvent<HTMLElement> | null) {
|
|
210
216
|
if (typeof e !== 'undefined' && e !== null) {
|
|
211
217
|
e.preventDefault();
|
|
212
218
|
|
|
@@ -217,12 +223,10 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
217
223
|
openAction();
|
|
218
224
|
|
|
219
225
|
//
|
|
220
|
-
const callback = (
|
|
221
|
-
|
|
222
|
-
handleCloseWin(e);
|
|
223
|
-
}
|
|
226
|
+
const callback = () => {
|
|
227
|
+
handleCloseWin(e);
|
|
224
228
|
};
|
|
225
|
-
onOpen?.(e, callback
|
|
229
|
+
onOpen?.(e, callback);
|
|
226
230
|
}
|
|
227
231
|
|
|
228
232
|
function closeAction() {
|
|
@@ -428,6 +432,23 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
428
432
|
|
|
429
433
|
}, [show, data, modalRef.current]); // When show`` defaults to true, `modalRef.current` will be null
|
|
430
434
|
|
|
435
|
+
// 监听回车键
|
|
436
|
+
useEffect(() => {
|
|
437
|
+
if (!modalShow || !onPressEnter) return;
|
|
438
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
439
|
+
if (e.key === 'Enter' || e.key === 'NumpadEnter') {
|
|
440
|
+
const callback = () => {
|
|
441
|
+
handleCloseWin(null);
|
|
442
|
+
};
|
|
443
|
+
onPressEnter?.(callback);
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
447
|
+
return () => {
|
|
448
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
449
|
+
};
|
|
450
|
+
}, [modalShow, onPressEnter]);
|
|
451
|
+
|
|
431
452
|
return (
|
|
432
453
|
<>
|
|
433
454
|
{triggerContent ? <>
|
|
@@ -468,7 +489,7 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
468
489
|
}}
|
|
469
490
|
>
|
|
470
491
|
<h5 className={`modal-title ${modalTitleClassName || ''}`}>{heading || ''}</h5>
|
|
471
|
-
{!closeDisabled ? <button type="button" className={enableVideo ? 'btn-close btn-close-white' : 'btn-close'} data-close="1" onClick={handleCloseWin}></button> : null}
|
|
492
|
+
{!closeDisabled ? <button type="button" className={enableVideo ? 'btn-close btn-close-white' : 'btn-close'} data-close="1" onClick={(e) => handleCloseWin(e)}></button> : null}
|
|
472
493
|
|
|
473
494
|
</div>
|
|
474
495
|
</>}
|
|
@@ -500,15 +521,13 @@ const ModalDialog = forwardRef((props: ModalDialogProps, externalRef: React.Forw
|
|
|
500
521
|
{closeBtnLabel || submitBtnLabel ? <>
|
|
501
522
|
<div className={`modal-footer ${modalFooterClassName || ''}`}>
|
|
502
523
|
|
|
503
|
-
{!closeDisabled ? <>{closeBtnLabel ? <button data-close="1" onClick={handleCloseWin} type="button" className={closeBtnClassName ? closeBtnClassName : 'btn btn-secondary'}>{closeBtnLabel}</button> : null}</> : null}
|
|
524
|
+
{!closeDisabled ? <>{closeBtnLabel ? <button data-close="1" onClick={(e) => handleCloseWin(e)} type="button" className={closeBtnClassName ? closeBtnClassName : 'btn btn-secondary'}>{closeBtnLabel}</button> : null}</> : null}
|
|
504
525
|
|
|
505
|
-
{submitBtnLabel ? <button data-confirm="1" data-incoming-data={`${incomingData}`} onClick={(e:
|
|
506
|
-
const callback = (
|
|
507
|
-
|
|
508
|
-
handleCloseWin(e);
|
|
509
|
-
}
|
|
526
|
+
{submitBtnLabel ? <button data-confirm="1" data-incoming-data={`${incomingData}`} onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
|
527
|
+
const callback = () => {
|
|
528
|
+
handleCloseWin(e);
|
|
510
529
|
};
|
|
511
|
-
onSubmit?.(e, callback
|
|
530
|
+
onSubmit?.(e, callback, incomingData);
|
|
512
531
|
}} type="button" className={submitBtnClassName ? submitBtnClassName : 'btn btn-primary'}>{submitBtnLabel}</button> : null}
|
|
513
532
|
</div>
|
|
514
533
|
</> : null}
|
package/lib/esm/Table/Table.tsx
CHANGED
|
@@ -8,7 +8,8 @@ import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
|
|
|
8
8
|
import { TableProvider } from './TableContext';
|
|
9
9
|
import useTableResponsive from './utils/hooks/useTableResponsive';
|
|
10
10
|
import useTableDraggable from './utils/hooks/useTableDraggable';
|
|
11
|
-
import
|
|
11
|
+
import useTableKeyPress from './utils/hooks/useTableKeyPress';
|
|
12
|
+
import { cellMark, removeCellFocusClassName, initRowColProps, getTableRowsColCount } from './utils/func';
|
|
12
13
|
|
|
13
14
|
export interface TableProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
14
15
|
// content ref
|
|
@@ -49,8 +50,16 @@ export interface TableProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
49
50
|
|
|
50
51
|
// key press
|
|
51
52
|
keyboardFocusable?: boolean;
|
|
52
|
-
onCellKeyPressed?: (
|
|
53
|
-
|
|
53
|
+
onCellKeyPressed?: (
|
|
54
|
+
classname: string,
|
|
55
|
+
elem: HTMLTableCellElement,
|
|
56
|
+
event: React.KeyboardEvent<Element>,
|
|
57
|
+
isLeftEdge: boolean,
|
|
58
|
+
isRightEdge: boolean,
|
|
59
|
+
isTopEdge: boolean,
|
|
60
|
+
isBottomEdge: boolean
|
|
61
|
+
) => void;
|
|
62
|
+
onCellPressEnter?: (classname: string, elem: HTMLTableCellElement, event: React.KeyboardEvent<Element>) => void;
|
|
54
63
|
|
|
55
64
|
}
|
|
56
65
|
|
|
@@ -113,7 +122,7 @@ const Table = forwardRef<HTMLDivElement, TableProps>((
|
|
|
113
122
|
const [selectedItems, setSelectedItems] = useState<any>(new Set());
|
|
114
123
|
|
|
115
124
|
// effective element movement on keystroke
|
|
116
|
-
const [rootDataInfo, setRootDataInfo] = useState<null | {totalRow: number}>(null);
|
|
125
|
+
const [rootDataInfo, setRootDataInfo] = useState<null | {totalRow: number; totalCol: {row: number; colCount: number}[];}>(null);
|
|
117
126
|
const refNode = useRef(new Map<string, HTMLTableElement>());
|
|
118
127
|
const [focusableCellId, setFocusableCellId] = useState<string>('');
|
|
119
128
|
|
|
@@ -150,6 +159,30 @@ const Table = forwardRef<HTMLDivElement, TableProps>((
|
|
|
150
159
|
onRowDrag: onRowDrag
|
|
151
160
|
}, [data, rootRef]);
|
|
152
161
|
|
|
162
|
+
const tableKeyPress = useTableKeyPress({
|
|
163
|
+
enabled: keyboardFocusable,
|
|
164
|
+
data: data,
|
|
165
|
+
spyElement: rootRef.current,
|
|
166
|
+
rootDataInfo,
|
|
167
|
+
refNode,
|
|
168
|
+
focusableCellId,
|
|
169
|
+
setFocusableCellId,
|
|
170
|
+
onCellKeyPressed,
|
|
171
|
+
onCellPressEnter,
|
|
172
|
+
}, [data, rootRef, rootDataInfo, refNode, focusableCellId]);
|
|
173
|
+
|
|
174
|
+
const updateFocusableCell = (row: number, col: number) => {
|
|
175
|
+
|
|
176
|
+
setFocusableCellId(cellMark(row, col));
|
|
177
|
+
|
|
178
|
+
// Find and focus the cell element
|
|
179
|
+
const targetCell = refNode.current.get(cellMark(row, col)) as HTMLElement;
|
|
180
|
+
|
|
181
|
+
if (typeof targetCell !== 'undefined') {
|
|
182
|
+
removeCellFocusClassName(rootRef.current);
|
|
183
|
+
targetCell.classList.add('cell-focus');
|
|
184
|
+
}
|
|
185
|
+
};
|
|
153
186
|
|
|
154
187
|
// initialize context
|
|
155
188
|
useEffect(() => {
|
|
@@ -174,27 +207,53 @@ const Table = forwardRef<HTMLDivElement, TableProps>((
|
|
|
174
207
|
if (rootRef.current) {
|
|
175
208
|
// Initialize custom props of table elements
|
|
176
209
|
initRowColProps(rootRef.current);
|
|
210
|
+
|
|
211
|
+
// Count the number of columns per row
|
|
212
|
+
const totalCol = getTableRowsColCount(rootRef.current);
|
|
213
|
+
setRootDataInfo({
|
|
214
|
+
totalRow: Array.isArray(data) ? data.length : 0,
|
|
215
|
+
totalCol
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Initialize the focused index
|
|
219
|
+
if (keyboardFocusable) {
|
|
220
|
+
updateFocusableCell(0, 0);
|
|
221
|
+
}
|
|
222
|
+
|
|
177
223
|
}
|
|
178
224
|
}, [data]); // Re-run when data changes
|
|
179
225
|
|
|
180
226
|
|
|
181
227
|
// exposes the following methods
|
|
182
228
|
useImperativeHandle(contentRef, () => ({
|
|
183
|
-
setFocusableCell:
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
// Find and focus the cell element
|
|
188
|
-
const cellElement = rootRef.current?.querySelector(`.${cellMark(row, col)}`);
|
|
189
|
-
if (cellElement) {
|
|
229
|
+
setFocusableCell: updateFocusableCell,
|
|
230
|
+
clearAllCellFocus: () => {
|
|
231
|
+
if (rootRef.current) {
|
|
190
232
|
removeCellFocusClassName(rootRef.current);
|
|
191
|
-
|
|
192
|
-
|
|
233
|
+
|
|
234
|
+
const focusedCells = rootRef.current.querySelectorAll('td.cell-focus, th.cell-focus');
|
|
235
|
+
focusedCells.forEach((cell: any) => {
|
|
236
|
+
if (typeof cell.blur === 'function') cell.blur();
|
|
237
|
+
if (cell.classList) cell.classList.remove('cell-focus');
|
|
238
|
+
});
|
|
193
239
|
}
|
|
240
|
+
},
|
|
241
|
+
getCellElement: (row: number, col: number) => {
|
|
242
|
+
// Find and focus the cell element
|
|
243
|
+
const targetCell = refNode.current.get(cellMark(row, col)) as HTMLElement;
|
|
244
|
+
return typeof targetCell !== 'undefined' ? targetCell : null;
|
|
245
|
+
},
|
|
246
|
+
forceFocusCell: (row: number, col: number) => {
|
|
247
|
+
// Find and focus the cell element
|
|
248
|
+
const targetCell = refNode.current.get(cellMark(row, col)) as HTMLElement;
|
|
194
249
|
|
|
195
|
-
|
|
250
|
+
if (typeof targetCell !== 'undefined') {
|
|
251
|
+
// After forcing focus, you can use the keyboard to listen directly
|
|
252
|
+
targetCell.focus();
|
|
253
|
+
}
|
|
196
254
|
},
|
|
197
|
-
|
|
255
|
+
triggerCellKeyPressed: tableKeyPress.triggerCellKeyPressed
|
|
256
|
+
}), [rootRef, data, rootDataInfo]);
|
|
198
257
|
|
|
199
258
|
return (
|
|
200
259
|
<>
|
|
@@ -2,6 +2,8 @@ import React, { forwardRef, useContext } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
|
|
5
7
|
import { TableContext } from './TableContext';
|
|
6
8
|
|
|
7
9
|
import { cellMark, removeCellFocusClassName } from './utils/func';
|
|
@@ -39,7 +41,7 @@ const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>((
|
|
|
39
41
|
const {
|
|
40
42
|
originData,
|
|
41
43
|
rootRef,
|
|
42
|
-
rootDataInfo,
|
|
44
|
+
rootDataInfo,
|
|
43
45
|
setRootDataInfo,
|
|
44
46
|
refNode,
|
|
45
47
|
focusableCellId,
|
|
@@ -58,7 +60,6 @@ const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>((
|
|
|
58
60
|
data: originData,
|
|
59
61
|
spyElement: rootRef.current,
|
|
60
62
|
rootDataInfo,
|
|
61
|
-
setRootDataInfo,
|
|
62
63
|
refNode,
|
|
63
64
|
focusableCellId,
|
|
64
65
|
setFocusableCellId,
|
|
@@ -84,7 +85,10 @@ const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>((
|
|
|
84
85
|
if (node) {
|
|
85
86
|
const _row = node.dataset.tableRow;
|
|
86
87
|
const _col = node.dataset.tableCol;
|
|
87
|
-
|
|
88
|
+
if (typeof _row !== 'undefined' && typeof _col !== 'undefined') {
|
|
89
|
+
refNode.current.set(cellMark(_row, _col), node);
|
|
90
|
+
}
|
|
91
|
+
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
}}
|
|
@@ -159,7 +159,10 @@ export function tableElemScrolledInit(root: HTMLDivElement, w: number) {
|
|
|
159
159
|
|
|
160
160
|
|
|
161
161
|
export function cellMark(row: number | string | undefined, col: number | string | undefined) {
|
|
162
|
-
|
|
162
|
+
const isNegative = (num: number) => {
|
|
163
|
+
return num < 0;
|
|
164
|
+
};
|
|
165
|
+
return `cell-${isNegative(row as number) ? 0 : row}-${isNegative(col as number) ? 0 : col}`;
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
export function removeCellFocusClassName(root: any) {
|
|
@@ -169,3 +172,11 @@ export function removeCellFocusClassName(root: any) {
|
|
|
169
172
|
});
|
|
170
173
|
}
|
|
171
174
|
}
|
|
175
|
+
|
|
176
|
+
export function getTableRowsColCount(root: HTMLDivElement) {
|
|
177
|
+
const rows = allRows(root);
|
|
178
|
+
return rows.map((row: HTMLTableRowElement, i: number) => ({
|
|
179
|
+
row: i,
|
|
180
|
+
colCount: row.children.length
|
|
181
|
+
}));
|
|
182
|
+
}
|