@kne/react-calendar 1.0.0 → 1.0.1

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/dist/index.js CHANGED
@@ -909,18 +909,44 @@ const ViewPanel = ({
909
909
  });
910
910
  };
911
911
 
912
- const LONG_PRESS_DELAY = 360;
913
- const MOVE_THRESHOLD = 18;
912
+ const LONG_PRESS_DELAY = 400;
913
+ const SCROLL_CANCEL_THRESHOLD = 12;
914
+ const TAP_MOVE_THRESHOLD = 8;
914
915
  const getPopoverKey = slot => slot ? `form:${slot.key}` : null;
915
- const getSlotElementFromTouch = (container, touch) => {
916
- const element = document.elementFromPoint(touch.clientX, touch.clientY);
917
- const slotElement = element?.closest?.('[data-slot-index]');
918
- if (!slotElement || !container?.contains(slotElement)) {
916
+ const getSlotIndexFromPoint = (container, clientX, clientY) => {
917
+ const slotElements = container?.querySelectorAll?.('[data-slot-index]');
918
+ if (!slotElements?.length) {
919
919
  return null;
920
920
  }
921
- return slotElement;
921
+ let closestIndex = null;
922
+ let closestDistance = Infinity;
923
+ for (const candidate of slotElements) {
924
+ const rect = candidate.getBoundingClientRect();
925
+ const index = Number(candidate.getAttribute('data-slot-index'));
926
+ if (Number.isNaN(index)) {
927
+ continue;
928
+ }
929
+ if (clientY >= rect.top && clientY <= rect.bottom && clientX >= rect.left && clientX <= rect.right) {
930
+ return index;
931
+ }
932
+ if (clientX < rect.left || clientX > rect.right) {
933
+ continue;
934
+ }
935
+ const centerY = (rect.top + rect.bottom) / 2;
936
+ const distance = Math.abs(clientY - centerY);
937
+ if (distance < closestDistance) {
938
+ closestDistance = distance;
939
+ closestIndex = index;
940
+ }
941
+ }
942
+ return closestIndex;
943
+ };
944
+ const clearDocumentTextSelection = () => {
945
+ const selection = document.getSelection?.();
946
+ if (selection && !selection.isCollapsed) {
947
+ selection.removeAllRanges();
948
+ }
922
949
  };
923
- const getTouchPoint = event => event.changedTouches?.[0] || event.touches?.[0];
924
950
  const useScheduleSelectionGesture = ({
925
951
  slots,
926
952
  selectedSlots,
@@ -938,9 +964,14 @@ const useScheduleSelectionGesture = ({
938
964
  const touchStateRef = react.useRef(null);
939
965
  const slotsDataRef = react.useRef(slots);
940
966
  const selectedSlotsRef = react.useRef(selectedSlots);
967
+ const allowMultiSelectRef = react.useRef(allowMultiSelect);
941
968
  const suppressTriggerUntilRef = react.useRef(0);
969
+ const suppressMouseUntilRef = react.useRef(0);
970
+ const scrollLockRef = react.useRef(null);
971
+ const handlersRef = react.useRef({});
942
972
  slotsDataRef.current = slots;
943
973
  selectedSlotsRef.current = selectedSlots;
974
+ allowMultiSelectRef.current = allowMultiSelect;
944
975
  const selectedKeys = react.useMemo(() => new Set(selectedSlots.map(slot => slot.key)), [selectedSlots]);
945
976
  const selectedAnchorKey = selectedSlots[selectedSlots.length - 1]?.key;
946
977
  const formPopoverKey = selectedAnchorKey ? `form:${selectedAnchorKey}` : null;
@@ -950,16 +981,55 @@ const useScheduleSelectionGesture = ({
950
981
  longPressTimerRef.current = null;
951
982
  }
952
983
  }, []);
984
+ const unlockContainerScroll = react.useCallback(() => {
985
+ const container = slotsRef.current;
986
+ if (!container || scrollLockRef.current == null) {
987
+ return;
988
+ }
989
+ const scrollTop = scrollLockRef.current;
990
+ container.style.overflow = '';
991
+ container.style.touchAction = '';
992
+ container.scrollTop = scrollTop;
993
+ scrollLockRef.current = null;
994
+ }, []);
995
+ const lockContainerScroll = react.useCallback(() => {
996
+ const container = slotsRef.current;
997
+ if (!container || scrollLockRef.current != null) {
998
+ return;
999
+ }
1000
+ scrollLockRef.current = container.scrollTop;
1001
+ container.style.overflow = 'hidden';
1002
+ container.style.touchAction = 'none';
1003
+ }, []);
1004
+ const resetGestureState = react.useCallback(() => {
1005
+ clearLongPress();
1006
+ const container = slotsRef.current;
1007
+ const touchState = touchStateRef.current;
1008
+ if (container && touchState?.pointerId != null && container.hasPointerCapture?.(touchState.pointerId)) {
1009
+ try {
1010
+ container.releasePointerCapture(touchState.pointerId);
1011
+ } catch {
1012
+ // Ignore capture release errors on stale pointers.
1013
+ }
1014
+ }
1015
+ draggingRef.current = false;
1016
+ dragStartIndexRef.current = null;
1017
+ touchStateRef.current = null;
1018
+ container?.classList.remove('schedule-calendar-touch-dragging');
1019
+ unlockContainerScroll();
1020
+ setDragging(false);
1021
+ }, [clearLongPress, unlockContainerScroll]);
953
1022
  const selectSlots = react.useCallback(nextSlots => {
954
1023
  selectedSlotsRef.current = nextSlots;
955
1024
  if (!nextSlots.length) {
956
1025
  setActivePopoverKey(null);
1026
+ resetGestureState();
957
1027
  }
958
1028
  setSelectedSlots(nextSlots);
959
1029
  onSlotRangeChange?.(nextSlots, {
960
1030
  action: nextSlots.length ? 'select' : 'clear'
961
1031
  });
962
- }, [onSlotRangeChange, setSelectedSlots]);
1032
+ }, [onSlotRangeChange, resetGestureState, setSelectedSlots]);
963
1033
  const getSelectableRange = react.useCallback((startIndex, endIndex) => {
964
1034
  const [start, end] = [Math.min(startIndex, endIndex), Math.max(startIndex, endIndex)];
965
1035
  return slotsDataRef.current.slice(start, end + 1).filter(slot => slot.status === 'free');
@@ -971,12 +1041,17 @@ const useScheduleSelectionGesture = ({
971
1041
  }
972
1042
  }, []);
973
1043
  const startSlotSelection = react.useCallback((slot, index, {
974
- showPopover = true
1044
+ showPopover = true,
1045
+ lockScroll = false
975
1046
  } = {}) => {
1047
+ clearDocumentTextSelection();
976
1048
  setActivePopoverKey(getPopoverKey(slot));
977
1049
  draggingRef.current = true;
978
1050
  dragStartIndexRef.current = index;
979
1051
  slotsRef.current?.classList.add('schedule-calendar-touch-dragging');
1052
+ if (lockScroll) {
1053
+ lockContainerScroll();
1054
+ }
980
1055
  setDragging(true);
981
1056
  selectSlots([slot]);
982
1057
  if (!showPopover) {
@@ -984,43 +1059,58 @@ const useScheduleSelectionGesture = ({
984
1059
  setActivePopoverKey(null);
985
1060
  }
986
1061
  onFreeSlotClick?.(slot);
987
- }, [onFreeSlotClick, selectSlots]);
1062
+ }, [lockContainerScroll, onFreeSlotClick, selectSlots]);
988
1063
  const finishSelection = react.useCallback(({
989
1064
  fromTouch = false
990
1065
  } = {}) => {
991
- clearLongPress();
992
- draggingRef.current = false;
993
- dragStartIndexRef.current = null;
994
- slotsRef.current?.classList.remove('schedule-calendar-touch-dragging');
995
- setDragging(false);
996
- if (selectedSlotsRef.current.length) {
1066
+ const hadSelection = selectedSlotsRef.current.length > 0;
1067
+ resetGestureState();
1068
+ if (hadSelection) {
997
1069
  if (fromTouch) {
998
1070
  suppressTriggerUntilRef.current = Date.now() + 500;
999
1071
  }
1000
1072
  showFormPopoverForSlots(selectedSlotsRef.current);
1001
1073
  }
1002
- }, [clearLongPress, showFormPopoverForSlots]);
1074
+ }, [resetGestureState, showFormPopoverForSlots]);
1003
1075
  const updateSelectionRange = react.useCallback(index => {
1004
1076
  const startIndex = dragStartIndexRef.current;
1005
- if (startIndex === null || !allowMultiSelect) {
1077
+ if (startIndex === null || !allowMultiSelectRef.current) {
1006
1078
  return;
1007
1079
  }
1008
1080
  const nextSlots = getSelectableRange(startIndex, index);
1009
1081
  selectSlots(nextSlots);
1010
- }, [allowMultiSelect, getSelectableRange, selectSlots]);
1082
+ }, [getSelectableRange, selectSlots]);
1083
+ const shouldIgnoreMouseSelectionEvent = react.useCallback(() => {
1084
+ return !!touchStateRef.current || Date.now() < suppressMouseUntilRef.current;
1085
+ }, []);
1011
1086
  const handleMouseDown = react.useCallback((event, slot, index) => {
1087
+ if (shouldIgnoreMouseSelectionEvent()) {
1088
+ return;
1089
+ }
1012
1090
  if (slot.status !== 'free') {
1013
1091
  return;
1014
1092
  }
1015
1093
  event.preventDefault();
1016
1094
  startSlotSelection(slot, index);
1017
- }, [startSlotSelection]);
1095
+ }, [shouldIgnoreMouseSelectionEvent, startSlotSelection]);
1018
1096
  const handleMouseEnter = react.useCallback(index => {
1019
- if (!draggingRef.current) {
1097
+ if (shouldIgnoreMouseSelectionEvent() || !draggingRef.current) {
1020
1098
  return;
1021
1099
  }
1022
1100
  updateSelectionRange(index);
1023
- }, [updateSelectionRange]);
1101
+ }, [shouldIgnoreMouseSelectionEvent, updateSelectionRange]);
1102
+ const handleMouseUp = react.useCallback(() => {
1103
+ if (shouldIgnoreMouseSelectionEvent()) {
1104
+ return;
1105
+ }
1106
+ finishSelection();
1107
+ }, [finishSelection, shouldIgnoreMouseSelectionEvent]);
1108
+ const handleMouseLeave = react.useCallback(() => {
1109
+ if (shouldIgnoreMouseSelectionEvent()) {
1110
+ return;
1111
+ }
1112
+ finishSelection();
1113
+ }, [finishSelection, shouldIgnoreMouseSelectionEvent]);
1024
1114
  const handlePopoverOpenChange = react.useCallback((open, currentPopoverKey, {
1025
1115
  isForm = false
1026
1116
  } = {}) => {
@@ -1038,25 +1128,77 @@ const useScheduleSelectionGesture = ({
1038
1128
  return prevKey === currentPopoverKey ? null : prevKey;
1039
1129
  });
1040
1130
  }, [selectSlots]);
