funda-ui 4.7.202 → 4.7.222

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.
@@ -654,8 +654,8 @@ function tableElemScrolledInit(root, w) {
654
654
  });
655
655
  }
656
656
  }
657
- function cellMark(col, row) {
658
- return "cell-".concat(col, "-").concat(row);
657
+ function cellMark(row, col) {
658
+ return "cell-".concat(row, "-").concat(col);
659
659
  }
660
660
  function removeCellFocusClassName(root) {
661
661
  if (root) {
@@ -1027,7 +1027,7 @@ function useTableDraggable(_ref, deps) {
1027
1027
  }
1028
1028
  /* harmony default export */ const hooks_useTableDraggable = (useTableDraggable);
1029
1029
  ;// CONCATENATED MODULE: ./src/Table.tsx
1030
- var _excluded = ["children", "wrapperClassName", "tableClassName", "bordered", "colGroup", "cellAutoWidth", "colSortable", "onColSort", "rowDraggable", "onRowDrag", "responsive", "enhancedResponsive", "enhancedResponsiveWithScrollBar", "data", "filterFields", "filterControlClassName", "filterControlPlaceholder", "filterLabel", "onChangeFilter", "dataSelected", "rowSelectable", "onChangeRowSelect", "keyboardFocusable", "onCellKeyPressed"];
1030
+ var _excluded = ["contentRef", "children", "wrapperClassName", "tableClassName", "bordered", "colGroup", "cellAutoWidth", "colSortable", "onColSort", "rowDraggable", "onRowDrag", "responsive", "enhancedResponsive", "enhancedResponsiveWithScrollBar", "data", "filterFields", "filterControlClassName", "filterControlPlaceholder", "filterLabel", "onChangeFilter", "dataSelected", "rowSelectable", "onChangeRowSelect", "keyboardFocusable", "onCellKeyPressed", "onCellPressEnter"];
1031
1031
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
1032
1032
  function Table_slicedToArray(arr, i) { return Table_arrayWithHoles(arr) || Table_iterableToArrayLimit(arr, i) || Table_unsupportedIterableToArray(arr, i) || Table_nonIterableRest(); }
1033
1033
  function Table_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -1043,8 +1043,10 @@ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) r
1043
1043
 
1044
1044
 
1045
1045
 
1046
+
1046
1047
  var Table = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.forwardRef)(function (_ref, externalRef) {
1047
- var children = _ref.children,
1048
+ var contentRef = _ref.contentRef,
1049
+ children = _ref.children,
1048
1050
  wrapperClassName = _ref.wrapperClassName,
1049
1051
  tableClassName = _ref.tableClassName,
1050
1052
  bordered = _ref.bordered,
@@ -1068,6 +1070,7 @@ var Table = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_a
1068
1070
  onChangeRowSelect = _ref.onChangeRowSelect,
1069
1071
  keyboardFocusable = _ref.keyboardFocusable,
1070
1072
  onCellKeyPressed = _ref.onCellKeyPressed,
1073
+ onCellPressEnter = _ref.onCellPressEnter,
1071
1074
  attributes = _objectWithoutProperties(_ref, _excluded);
1072
1075
  var uniqueID = useComId_default()();
1073
1076
  var rootRef = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);
@@ -1139,6 +1142,32 @@ var Table = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_a
1139
1142
  setSelectedItems(newSelectedItems);
1140
1143
  }
1141
1144
  }, [data, dataSelected]);
