funda-ui 4.7.212 → 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.
package/Date/index.js CHANGED
@@ -5424,9 +5424,14 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5424
5424
 
5425
5425
  e.target.select();
5426
5426
  resetDefauleValueExist();
5427
- var _date = "".concat(splitVals[0], "-").concat(splitVals[1], "-").concat(splitVals[2]);
5428
- var _full = "".concat(_date, " ").concat(splitVals[3], ":").concat(splitVals[4], ":").concat(splitVals[5]);
5429
- _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, valueResConverter(_full), (0,cjs_date.isValidDate)(_full), getAllSplittingInputs());
5427
+
5428
+ // If there is no valid default value in the input field,
5429
+ // onChange should be triggered only after the resetDefauleValueExist() function is processed
5430
+ if (!dateDefaultValueExist) {
5431
+ var _date = "".concat(splitVals[0], "-").concat(splitVals[1], "-").concat(splitVals[2]);
5432
+ var _full = "".concat(_date, " ").concat(splitVals[3], ":").concat(splitVals[4], ":").concat(splitVals[5]);
5433
+ _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, valueResConverter(_full), (0,cjs_date.isValidDate)(_full), getAllSplittingInputs());
5434
+ }
5430
5435
  }
5431
5436
  function handleKeyPressed(_x2) {
5432
5437
  return _handleKeyPressed.apply(this, arguments);
@@ -5461,17 +5466,19 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5461
5466
  }