1131
+ handlersRef.current = {
1132
+ clearLongPress,
1133
+ finishSelection,
1134
+ onFreeSlotClick,
1135
+ resetGestureState,
1136
+ selectSlots,
1137
+ showFormPopoverForSlots,
1138
+ startSlotSelection,
1139
+ updateSelectionRange
1140
+ };
1041
1141
  react.useEffect(() => {
1042
1142
  const container = slotsRef.current;
1043
1143
  if (!container) {
1044
1144
  return undefined;
1045
1145
  }
1046
- const clearTouchState = () => {
1047
- clearLongPress();
1048
- if (!draggingRef.current) {
1049
- slotsRef.current?.classList.remove('schedule-calendar-touch-dragging');
1146
+ const releasePointerCapture = pointerId => {
1147
+ if (pointerId == null || !container.hasPointerCapture?.(pointerId)) {
1148
+ return;
1149
+ }
1150
+ try {
1151
+ container.releasePointerCapture(pointerId);
1152
+ } catch {
1153
+ // Ignore capture release errors on stale pointers.
1050
1154
  }
1155
+ };
1156
+ const clearPendingTouch = () => {
1157
+ handlersRef.current.clearLongPress();
1051
1158
  touchStateRef.current = null;
1052
1159
  };
1053
- const handleTouchStart = event => {
1054
- if (event.touches.length !== 1) {
1160
+ const isStillOnSameSlot = (touchState, clientX, clientY) => {
1161
+ const currentIndex = getSlotIndexFromPoint(container, clientX, clientY);
1162
+ return currentIndex === touchState.index;
1163
+ };
1164
+ const shouldCancelPendingGesture = (touchState, clientX, clientY) => {
1165
+ const moveX = Math.abs(clientX - touchState.x);
1166
+ const moveY = Math.abs(clientY - touchState.y);
1167
+ if (moveY > SCROLL_CANCEL_THRESHOLD) {
1168
+ return true;
1169
+ }
1170
+ if (!isStillOnSameSlot(touchState, clientX, clientY)) {
1171
+ return true;
1172
+ }
1173
+ if (!allowMultiSelectRef.current && (moveX > TAP_MOVE_THRESHOLD || moveY > TAP_MOVE_THRESHOLD)) {
1174
+ return true;
1175
+ }
1176
+ return false;
1177
+ };
1178
+ const activateLongPress = touchState => {
1179
+ if (!isStillOnSameSlot(touchState, touchState.lastX, touchState.lastY)) {
1180
+ return;
1181
+ }
1182
+ touchState.longPressed = true;
1183
+ touchState.active = true;
1184
+ clearDocumentTextSelection();
1185
+ try {
1186
+ container.setPointerCapture(touchState.pointerId);
1187
+ } catch {
1188
+ // Continue when capture is unavailable.
1189
+ }
1190
+ slotsRef.current?.classList.add('schedule-calendar-touch-dragging');
1191
+ handlersRef.current.startSlotSelection(touchState.slot, touchState.index, {
1192
+ showPopover: false,
1193
+ lockScroll: true
1194
+ });
1195
+ };
1196
+ const handlePointerDown = event => {
1197
+ if (event.pointerType === 'mouse' || event.isPrimary === false) {
1055
1198
  return;
1056
1199
  }
1057
- const touch = event.touches[0];
1058
- const slotElement = getSlotElementFromTouch(container, touch);
1059
- if (!slotElement) {
1200
+ const slotElement = event.target?.closest?.('[data-slot-index]');
1201
+ if (!slotElement || !container.contains(slotElement)) {
1060
1202
  return;
1061
1203
  }
1062
1204
  const index = Number(slotElement.getAttribute('data-slot-index'));
@@ -1064,114 +1206,134 @@ const useScheduleSelectionGesture = ({
1064
1206
  if (Number.isNaN(index) || slot?.status !== 'free') {
1065
1207
  return;
1066
1208
  }
1067
- clearTouchState();
1209
+ handlersRef.current.resetGestureState();
1068
1210
  touchStateRef.current = {
1069
- identifier: touch.identifier,
1070
- x: touch.clientX,
1071
- y: touch.clientY,
1211
+ pointerId: event.pointerId,
1212
+ x: event.clientX,
1213
+ y: event.clientY,
1214
+ lastX: event.clientX,
1215
+ lastY: event.clientY,
1072
1216
  slot,
1073
1217
  index,
1074
1218
  moved: false,
1075
1219
  longPressed: false,
1076
- active: false
1220
+ active: false,
1221
+ selectionTriggered: false
1077
1222
  };
1223
+ if (!allowMultiSelectRef.current) {
1224
+ return;
1225
+ }
1078
1226
  longPressTimerRef.current = window.setTimeout(() => {
1079
1227
  const touchState = touchStateRef.current;
1080
- if (!touchState) {
1228
+ if (!touchState || touchState.pointerId !== event.pointerId || touchState.moved) {
1081
1229
  return;
1082
1230
  }
1083
- touchState.longPressed = true;
1084
- touchState.active = true;
1085
- slotsRef.current?.classList.add('schedule-calendar-touch-dragging');
1086
- startSlotSelection(slot, index, {
1087
- showPopover: false
1088
- });
1231
+ activateLongPress(touchState);
1089
1232
  longPressTimerRef.current = null;
1090
1233
  }, LONG_PRESS_DELAY);
1091
1234
  };
1092
- const handleTouchMove = event => {
1235
+ const handlePointerMove = event => {
1093
1236
  const touchState = touchStateRef.current;
1094
- if (!touchState) {
1095
- return;
1096
- }
1097
- const touch = Array.from(event.touches).find(item => item.identifier === touchState.identifier) || event.touches[0];
1098
- if (!touch) {
1237
+ if (!touchState || event.pointerId !== touchState.pointerId) {
1099
1238
  return;
1100
1239
  }
1240
+ touchState.lastX = event.clientX;
1241
+ touchState.lastY = event.clientY;
1101
1242
  if (!touchState.active) {
1102
- const moveX = Math.abs(touch.clientX - touchState.x);
1103
- const moveY = Math.abs(touch.clientY - touchState.y);
1104
- if (moveX > MOVE_THRESHOLD || moveY > MOVE_THRESHOLD) {
1243
+ if (shouldCancelPendingGesture(touchState, event.clientX, event.clientY)) {
1105
1244
  touchState.moved = true;
1106
- clearTouchState();
1245
+ clearPendingTouch();
1107
1246
  }
1108
1247
  return;
1109
1248
  }
1110
1249
  event.preventDefault();
1111
- const slotElement = getSlotElementFromTouch(container, touch);
1112
- if (!slotElement) {
1113
- return;
1114
- }
1115
- const index = Number(slotElement.getAttribute('data-slot-index'));
1116
- if (!Number.isNaN(index)) {
1117
- updateSelectionRange(index);
1250
+ event.stopPropagation();
1251
+ clearDocumentTextSelection();
1252
+ const index = getSlotIndexFromPoint(container, event.clientX, event.clientY);
1253
+ if (index !== null) {
1254
+ handlersRef.current.updateSelectionRange(index);
1118
1255
  }
1119
1256
  };
1120
- const handleTouchEnd = event => {
1257
+ const handlePointerUp = event => {
1121
1258
  const touchState = touchStateRef.current;
1122
- if (!touchState) {
1123
- return;
1124
- }
1125
- const touch = Array.from(event.changedTouches || []).find(item => item.identifier === touchState.identifier) || getTouchPoint(event);
1126
- if (!touch) {
1127
- clearTouchState();
1259
+ if (!touchState || event.pointerId !== touchState.pointerId) {
1128
1260
  return;
1129
1261
  }
1262
+ releasePointerCapture(event.pointerId);
1263
+ suppressMouseUntilRef.current = Date.now() + 700;
1130
1264
  if (touchState.active) {
1131
1265
  event.preventDefault();
1266
+ touchState.selectionTriggered = true;
1267
+ const index = getSlotIndexFromPoint(container, event.clientX, event.clientY);
1268
+ if (index !== null) {
1269
+ handlersRef.current.updateSelectionRange(index);
1270
+ }
1132
1271
  suppressTriggerUntilRef.current = Date.now() + 500;
1133
- finishSelection({
1272
+ handlersRef.current.finishSelection({
1134
1273
  fromTouch: true
1135
1274
  });
1136
- touchStateRef.current = null;
1137
1275
  return;
1138
1276
  }
1139
- const quickTap = !touchState.longPressed && !touchState.moved;
1140
- clearTouchState();
1277
+ handlersRef.current.clearLongPress();
1278
+ const quickTap = !touchState.moved && !touchState.longPressed && Math.abs(event.clientX - touchState.x) <= TAP_MOVE_THRESHOLD && Math.abs(event.clientY - touchState.y) <= TAP_MOVE_THRESHOLD && isStillOnSameSlot(touchState, event.clientX, event.clientY);
1279
+ const {
1280
+ slot
1281
+ } = touchState;
1282
+ touchStateRef.current = null;
1141
1283
  if (quickTap) {
1284
+ touchState.selectionTriggered = true;
1142
1285
  suppressTriggerUntilRef.current = Date.now() + 500;
1143
- selectSlots([touchState.slot]);
1144
- showFormPopoverForSlots([touchState.slot]);
1145
- onFreeSlotClick?.(touchState.slot);
1286
+ handlersRef.current.selectSlots([slot]);
1287
+ handlersRef.current.showFormPopoverForSlots([slot]);
1288
+ handlersRef.current.onFreeSlotClick?.(slot);
1289
+ return;
1146
1290
  }
1291
+ handlersRef.current.resetGestureState();
1147
1292
  };
1148
1293
  const handleContextMenu = event => {
1149
- if (touchStateRef.current || draggingRef.current) {
1294
+ if (touchStateRef.current?.active || draggingRef.current) {
1150
1295
  event.preventDefault();
1151
1296
  }
1152
1297
  };
1153
- container.addEventListener('touchstart', handleTouchStart, {
1298
+ const handleSelectStart = event => {
1299
+ if (!touchStateRef.current?.active && !draggingRef.current) {
1300
+ return;
1301
+ }
1302
+ event.preventDefault();
1303
+ };
1304
+ const handleTouchMove = event => {
1305
+ if (!draggingRef.current && !touchStateRef.current?.active) {
1306
+ return;
1307
+ }
1308
+ event.preventDefault();
1309
+ };
1310
+ const touchOptions = {
1311
+ passive: false,
1312
+ capture: true
1313
+ };
1314
+ container.addEventListener('pointerdown', handlePointerDown, {
1154
1315
  passive: true
1155
1316
  });
1156
- container.addEventListener('touchmove', handleTouchMove, {
1317
+ container.addEventListener('pointermove', handlePointerMove, {
1157
1318
  passive: false
1158
1319
  });
1159
- container.addEventListener('touchend', handleTouchEnd, {
1320
+ container.addEventListener('pointerup', handlePointerUp, {
1160
1321
  passive: false
1161
1322
  });
1162
- container.addEventListener('touchcancel', handleTouchEnd, {
1323
+ container.addEventListener('pointercancel', handlePointerUp, {
1163
1324
  passive: false
1164
1325
  });
1326
+ container.addEventListener('touchmove', handleTouchMove, touchOptions);
1165
1327
  container.addEventListener('contextmenu', handleContextMenu);
1328
+ container.addEventListener('selectstart', handleSelectStart);
1166
1329
  return () => {
1167
- clearTouchState();
1168
- container.removeEventListener('touchstart', handleTouchStart);
1169
- container.removeEventListener('touchmove', handleTouchMove);
1170
- container.removeEventListener('touchend', handleTouchEnd);
1171
- container.removeEventListener('touchcancel', handleTouchEnd);
1172
- container.removeEventListener('contextmenu', handleContextMenu);
1330
+ releasePointerCapture(touchStateRef.current?.pointerId);
1331
+ handlersRef.current.clearLongPress();
1332
+ handlersRef.current.resetGestureState();
1333
+ longPressTimerRef.current = null;
1334
+ container.removeEventListener('touchmove', handleTouchMove, touchOptions);
1173
1335
  };
1174
- }, [clearLongPress, finishSelection, onFreeSlotClick, selectSlots, showFormPopoverForSlots, startSlotSelection, updateSelectionRange]);
1336
+ }, []);
1175
1337
  return {
1176
1338
  activePopoverKey,
1177
1339
  dragging,
@@ -1184,6 +1346,8 @@ const useScheduleSelectionGesture = ({
1184
1346
  finishSelection,
1185
1347
  handleMouseDown,
1186
1348
  handleMouseEnter,
1349
+ handleMouseUp,
1350
+ handleMouseLeave,
1187
1351
  handlePopoverOpenChange
1188
1352
  };
1189
1353
  };
@@ -1263,6 +1427,7 @@ const SlotItem = ({
1263
1427
  if (content) {
1264
1428
  const customNode = /*#__PURE__*/jsxRuntime.jsx("div", {
1265
1429
  "data-slot-index": slot.index,
1430
+ "data-slot-status": slot.status,
1266
1431
  onContextMenu: onContextMenu,
1267
1432
  onMouseDown: onMouseDown,
1268
1433
  onPointerDown: onPointerDown,
@@ -1322,19 +1487,10 @@ const SlotItem = ({
1322
1487
  }
1323
1488
  return node;
1324
1489
  };
1325
- const inner = /*#__PURE__*/jsxRuntime.jsxs("button", {
1326
- type: "button",
1327
- className: classNames(style$1['slot-item'], style$1[`slot-${slot.status}`], {
1328
- [style$1['slot-selected']]: selected
1329
- }),
1330
- "data-slot-index": slot.index,
1331
- disabled: slot.status === 'disabled',
1332
- onContextMenu: onContextMenu,
1333
- onMouseDown: onMouseDown,
1334
- onPointerDown: onPointerDown,
1335
- onMouseEnter: onMouseEnter,
1336
- onMouseUp: onMouseUp,
1337
- onClick: onClick,
1490
+ const slotClassName = classNames(style$1['slot-item'], style$1[`slot-${slot.status}`], {
1491
+ [style$1['slot-selected']]: selected
1492
+ });
1493
+ const slotChildren = /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1338
1494
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1339
1495
  className: style$1['slot-dot']
1340
1496
  }), /*#__PURE__*/jsxRuntime.jsx("span", {
@@ -1358,6 +1514,36 @@ const SlotItem = ({
1358
1514
  children: slot.events.map(event => event.title).join('、')
1359
1515
  }) : null]
1360
1516
  });
1517
+ const slotHandlers = {
1518
+ onContextMenu,
1519
+ onMouseDown,
1520
+ onPointerDown,
1521
+ onMouseEnter,
1522
+ onMouseUp,
1523
+ onClick
1524
+ };
1525
+ const inner = slot.status === 'disabled' ? /*#__PURE__*/jsxRuntime.jsx("button", {
1526
+ type: "button",
1527
+ className: slotClassName,
1528
+ "data-slot-index": slot.index,
1529
+ "data-slot-status": slot.status,
1530
+ disabled: true,
1531
+ onContextMenu: onContextMenu,
1532
+ onMouseDown: onMouseDown,
1533
+ onPointerDown: onPointerDown,
1534
+ onMouseEnter: onMouseEnter,
1535
+ onMouseUp: onMouseUp,
1536
+ onClick: onClick,
1537
+ children: slotChildren
1538
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
1539
+ role: "button",
1540
+ tabIndex: 0,
1541
+ className: slotClassName,
1542
+ "data-slot-index": slot.index,
1543
+ "data-slot-status": slot.status,
1544
+ ...slotHandlers,
1545
+ children: slotChildren
1546
+ });
1361
1547
  return wrapWithPopover(inner);
1362
1548
  };
1363
1549
 
@@ -1407,9 +1593,10 @@ const SchedulePanel = ({
1407
1593
  selectedKeys,
1408
1594
  selectSlots,
1409
1595
  slotsRef,
1410
- finishSelection,
1411
1596
  handleMouseDown,
1412
1597
  handleMouseEnter,
1598
+ handleMouseUp,
1599
+ handleMouseLeave,
1413
1600
  handlePopoverOpenChange
1414
1601
  } = useScheduleSelectionGesture({
1415
1602
  slots,
@@ -1487,8 +1674,8 @@ const SchedulePanel = ({
1487
1674
  [style$1['slots-dragging']]: dragging
1488
1675
  }),
1489
1676
  onScroll: onScroll,
1490
- onMouseUp: () => finishSelection(),
1491
- onMouseLeave: () => finishSelection(),
1677
+ onMouseUp: handleMouseUp,
1678
+ onMouseLeave: handleMouseLeave,
1492
1679
  children: [/*#__PURE__*/jsxRuntime.jsx(PanelScrollShadow, {
1493
1680
  visible: scrolled
1494
1681
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
@@ -1519,7 +1706,7 @@ const SchedulePanel = ({
1519
1706
  },
1520
1707
  onMouseDown: event => handleMouseDown(event, slot, index),
1521
1708
  onMouseEnter: () => handleMouseEnter(index),
1522
- onMouseUp: () => finishSelection(),
1709
+ onMouseUp: handleMouseUp,
1523
1710
  onClick: undefined
1524
1711
  }, slot.key);
1525
1712
  })