1145
+
1146
+ // Synchronous execution, which blocks rendering
1147
+ (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useLayoutEffect)(function () {
1148
+ if (rootRef.current) {
1149
+ // Initialize custom props of table elements
1150
+ initRowColProps(rootRef.current);
1151
+ }
1152
+ }, [data]); // Re-run when data changes
1153
+
1154
+ // exposes the following methods
1155
+ (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useImperativeHandle)(contentRef, function () {
1156
+ return {
1157
+ setFocusableCell: function setFocusableCell(row, col) {
1158
+ var _rootRef$current;
1159
+ setFocusableCellId(cellMark(row, col));
1160
+
1161
+ // Find and focus the cell element
1162
+ var cellElement = (_rootRef$current = rootRef.current) === null || _rootRef$current === void 0 ? void 0 : _rootRef$current.querySelector(".".concat(cellMark(row, col)));
1163
+ if (cellElement) {
1164
+ removeCellFocusClassName(rootRef.current);
1165
+ cellElement.focus(); // !!!Required
1166
+ cellElement.classList.add('cell-focus');
1167
+ }
1168
+ }
1169
+ };
1170
+ }, [rootRef]);
1142
1171
  return /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement((external_root_React_commonjs2_react_commonjs_react_amd_react_default()).Fragment, null, /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement(TableProvider, {
1143
1172
  value: {
1144
1173
  originData: data,
@@ -1170,7 +1199,8 @@ var Table = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_a
1170
1199
  refNode: refNode,
1171
1200
  focusableCellId: focusableCellId,
1172
1201
  setFocusableCellId: setFocusableCellId,
1173
- onCellKeyPressed: onCellKeyPressed
1202
+ onCellKeyPressed: onCellKeyPressed,
1203
+ onCellPressEnter: onCellPressEnter
1174
1204
  }
1175
1205
  }, /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement("div", _extends({}, attributes, {
1176
1206
  id: uniqueID,
@@ -1252,7 +1282,8 @@ const App = () => {
1252
1282
  refNode,
1253
1283
  focusableCellId,
1254
1284
  setFocusableCellId,
1255
- onCellKeyPressed
1285
+ onCellKeyPressed,
1286
+ onCellPressEnter,
1256
1287
  }, [rootRef]);
1257
1288
 
1258
1289
 
@@ -1278,20 +1309,32 @@ var useTableKeyPress = function useTableKeyPress(_ref, deps) {
1278
1309
  focusableCellId = _ref.focusableCellId,
1279
1310
  setFocusableCellId = _ref.setFocusableCellId,
1280
1311
  onCellKeyPressed = _ref.onCellKeyPressed,
1312
+ onCellPressEnter = _ref.onCellPressEnter,
1281
1313
  onKeyDown = _ref.onKeyDown;
1282
1314
  var handleKeyPressed = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useCallback)( /*#__PURE__*/function () {
1283
1315
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {
1284
- var key, oldCellSignal, _row, _col, move;
1316
+ var key, currentCell, row, col, nextCellSignal, oldCellSignal, _row, _col, move, _nextCellSignal;
1285
1317
  return _regeneratorRuntime().wrap(function _callee$(_context) {
1286
1318
  while (1) switch (_context.prev = _context.next) {
1287
1319
  case 0:
1320
+ key = event.code;
1321
+ if (!((key === 'Enter' || key === 'NumpadEnter') && !enabled)) {
1322
+ _context.next = 8;
1323
+ break;
1324
+ }
1325
+ currentCell = event.target;
1326
+ row = Number(currentCell.getAttribute('data-table-row'));
1327
+ col = Number(currentCell.getAttribute('data-table-col'));
1328
+ nextCellSignal = cellMark(row, col);
1329
+ onCellPressEnter === null || onCellPressEnter === void 0 ? void 0 : onCellPressEnter(nextCellSignal, refNode.current.get(nextCellSignal), event);
1330
+ return _context.abrupt("return");
1331
+ case 8:
1288
1332
  if (!(!Array.isArray(data) || rootDataInfo === null || spyElement === null || typeof enabled === 'undefined' || enabled === false)) {
1289
- _context.next = 2;
1333
+ _context.next = 10;
1290
1334
  break;
1291
1335
  }
1292
1336
  return _context.abrupt("return");
1293
- case 2:
1294
- key = event.code;
1337
+ case 10:
1295
1338
  oldCellSignal = focusableCellId === null || focusableCellId === void 0 ? void 0 : focusableCellId.replace('cell-', '').split('-');
1296
1339
  _row = Number(oldCellSignal[0]);
1297
1340
  _col = Number(oldCellSignal[1]);
@@ -1299,15 +1342,19 @@ var useTableKeyPress = function useTableKeyPress(_ref, deps) {
1299
1342
  var _spyElement$querySele;
1300
1343
  switch (key) {
1301
1344
  case 'ArrowLeft':
1345
+ case 'Numpad4':
1302
1346
  _col = _col - 1 < 0 ? 0 : _col - 1;
1303
1347
  break;
1304
1348
  case 'ArrowRight':
1349
+ case 'Numpad6':
1305
1350
  _col = _col + 1 > data.length - 1 ? data.length - 1 : _col + 1;
1306
1351
  break;
1307
1352
  case 'ArrowUp':
1353
+ case 'Numpad8':
1308
1354
  _row = _row - 1 < 0 ? 0 : _row - 1;
1309
1355
  break;
1310
1356
  case 'ArrowDown':
1357
+ case 'Numpad2':
1311
1358
  _row = _row + 1 > rootDataInfo.totalRow - 1 ? rootDataInfo.totalRow - 1 : _row + 1;
1312
1359
  break;
1313
1360
  }
@@ -1324,19 +1371,23 @@ var useTableKeyPress = function useTableKeyPress(_ref, deps) {
1324
1371
  onCellKeyPressed === null || onCellKeyPressed === void 0 ? void 0 : onCellKeyPressed(nextCellSignal, refNode.current.get(nextCellSignal), event);
1325
1372
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
1326
1373
  };
1327
- if (key === 'ArrowLeft') {
1374
+ if (key === 'ArrowLeft' || key === 'Numpad4') {
1328
1375
  move('ArrowLeft');
1329
1376
  }
1330
- if (key === 'ArrowRight') {
1377
+ if (key === 'ArrowRight' || key === 'Numpad6') {
1331
1378
  move('ArrowRight');
1332
1379
  }
1333
- if (key === 'ArrowUp') {
1380
+ if (key === 'ArrowUp' || key === 'Numpad8') {
1334
1381
  move('ArrowUp');
1335
1382
  }
1336
- if (key === 'ArrowDown') {
1383
+ if (key === 'ArrowDown' || key === 'Numpad2') {
1337
1384
  move('ArrowDown');
1338
1385
  }
1339
- case 11:
1386
+ if (key === 'Enter' || key === 'NumpadEnter') {
1387
+ _nextCellSignal = cellMark(_row, _col);
1388
+ onCellPressEnter === null || onCellPressEnter === void 0 ? void 0 : onCellPressEnter(_nextCellSignal, refNode.current.get(_nextCellSignal), event);
1389
+ }
1390
+ case 19:
1340
1391
  case "end":
1341
1392
  return _context.stop();
1342
1393
  }
@@ -1402,7 +1453,8 @@ var TableCell = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_rea
1402
1453
  focusableCellId = _useContext.focusableCellId,
1403
1454
  setFocusableCellId = _useContext.setFocusableCellId,
1404
1455
  keyboardFocusable = _useContext.keyboardFocusable,
1405
- onCellKeyPressed = _useContext.onCellKeyPressed;
1456
+ onCellKeyPressed = _useContext.onCellKeyPressed,
1457
+ onCellPressEnter = _useContext.onCellPressEnter;
1406
1458
  var CellComponent = scope ? 'th' : 'td';
1407
1459
 
1408
1460
  // key press initialization
@@ -1416,6 +1468,7 @@ var TableCell = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_rea
1416
1468
  focusableCellId: focusableCellId,
1417
1469
  setFocusableCellId: setFocusableCellId,
1418
1470
  onCellKeyPressed: onCellKeyPressed,
1471
+ onCellPressEnter: onCellPressEnter,
1419
1472
  onKeyDown: onKeyDown
1420
1473
  }, [rootRef]),
1421
1474
  handleKeyPressed = _useTableKeyPress.handleKeyPressed;
@@ -9,6 +9,8 @@
9
9
 
10
10
  console.log(getTimeslots("10:00", "14:00", 60, true)); //['10:00 - 11:00', '11:00 - 12:00', '12:00 - 13:00', '13:00 - 14:00']
11
11
  console.log(getTimeslots("10:00", "14:00", 60)); // ['10:00', '11:00', '12:00', '13:00']
12
+ console.log(getTimeslots("08:00:00", "08:02:00", 0.4)); // ['08:00:00', '08:00:24', '08:00:48', '08:01:12', '08:01:36', '08:02:00']
13
+
12
14
  */
13
15
  declare function getTimeslots(startTime: string, endTime: string, timeInterval: number, formatRange?: boolean): string[];
14
16
  /**
@@ -62,49 +62,54 @@ __webpack_require__.r(__webpack_exports__);
62
62
 
63
63
  console.log(getTimeslots("10:00", "14:00", 60, true)); //['10:00 - 11:00', '11:00 - 12:00', '12:00 - 13:00', '13:00 - 14:00']
64
64
  console.log(getTimeslots("10:00", "14:00", 60)); // ['10:00', '11:00', '12:00', '13:00']
65
+ console.log(getTimeslots("08:00:00", "08:02:00", 0.4)); // ['08:00:00', '08:00:24', '08:00:48', '08:01:12', '08:01:36', '08:02:00']
66
+
65
67
  */
66
68
 
67
69
  function getTimeslots(startTime, endTime, timeInterval) {
68
70
  var formatRange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
71
+ // Parse time string to seconds
69
72
  var parseTime = function parseTime(s) {
70
- var c = s.split(':');
71
- return parseInt(c[0]) * 60 + parseInt(c[1]);
72
- };
73
- var convertHours = function convertHours(mins) {
74
- var hour = Math.floor(mins / 60);
75
- mins = Math.trunc(mins % 60);
76
- var converted = pad(hour, 2) + ':' + pad(mins, 2);
77
- return converted;
73
+ var c = s.split(":").map(Number);
74
+ // Support HH:mm or HH:mm:ss
75
+ return c[0] * 3600 + c[1] * 60 + (c[2] || 0);
78
76
  };
77
+
78
+ // Pad with zeros
79
79
  var pad = function pad(str, max) {
80
80
  str = str.toString();
81
81
  return str.length < max ? pad("0" + str, max) : str;
82
82
  };
83
83
 
84
- // calculate time slot
84
+ // Convert seconds to HH:mm:ss
85
+ var convertTime = function convertTime(secs) {
86
+ var hour = Math.floor(secs / 3600);
87
+ var min = Math.floor(secs % 3600 / 60);
88
+ var sec = secs % 60;
89
+ return pad(hour, 2) + ":" + pad(min, 2) + ":" + pad(sec, 2);
90
+ };
91
+
92
+ // Calculate time slots
85
93
  var calculateTimeSlot = function calculateTimeSlot(_startTime, _endTime, _timeInterval) {
86
94
  var timeSlots = [];
87
- // Round start and end times to next 30 min interval
88
- _startTime = Math.ceil(_startTime / 30) * 30;
89
- _endTime = Math.ceil(_endTime / 30) * 30;
90
-
91
- // Start and end of interval in the loop
92
95
  var currentTime = _startTime;
93
- while (currentTime < _endTime) {
96
+ while (currentTime <= _endTime) {
94
97
  if (formatRange) {
95
- var t = convertHours(currentTime) + ' - ' + convertHours(currentTime + _timeInterval);
98
+ var t = convertTime(currentTime) + ' - ' + convertTime(Math.min(currentTime + _timeInterval, _endTime));
96
99
  timeSlots.push(t);
97
100
  } else {
98
- timeSlots.push(convertHours(currentTime));
101
+ timeSlots.push(convertTime(currentTime));
99
102
  }
100
103
  currentTime += _timeInterval;
101
104
  }
102
105
  return timeSlots;
103
106
  };
104
- var inputEndTime = parseTime(endTime);
105
107
  var inputStartTime = parseTime(startTime);
106
- var timeSegment = calculateTimeSlot(inputStartTime, inputEndTime, timeInterval);
107
- return timeSegment;
108
+ var inputEndTime = parseTime(endTime);
109
+ // If timeInterval is not an integer, treat as minutes with decimals, convert to seconds
110
+ var isDecimal = !Number.isInteger(timeInterval);
111
+ var intervalInSeconds = isDecimal ? Math.round(timeInterval * 60) : timeInterval * 60;
112
+ return calculateTimeSlot(inputStartTime, inputEndTime, intervalInSeconds);
108
113
  }
109
114
 
110
115
  /**
@@ -641,12 +641,17 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
641
641
 
642
642
  e.target.select();
643
643
 
644
+
644
645
  resetDefauleValueExist();
645
646
 
647
+ // If there is no valid default value in the input field,
648
+ // onChange should be triggered only after the resetDefauleValueExist() function is processed
649
+ if (!dateDefaultValueExist) {
650
+ const _date = `${splitVals[0]}-${splitVals[1]}-${splitVals[2]}`;
651
+ const _full = `${_date} ${splitVals[3]}:${splitVals[4]}:${splitVals[5]}`;
652
+ onChange?.(inputRef.current, valueResConverter(_full), isValidDate(_full), getAllSplittingInputs());
653
+ }
646
654
 
647
- const _date = `${splitVals[0]}-${splitVals[1]}-${splitVals[2]}`;
648
- const _full = `${_date} ${splitVals[3]}:${splitVals[4]}:${splitVals[5]}`;
649
- onChange?.(inputRef.current, valueResConverter(_full), isValidDate(_full), getAllSplittingInputs());
650
655
 
651
656
  }
652
657
 
@@ -670,9 +675,17 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
670
675
  async function handleKeyPressedForSplitInputs(event: KeyboardEvent<HTMLDivElement>) {
671
676
  const key = event.code;
672
677
  const btnMark = (event.target as any).dataset.mark;
673
- const move = (key: string) => {
678
+
679
+ // Check for both regular arrow keys and numpad arrow keys
680
+ const isLeftArrow = key === 'ArrowLeft' || key === 'Numpad4';
681
+ const isRightArrow = key === 'ArrowRight' || key === 'Numpad6';
682
+
683
+ const move = (direction: 'left' | 'right') => {
674
684
  const currentIndex = splitInputsIds.findIndex((s: string) => s === btnMark);
675
- const nextIndex = key === 'ArrowLeft' ? currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
685
+ const nextIndex = direction === 'left'
686
+ ? currentIndex === 0 ? splitInputsIds.length - 1 : currentIndex - 1
687
+ : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
688
+
676
689
  const nextOption = splitInputsIds.at(nextIndex);
677
690
  if (nextOption) {
678
691
  setTimeout(() => {
@@ -681,13 +694,13 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
681
694
  setFocusableSplitInputId(nextOption);
682
695
  }
683
696
  };
684
-
685
- if (key === 'ArrowLeft') {
686
- move('ArrowLeft');
697
+
698
+ if (isLeftArrow) {
699
+ move('left');
687
700
  }
688
701
 
689
- if (key === 'ArrowRight') {
690
- move('ArrowRight');
702
+ if (isRightArrow) {
703
+ move('right');
691
704
  }
692
705
  }
693
706
 
@@ -700,6 +713,7 @@ const Date = forwardRef((props: DateProps, externalRef: any) => {
700
713
 
701
714
 
702
715
  function resetDefauleValueExist() {
716
+ // Does the current input box have a "valid default value"?
703
717
  if (!dateDefaultValueExist) setDateDefaultValueExist(true);
704
718
  }
705
719
 
@@ -53,7 +53,19 @@ import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
53
53
 
54
54
 
55
55
 
56
- export type SelectOptionChangeFnType = (arg1: any, arg2: any, arg3: any) => void;
56
+ export interface MultiSelectValue {
57
+ items: { label: string; value: string }[];
58
+ labels: string[];
59
+ values: string[];
60
+ labelsOfString: string;
61
+ valuesOfString: string;
62
+ }
63
+
64
+ export type SelectOptionChangeFnType = (
65
+ event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
66
+ element: HTMLElement,
67
+ value: OptionConfig | MultiSelectValue
68
+ ) => void | Promise<void>;
57
69
 
58
70
 
59
71
  export interface MultiSelectControlValConfig {
@@ -69,7 +81,8 @@ export interface OptionConfig {
69
81
  listItemLabel?: string;
70
82
  value: string | number | boolean;
71
83
  queryString: string | number;
72
- callback?: () => void;
84
+ callback?: () => void | Promise<void>;
85
+ [key: string]: string | number | boolean | any[] | (() => void | Promise<void>) | undefined;
73
86
  }
74
87
 
75
88
 
@@ -147,14 +160,28 @@ export type SelectProps = {
147
160
  fetchFuncAsync?: any;
148
161
  fetchFuncMethod?: string;
149
162
  fetchFuncMethodParams?: any[];
150
- fetchCallback?: (data: any) => void;
151
- onFetch?: (e: any, e2: any, value: string, data: any, incomingData: string | null | undefined) => void;
152
- onLoad?: (e: any, e2: any, value: string | null | undefined) => void;
153
- onSelect?: (data: any) => void;
163
+ fetchCallback?: (data: OptionConfig[]) => OptionConfig[];
164
+ onFetch?: (
165
+ event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
166
+ element: HTMLElement,
167
+ value: string,
168
+ data: OptionConfig[],
169
+ incomingData: string | null | undefined
170
+ ) => void;
171
+ onLoad?: (
172
+ event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
173
+ element: HTMLElement,
174
+ value: string | null | undefined
175
+ ) => void;
176
+ onSelect?: (data: OptionConfig) => void | Promise<void>;
154
177
  onChange?: SelectOptionChangeFnType | null;
155
- onBlur?: (e: any) => void;
156
- onFocus?: (e: any) => void;
157
- onKeyPressed?: (arg1: any, arg2: any, arg3: any) => void;
178
+ onBlur?: (event: React.FocusEvent<HTMLElement>) => void;
179
+ onFocus?: (event: React.FocusEvent<HTMLElement>) => void;
180
+ onKeyPressed?: (
181
+ event: React.KeyboardEvent<HTMLElement>,
182
+ element: HTMLElement,
183
+ value: string
184
+ ) => void;
158
185
  };
159
186
 
160
187
 
@@ -1402,7 +1429,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1402
1429
  //
1403
1430
  if (noCallback && typeof (onChange) === 'function') {
1404
1431
 
1405
- onChange?.(
1432
+ await onChange?.(
1406
1433
  selectInputRef.current,
1407
1434
  valueInputRef.current,
1408
1435
  !MULTI_SEL_VALID ? curItem : multipleSelectionCallback(currentControlValueArr, currentControlLabelArr)
@@ -1547,7 +1574,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1547
1574
  //
1548
1575
  if (noCallback && typeof (onChange) === 'function') {
1549
1576
 
1550
- onChange?.(
1577
+ await onChange?.(
1551
1578
  selectInputRef.current,
1552
1579
  valueInputRef.current,
1553
1580
  !MULTI_SEL_VALID ? curItem : multipleSelectionCallback(currentControlValueArr, currentControlLabelArr)
@@ -1641,7 +1668,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1641
1668
 
1642
1669
 
1643
1670
 
1644
- function handleSelectAll(event: any) {
1671
+ async function handleSelectAll(event: any) {
1645
1672
  event.preventDefault();
1646
1673
  event.stopPropagation(); /* REQUIRED */
1647
1674
 
@@ -1664,7 +1691,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1664
1691
 
1665
1692
  }
1666
1693
 
1667
- onChange?.(
1694
+ await onChange?.(
1668
1695
  selectInputRef.current,
1669
1696
  valueInputRef.current,
1670
1697
  multipleSelectionCallback(_values, _labels)
@@ -1696,7 +1723,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1696
1723
 
1697
1724
 
1698
1725
 
1699
- function handleMultiControlItemRemove(event: any) {
1726
+ async function handleMultiControlItemRemove(event: any) {
1700
1727
  event.preventDefault();
1701
1728
  event.stopPropagation(); /* REQUIRED */
1702
1729
 
@@ -1732,7 +1759,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1732
1759
  //
1733
1760
  if (typeof (onChange) === 'function') {
1734
1761
 
1735
- onChange?.(
1762
+ await onChange?.(
1736
1763
  selectInputRef.current,
1737
1764
  valueInputRef.current,
1738
1765
  multipleSelectionCallback(currentControlValueArr, currentControlLabelArr)
@@ -1971,7 +1998,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1971
1998
  //
1972
1999
  if (typeof (onChange) === 'function') {
1973
2000
 
1974
- onChange?.(
2001
+ await onChange?.(
1975
2002
  selectInputRef.current,
1976
2003
  valueInputRef.current,
1977
2004
  !MULTI_SEL_VALID ? currentData : multipleSelectionCallback(currentControlValueArr, currentControlLabelArr)
@@ -2214,14 +2241,14 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
2214
2241
  <button
2215
2242
  tabIndex={-1}
2216
2243
  type="button"
2217
- onClick={(e: React.MouseEvent) => {
2244
+ onClick={async (e: React.MouseEvent) => {
2218
2245
  e.preventDefault();
2219
2246
  e.stopPropagation();
2220
2247
 
2221
2248
  if (MULTI_SEL_VALID) {
2222
2249
  updateOptionCheckboxes('remove');
2223
2250
 
2224
- onChange?.(
2251
+ await onChange?.(
2225
2252
  selectInputRef.current,
2226
2253
  valueInputRef.current,
2227
2254
  multipleSelectionCallback([], [])
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState, forwardRef, useRef } from 'react';
1
+ import React, { useEffect, useState, forwardRef, useRef, useLayoutEffect, useImperativeHandle } from 'react';
2
2
 
3
3
 
4
4
  import useComId from 'funda-utils/dist/cjs/useComId';
@@ -8,9 +8,11 @@ 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
-
11
+ import { cellMark, removeCellFocusClassName, initRowColProps } from './utils/func';
12
12
 
13
13
  export interface TableProps extends React.HTMLAttributes<HTMLDivElement> {
14
+ // content ref
15
+ contentRef?: React.ForwardedRef<any>; // could use "Array" on contentRef.current, such as contentRef.current[0], contentRef.current[1]
14
16
 
15
17
  // basic
16
18
  wrapperClassName?: string;
@@ -48,11 +50,15 @@ export interface TableProps extends React.HTMLAttributes<HTMLDivElement> {
48
50
  // key press
49
51
  keyboardFocusable?: boolean;
50
52
  onCellKeyPressed?: (classname: string, elem: HTMLTableCellElement, event: KeyboardEvent) => void;
53
+ onCellPressEnter?: (classname: string, elem: HTMLTableCellElement, event: KeyboardEvent) => void;
54
+
51
55
  }
52
56
 
53
57
 
54
58
  const Table = forwardRef<HTMLDivElement, TableProps>((
55
59
  {
60
+ contentRef,
61
+
56
62
  // basic
57
63
  children,
58
64
  wrapperClassName,
@@ -90,6 +96,7 @@ const Table = forwardRef<HTMLDivElement, TableProps>((
90
96
  // key press
91
97
  keyboardFocusable,
92
98
  onCellKeyPressed,
99
+ onCellPressEnter,
93
100
 
94
101
  ...attributes
95
102
  },
@@ -162,6 +169,33 @@ const Table = forwardRef<HTMLDivElement, TableProps>((
162
169
  }
163
170
  }, [data, dataSelected]);
164
171
 
172
+ // Synchronous execution, which blocks rendering
173
+ useLayoutEffect(() => {
174
+ if (rootRef.current) {
175
+ // Initialize custom props of table elements
176
+ initRowColProps(rootRef.current);
177
+ }
178
+ }, [data]); // Re-run when data changes
179
+
180
+
181
+ // exposes the following methods
182
+ useImperativeHandle(contentRef, () => ({
183
+ setFocusableCell: (row: number, col: number) => {
184
+
185
+ setFocusableCellId(cellMark(row, col));
186
+
187
+ // Find and focus the cell element
188
+ const cellElement = rootRef.current?.querySelector(`.${cellMark(row, col)}`);
189
+ if (cellElement) {
190
+ removeCellFocusClassName(rootRef.current);
191
+ cellElement.focus(); // !!!Required
192
+ cellElement.classList.add('cell-focus');
193
+ }
194
+
195
+
196
+ },
197
+ }), [rootRef]);
198
+
165
199
  return (
166
200
  <>
167
201
 
@@ -202,6 +236,7 @@ const Table = forwardRef<HTMLDivElement, TableProps>((
202
236
  focusableCellId,
203
237
  setFocusableCellId,
204
238
  onCellKeyPressed,
239
+ onCellPressEnter,
205
240
 
206
241
 
207
242
  }}>
@@ -2,8 +2,6 @@ import React, { forwardRef, useContext } from 'react';
2
2
 
3
3
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
4
4
 
5
-
6
-
7
5
  import { TableContext } from './TableContext';
8
6
 
9
7
  import { cellMark, removeCellFocusClassName } from './utils/func';
@@ -48,6 +46,7 @@ const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>((
48
46
  setFocusableCellId,
49
47
  keyboardFocusable,
50
48
  onCellKeyPressed,
49
+ onCellPressEnter,
51
50
  } = useContext(TableContext);
52
51
 
53
52
 
@@ -64,6 +63,7 @@ const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>((
64
63
  focusableCellId,
65
64
  setFocusableCellId,
66
65
  onCellKeyPressed,
66
+ onCellPressEnter,
67
67
  onKeyDown
68
68
  }, [rootRef]);
69
69
 
@@ -158,8 +158,8 @@ export function tableElemScrolledInit(root: HTMLDivElement, w: number) {
158
158
  }
159
159
 
160
160
 
161
- export function cellMark(col: number | string | undefined, row: number | string | undefined) {
162
- return `cell-${col}-${row}`;
161
+ export function cellMark(row: number | string | undefined, col: number | string | undefined) {
162
+ return `cell-${row}-${col}`;
163
163
  }
164
164
 
165
165
  export function removeCellFocusClassName(root: any) {