react-big-schedule 5.4.10-beta.2 → 5.5.0

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.
@@ -97,6 +97,8 @@ AgendaResourceEvents.propTypes = {
97
97
  viewEvent2Click: _propTypes["default"].func,
98
98
  viewEvent2Text: _propTypes["default"].string,
99
99
  slotClickedFunc: _propTypes["default"].func,
100
- slotItemTemplateResolver: _propTypes["default"].func
100
+ slotItemTemplateResolver: _propTypes["default"].func,
101
+ eventItemTemplateResolver: _propTypes["default"].func,
102
+ eventItemPopoverTemplateResolver: _propTypes["default"].func
101
103
  };
102
104
  var _default = exports["default"] = AgendaResourceEvents;
@@ -47,6 +47,15 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
47
47
  var _this;
48
48
  _classCallCheck(this, ResourceEvents);
49
49
  _this = _callSuper(this, ResourceEvents, [props]);
50
+ _defineProperty(_this, "cleanupDragInteraction", function () {
51
+ document.documentElement.removeEventListener('touchmove', _this.doDrag, false);
52
+ document.documentElement.removeEventListener('touchend', _this.stopDrag, false);
53
+ document.documentElement.removeEventListener('touchcancel', _this.cancelDrag, false);
54
+ document.documentElement.removeEventListener('mousemove', _this.doDrag, false);
55
+ document.documentElement.removeEventListener('mouseup', _this.stopDrag, false);
56
+ document.onselectstart = null;
57
+ document.ondragstart = null;
58
+ });
50
59
  _defineProperty(_this, "supportTouchHelper", function () {
51
60
  var evType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'add';
52
61
  var ev = evType === 'add' ? _this.eventContainer.addEventListener : _this.eventContainer.removeEventListener;
@@ -78,13 +87,23 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
78
87
  var left = leftIndex * cellWidth;
79
88
  var rightIndex = Math.ceil(startX / cellWidth);
80
89
  var width = (rightIndex - leftIndex) * cellWidth;
90
+
91
+ // Get the row index of this resource
92
+ var startRowIndex = _this.getResourceRowIndex(resourceEvents.slotId);
81
93
  _this.setState({
82
94
  startX: startX,
83
95
  left: left,
84
96
  leftIndex: leftIndex,
85
97
  width: width,
86
98
  rightIndex: rightIndex,
87
- isSelecting: true
99
+ isSelecting: true,
100
+ originalStartRowIndex: startRowIndex,
101
+ startRowIndex: startRowIndex,
102
+ endRowIndex: startRowIndex // Initially same as start
103
+ });
104
+ _this.emitSelectionChange(true, _this.getSelectedResourceIds(startRowIndex, startRowIndex), {
105
+ left: left,
106
+ width: width
88
107
  });
89
108
  if (_this.supportTouch) {
90
109
  document.documentElement.addEventListener('touchmove', _this.doDrag, false);
@@ -110,7 +129,9 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
110
129
  if (toReturn) {
111
130
  return;
112
131
  }
113
- var startX = _this.state.startX;
132
+ var _this$state = _this.state,
133
+ startX = _this$state.startX,
134
+ originalStartRowIndex = _this$state.originalStartRowIndex;
114
135
  var schedulerData = _this.props.schedulerData;
115
136
  var headers = schedulerData.headers;
116
137
  var cellWidth = schedulerData.getContentCellWidth();
@@ -122,12 +143,51 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
122
143
  var rightIndex = Math.ceil(Math.max(startX, currentX) / cellWidth);
123
144
  rightIndex = rightIndex > headers.length ? headers.length : rightIndex;
124
145
  var width = (rightIndex - leftIndex) * cellWidth;
146
+
147
+ // Calculate current row based on per-row heights (not a uniform row height assumption).
148
+ var clientY = ev.clientY;
149
+ if (_this.supportTouch && ev.changedTouches && ev.changedTouches.length > 0) {
150
+ clientY = ev.changedTouches[0].clientY;
151
+ }
152
+ var currentY = clientY - pos.y;
153
+ var displayRenderData = _this.getDisplayRenderData();
154
+ var rowHeights = displayRenderData.map(function (row) {
155
+ return (row === null || row === void 0 ? void 0 : row.rowHeight) || 50;
156
+ });
157
+ var startRowTop = rowHeights.slice(0, Math.max(0, originalStartRowIndex)).reduce(function (sum, h) {
158
+ return sum + h;
159
+ }, 0);
160
+ var absoluteY = startRowTop + currentY;
161
+ var cumulativeHeight = 0;
162
+ var currentRowIndex = rowHeights.length - 1;
163
+ for (var i = 0; i < rowHeights.length; i += 1) {
164
+ cumulativeHeight += rowHeights[i];
165
+ if (absoluteY < cumulativeHeight) {
166
+ currentRowIndex = i;
167
+ break;
168
+ }
169
+ }
170
+ if (absoluteY < 0) {
171
+ currentRowIndex = 0;
172
+ }
173
+ var minRowIndex = Math.min(originalStartRowIndex, currentRowIndex);
174
+ var maxRowIndex = Math.max(originalStartRowIndex, currentRowIndex);
175
+
176
+ // Clamp to valid row indices
177
+ var clampedMinRow = Math.max(0, minRowIndex);
178
+ var clampedMaxRow = Math.min(displayRenderData.length - 1, maxRowIndex);
125
179
  _this.setState({
126
180
  leftIndex: leftIndex,
127
181
  left: left,
128
182
  rightIndex: rightIndex,
129
183
  width: width,
130
- isSelecting: true
184
+ isSelecting: true,
185
+ startRowIndex: clampedMinRow,
186
+ endRowIndex: clampedMaxRow
187
+ });
188
+ _this.emitSelectionChange(true, _this.getSelectedResourceIds(clampedMinRow, clampedMaxRow), {
189
+ left: left,
190
+ width: width
131
191
  });
132
192
  });
133
193
  _defineProperty(_this, "dragHelper", function (ev, dragType) {
@@ -145,7 +205,8 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
145
205
  return [clientX, false];
146
206
  });
147
207
  _defineProperty(_this, "stopDrag", function (ev) {
148
- ev.stopPropagation();
208
+ var _schedulerData$getRes;
209
+ if (ev !== null && ev !== void 0 && ev.stopPropagation) ev.stopPropagation();
149
210
  var _this$props = _this.props,
150
211
  schedulerData = _this$props.schedulerData,
151
212
  newEvent = _this$props.newEvent,
@@ -155,40 +216,68 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
155
216
  config = schedulerData.config,
156
217
  cellUnit = schedulerData.cellUnit,
157
218
  localeDayjs = schedulerData.localeDayjs;
158
- var _this$state = _this.state,
159
- leftIndex = _this$state.leftIndex,
160
- rightIndex = _this$state.rightIndex;
161
- if (_this.supportTouch) {
162
- document.documentElement.removeEventListener('touchmove', _this.doDrag, false);
163
- document.documentElement.removeEventListener('touchend', _this.stopDrag, false);
164
- document.documentElement.removeEventListener('touchcancel', _this.cancelDrag, false);
165
- } else {
166
- document.documentElement.removeEventListener('mousemove', _this.doDrag, false);
167
- document.documentElement.removeEventListener('mouseup', _this.stopDrag, false);
219
+ var _this$state2 = _this.state,
220
+ leftIndex = _this$state2.leftIndex,
221
+ rightIndex = _this$state2.rightIndex;
222
+ _this.cleanupDragInteraction();
223
+ if (headers.length === 0 || !resourceEvents.headerItems || resourceEvents.headerItems.length === 0) {
224
+ _this.setState({
225
+ startX: 0,
226
+ leftIndex: 0,
227
+ left: 0,
228
+ rightIndex: 0,
229
+ width: 0,
230
+ isSelecting: false,
231
+ originalStartRowIndex: -1,
232
+ startRowIndex: -1,
233
+ endRowIndex: -1
234
+ });
235
+ _this.emitSelectionChange(false, [], {
236
+ left: 0,
237
+ width: 0
238
+ });
239
+ return;
168
240
  }
169
- document.onselectstart = null;
170
- document.ondragstart = null;
171
- var startTime = headers[leftIndex].time;
172
- var endTime = resourceEvents.headerItems[rightIndex - 1].end;
241
+ var maxLeftIndex = headers.length - 1;
242
+ var safeLeftIndex = Math.max(0, Math.min(leftIndex, maxLeftIndex));
243
+ var maxRightIndex = Math.min(headers.length, resourceEvents.headerItems.length);
244
+ var safeRightIndex = Math.max(1, rightIndex, safeLeftIndex + 1);
245
+ safeRightIndex = Math.min(safeRightIndex, maxRightIndex);
246
+ var startTime = headers[safeLeftIndex].time;
247
+ var endTime = resourceEvents.headerItems[safeRightIndex - 1].end;
173
248
  if (cellUnit !== _default2.CellUnit.Hour) {
174
- endTime = localeDayjs(new Date(resourceEvents.headerItems[rightIndex - 1].start)).hour(23).minute(59).second(59).format(_default2.DATETIME_FORMAT);
249
+ endTime = localeDayjs(new Date(resourceEvents.headerItems[safeRightIndex - 1].start)).hour(23).minute(59).second(59).format(_default2.DATETIME_FORMAT);
175
250
  }
176
- var slotId = resourceEvents.slotId;
177
- var slotName = resourceEvents.slotName;
251
+
252
+ // Get selected resource IDs
253
+ var selectedResourceIds = _this.getSelectedResourceIds();
254
+ var slotId = selectedResourceIds.length > 0 ? selectedResourceIds[0] : resourceEvents.slotId;
255
+ var slotName = selectedResourceIds.length > 0 ? ((_schedulerData$getRes = schedulerData.getResourceById(slotId)) === null || _schedulerData$getRes === void 0 ? void 0 : _schedulerData$getRes.name) || slotId : resourceEvents.slotName;
178
256
  _this.setState({
179
257
  startX: 0,
180
258
  leftIndex: 0,
181
259
  left: 0,
182
260
  rightIndex: 0,
183
261
  width: 0,
184
- isSelecting: false
262
+ isSelecting: false,
263
+ originalStartRowIndex: -1,
264
+ startRowIndex: -1,
265
+ endRowIndex: -1
266
+ });
267
+ _this.emitSelectionChange(false, [], {
268
+ left: 0,
269
+ width: 0
185
270
  });
186
271
  var hasConflict = false;
187
272
  if (config.checkConflict) {
188
273
  var start = localeDayjs(new Date(startTime));
189
274
  var end = localeDayjs(endTime);
190
275
  events.forEach(function (e) {
191
- if (schedulerData._getEventSlotId(e) === slotId) {
276
+ var eventResourceIds = e.resourceIds || [e.resourceId];
277
+ var hasOverlap = selectedResourceIds.some(function (selectedId) {
278
+ return eventResourceIds.includes(selectedId);
279
+ });
280
+ if (hasOverlap) {
192
281
  var eStart = localeDayjs(e.start);
193
282
  var eEnd = localeDayjs(e.end);
194
283
  if (start >= eStart && start < eEnd || end > eStart && end <= eEnd || eStart >= start && eStart < end || eEnd > start && eEnd <= end) hasConflict = true;
@@ -202,6 +291,10 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
202
291
  id: undefined,
203
292
  start: startTime,
204
293
  end: endTime,
294
+ resourceId: slotId,
295
+ // Keep for backward compatibility
296
+ resourceIds: selectedResourceIds,
297
+ // Add multi-resource support
205
298
  slotId: slotId,
206
299
  slotName: slotName,
207
300
  title: undefined
@@ -209,25 +302,40 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
209
302
  } else {
210
303
  console.log('Conflict occurred, set conflictOccurred func in Scheduler to handle it');
211
304
  }
212
- } else if (newEvent !== undefined) newEvent(schedulerData, slotId, slotName, startTime, endTime);
305
+ } else if (newEvent !== undefined) {
306
+ // Pass resourceIds for multi-resource events
307
+ newEvent(schedulerData, slotId, slotName, startTime, endTime, undefined, {
308
+ resourceIds: selectedResourceIds.length > 1 ? selectedResourceIds : undefined
309
+ });
310
+ }
213
311
  });
214
312
  _defineProperty(_this, "cancelDrag", function (ev) {
215
- ev.stopPropagation();
313
+ if (ev !== null && ev !== void 0 && ev.stopPropagation) ev.stopPropagation();
216
314
  var isSelecting = _this.state.isSelecting;
217
315
  if (isSelecting) {
218
- document.documentElement.removeEventListener('touchmove', _this.doDrag, false);
219
- document.documentElement.removeEventListener('touchend', _this.stopDrag, false);
220
- document.documentElement.removeEventListener('touchcancel', _this.cancelDrag, false);
221
- document.onselectstart = null;
222
- document.ondragstart = null;
316
+ _this.cleanupDragInteraction();
223
317
  _this.setState({
224
318
  startX: 0,
225
319
  leftIndex: 0,
226
320
  left: 0,
227
321
  rightIndex: 0,
228
322
  width: 0,
229
- isSelecting: false
323
+ isSelecting: false,
324
+ originalStartRowIndex: -1,
325
+ startRowIndex: -1,
326
+ endRowIndex: -1
230
327
  });
328
+ _this.emitSelectionChange(false, [], {
329
+ left: 0,
330
+ width: 0
331
+ });
332
+ }
333
+ });
334
+ _defineProperty(_this, "emitSelectionChange", function (isSelecting, selectedResourceIds) {
335
+ var preview = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
336
+ var onSelectionChange = _this.props.onSelectionChange;
337
+ if (onSelectionChange) {
338
+ onSelectionChange(isSelecting, selectedResourceIds, preview);
231
339
  }
232
340
  });
233
341
  _defineProperty(_this, "onAddMoreClick", function (headerItem) {
@@ -262,10 +370,44 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
262
370
  dropRef(element);
263
371
  }
264
372
  });
373
+ _defineProperty(_this, "getResourceRowIndex", function (slotId) {
374
+ return _this.getDisplayRenderData().findIndex(function (row) {
375
+ return row.slotId === slotId;
376
+ });
377
+ });
378
+ _defineProperty(_this, "getDisplayRenderData", function () {
379
+ var schedulerData = _this.props.schedulerData;
380
+ return schedulerData.renderData.filter(function (row) {
381
+ return row.render;
382
+ });
383
+ });
384
+ _defineProperty(_this, "getSelectedResourceIds", function (startOverride, endOverride) {
385
+ var _this$state3 = _this.state,
386
+ startRowIndex = _this$state3.startRowIndex,
387
+ endRowIndex = _this$state3.endRowIndex;
388
+ var displayRenderData = _this.getDisplayRenderData();
389
+ var from = startOverride !== undefined ? startOverride : startRowIndex;
390
+ var to = endOverride !== undefined ? endOverride : endRowIndex;
391
+ if (from === -1 || to === -1) {
392
+ return [];
393
+ }
394
+ var selectedResourceIds = [];
395
+ for (var i = from; i <= to; i++) {
396
+ var row = displayRenderData[i];
397
+ if (row && !row.groupOnly) {
398
+ selectedResourceIds.push(row.slotId);
399
+ }
400
+ }
401
+ return selectedResourceIds;
402
+ });
265
403
  _this.state = {
266
404
  isSelecting: false,
267
405
  left: 0,
268
- width: 0
406
+ width: 0,
407
+ // Add vertical selection tracking
408
+ originalStartRowIndex: -1,
409
+ startRowIndex: -1,
410
+ endRowIndex: -1
269
411
  };
270
412
  _this.supportTouch = false; // 'ontouchstart' in window;
271
413
  return _this;
@@ -284,18 +426,30 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
284
426
  }, {
285
427
  key: "componentDidUpdate",
286
428
  value: function componentDidUpdate(prevProps) {
287
- if (prevProps !== this.props) {
288
- var schedulerData = this.props.schedulerData;
429
+ var _prevProps$schedulerD, _this$props$scheduler;
430
+ var prevCreatable = (_prevProps$schedulerD = prevProps.schedulerData) === null || _prevProps$schedulerD === void 0 || (_prevProps$schedulerD = _prevProps$schedulerD.config) === null || _prevProps$schedulerD === void 0 ? void 0 : _prevProps$schedulerD.creatable;
431
+ var currentCreatable = (_this$props$scheduler = this.props.schedulerData) === null || _this$props$scheduler === void 0 || (_this$props$scheduler = _this$props$scheduler.config) === null || _this$props$scheduler === void 0 ? void 0 : _this$props$scheduler.creatable;
432
+ if (prevCreatable !== currentCreatable) {
289
433
  this.supportTouchHelper('remove');
290
- if (schedulerData.config.creatable) {
434
+ if (currentCreatable) {
291
435
  this.supportTouchHelper();
292
436
  }
293
437
  }
294
438
  }
439
+ }, {
440
+ key: "componentWillUnmount",
441
+ value: function componentWillUnmount() {
442
+ this.cleanupDragInteraction();
443
+ this.supportTouchHelper('remove');
444
+ this.emitSelectionChange(false, []);
445
+ }
295
446
  }, {
296
447
  key: "render",
297
448
  value: function render() {
298
- var _this2 = this;
449
+ var _this$props$selection,
450
+ _this$props$selection2,
451
+ _this$props$selection3,
452
+ _this2 = this;
299
453
  var _this$props3 = this.props,
300
454
  resourceEvents = _this$props3.resourceEvents,
301
455
  schedulerData = _this$props3.schedulerData,
@@ -305,10 +459,12 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
305
459
  endDate = schedulerData.endDate,
306
460
  config = schedulerData.config,
307
461
  localeDayjs = schedulerData.localeDayjs;
308
- var _this$state2 = this.state,
309
- isSelecting = _this$state2.isSelecting,
310
- left = _this$state2.left,
311
- width = _this$state2.width;
462
+ var _this$state4 = this.state,
463
+ isSelecting = _this$state4.isSelecting,
464
+ left = _this$state4.left,
465
+ width = _this$state4.width,
466
+ startRowIndex = _this$state4.startRowIndex,
467
+ endRowIndex = _this$state4.endRowIndex;
312
468
  var cellWidth = schedulerData.getContentCellWidth();
313
469
  var cellMaxEvents = schedulerData.getCellMaxEvents();
314
470
  var rowWidth = schedulerData.getContentTableWidth();
@@ -317,6 +473,20 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
317
473
  left: left,
318
474
  width: width
319
475
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {});
476
+ var sharedSelecting = (_this$props$selection = this.props.selectionPreview) === null || _this$props$selection === void 0 ? void 0 : _this$props$selection.isSelecting;
477
+ var isSharedSelectedRow = sharedSelecting && this.props.isRowSelected;
478
+ var sharedLeft = ((_this$props$selection2 = this.props.selectionPreview) === null || _this$props$selection2 === void 0 ? void 0 : _this$props$selection2.left) || 0;
479
+ var sharedWidth = ((_this$props$selection3 = this.props.selectionPreview) === null || _this$props$selection3 === void 0 ? void 0 : _this$props$selection3.width) || 0;
480
+ var sharedSelectedArea = !isSelecting && isSharedSelectedRow ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_SelectedArea["default"], {
481
+ schedulerData: schedulerData,
482
+ left: sharedLeft,
483
+ width: sharedWidth
484
+ }) : null;
485
+
486
+ // Add vertical selection overlay
487
+ var verticalSelectionOverlay = isSelecting && startRowIndex !== endRowIndex ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
488
+ className: "vertical-selection-overlay"
489
+ }) : null;
320
490
  var eventList = [];
321
491
  resourceEvents.headerItems.forEach(function (headerItem, index) {
322
492
  if (headerItem.count > 0 || headerItem.summary !== undefined) {
@@ -373,6 +543,7 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
373
543
  _width = evt.span * cellWidth - (index > 0 ? 5 : 6) > 0 ? evt.span * cellWidth - (index > 0 ? 5 : 6) : 0;
374
544
  }
375
545
  var top = marginTop + idx * config.eventItemLineHeight;
546
+ var eventKey = "".concat(evt.eventItem.id, "_").concat(resourceEvents.slotId, "_").concat(index);
376
547
  var eventItem = /*#__PURE__*/(0, _jsxRuntime.jsx)(_EventItem["default"], {
377
548
  schedulerData: schedulerData,
378
549
  eventItem: evt.eventItem,
@@ -398,7 +569,7 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
398
569
  updateEventEnd: _this2.props.updateEventEnd,
399
570
  moveEvent: _this2.props.moveEvent,
400
571
  conflictOccurred: _this2.props.conflictOccurred
401
- });
572
+ }, eventKey);
402
573
  eventList.push(eventItem);
403
574
  }
404
575
  });