5462
5467
  function _handleKeyPressedForSplitInputs() {
5463
5468
  _handleKeyPressedForSplitInputs = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(event) {
5464
- var key, btnMark, move;
5469
+ var key, btnMark, isLeftArrow, isRightArrow, move;
5465
5470
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
5466
5471
  while (1) switch (_context2.prev = _context2.next) {
5467
5472
  case 0:
5468
5473
  key = event.code;
5469
- btnMark = event.target.dataset.mark;
5470
- move = function move(key) {
5474
+ btnMark = event.target.dataset.mark; // Check for both regular arrow keys and numpad arrow keys
5475
+ isLeftArrow = key === 'ArrowLeft' || key === 'Numpad4';
5476
+ isRightArrow = key === 'ArrowRight' || key === 'Numpad6';
5477
+ move = function move(direction) {
5471
5478
  var currentIndex = splitInputsIds.findIndex(function (s) {
5472
5479
  return s === btnMark;
5473
5480
  });
5474
- var nextIndex = key === 'ArrowLeft' ? currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
5481
+ var nextIndex = direction === 'left' ? currentIndex === 0 ? splitInputsIds.length - 1 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
5475
5482
  var nextOption = splitInputsIds.at(nextIndex);
5476
5483
  if (nextOption) {
5477
5484
  setTimeout(function () {
@@ -5481,13 +5488,13 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5481
5488
  setFocusableSplitInputId(nextOption);
5482
5489
  }
5483
5490
  };
5484
- if (key === 'ArrowLeft') {
5485
- move('ArrowLeft');
5491
+ if (isLeftArrow) {
5492
+ move('left');
5486
5493
  }
5487
- if (key === 'ArrowRight') {
5488
- move('ArrowRight');
5494
+ if (isRightArrow) {
5495
+ move('right');
5489
5496
  }
5490
- case 5:
5497
+ case 7:
5491
5498
  case "end":
5492
5499
  return _context2.stop();
5493
5500
  }
@@ -5500,6 +5507,7 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5500
5507
  _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, '', false, getAllSplittingInputs());
5501
5508
  }
5502
5509
  function resetDefauleValueExist() {
5510
+ // Does the current input box have a "valid default value"?
5503
5511
  if (!dateDefaultValueExist) setDateDefaultValueExist(true);
5504
5512
  }
5505
5513
  function resetPopupBlurStatus() {
package/Table/index.js CHANGED
@@ -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;
package/Utils/time.d.ts CHANGED
@@ -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
  /**
package/Utils/time.js CHANGED
@@ -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
  /**
@@ -5424,9 +5424,14 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5424
5424
 
5425
5425
  e.target.select();
5426
5426
  resetDefauleValueExist();
5427
- var _date = "".concat(splitVals[0], "-").concat(splitVals[1], "-").concat(splitVals[2]);
5428
- var _full = "".concat(_date, " ").concat(splitVals[3], ":").concat(splitVals[4], ":").concat(splitVals[5]);
5429
- _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, valueResConverter(_full), (0,cjs_date.isValidDate)(_full), getAllSplittingInputs());
5427
+
5428
+ // If there is no valid default value in the input field,
5429
+ // onChange should be triggered only after the resetDefauleValueExist() function is processed
5430
+ if (!dateDefaultValueExist) {
5431
+ var _date = "".concat(splitVals[0], "-").concat(splitVals[1], "-").concat(splitVals[2]);
5432
+ var _full = "".concat(_date, " ").concat(splitVals[3], ":").concat(splitVals[4], ":").concat(splitVals[5]);
5433
+ _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, valueResConverter(_full), (0,cjs_date.isValidDate)(_full), getAllSplittingInputs());
5434
+ }
5430
5435
  }
5431
5436
  function handleKeyPressed(_x2) {
5432
5437
  return _handleKeyPressed.apply(this, arguments);
@@ -5461,17 +5466,19 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5461
5466
  }
5462
5467
  function _handleKeyPressedForSplitInputs() {
5463
5468
  _handleKeyPressedForSplitInputs = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(event) {
5464
- var key, btnMark, move;
5469
+ var key, btnMark, isLeftArrow, isRightArrow, move;
5465
5470
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
5466
5471
  while (1) switch (_context2.prev = _context2.next) {
5467
5472
  case 0:
5468
5473
  key = event.code;
5469
- btnMark = event.target.dataset.mark;
5470
- move = function move(key) {
5474
+ btnMark = event.target.dataset.mark; // Check for both regular arrow keys and numpad arrow keys
5475
+ isLeftArrow = key === 'ArrowLeft' || key === 'Numpad4';
5476
+ isRightArrow = key === 'ArrowRight' || key === 'Numpad6';
5477
+ move = function move(direction) {
5471
5478
  var currentIndex = splitInputsIds.findIndex(function (s) {
5472
5479
  return s === btnMark;
5473
5480
  });
5474
- var nextIndex = key === 'ArrowLeft' ? currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
5481
+ var nextIndex = direction === 'left' ? currentIndex === 0 ? splitInputsIds.length - 1 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
5475
5482
  var nextOption = splitInputsIds.at(nextIndex);
5476
5483
  if (nextOption) {
5477
5484
  setTimeout(function () {
@@ -5481,13 +5488,13 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5481
5488
  setFocusableSplitInputId(nextOption);
5482
5489
  }
5483
5490
  };
5484
- if (key === 'ArrowLeft') {
5485
- move('ArrowLeft');
5491
+ if (isLeftArrow) {
5492
+ move('left');
5486
5493
  }
5487
- if (key === 'ArrowRight') {
5488
- move('ArrowRight');
5494
+ if (isRightArrow) {
5495
+ move('right');
5489
5496
  }
5490
- case 5:
5497
+ case 7:
5491
5498
  case "end":
5492
5499
  return _context2.stop();
5493
5500
  }
@@ -5500,6 +5507,7 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5500
5507
  _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, '', false, getAllSplittingInputs());
5501
5508
  }
5502
5509
  function resetDefauleValueExist() {
5510
+ // Does the current input box have a "valid default value"?
5503
5511
  if (!dateDefaultValueExist) setDateDefaultValueExist(true);
5504
5512
  }
5505
5513
  function resetPopupBlurStatus() {
@@ -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
 
@@ -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) {
@@ -22,7 +22,8 @@ const App = () => {
22
22
  refNode,
23
23
  focusableCellId,
24
24
  setFocusableCellId,
25
- onCellKeyPressed
25
+ onCellKeyPressed,
26
+ onCellPressEnter,
26
27
  }, [rootRef]);
27
28
 
28
29
 
@@ -50,6 +51,7 @@ export interface UseTableKeyPressProps {
50
51
  focusableCellId: string;
51
52
  setFocusableCellId: (s: string) => void;
52
53
  onCellKeyPressed: (classname: string, elem: HTMLTableCellElement, event: KeyboardEvent) => void;
54
+ onCellPressEnter: (classname: string, elem: HTMLTableCellElement, event: KeyboardEvent) => void;
53
55
  onKeyDown?: (e: any) => void;
54
56
  }
55
57
 
@@ -64,13 +66,24 @@ const useTableKeyPress = ({
64
66
  focusableCellId,
65
67
  setFocusableCellId,
66
68
  onCellKeyPressed,
69
+ onCellPressEnter,
67
70
  onKeyDown
68
71
  }: UseTableKeyPressProps, deps: any[]) => {
69
72
 
70
73
  const handleKeyPressed = useCallback( async (event: KeyboardEvent<HTMLTableCellElement>) => {
74
+ const key = event.code;
75
+
76
+ if ((key === 'Enter' || key === 'NumpadEnter') && !enabled) {
77
+ const currentCell = event.target as HTMLTableCellElement;
78
+ const row = Number(currentCell.getAttribute('data-table-row'));
79
+ const col = Number(currentCell.getAttribute('data-table-col'));
80
+ const nextCellSignal: string = cellMark(row, col);
81
+ onCellPressEnter?.(nextCellSignal, refNode.current.get(nextCellSignal), event);
82
+ return;
83
+ }
84
+
71
85
  if (!Array.isArray(data) || rootDataInfo === null || spyElement === null || typeof enabled === 'undefined' || enabled === false) return;
72
86
 
73
- const key = event.code;
74
87
  const oldCellSignal = focusableCellId?.replace('cell-', '').split('-');
75
88
  let _row = Number(oldCellSignal[0]);
76
89
  let _col = Number(oldCellSignal[1]);
@@ -80,15 +93,19 @@ const useTableKeyPress = ({
80
93
 
81
94
  switch (key) {
82
95
  case 'ArrowLeft':
96
+ case 'Numpad4':
83
97
  _col = _col - 1 < 0 ? 0 : _col - 1;
84
98
  break;
85
99
  case 'ArrowRight':
100
+ case 'Numpad6':
86
101
  _col = _col + 1 > data.length - 1 ? data.length -1 : _col + 1;
87
102
  break;
88
103
  case 'ArrowUp':
104
+ case 'Numpad8':
89
105
  _row = _row - 1 < 0 ? 0 : _row - 1;
90
106
  break;
91
107
  case 'ArrowDown':
108
+ case 'Numpad2':
92
109
  _row = _row + 1 > rootDataInfo.totalRow - 1 ? rootDataInfo.totalRow - 1 : _row + 1;
93
110
  break;
94
111
  }
@@ -109,23 +126,28 @@ const useTableKeyPress = ({
109
126
 
110
127
  };
111
128
 
112
- if (key === 'ArrowLeft') {
129
+ if (key === 'ArrowLeft' || key === 'Numpad4') {
113
130
  move('ArrowLeft');
114
131
  }
115
132
 
116
- if (key === 'ArrowRight') {
133
+ if (key === 'ArrowRight' || key === 'Numpad6') {
117
134
  move('ArrowRight');
118
135
  }
119
136
 
120
137
 
121
- if (key === 'ArrowUp') {
138
+ if (key === 'ArrowUp' || key === 'Numpad8') {
122
139
  move('ArrowUp');
123
140
  }
124
141
 
125
- if (key === 'ArrowDown') {
142
+ if (key === 'ArrowDown' || key === 'Numpad2') {
126
143
  move('ArrowDown');
127
144
  }
128
145
 
146
+ if (key === 'Enter' || key === 'NumpadEnter') {
147
+ const nextCellSignal: string = cellMark(_row, _col);
148
+ onCellPressEnter?.(nextCellSignal, refNode.current.get(nextCellSignal), event);
149
+ }
150
+
129
151
  }, [focusableCellId]);
130
152
 
131
153
  useEffect(() => {
@@ -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
 
14
16
  function getTimeslots(
@@ -17,49 +19,49 @@ function getTimeslots(
17
19
  timeInterval: number,
18
20
  formatRange: boolean = false
19
21
  ): string[] {
22
+ // Parse time string to seconds
20
23
  const parseTime = (s: string): number => {
21
- const c = s.split(':');
22
- return parseInt(c[0]) * 60 + parseInt(c[1]);
23
- }
24
-
25
- const convertHours = (mins: number): string => {
26
- const hour = Math.floor(mins / 60);
27
- mins = Math.trunc(mins % 60);
28
- const converted = pad(hour, 2) + ':' + pad(mins, 2);
29
- return converted;
24
+ const c = s.split(":").map(Number);
25
+ // Support HH:mm or HH:mm:ss
26
+ return c[0] * 3600 + c[1] * 60 + (c[2] || 0);
30
27
  }
31
28
 
29
+ // Pad with zeros
32
30
  const pad = (str: string | number, max: number): string => {
33
31
  str = str.toString();
34
32
  return str.length < max ? pad("0" + str, max) : str;
35
33
  }
36
34
 
37
- // calculate time slot
35
+ // Convert seconds to HH:mm:ss
36
+ const convertTime = (secs: number): string => {
37
+ const hour = Math.floor(secs / 3600);
38
+ const min = Math.floor((secs % 3600) / 60);
39
+ const sec = secs % 60;
40
+ return pad(hour, 2) + ":" + pad(min, 2) + ":" + pad(sec, 2);
41
+ }
42
+
43
+ // Calculate time slots
38
44
  const calculateTimeSlot = (_startTime: number, _endTime: number, _timeInterval: number): string[] => {
39
45
  const timeSlots: string[] = [];
40
- // Round start and end times to next 30 min interval
41
- _startTime = Math.ceil(_startTime / 30) * 30;
42
- _endTime = Math.ceil(_endTime / 30) * 30;
43
-
44
- // Start and end of interval in the loop
45
46
  let currentTime = _startTime;
46
- while (currentTime < _endTime) {
47
+ while (currentTime <= _endTime) {
47
48
  if (formatRange) {
48
- const t = convertHours(currentTime) + ' - ' + convertHours(currentTime + _timeInterval);
49
+ const t = convertTime(currentTime) + ' - ' + convertTime(Math.min(currentTime + _timeInterval, _endTime));
49
50
  timeSlots.push(t);
50
51
  } else {
51
- timeSlots.push(convertHours(currentTime));
52
+ timeSlots.push(convertTime(currentTime));
52
53
  }
53
54
  currentTime += _timeInterval;
54
55
  }
55
56
  return timeSlots;
56
57
  }
57
58
 
58
- const inputEndTime = parseTime(endTime);
59
59
  const inputStartTime = parseTime(startTime);
60
- const timeSegment = calculateTimeSlot(inputStartTime, inputEndTime, timeInterval);
61
-
62
- return timeSegment;
60
+ const inputEndTime = parseTime(endTime);
61
+ // If timeInterval is not an integer, treat as minutes with decimals, convert to seconds
62
+ const isDecimal = !Number.isInteger(timeInterval);
63
+ const intervalInSeconds = isDecimal ? Math.round(timeInterval * 60) : timeInterval * 60;
64
+ return calculateTimeSlot(inputStartTime, inputEndTime, intervalInSeconds);
63
65
  }
64
66
 
65
67
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "UIUX Lab",
3
3
  "email": "uiuxlab@gmail.com",
4
4
  "name": "funda-ui",
5
- "version": "4.7.212",
5
+ "version": "4.7.222",
6
6
  "description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
7
7
  "repository": {
8
8
  "type": "git",