@@ -414,9 +585,6 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
414
585
  width: _width2,
415
586
  top: top,
416
587
  clickAction: _this2.onAddMoreClick
417
- // Any specific AddMore requirements
418
- ,
419
- onSetAddMoreState: _this2.props.onSetAddMoreState
420
588
  });
421
589
  eventList.push(addMoreItem);
422
590
  }
@@ -442,7 +610,7 @@ var ResourceEvents = /*#__PURE__*/function (_PureComponent) {
442
610
  style: {
443
611
  height: resourceEvents.rowHeight
444
612
  },
445
- children: [selectedArea, eventList]
613
+ children: [selectedArea, sharedSelectedArea, verticalSelectionOverlay, eventList]
446
614
  });
447
615
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("tr", {
448
616
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
@@ -473,13 +641,22 @@ _defineProperty(ResourceEvents, "propTypes", {
473
641
  viewEvent2Click: _propTypes.PropTypes.func,
474
642
  viewEvent2Text: _propTypes.PropTypes.string,
475
643
  newEvent: _propTypes.PropTypes.func,
476
- eventItemTemplateResolver: _propTypes.PropTypes.func
644
+ eventItemTemplateResolver: _propTypes.PropTypes.func,
645
+ onSelectionChange: _propTypes.PropTypes.func,
646
+ isRowSelected: _propTypes.PropTypes.bool,
647
+ selectionPreview: _propTypes.PropTypes.object
477
648
  });
478
649
  var ResourceEventsWithDnD = function ResourceEventsWithDnD(props) {
479
650
  var schedulerData = props.schedulerData,
480
651
  dndContext = props.dndContext;
481
652
  var config = schedulerData.config;
482
653
  var componentRef = _react["default"].useRef(null);
654
+ var propsRef = _react["default"].useRef(props);
655
+
656
+ // Keep propsRef up to date
657
+ _react["default"].useEffect(function () {
658
+ propsRef.current = props;
659
+ }, [props]);
483
660
 
484
661
  // Always call useDrop unconditionally (Rules of Hooks)
485
662
  // Disable functionality when drag and drop is not enabled
@@ -500,13 +677,13 @@ var ResourceEventsWithDnD = function ResourceEventsWithDnD(props) {
500
677
  return {
501
678
  accept: _toConsumableArray(dndContext.sourceMap.keys()),
502
679
  drop: function drop(item, monitor) {
503
- return spec.drop(props, monitor, componentRef.current);
680
+ return spec.drop(propsRef.current, monitor, componentRef.current);
504
681
  },
505
682
  hover: function hover(item, monitor) {
506
- return spec.hover(props, monitor, componentRef.current);
683
+ return spec.hover(propsRef.current, monitor, componentRef.current);
507
684
  },
508
685
  canDrop: function canDrop(item, monitor) {
509
- return spec.canDrop(props, monitor);
686
+ return spec.canDrop(propsRef.current, monitor);
510
687
  },
511
688
  collect: function collect(monitor) {
512
689
  return {
@@ -515,7 +692,7 @@ var ResourceEventsWithDnD = function ResourceEventsWithDnD(props) {
515
692
  };
516
693
  }
517
694
  };
518
- }, [props, dndContext, config.dragAndDropEnabled]),
695
+ }, [dndContext, config.dragAndDropEnabled]),
519
696
  _useDrop2 = _slicedToArray(_useDrop, 2),
520
697
  _useDrop2$ = _useDrop2[0],
521
698
  isOver = _useDrop2$.isOver,
@@ -530,4 +707,4 @@ var ResourceEventsWithDnD = function ResourceEventsWithDnD(props) {
530
707
  }));
531
708
  };
532
709
  ResourceEventsWithDnD.displayName = 'ResourceEventsWithDnD';
533
- var _default = exports["default"] = ResourceEventsWithDnD;
710
+ var _default = exports["default"] = /*#__PURE__*/_react["default"].memo(ResourceEventsWithDnD);
@@ -37,7 +37,9 @@ function ResourceView(_ref) {
37
37
  slotClickedFunc = _ref.slotClickedFunc,
38
38
  slotItemTemplateResolver = _ref.slotItemTemplateResolver,
39
39
  toggleExpandFunc = _ref.toggleExpandFunc,
40
- CustomResourceCell = _ref.CustomResourceCell;
40
+ CustomResourceCell = _ref.CustomResourceCell,
41
+ isSelecting = _ref.isSelecting,
42
+ selectedResourceIds = _ref.selectedResourceIds;
41
43
  var renderData = schedulerData.renderData;
42
44
  var width = schedulerData.getResourceTableWidth() - 2;
43
45
  var paddingBottom = contentScrollbarHeight;
@@ -64,8 +66,20 @@ function ResourceView(_ref) {
64
66
  indents.push(indent);
65
67
  var tdStyle = {
66
68
  height: item.rowHeight,
67
- backgroundColor: item.groupOnly ? schedulerData.config.groupOnlySlotColor : undefined
69
+ backgroundColor: item.groupOnly ? schedulerData.config.groupOnlySlotColor : undefined,
70
+ borderLeft: '3px solid transparent'
68
71
  };
72
+ var selectedBorderColor = schedulerData.config.selectedSlotBorderColor || '#1677ff';
73
+ var selectedShadowColor = schedulerData.config.selectedSlotShadowColor || '#91caff';
74
+ var selectedSlotColor = schedulerData.config.selectedSlotColor || '#e6f4ff';
75
+ var isRowSelected = isSelecting && Array.isArray(selectedResourceIds) && selectedResourceIds.includes(item.slotId);
76
+ if (isRowSelected) {
77
+ tdStyle.borderLeft = "3px solid ".concat(selectedBorderColor);
78
+ tdStyle.boxShadow = "inset 0 0 0 1px ".concat(selectedShadowColor);
79
+ if (!item.groupOnly) {
80
+ tdStyle.backgroundColor = selectedSlotColor;
81
+ }
82
+ }
69
83
  if (CustomResourceCell) {
70
84
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("tr", {
71
85
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
@@ -155,6 +169,8 @@ ResourceView.propTypes = {
155
169
  slotClickedFunc: _propTypes["default"].func,
156
170
  slotItemTemplateResolver: _propTypes["default"].func,
157
171
  toggleExpandFunc: _propTypes["default"].func,
158
- CustomResourceCell: _propTypes["default"].func
172
+ CustomResourceCell: _propTypes["default"].func,
173
+ isSelecting: _propTypes["default"].bool,
174
+ selectedResourceIds: _propTypes["default"].arrayOf(_propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]))
159
175
  };
160
176
  var _default = exports["default"] = /*#__PURE__*/_react["default"].memo(ResourceView);
@@ -48,6 +48,7 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
48
48
  this.schedulerHeaderHeight = 0;
49
49
  this._shouldReloadViewType = false;
50
50
  this.version = 0;
51
+ this._batchCount = 0;
51
52
  this._versionChangeCallback = null;
52
53
  this.calendarPopoverLocale = undefined;
53
54
  _dayjs["default"].extend(_quarterOfYear["default"]);
@@ -89,11 +90,37 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
89
90
  value: function setVersionChangeNotifier(callback) {
90
91
  this._versionChangeCallback = typeof callback === 'function' ? callback : null;
91
92
  }
93
+ }, {
94
+ key: "beginBatch",
95
+ value: function beginBatch() {
96
+ this._batchCount = (this._batchCount || 0) + 1;
97
+ }
98
+ }, {
99
+ key: "endBatch",
100
+ value: function endBatch() {
101
+ if (this._batchCount === undefined || this._batchCount <= 0) {
102
+ this._batchCount = 0;
103
+ console.warn('SchedulerData.endBatch called without a matching beginBatch');
104
+ return;
105
+ }
106
+ if (this._batchCount > 0) {
107
+ this._batchCount -= 1;
108
+ if (this._batchCount === 0 && this._pendingVersion !== undefined) {
109
+ if (typeof this._versionChangeCallback === 'function') {
110
+ this._versionChangeCallback(this._pendingVersion);
111
+ }
112
+ this._pendingVersion = undefined;
113
+ }
114
+ }
115
+ }
92
116
  }, {
93
117
  key: "bumpVersion",
94
118
  value: function bumpVersion() {
95
119
  this.version += 1;
96
- if (typeof this._versionChangeCallback === 'function') {
120
+ if (this._batchCount > 0) {
121
+ // Defer callback until batch ends
122
+ this._pendingVersion = this.version;
123
+ } else if (typeof this._versionChangeCallback === 'function') {
97
124
  this._versionChangeCallback(this.version);
98
125
  }
99
126
  }
@@ -158,15 +185,17 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
158
185
  }, {
159
186
  key: "setBesidesWidth",
160
187
  value: function setBesidesWidth(besidesWidth) {
161
- if (besidesWidth >= 0) {
188
+ if (besidesWidth >= 0 && this.config.besidesWidth !== besidesWidth) {
162
189
  this.config.besidesWidth = besidesWidth;
190
+ this.bumpVersion();
163
191
  }
164
192
  }
165
193
  }, {
166
194
  key: "setUnderneathHeight",
167
195
  value: function setUnderneathHeight(underneathHeight) {
168
- if (underneathHeight >= 0) {
196
+ if (underneathHeight >= 0 && this.config.underneathHeight !== underneathHeight) {
169
197
  this.config.underneathHeight = underneathHeight;
198
+ this.bumpVersion();
170
199
  }
171
200
  }
172
201
  }, {
@@ -207,6 +236,7 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
207
236
  });
208
237
  if (index !== -1) {
209
238
  this.eventGroups.splice(index, 1);
239
+ this._createRenderData();
210
240
  this.bumpVersion();
211
241
  }
212
242
  }
@@ -268,9 +298,23 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
268
298
  var viewType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _default.ViewType.Week;
269
299
  var showAgenda = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
270
300
  var isEventPerspective = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
301
+ var previousShowAgenda = this.showAgenda;
302
+ var previousIsEventPerspective = this.isEventPerspective;
271
303
  this.showAgenda = showAgenda;
272
304
  this.isEventPerspective = isEventPerspective;
273
- this.cellUnit = _default.CellUnit.Day;
305
+ var isCustomView = viewType === _default.ViewType.Custom || viewType === _default.ViewType.Custom1 || viewType === _default.ViewType.Custom2;
306
+
307
+ // Force built-in views only; custom views can provide their own cellUnit via custom date behavior.
308
+ if (viewType === _default.ViewType.Day) {
309
+ this.cellUnit = _default.CellUnit.Hour;
310
+ } else if (!isCustomView) {
311
+ this.cellUnit = _default.CellUnit.Day;
312
+ }
313
+
314
+ // If showAgenda or isEventPerspective changed, force reload
315
+ if (previousShowAgenda !== showAgenda || previousIsEventPerspective !== isEventPerspective) {
316
+ this._shouldReloadViewType = true;
317
+ }
274
318
  if (this.viewType !== viewType || this._shouldReloadViewType) {
275
319
  var date = this.startDate;
276
320
  if (viewType === _default.ViewType.Custom || viewType === _default.ViewType.Custom1 || viewType === _default.ViewType.Custom2) {
@@ -332,7 +376,13 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
332
376
  }, {
333
377
  key: "setSchedulerMaxHeight",
334
378
  value: function setSchedulerMaxHeight(newSchedulerMaxHeight) {
335
- this.config.schedulerMaxHeight = newSchedulerMaxHeight;
379
+ if (newSchedulerMaxHeight < 0) {
380
+ return;
381
+ }
382
+ if (this.config.schedulerMaxHeight !== newSchedulerMaxHeight) {
383
+ this.config.schedulerMaxHeight = newSchedulerMaxHeight;
384
+ this.bumpVersion();
385
+ }
336
386
  }
337
387
  }, {
338
388
  key: "isSchedulerResponsive",
@@ -345,6 +395,7 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
345
395
  var slotEntered = false;
346
396
  var slotIndent = -1;
347
397
  var isExpanded = false;
398
+ var changed = false;
348
399
  var expandedMap = new Map();
349
400
  this.renderData.forEach(function (item) {
350
401
  if (slotEntered === false) {
@@ -352,6 +403,7 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
352
403
  slotEntered = true;
353
404
  isExpanded = !item.expanded;
354
405
  item.expanded = isExpanded;
406
+ changed = true;
355
407
  slotIndent = item.indent;
356
408
  expandedMap.set(item.indent, {
357
409
  expanded: item.expanded,
@@ -360,7 +412,11 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
360
412
  }
361
413
  } else if (item.indent > slotIndent) {
362
414
  var expandStatus = expandedMap.get(item.indent - 1);
363
- item.render = expandStatus.expanded && expandStatus.render;
415
+ var newRender = expandStatus.expanded && expandStatus.render;
416
+ if (item.render !== newRender) {
417
+ item.render = newRender;
418
+ changed = true;
419
+ }
364
420
  if (item.hasChildren) {
365
421
  expandedMap.set(item.indent, {
366
422
  expanded: item.expanded,
@@ -371,7 +427,9 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
371
427
  slotEntered = false;
372
428
  }
373
429
  });
374
- this.bumpVersion();
430
+ if (changed) {
431
+ this.bumpVersion();
432
+ }
375
433
  }
376
434
  }, {
377
435
  key: "isResourceViewResponsive",
@@ -931,7 +989,17 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
931
989
  }, {
932
990
  key: "_getEventSlotId",
933
991
  value: function _getEventSlotId(event) {
934
- return this.isEventPerspective ? this._getEventGroupId(event) : event.resourceId;
992
+ if (this.isEventPerspective) {
993
+ return this._getEventGroupId(event);
994
+ }
995
+ // Support for multi-resource events
996
+ if (event.resourceIds && event.resourceIds.length > 0) {
997
+ // For multi-resource events, return the first resourceId for backward compatibility
998
+ // The rendering logic will handle showing on multiple rows
999
+ return event.resourceIds[0];
1000
+ }
1001
+ // Fallback to single resourceId
1002
+ return event.resourceId;
935
1003
  }
936
1004
  }, {
937
1005
  key: "_getEventGroupId",
@@ -1168,9 +1236,10 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
1168
1236
  console.error("Event undefined: ".concat(index));
1169
1237
  throw new Error("Event undefined: ".concat(index));
1170
1238
  }
1171
- if (e.id === undefined || e.resourceId === undefined || e.title === undefined || e.start === undefined || e.end === undefined) {
1172
- console.error('Event property missed', index, e);
1173
- throw new Error("Event property undefined: ".concat(index));
1239
+ var hasResourceTarget = e.resourceId !== undefined || Array.isArray(e.resourceIds) && e.resourceIds.length > 0;
1240
+ if (e.id === undefined || !hasResourceTarget || e.title === undefined || e.start === undefined || e.end === undefined) {
1241
+ console.error('Event property missed (id, resourceId/resourceIds, title, start, end)', index, e);
1242
+ throw new Error("Event property undefined (id/resourceId|resourceIds/title/start/end): ".concat(index));
1174
1243
  }
1175
1244
  });
1176
1245
  }
@@ -1202,42 +1271,54 @@ var SchedulerData = exports["default"] = /*#__PURE__*/function () {
1202
1271
  var cellMaxEventsCount = this.getCellMaxEvents();
1203
1272
  var cellMaxEventsCountValue = 30;
1204
1273
  this.events.forEach(function (item) {
1205
- var resourceEventsList = initRenderData.filter(function (x) {
1206
- return x.slotId === _this6._getEventSlotId(item);
1207
- });
1208
- if (resourceEventsList.length > 0) {
1209
- var resourceEvents = resourceEventsList[0];
1210
- var span = _this6._getSpan(item.start, item.end, _this6.headers);
1211
- var eventStart = new Date(item.start);
1212
- var eventEnd = new Date(item.end);
1213
- var pos = -1;
1214
- resourceEvents.headerItems.forEach(function (header, index) {
1215
- var headerStart = new Date(header.start);
1216
- var headerEnd = new Date(header.end);
1217
- if (headerEnd > eventStart && headerStart < eventEnd) {
1218
- header.count += 1;
1219
- if (header.count > resourceEvents.rowMaxCount) {
1220
- resourceEvents.rowMaxCount = header.count;
1221
- var rowsCount = cellMaxEventsCount <= cellMaxEventsCountValue && resourceEvents.rowMaxCount > cellMaxEventsCount ? cellMaxEventsCount : resourceEvents.rowMaxCount;
1222
- var newRowHeight = rowsCount * _this6.config.eventItemLineHeight + (_this6.config.creatable && _this6.config.checkConflict === false ? 20 : 2);
1223
- if (newRowHeight > resourceEvents.rowHeight) resourceEvents.rowHeight = newRowHeight;
1224
- }
1225
- if (pos === -1) {
1226
- var tmp = 0;
1227
- while (header.events[tmp] !== undefined) tmp += 1;
1228
- pos = tmp;
1229
- }
1230
- var render = headerStart <= eventStart || index === 0;
1231
- if (render === false) {
1232
- var previousHeader = resourceEvents.headerItems[index - 1];
1233
- var previousHeaderStart = new Date(previousHeader.start);
1234
- var previousHeaderEnd = new Date(previousHeader.end);
1235
- if (previousHeaderEnd <= eventStart || previousHeaderStart >= eventEnd) render = true;
1236
- }
1237
- header.events[pos] = _this6._createHeaderEvent(render, span, item);
1238
- }
1239
- });
1274
+ var targetSlotIds = [];
1275
+ if (_this6.isEventPerspective) {
1276
+ targetSlotIds = [_this6._getEventSlotId(item)];
1277
+ } else if (item.resourceIds && item.resourceIds.length > 0) {
1278
+ // Multi-resource event
1279
+ targetSlotIds = item.resourceIds;
1280
+ } else if (item.resourceId) {
1281
+ // Single resource event (backward compatibility)
1282
+ targetSlotIds = [item.resourceId];
1240
1283
  }
1284
+ targetSlotIds.forEach(function (slotId) {
1285
+ var resourceEventsList = initRenderData.filter(function (x) {
1286
+ return x.slotId === slotId;
1287
+ });
1288
+ if (resourceEventsList.length > 0) {
1289
+ var resourceEvents = resourceEventsList[0];
1290
+ var span = _this6._getSpan(item.start, item.end, _this6.headers);
1291
+ var eventStart = new Date(item.start);
1292
+ var eventEnd = new Date(item.end);
1293
+ var pos = -1;
1294
+ resourceEvents.headerItems.forEach(function (header, index) {
1295
+ var headerStart = new Date(header.start);
1296
+ var headerEnd = new Date(header.end);
1297
+ if (headerEnd > eventStart && headerStart < eventEnd) {
1298
+ header.count += 1;
1299
+ if (header.count > resourceEvents.rowMaxCount) {
1300
+ resourceEvents.rowMaxCount = header.count;
1301
+ var rowsCount = cellMaxEventsCount <= cellMaxEventsCountValue && resourceEvents.rowMaxCount > cellMaxEventsCount ? cellMaxEventsCount : resourceEvents.rowMaxCount;
1302
+ var newRowHeight = rowsCount * _this6.config.eventItemLineHeight + (_this6.config.creatable && _this6.config.checkConflict === false ? 20 : 2);
1303
+ if (newRowHeight > resourceEvents.rowHeight) resourceEvents.rowHeight = newRowHeight;
1304
+ }
1305
+ if (pos === -1) {
1306
+ var tmp = 0;
1307
+ while (header.events[tmp] !== undefined) tmp += 1;
1308
+ pos = tmp;
1309
+ }
1310
+ var render = headerStart <= eventStart || index === 0;
1311
+ if (render === false) {
1312
+ var previousHeader = resourceEvents.headerItems[index - 1];
1313
+ var previousHeaderStart = new Date(previousHeader.start);
1314
+ var previousHeaderEnd = new Date(previousHeader.end);
1315
+ if (previousHeaderEnd <= eventStart || previousHeaderStart >= eventEnd) render = true;
1316
+ }
1317
+ header.events[pos] = _this6._createHeaderEvent(render, span, item);
1318
+ }
1319
+ });
1320
+ }
1321
+ });
1241
1322
  });
1242
1323
  if (cellMaxEventsCount <= cellMaxEventsCountValue || this.behaviors.getSummaryFunc !== undefined) {
1243
1324
  initRenderData.forEach(function (resourceEvents) {
@@ -229,9 +229,43 @@ function Scheduler(props) {
229
229
  _useState0 = _slicedToArray(_useState9, 2),
230
230
  resourceScrollbarWidth = _useState0[0],
231
231
  setResourceScrollbarWidth = _useState0[1];
232
- var _useState1 = (0, _react.useState)(0),
232
+ var _useState1 = (0, _react.useState)({
233
+ isSelecting: false,
234
+ selectedResourceIds: [],
235
+ left: 0,
236
+ width: 0
237
+ }),
233
238
  _useState10 = _slicedToArray(_useState1, 2),
234
- setRenderTrigger = _useState10[1];
239
+ selectionState = _useState10[0],
240
+ setSelectionState = _useState10[1];
241
+ var _useState11 = (0, _react.useState)(0),
242
+ _useState12 = _slicedToArray(_useState11, 2),
243
+ setRenderTrigger = _useState12[1];
244
+
245
+ // Callback ref pattern for ResizeObserver to handle parent element reassignment
246
+ var _useState13 = (0, _react.useState)(null),
247
+ _useState14 = _slicedToArray(_useState13, 2),
248
+ parentEl = _useState14[0],
249
+ setParentEl = _useState14[1];
250
+ var setParentRef = (0, _react.useCallback)(function (el) {
251
+ if (parentRef) {
252
+ parentRef.current = el;
253
+ }
254
+ setParentEl(el);
255
+ }, [parentRef]);
256
+
257
+ // Layout/header refs - declare before setSchedulerHeaderRef useCallback
258
+ var schedulerHeaderRef = (0, _react.useRef)(null);
259
+
260
+ // Callback ref pattern for ResizeObserver to handle schedulerHeader element reassignment
261
+ var _useState15 = (0, _react.useState)(null),
262
+ _useState16 = _slicedToArray(_useState15, 2),
263
+ schedulerHeaderEl = _useState16[0],
264
+ setSchedulerHeaderEl = _useState16[1];
265
+ var setSchedulerHeaderRef = (0, _react.useCallback)(function (el) {
266
+ schedulerHeaderRef.current = el;
267
+ setSchedulerHeaderEl(el);
268
+ }, []);
235
269
 
236
270
  // Scroll sync refs
237
271
  var schedulerHeadRef = (0, _react.useRef)(null);
@@ -239,9 +273,6 @@ function Scheduler(props) {
239
273
  var schedulerContentRef = (0, _react.useRef)(null);
240
274
  var schedulerContentBgTableRef = (0, _react.useRef)(null);
241
275
 
242
- // Layout/header refs
243
- var schedulerHeaderRef = (0, _react.useRef)(null);
244
-
245
276
  // Observer refs
246
277
  var ulObserverRef = (0, _react.useRef)(null);
247
278
  var headerObserverRef = (0, _react.useRef)(null);
@@ -280,26 +311,31 @@ function Scheduler(props) {
280
311
  }
281
312
  }, [schedulerData, parentRef, onWindowResize]);
282
313
  (0, _react.useEffect)(function () {
283
- if (parentRef !== undefined && schedulerData.config.responsiveByParent && !!parentRef.current) {
284
- schedulerData._setDocumentWidth(parentRef.current.offsetWidth);
314
+ if (parentRef !== undefined && schedulerData.config.responsiveByParent && !!parentEl) {
315
+ schedulerData._setDocumentWidth(parentEl.offsetWidth);
316
+
317
+ // Disconnect any previous observer to prevent memory leaks
318
+ if (ulObserverRef.current) {
319
+ ulObserverRef.current.disconnect();
320
+ }
285
321
  ulObserverRef.current = new ResizeObserver(function () {
286
- if (parentRef.current) {
287
- schedulerData._setDocumentWidth(parentRef.current.offsetWidth);
288
- schedulerData._setDocumentHeight(parentRef.current.offsetHeight);
322
+ if (parentEl) {
323
+ schedulerData._setDocumentWidth(parentEl.offsetWidth);
324
+ schedulerData._setDocumentHeight(parentEl.offsetHeight);
289
325
  }
290
326
  });
291
- ulObserverRef.current.observe(parentRef.current);
327
+ ulObserverRef.current.observe(parentEl);
292
328
  return function () {
293
- if (ulObserverRef.current && parentRef.current) {
294
- ulObserverRef.current.unobserve(parentRef.current);
329
+ if (ulObserverRef.current) {
330
+ ulObserverRef.current.disconnect();
295
331
  }
296
332
  };
297
333
  }
298
- }, [parentRef, schedulerData]);
334
+ }, [parentEl, parentRef, schedulerData]);
299
335
  (0, _react.useEffect)(function () {
300
- if (schedulerData.config.responsiveByParent && !!schedulerHeaderRef.current) {
301
- schedulerData._setDocumentWidth(schedulerHeaderRef.current.offsetWidth);
302
- schedulerData._setDocumentHeight(schedulerHeaderRef.current.offsetHeight);
336
+ if (schedulerData.config.responsiveByParent && !!schedulerHeaderEl) {
337
+ schedulerData._setDocumentWidth(schedulerHeaderEl.offsetWidth);
338
+ schedulerData._setDocumentHeight(schedulerHeaderEl.offsetHeight);
303
339
  headerObserverRef.current = new ResizeObserver(function (entries) {
304
340
  entries.forEach(function (entry) {
305
341
  var node = entry.target;
@@ -309,14 +345,14 @@ function Scheduler(props) {
309
345
  schedulerData._setSchedulerHeaderHeight(totalHeight);
310
346
  });
311
347
  });
312
- headerObserverRef.current.observe(schedulerHeaderRef.current);
348
+ headerObserverRef.current.observe(schedulerHeaderEl);
313
349
  return function () {
314
- if (headerObserverRef.current && schedulerHeaderRef.current) {
315
- headerObserverRef.current.unobserve(schedulerHeaderRef.current);
350
+ if (headerObserverRef.current && schedulerHeaderEl) {
351
+ headerObserverRef.current.unobserve(schedulerHeaderEl);
316
352
  }
317
353
  };
318
354
  }
319
- }, [schedulerHeaderRef, schedulerData]);
355
+ }, [schedulerHeaderEl, schedulerData]);
320
356
  var resolveScrollbarSize = (0, _react.useCallback)(function () {
321
357
  var prev = scrollbarSizeRef.current;
322
358
  var newContentHeight = schedulerContentRef.current ? schedulerContentRef.current.offsetHeight - schedulerContentRef.current.clientHeight : 17;
@@ -471,6 +507,37 @@ function Scheduler(props) {
471
507
  });
472
508
  }, [renderData]);
473
509
  var eventDndSource = dndContext.getDndSource();
510
+ var handleSelectionChange = (0, _react.useCallback)(function (isSelecting, selectedResourceIds) {
511
+ var preview = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
512
+ var nextSelectedResourceIds = selectedResourceIds || [];
513
+ var nextLeft = preview.left || 0;
514
+ var nextWidth = preview.width || 0;
515
+ setSelectionState(function (prev) {
516
+ var sameIdsLength = prev.selectedResourceIds.length === nextSelectedResourceIds.length;
517
+ var sameIds = sameIdsLength && prev.selectedResourceIds.every(function (id, index) {
518
+ return id === nextSelectedResourceIds[index];
519
+ });
520
+ if (prev.isSelecting === isSelecting && prev.left === nextLeft && prev.width === nextWidth && sameIds) {
521
+ return prev;
522
+ }
523
+ return {
524
+ isSelecting: isSelecting,
525
+ selectedResourceIds: nextSelectedResourceIds,
526
+ left: nextLeft,
527
+ width: nextWidth
528
+ };
529
+ });
530
+ }, []);
531
+ var selectionPreview = (0, _react.useMemo)(function () {
532
+ return {
533
+ isSelecting: selectionState.isSelecting,
534
+ left: selectionState.left,
535
+ width: selectionState.width
536
+ };
537
+ }, [selectionState.isSelecting, selectionState.left, selectionState.width]);
538
+ var selectedIdsSet = (0, _react.useMemo)(function () {
539
+ return new Set(selectionState.selectedResourceIds);
540
+ }, [selectionState.selectedResourceIds]);
474
541
  var resourceEventsList = (0, _react.useMemo)(function () {
475
542
  return displayRenderData.map(function (item) {
476
543
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ResourceEvents["default"], {
@@ -492,10 +559,13 @@ function Scheduler(props) {
492
559
  viewEvent2Click: props.viewEvent2Click,
493
560
  viewEvent2Text: props.viewEvent2Text,
494
561
  newEvent: props.newEvent,
495
- eventItemTemplateResolver: props.eventItemTemplateResolver
562
+ eventItemTemplateResolver: props.eventItemTemplateResolver,
563
+ onSelectionChange: handleSelectionChange,
564
+ isRowSelected: selectedIdsSet.has(item.slotId),
565
+ selectionPreview: selectionPreview
496
566
  }, item.slotId);
497
567
  });
498
- }, [displayRenderData, schedulerData, schedulerDataVersion, eventDndSource, dndContext, props.onSetAddMoreState, props.updateEventStart, props.updateEventEnd, props.moveEvent, props.movingEvent, props.conflictOccurred, props.subtitleGetter, props.eventItemClick, props.viewEventClick, props.viewEventText, props.viewEvent2Click, props.viewEvent2Text, props.newEvent, props.eventItemTemplateResolver]);
568
+ }, [displayRenderData, schedulerData, schedulerDataVersion, eventDndSource, dndContext, props.onSetAddMoreState, props.updateEventStart, props.updateEventEnd, props.moveEvent, props.movingEvent, props.conflictOccurred, props.subtitleGetter, props.eventItemClick, props.viewEventClick, props.viewEventText, props.viewEvent2Click, props.viewEvent2Text, props.newEvent, props.eventItemTemplateResolver, handleSelectionChange, selectedIdsSet, selectionPreview]);
499
569
  var tbodyContent = /*#__PURE__*/(0, _jsxRuntime.jsx)("tr", {});
500
570
  if (showAgenda) {
501
571
  tbodyContent = /*#__PURE__*/(0, _jsxRuntime.jsx)(_AgendaView["default"], {
@@ -515,7 +585,6 @@ function Scheduler(props) {
515
585
  var _config$headerBorderC2, _config$headerBorderC3, _config$weekNumberLab;
516
586
  var resourceTableWidth = schedulerData.getResourceTableWidth();
517
587
  var schedulerContainerWidth = width - (config.resourceViewEnabled ? resourceTableWidth : 0);
518
- var _schedulerWidth = schedulerData.getContentTableWidth() - 1;
519
588
  var contentHeight = config.schedulerContentHeight;
520
589
  var resourcePaddingBottom = resourceScrollbarHeight === 0 ? contentScrollbarHeight : 0;
521
590
  var contentPaddingBottom = contentScrollbarHeight === 0 ? resourceScrollbarHeight : 0;
@@ -582,7 +651,7 @@ function Scheduler(props) {
582
651
  };
583
652
  var schedulerHeadInnerStyle = {
584
653
  paddingRight: "".concat(contentScrollbarWidth, "px"),
585
- width: _schedulerWidth + contentScrollbarWidth
654
+ width: schedulerWidth + contentScrollbarWidth
586
655
  };
587
656
  tbodyContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)("tr", {
588
657
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
@@ -629,7 +698,9 @@ function Scheduler(props) {
629
698
  slotClickedFunc: props.slotClickedFunc,
630
699
  slotItemTemplateResolver: props.slotItemTemplateResolver,
631
700
  toggleExpandFunc: props.toggleExpandFunc,
632
- CustomResourceCell: props.CustomResourceCell
701
+ CustomResourceCell: props.CustomResourceCell,
702
+ isSelecting: selectionState.isSelecting,
703
+ selectedResourceIds: selectionState.selectedResourceIds
633
704
  })
634
705
  })]
635
706
  })
@@ -704,7 +775,7 @@ function Scheduler(props) {
704
775
  }, [config.headerEnabled]);
705
776
  var schedulerHeader = (0, _react.useMemo)(function () {
706
777
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SchedulerHeader["default"], {
707
- ref: schedulerHeaderRef,
778
+ ref: setSchedulerHeaderRef,
708
779
  style: schedulerHeaderStyle,
709
780
  onViewChange: handleViewChange,
710
781
  schedulerData: schedulerData,
@@ -724,6 +795,7 @@ function Scheduler(props) {
724
795
  id: "rbs-root",
725
796
  className: "rbs",
726
797
  style: rootTableStyle,
798
+ ref: setParentRef,
727
799
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("thead", {
728
800
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("tr", {
729
801
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
@@ -36,6 +36,8 @@
36
36
  .rbs {
37
37
  margin: 20px auto;
38
38
  border-spacing: 0;
39
+ --selection-bg: rgba(0, 123, 255, 0.1);
40
+ --selection-border: #007bff;
39
41
  }
40
42
 
41
43
  .rbs td {
@@ -198,6 +200,18 @@
198
200
  position: absolute;
199
201
  }
200
202
 
203
+ .rbs .vertical-selection-overlay {
204
+ position: absolute;
205
+ top: 0;
206
+ left: 0;
207
+ width: 100%;
208
+ height: 100%;
209
+ background-color: var(--selection-bg);
210
+ border: 2px dashed var(--selection-border);
211
+ pointer-events: none;
212
+ z-index: 10;
213
+ }
214
+
201
215
  /* Slots and Cells */
202
216
  .rbs .slot-cell,
203
217
  .rbs .slot-text {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-big-schedule",
3
- "version": "5.4.10-beta.2",
3
+ "version": "5.5.0",
4
4
  "description": "React Big Schedule is a powerful and intuitive scheduler and resource planning solution built with React. Seamlessly integrate this modern browser-compatible component into your applications to effectively manage time, appointments, and resources. With drag-and-drop functionality, interactive UI, and granular views, react-big-schedule empowers users to effortlessly schedule and allocate resources with precision. Enhance productivity and streamline your workflow with this React-based solution, designed to optimize time management and simplify calendar-based operations. Perfect for applications requiring advanced scheduling capabilities, react-big-schedule offers a seamless and intuitive experience for managing appointments, resource allocation, and time slots. Unlock the potential of your React projects with react-big-schedule and revolutionize the way you handle scheduling and resource planning. It is the updated version of react-big-scheduler",
5
5
  "keywords": [
6
6
  "react-big-schedule",
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "@ant-design/icons": "^6.2.2",
68
- "antd": "^6.3.6",
68
+ "antd": "^6.3.7",
69
69
  "dayjs": "^1.11.20",
70
70
  "prop-types": "^15.8.1",
71
71
  "react": "^19.2.5",