@super-calendar/dom 2.3.1 → 2.4.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.
- package/dist/index.d.mts +80 -222
- package/dist/index.d.ts +80 -222
- package/dist/index.js +429 -69
- package/dist/index.mjs +432 -72
- package/package.json +2 -2
- package/src/Calendar.tsx +192 -50
- package/src/ResourceTimeline.tsx +215 -9
- package/src/TimeGrid.tsx +345 -72
package/dist/index.js
CHANGED
|
@@ -728,9 +728,20 @@ function MonthView({ date, weekStartsOn = 0, weekdayFormat = "short", events, ev
|
|
|
728
728
|
}
|
|
729
729
|
//#endregion
|
|
730
730
|
//#region src/TimeGrid.tsx
|
|
731
|
-
const
|
|
732
|
-
const GUTTER_WIDTH = 56;
|
|
731
|
+
const GUTTER_WIDTH$1 = 56;
|
|
733
732
|
const clamp$1 = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
733
|
+
const VISUALLY_HIDDEN = {
|
|
734
|
+
position: "absolute",
|
|
735
|
+
width: 1,
|
|
736
|
+
height: 1,
|
|
737
|
+
padding: 0,
|
|
738
|
+
margin: -1,
|
|
739
|
+
overflow: "hidden",
|
|
740
|
+
clip: "rect(0 0 0 0)",
|
|
741
|
+
clipPath: "inset(50%)",
|
|
742
|
+
whiteSpace: "nowrap",
|
|
743
|
+
border: 0
|
|
744
|
+
};
|
|
734
745
|
const DOM_TITLE_LINE_HEIGHT = 16;
|
|
735
746
|
const DOM_TIME_LINE_HEIGHT = 30;
|
|
736
747
|
const DOM_BOX_PADDING_V = 2;
|
|
@@ -801,6 +812,17 @@ function DefaultDomEvent({ event, mode, isAllDay, boxHeight, ampm = false, theme
|
|
|
801
812
|
}) : null]
|
|
802
813
|
});
|
|
803
814
|
}
|
|
815
|
+
const NOW_TICK_MS = 6e4;
|
|
816
|
+
function useNow(enabled) {
|
|
817
|
+
const [now, setNow] = (0, react.useState)(() => /* @__PURE__ */ new Date());
|
|
818
|
+
(0, react.useEffect)(() => {
|
|
819
|
+
if (!enabled) return;
|
|
820
|
+
setNow(/* @__PURE__ */ new Date());
|
|
821
|
+
const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), NOW_TICK_MS);
|
|
822
|
+
return () => clearInterval(id);
|
|
823
|
+
}, [enabled]);
|
|
824
|
+
return now;
|
|
825
|
+
}
|
|
804
826
|
/**
|
|
805
827
|
* A day / week / N-day time grid rendered with plain DOM elements. Events are
|
|
806
828
|
* positioned with the library's pure `layoutDayEvents`, so overlap columns and
|
|
@@ -812,7 +834,7 @@ function DefaultDomEvent({ event, mode, isAllDay, boxHeight, ampm = false, theme
|
|
|
812
834
|
* <TimeGrid mode="week" date={new Date()} events={events} />
|
|
813
835
|
* ```
|
|
814
836
|
*/
|
|
815
|
-
function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStartsOn = 0, weekdayFormat = "short", hourHeight: initialHourHeight = 48, scrollOffsetMinutes = 480, zoomable = true, minHourHeight = 24, maxHourHeight = 160, dragStepMinutes = 15, ampm = false, timeslots = 1, businessHours, showNowIndicator = true, showAllDayEventCell = true, locale, theme: themeOverrides, height = 600, renderEvent, eventAccessibilityLabel, hourComponent, onPressEvent, onPressDateHeader, onPressCell, onCreateEvent, onDragStart, onDragEvent, className, style, classNames, styles }) {
|
|
837
|
+
function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStartsOn = 0, weekdayFormat = "short", hourHeight: initialHourHeight = 48, scrollOffsetMinutes = 480, zoomable = true, minHourHeight = 24, maxHourHeight = 160, dragStepMinutes = 15, ampm = false, timeslots = 1, minHour = 0, maxHour = 24, hideHours = false, showWeekNumber = false, weekNumberPrefix = "W", keyboardEventNavigation = false, businessHours, showNowIndicator = true, showAllDayEventCell = true, locale, theme: themeOverrides, height = 600, renderEvent, eventAccessibilityLabel, hourComponent, onPressEvent, onPressDateHeader, onPressCell, onCreateEvent, onDragStart, onDragEvent, className, style, classNames, styles }) {
|
|
816
838
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
817
839
|
const slot = createSlots({
|
|
818
840
|
classNames,
|
|
@@ -821,6 +843,12 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
821
843
|
const scrollRef = (0, react.useRef)(null);
|
|
822
844
|
const dfns = locale ? { locale } : void 0;
|
|
823
845
|
const snapHours = dragStepMinutes / 60;
|
|
846
|
+
const windowStart = Math.max(0, Math.min(minHour, 23));
|
|
847
|
+
const windowEnd = Math.max(windowStart + 1, Math.min(maxHour, 24));
|
|
848
|
+
const windowHours = windowEnd - windowStart;
|
|
849
|
+
const gutterWidth = hideHours ? 0 : GUTTER_WIDTH$1;
|
|
850
|
+
const visibleHours = (0, react.useMemo)(() => Array.from({ length: windowHours }, (_, i) => windowStart + i), [windowStart, windowHours]);
|
|
851
|
+
const now = useNow(showNowIndicator);
|
|
824
852
|
const [hourHeight, setHourHeight] = (0, react.useState)(initialHourHeight);
|
|
825
853
|
(0, react.useEffect)(() => setHourHeight(initialHourHeight), [initialHourHeight]);
|
|
826
854
|
const hourHeightRef = (0, react.useRef)(hourHeight);
|
|
@@ -848,8 +876,8 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
848
876
|
}), [days, events]);
|
|
849
877
|
const hasAllDay = allDayByDay.some((list) => list.length > 0);
|
|
850
878
|
(0, react.useEffect)(() => {
|
|
851
|
-
if (scrollRef.current) scrollRef.current.scrollTop = scrollOffsetMinutes / 60 * hourHeightRef.current;
|
|
852
|
-
}, [scrollOffsetMinutes]);
|
|
879
|
+
if (scrollRef.current) scrollRef.current.scrollTop = Math.max(0, (scrollOffsetMinutes / 60 - windowStart) * hourHeightRef.current);
|
|
880
|
+
}, [scrollOffsetMinutes, windowStart]);
|
|
853
881
|
(0, react.useEffect)(() => {
|
|
854
882
|
const el = scrollRef.current;
|
|
855
883
|
if (!el || !zoomable) return;
|
|
@@ -892,23 +920,30 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
892
920
|
if (pinch.current.size < 2) pinchBase.current = null;
|
|
893
921
|
};
|
|
894
922
|
const Renderer = renderEvent;
|
|
895
|
-
const totalHeight =
|
|
896
|
-
const beginDrag = (e, event, key, kind, startHours, durationHours) => {
|
|
923
|
+
const totalHeight = windowHours * hourHeight;
|
|
924
|
+
const beginDrag = (e, event, key, kind, startHours, durationHours, dayIndex) => {
|
|
897
925
|
if (!onDragEvent) return;
|
|
898
926
|
e.stopPropagation();
|
|
899
927
|
try {
|
|
900
928
|
e.target.setPointerCapture?.(e.pointerId);
|
|
901
929
|
} catch {}
|
|
930
|
+
const column = kind === "move" ? e.currentTarget.parentElement : null;
|
|
931
|
+
const dayWidth = column ? column.getBoundingClientRect().width : 0;
|
|
902
932
|
dragOrigin.current = {
|
|
933
|
+
pointerX: e.clientX,
|
|
903
934
|
pointerY: e.clientY,
|
|
904
935
|
startHours,
|
|
905
|
-
durationHours
|
|
936
|
+
durationHours,
|
|
937
|
+
dayIndex,
|
|
938
|
+
dayWidth
|
|
906
939
|
};
|
|
907
940
|
applyDrag({
|
|
908
941
|
key,
|
|
909
942
|
kind,
|
|
910
943
|
startHours,
|
|
911
944
|
durationHours,
|
|
945
|
+
dayDelta: 0,
|
|
946
|
+
dayOffsetPx: 0,
|
|
912
947
|
moved: false
|
|
913
948
|
});
|
|
914
949
|
onDragStart?.(event);
|
|
@@ -923,14 +958,19 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
923
958
|
const dHours = (e.clientY - dragOrigin.current.pointerY) / hourHeightRef.current;
|
|
924
959
|
const snap = (v) => Math.round(v / snapHours) * snapHours;
|
|
925
960
|
if (d.kind === "move") {
|
|
926
|
-
const startHours = clamp$1(snap(dragOrigin.current.startHours + dHours),
|
|
961
|
+
const startHours = clamp$1(snap(dragOrigin.current.startHours + dHours), windowStart, Math.max(windowStart, windowEnd - d.durationHours));
|
|
962
|
+
const o = dragOrigin.current;
|
|
963
|
+
const rawDayDelta = o.dayWidth > 0 ? Math.round((e.clientX - o.pointerX) / o.dayWidth) : 0;
|
|
964
|
+
const dayDelta = clamp$1(o.dayIndex + rawDayDelta, 0, days.length - 1) - o.dayIndex;
|
|
927
965
|
applyDrag({
|
|
928
966
|
...d,
|
|
929
967
|
startHours,
|
|
968
|
+
dayDelta,
|
|
969
|
+
dayOffsetPx: dayDelta * o.dayWidth,
|
|
930
970
|
moved: true
|
|
931
971
|
});
|
|
932
972
|
} else {
|
|
933
|
-
const durationHours = clamp$1(snap(dragOrigin.current.durationHours + dHours), snapHours,
|
|
973
|
+
const durationHours = clamp$1(snap(dragOrigin.current.durationHours + dHours), snapHours, Math.max(snapHours, windowEnd - d.startHours));
|
|
934
974
|
applyDrag({
|
|
935
975
|
...d,
|
|
936
976
|
durationHours,
|
|
@@ -949,7 +989,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
949
989
|
onPress();
|
|
950
990
|
return;
|
|
951
991
|
}
|
|
952
|
-
const base = (0, date_fns.startOfDay)(day);
|
|
992
|
+
const base = (0, date_fns.startOfDay)((0, date_fns.addDays)(day, d.dayDelta));
|
|
953
993
|
const start = (0, date_fns.addMinutes)(base, Math.round(d.startHours * 60));
|
|
954
994
|
const end = (0, date_fns.addMinutes)(base, Math.round((d.startHours + d.durationHours) * 60));
|
|
955
995
|
onDragEvent?.(event, start, end);
|
|
@@ -997,10 +1037,10 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
997
1037
|
const moved = Math.abs(endPx - o.startPx) > 4;
|
|
998
1038
|
const h = hourHeightRef.current;
|
|
999
1039
|
if (moved && onCreateEvent) {
|
|
1000
|
-
const range = (0, _super_calendar_core.cellRangeFromDrag)(day, o.startPx, endPx, h,
|
|
1040
|
+
const range = (0, _super_calendar_core.cellRangeFromDrag)(day, o.startPx, endPx, h, windowStart, dragStepMinutes);
|
|
1001
1041
|
if (range) onCreateEvent(range.start, range.end);
|
|
1002
1042
|
} else if (onPressCell) {
|
|
1003
|
-
const at = (0, _super_calendar_core.cellRangeFromDrag)(day, o.startPx, o.startPx, h,
|
|
1043
|
+
const at = (0, _super_calendar_core.cellRangeFromDrag)(day, o.startPx, o.startPx, h, windowStart, dragStepMinutes);
|
|
1004
1044
|
if (at) onPressCell(at.start);
|
|
1005
1045
|
}
|
|
1006
1046
|
createOrigin.current = null;
|
|
@@ -1011,7 +1051,72 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1011
1051
|
setCreateBox(null);
|
|
1012
1052
|
};
|
|
1013
1053
|
const positionedByDay = (0, react.useMemo)(() => days.map((day) => (0, _super_calendar_core.layoutDayEvents)(events, day)), [days, events]);
|
|
1014
|
-
const
|
|
1054
|
+
const navByDay = (0, react.useMemo)(() => positionedByDay.map((list, day) => list.map((pe, idx) => ({
|
|
1055
|
+
key: `${day}:${idx}`,
|
|
1056
|
+
start: pe.startHours,
|
|
1057
|
+
dur: pe.durationHours
|
|
1058
|
+
})).filter((n) => !(n.start >= windowEnd || n.start + n.dur <= windowStart)).sort((a, b) => a.start - b.start)), [
|
|
1059
|
+
positionedByDay,
|
|
1060
|
+
windowStart,
|
|
1061
|
+
windowEnd
|
|
1062
|
+
]);
|
|
1063
|
+
const nextEventKey = (currentKey, arrowKey) => {
|
|
1064
|
+
let day = -1;
|
|
1065
|
+
let pos = -1;
|
|
1066
|
+
for (let d = 0; d < navByDay.length; d++) {
|
|
1067
|
+
const p = navByDay[d].findIndex((n) => n.key === currentKey);
|
|
1068
|
+
if (p !== -1) {
|
|
1069
|
+
day = d;
|
|
1070
|
+
pos = p;
|
|
1071
|
+
break;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
if (day === -1) return null;
|
|
1075
|
+
const start = navByDay[day][pos].start;
|
|
1076
|
+
const nearestInDay = (d) => {
|
|
1077
|
+
let best = null;
|
|
1078
|
+
let bestDiff = Number.POSITIVE_INFINITY;
|
|
1079
|
+
for (const n of navByDay[d]) {
|
|
1080
|
+
const diff = Math.abs(n.start - start);
|
|
1081
|
+
if (diff < bestDiff) {
|
|
1082
|
+
bestDiff = diff;
|
|
1083
|
+
best = n.key;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
return best;
|
|
1087
|
+
};
|
|
1088
|
+
switch (arrowKey) {
|
|
1089
|
+
case "ArrowDown": return navByDay[day][Math.min(pos + 1, navByDay[day].length - 1)].key;
|
|
1090
|
+
case "ArrowUp": return navByDay[day][Math.max(pos - 1, 0)].key;
|
|
1091
|
+
case "ArrowRight":
|
|
1092
|
+
for (let d = day + 1; d < navByDay.length; d++) {
|
|
1093
|
+
const k = nearestInDay(d);
|
|
1094
|
+
if (k) return k;
|
|
1095
|
+
}
|
|
1096
|
+
return null;
|
|
1097
|
+
case "ArrowLeft":
|
|
1098
|
+
for (let d = day - 1; d >= 0; d--) {
|
|
1099
|
+
const k = nearestInDay(d);
|
|
1100
|
+
if (k) return k;
|
|
1101
|
+
}
|
|
1102
|
+
return null;
|
|
1103
|
+
case "Home": return navByDay[day][0].key;
|
|
1104
|
+
case "End": return navByDay[day][navByDay[day].length - 1].key;
|
|
1105
|
+
default: return null;
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
const onEventKeyDown = (currentKey, e) => {
|
|
1109
|
+
const next = nextEventKey(currentKey, e.key);
|
|
1110
|
+
if (!next) return;
|
|
1111
|
+
e.preventDefault();
|
|
1112
|
+
scrollRef.current?.querySelector(`[data-event-key="${next}"]`)?.focus();
|
|
1113
|
+
};
|
|
1114
|
+
const bandsByDay = (0, react.useMemo)(() => days.map((day) => (0, _super_calendar_core.closedHourBands)(day, businessHours, windowStart, windowEnd)), [
|
|
1115
|
+
days,
|
|
1116
|
+
businessHours,
|
|
1117
|
+
windowStart,
|
|
1118
|
+
windowEnd
|
|
1119
|
+
]);
|
|
1015
1120
|
const gridLines = (0, react.useMemo)(() => {
|
|
1016
1121
|
const hourLines = `repeating-linear-gradient(to bottom, transparent 0, transparent ${hourHeight - 1}px, ${theme.gridLine} ${hourHeight - 1}px, ${theme.gridLine} ${hourHeight}px)`;
|
|
1017
1122
|
if (timeslots <= 1) return hourLines;
|
|
@@ -1037,41 +1142,57 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1037
1142
|
base: { display: "flex" },
|
|
1038
1143
|
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
1039
1144
|
}),
|
|
1040
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1145
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1146
|
+
...slot("weekNumber", {
|
|
1147
|
+
base: {
|
|
1148
|
+
width: gutterWidth,
|
|
1149
|
+
flex: "none",
|
|
1150
|
+
display: "flex",
|
|
1151
|
+
alignItems: "center",
|
|
1152
|
+
justifyContent: "center",
|
|
1153
|
+
overflow: "hidden"
|
|
1154
|
+
},
|
|
1155
|
+
themed: {
|
|
1156
|
+
fontSize: 10,
|
|
1157
|
+
color: theme.textMuted
|
|
1158
|
+
}
|
|
1159
|
+
}),
|
|
1160
|
+
children: showWeekNumber && gutterWidth > 0 && days[0] ? `${weekNumberPrefix}${(0, date_fns.getISOWeek)(days.find((d) => d.getDay() === 4) ?? days[0])}` : null
|
|
1161
|
+
}), days.map((day) => {
|
|
1044
1162
|
const today = (0, _super_calendar_core.getIsToday)(day);
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1163
|
+
const dateLabel = (0, date_fns.format)(day, "EEEE, d MMMM yyyy", dfns);
|
|
1164
|
+
const headerProps = slot("columnHeader", {
|
|
1165
|
+
base: {
|
|
1166
|
+
flex: 1,
|
|
1167
|
+
border: "none",
|
|
1168
|
+
background: "transparent",
|
|
1169
|
+
font: "inherit",
|
|
1170
|
+
cursor: onPressDateHeader ? "pointer" : "default",
|
|
1171
|
+
display: "flex",
|
|
1172
|
+
flexDirection: "column",
|
|
1173
|
+
alignItems: "center",
|
|
1174
|
+
gap: 2
|
|
1175
|
+
},
|
|
1176
|
+
themed: {
|
|
1177
|
+
color: theme.textMuted,
|
|
1178
|
+
padding: "6px 0"
|
|
1179
|
+
}
|
|
1180
|
+
});
|
|
1181
|
+
const inner = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1182
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1183
|
+
style: VISUALLY_HIDDEN,
|
|
1184
|
+
children: dateLabel
|
|
1067
1185
|
}),
|
|
1068
|
-
|
|
1186
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1187
|
+
"aria-hidden": true,
|
|
1069
1188
|
...slot("columnHeaderWeekday", { themed: {
|
|
1070
1189
|
fontSize: 11,
|
|
1071
1190
|
fontWeight: 600
|
|
1072
1191
|
} }),
|
|
1073
1192
|
children: (0, date_fns.format)(day, (0, _super_calendar_core.weekdayFormatToken)(weekdayFormat), dfns)
|
|
1074
|
-
}),
|
|
1193
|
+
}),
|
|
1194
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1195
|
+
"aria-hidden": true,
|
|
1075
1196
|
...dataState({ "data-today": today }),
|
|
1076
1197
|
...slot("columnHeaderDate", {
|
|
1077
1198
|
base: {
|
|
@@ -1090,7 +1211,18 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1090
1211
|
}
|
|
1091
1212
|
}),
|
|
1092
1213
|
children: (0, date_fns.format)(day, "d", dfns)
|
|
1093
|
-
})
|
|
1214
|
+
})
|
|
1215
|
+
] });
|
|
1216
|
+
return onPressDateHeader ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1217
|
+
type: "button",
|
|
1218
|
+
onClick: () => onPressDateHeader(day),
|
|
1219
|
+
...dataState({ "data-today": today }),
|
|
1220
|
+
...headerProps,
|
|
1221
|
+
children: inner
|
|
1222
|
+
}, day.toISOString()) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1223
|
+
...dataState({ "data-today": today }),
|
|
1224
|
+
...headerProps,
|
|
1225
|
+
children: inner
|
|
1094
1226
|
}, day.toISOString());
|
|
1095
1227
|
})]
|
|
1096
1228
|
}),
|
|
@@ -1102,8 +1234,10 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1102
1234
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1103
1235
|
...slot("allDayLabel", {
|
|
1104
1236
|
base: {
|
|
1105
|
-
width:
|
|
1237
|
+
width: gutterWidth,
|
|
1106
1238
|
flex: "none",
|
|
1239
|
+
minWidth: 0,
|
|
1240
|
+
overflow: "hidden",
|
|
1107
1241
|
textAlign: "right"
|
|
1108
1242
|
},
|
|
1109
1243
|
themed: {
|
|
@@ -1186,17 +1320,17 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1186
1320
|
height: totalHeight,
|
|
1187
1321
|
position: "relative"
|
|
1188
1322
|
},
|
|
1189
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1323
|
+
children: [hideHours ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1190
1324
|
...slot("hourGutter", { base: {
|
|
1191
|
-
width:
|
|
1325
|
+
width: gutterWidth,
|
|
1192
1326
|
flex: "none",
|
|
1193
1327
|
position: "relative"
|
|
1194
1328
|
} }),
|
|
1195
|
-
children:
|
|
1329
|
+
children: visibleHours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1196
1330
|
...slot("hourLabel", {
|
|
1197
1331
|
base: {
|
|
1198
1332
|
position: "absolute",
|
|
1199
|
-
top: h * hourHeight - 6,
|
|
1333
|
+
top: Math.max(0, (h - windowStart) * hourHeight - 6),
|
|
1200
1334
|
right: 6
|
|
1201
1335
|
},
|
|
1202
1336
|
themed: {
|
|
@@ -1208,9 +1342,9 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1208
1342
|
}, h))
|
|
1209
1343
|
}), days.map((day, dayIndex) => {
|
|
1210
1344
|
const positioned = positionedByDay[dayIndex];
|
|
1211
|
-
const
|
|
1212
|
-
const
|
|
1213
|
-
const nowTop = (
|
|
1345
|
+
const nowHours = (now.getHours() * 60 + now.getMinutes()) / 60;
|
|
1346
|
+
const showNow = showNowIndicator && (0, _super_calendar_core.isSameCalendarDay)(day, now) && nowHours >= windowStart && nowHours <= windowEnd;
|
|
1347
|
+
const nowTop = (nowHours - windowStart) * hourHeight;
|
|
1214
1348
|
const bands = bandsByDay[dayIndex];
|
|
1215
1349
|
const ghost = createBox?.dayIndex === dayIndex ? createBox : null;
|
|
1216
1350
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1240,7 +1374,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1240
1374
|
position: "absolute",
|
|
1241
1375
|
left: 0,
|
|
1242
1376
|
right: 0,
|
|
1243
|
-
top: b.start * hourHeight,
|
|
1377
|
+
top: (b.start - windowStart) * hourHeight,
|
|
1244
1378
|
height: (b.end - b.start) * hourHeight,
|
|
1245
1379
|
pointerEvents: "none",
|
|
1246
1380
|
zIndex: 0
|
|
@@ -1265,7 +1399,8 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1265
1399
|
const active = drag?.key === key ? drag : null;
|
|
1266
1400
|
const startHours = active ? active.startHours : pe.startHours;
|
|
1267
1401
|
const durationHours = active ? active.durationHours : pe.durationHours;
|
|
1268
|
-
|
|
1402
|
+
if (!active && (pe.startHours >= windowEnd || pe.startHours + pe.durationHours <= windowStart)) return null;
|
|
1403
|
+
const top = (startHours - windowStart) * hourHeight;
|
|
1269
1404
|
const boxHeight = Math.max(durationHours * hourHeight, 14);
|
|
1270
1405
|
const widthPct = 100 / pe.columns;
|
|
1271
1406
|
const onPress = () => onPressEvent?.(pe.event);
|
|
@@ -1283,6 +1418,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1283
1418
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1284
1419
|
role: "button",
|
|
1285
1420
|
tabIndex: 0,
|
|
1421
|
+
"data-event-key": keyboardEventNavigation ? key : void 0,
|
|
1286
1422
|
"aria-label": eventAccessibilityLabel ? eventAccessibilityLabel(pe.event, {
|
|
1287
1423
|
mode,
|
|
1288
1424
|
isAllDay: false,
|
|
@@ -1298,9 +1434,11 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1298
1434
|
if (e.key === "Enter" || e.key === " ") {
|
|
1299
1435
|
e.preventDefault();
|
|
1300
1436
|
onPress();
|
|
1437
|
+
return;
|
|
1301
1438
|
}
|
|
1439
|
+
if (keyboardEventNavigation) onEventKeyDown(key, e);
|
|
1302
1440
|
},
|
|
1303
|
-
onPointerDown: draggable ? (e) => beginDrag(e, pe.event, key, "move", pe.startHours, pe.durationHours) : void 0,
|
|
1441
|
+
onPointerDown: draggable ? (e) => beginDrag(e, pe.event, key, "move", pe.startHours, pe.durationHours, dayIndex) : void 0,
|
|
1304
1442
|
onPointerMove: draggable ? moveDrag : void 0,
|
|
1305
1443
|
onPointerUp: draggable ? (e) => endDrag(e, day, pe.event, onPress) : void 0,
|
|
1306
1444
|
onPointerCancel: draggable ? cancelDrag : void 0,
|
|
@@ -1315,7 +1453,8 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1315
1453
|
cursor: draggable ? "grab" : "pointer",
|
|
1316
1454
|
touchAction: draggable ? "none" : "auto",
|
|
1317
1455
|
zIndex: active ? 3 : 1,
|
|
1318
|
-
opacity: active ? .85 : 1
|
|
1456
|
+
opacity: active ? .85 : 1,
|
|
1457
|
+
...active && active.dayOffsetPx !== 0 ? { transform: `translateX(${active.dayOffsetPx}px)` } : null
|
|
1319
1458
|
} }),
|
|
1320
1459
|
children: [Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultDomEvent, {
|
|
1321
1460
|
...args,
|
|
@@ -1324,7 +1463,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1324
1463
|
}), draggable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1325
1464
|
onPointerDown: (e) => {
|
|
1326
1465
|
e.stopPropagation();
|
|
1327
|
-
beginDrag(e, pe.event, key, "resize", pe.startHours, pe.durationHours);
|
|
1466
|
+
beginDrag(e, pe.event, key, "resize", pe.startHours, pe.durationHours, dayIndex);
|
|
1328
1467
|
},
|
|
1329
1468
|
style: {
|
|
1330
1469
|
position: "absolute",
|
|
@@ -1391,6 +1530,18 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1391
1530
|
}
|
|
1392
1531
|
//#endregion
|
|
1393
1532
|
//#region src/Calendar.tsx
|
|
1533
|
+
const EMPTY_EVENTS = [];
|
|
1534
|
+
function expansionRange(mode, date, weekStartsOn, numberOfDays) {
|
|
1535
|
+
if (mode === "month") return [(0, date_fns.startOfWeek)((0, date_fns.startOfMonth)(date), { weekStartsOn }), (0, date_fns.endOfWeek)((0, date_fns.endOfMonth)(date), { weekStartsOn })];
|
|
1536
|
+
if (mode === "schedule") return [(0, date_fns.startOfDay)(date), (0, date_fns.endOfDay)((0, date_fns.addMonths)(date, 3))];
|
|
1537
|
+
const days = (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays ?? 1);
|
|
1538
|
+
return [(0, date_fns.startOfDay)(days[0]), (0, date_fns.endOfDay)(days[days.length - 1])];
|
|
1539
|
+
}
|
|
1540
|
+
function pageStep(mode, date, direction, weekStartsOn, numberOfDays) {
|
|
1541
|
+
if (mode === "month") return (0, date_fns.addMonths)(date, direction);
|
|
1542
|
+
if (mode === "schedule") return (0, date_fns.addDays)(date, direction * 7);
|
|
1543
|
+
return (0, date_fns.addDays)(date, direction * (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays ?? 1).length);
|
|
1544
|
+
}
|
|
1394
1545
|
/**
|
|
1395
1546
|
* Batteries-included entry point for the react-dom renderer: it picks the right
|
|
1396
1547
|
* view for `mode`. `month` renders a single {@link MonthView}; `schedule` renders
|
|
@@ -1402,9 +1553,37 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1402
1553
|
* <Calendar mode="week" date={new Date()} events={events} />
|
|
1403
1554
|
* ```
|
|
1404
1555
|
*/
|
|
1405
|
-
function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays, locale, theme, height, className, style, onPressEvent, eventAccessibilityLabel, ampm, hourHeight, scrollOffsetMinutes, timeslots, businessHours, showNowIndicator, showAllDayEventCell, dragStepMinutes, onPressCell, onCreateEvent, onDragStart, onDragEvent, onPressDateHeader, renderTimeEvent, hourComponent, maxVisibleEventCount, moreLabel, showAdjacentMonths, weekdayFormat, fillCellOnSelection, selectedRange, selectedDates, minDate, maxDate, isDateDisabled, keyboardDayNavigation, onPressDay, onPressMore, renderMonthEvent, renderScheduleEvent, classNames, styles }) {
|
|
1406
|
-
|
|
1407
|
-
|
|
1556
|
+
function Calendar({ mode = "week", date, events, onChangeDate, weekStartsOn = 0, numberOfDays, locale, timeZone, theme, height, className, style, onPressEvent, eventAccessibilityLabel, ampm, hourHeight, scrollOffsetMinutes, timeslots, minHour, maxHour, hideHours, showWeekNumber, weekNumberPrefix, businessHours, showNowIndicator, showAllDayEventCell, dragStepMinutes, onPressCell, onCreateEvent, onDragStart, onDragEvent, onPressDateHeader, renderTimeEvent, hourComponent, keyboardEventNavigation, maxVisibleEventCount, moreLabel, showAdjacentMonths, weekdayFormat, fillCellOnSelection, selectedRange, selectedDates, minDate, maxDate, isDateDisabled, keyboardDayNavigation, onPressDay, onPressMore, renderMonthEvent, renderScheduleEvent, classNames, styles }) {
|
|
1557
|
+
const displayEvents = (0, react.useMemo)(() => {
|
|
1558
|
+
let out = events ?? EMPTY_EVENTS;
|
|
1559
|
+
if (out.some((e) => e.recurrence)) {
|
|
1560
|
+
let [start, end] = expansionRange(mode, date, weekStartsOn, numberOfDays);
|
|
1561
|
+
if (timeZone) {
|
|
1562
|
+
start = (0, date_fns.addDays)(start, -1);
|
|
1563
|
+
end = (0, date_fns.addDays)(end, 1);
|
|
1564
|
+
}
|
|
1565
|
+
out = (0, _super_calendar_core.expandRecurringEvents)(out, start, end);
|
|
1566
|
+
}
|
|
1567
|
+
if (timeZone) out = (0, _super_calendar_core.eventsInTimeZone)(out, timeZone);
|
|
1568
|
+
return out;
|
|
1569
|
+
}, [
|
|
1570
|
+
events,
|
|
1571
|
+
mode,
|
|
1572
|
+
date.getTime(),
|
|
1573
|
+
weekStartsOn,
|
|
1574
|
+
numberOfDays,
|
|
1575
|
+
timeZone
|
|
1576
|
+
]);
|
|
1577
|
+
const handlePageKeys = (e) => {
|
|
1578
|
+
if (!onChangeDate) return;
|
|
1579
|
+
if (e.key === "PageDown") onChangeDate(pageStep(mode, date, 1, weekStartsOn, numberOfDays));
|
|
1580
|
+
else if (e.key === "PageUp") onChangeDate(pageStep(mode, date, -1, weekStartsOn, numberOfDays));
|
|
1581
|
+
else return;
|
|
1582
|
+
e.preventDefault();
|
|
1583
|
+
};
|
|
1584
|
+
let view;
|
|
1585
|
+
if (mode === "schedule") view = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Agenda, {
|
|
1586
|
+
events: displayEvents,
|
|
1408
1587
|
locale,
|
|
1409
1588
|
ampm,
|
|
1410
1589
|
theme,
|
|
@@ -1419,9 +1598,9 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1419
1598
|
onPressEvent,
|
|
1420
1599
|
onPressDay
|
|
1421
1600
|
});
|
|
1422
|
-
if (mode === "month")
|
|
1601
|
+
else if (mode === "month") view = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthView, {
|
|
1423
1602
|
date,
|
|
1424
|
-
events:
|
|
1603
|
+
events: displayEvents,
|
|
1425
1604
|
weekStartsOn,
|
|
1426
1605
|
weekdayFormat,
|
|
1427
1606
|
locale,
|
|
@@ -1447,10 +1626,10 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1447
1626
|
renderEvent: renderMonthEvent,
|
|
1448
1627
|
eventAccessibilityLabel
|
|
1449
1628
|
});
|
|
1450
|
-
|
|
1629
|
+
else view = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeGrid, {
|
|
1451
1630
|
date,
|
|
1452
1631
|
mode,
|
|
1453
|
-
events,
|
|
1632
|
+
events: displayEvents,
|
|
1454
1633
|
weekStartsOn,
|
|
1455
1634
|
weekdayFormat,
|
|
1456
1635
|
numberOfDays,
|
|
@@ -1465,6 +1644,11 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1465
1644
|
hourHeight,
|
|
1466
1645
|
scrollOffsetMinutes,
|
|
1467
1646
|
timeslots,
|
|
1647
|
+
minHour,
|
|
1648
|
+
maxHour,
|
|
1649
|
+
hideHours,
|
|
1650
|
+
showWeekNumber,
|
|
1651
|
+
weekNumberPrefix,
|
|
1468
1652
|
businessHours,
|
|
1469
1653
|
showNowIndicator,
|
|
1470
1654
|
showAllDayEventCell,
|
|
@@ -1477,7 +1661,13 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1477
1661
|
onPressDateHeader,
|
|
1478
1662
|
renderEvent: renderTimeEvent,
|
|
1479
1663
|
eventAccessibilityLabel,
|
|
1480
|
-
hourComponent
|
|
1664
|
+
hourComponent,
|
|
1665
|
+
keyboardEventNavigation
|
|
1666
|
+
});
|
|
1667
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1668
|
+
style: { display: "contents" },
|
|
1669
|
+
onKeyDown: handlePageKeys,
|
|
1670
|
+
children: view
|
|
1481
1671
|
});
|
|
1482
1672
|
}
|
|
1483
1673
|
//#endregion
|
|
@@ -1835,7 +2025,9 @@ function DateRangePicker({ value, onChange, formatLabel = defaultRangeLabel, wee
|
|
|
1835
2025
|
//#endregion
|
|
1836
2026
|
//#region src/ResourceTimeline.tsx
|
|
1837
2027
|
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
1838
|
-
|
|
2028
|
+
const GUTTER_WIDTH = 56;
|
|
2029
|
+
function DefaultBar({ event, height, boxProps, theme }) {
|
|
2030
|
+
const showTime = height != null ? height > 34 : true;
|
|
1839
2031
|
const time = (0, _super_calendar_core.eventTimeLabel)({
|
|
1840
2032
|
mode: "day",
|
|
1841
2033
|
isAllDay: false,
|
|
@@ -1875,7 +2067,7 @@ function DefaultBar({ event, boxProps, theme }) {
|
|
|
1875
2067
|
textOverflow: "ellipsis"
|
|
1876
2068
|
},
|
|
1877
2069
|
children: event.title
|
|
1878
|
-
}), time ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2070
|
+
}), time && showTime ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1879
2071
|
style: {
|
|
1880
2072
|
opacity: .75,
|
|
1881
2073
|
fontSize: 11
|
|
@@ -1900,7 +2092,7 @@ function DefaultBar({ event, boxProps, theme }) {
|
|
|
1900
2092
|
* />
|
|
1901
2093
|
* ```
|
|
1902
2094
|
*/
|
|
1903
|
-
function ResourceTimeline({ date, resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, rowHeight = 56, labelWidth = 140, ampm = false, theme: themeOverrides, renderEvent, onPressEvent, onDragEvent, dragStepMinutes = 15, className, style, classNames, styles }) {
|
|
2095
|
+
function ResourceTimeline({ date, orientation = "horizontal", resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, hourHeight = 48, rowHeight = 56, labelWidth = 140, ampm = false, theme: themeOverrides, renderEvent, onPressEvent, onDragEvent, dragStepMinutes = 15, className, style, classNames, styles }) {
|
|
1904
2096
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
1905
2097
|
const slot = createSlots({
|
|
1906
2098
|
classNames,
|
|
@@ -1908,6 +2100,8 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
|
|
|
1908
2100
|
});
|
|
1909
2101
|
const Renderer = renderEvent;
|
|
1910
2102
|
const snapHours = dragStepMinutes / 60;
|
|
2103
|
+
const vertical = orientation === "vertical";
|
|
2104
|
+
const hourSize = vertical ? hourHeight : hourWidth;
|
|
1911
2105
|
const [drag, setDrag] = (0, react.useState)(null);
|
|
1912
2106
|
const dragRef = (0, react.useRef)(null);
|
|
1913
2107
|
const origin = (0, react.useRef)(null);
|
|
@@ -1922,7 +2116,7 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
|
|
|
1922
2116
|
e.target.setPointerCapture?.(e.pointerId);
|
|
1923
2117
|
} catch {}
|
|
1924
2118
|
origin.current = {
|
|
1925
|
-
x: e.clientX,
|
|
2119
|
+
x: vertical ? e.clientY : e.clientX,
|
|
1926
2120
|
startHours,
|
|
1927
2121
|
durationHours
|
|
1928
2122
|
};
|
|
@@ -1937,7 +2131,7 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
|
|
|
1937
2131
|
const moveDrag = (e) => {
|
|
1938
2132
|
const d = dragRef.current;
|
|
1939
2133
|
if (!d || !origin.current) return;
|
|
1940
|
-
const dHours = (e.clientX - origin.current.x) /
|
|
2134
|
+
const dHours = ((vertical ? e.clientY : e.clientX) - origin.current.x) / hourSize;
|
|
1941
2135
|
const snap = (v) => Math.round(v / snapHours) * snapHours;
|
|
1942
2136
|
if (d.kind === "move") {
|
|
1943
2137
|
const startHours = clamp(snap(origin.current.startHours + dHours), startHour, endHour - d.durationHours);
|
|
@@ -1992,6 +2186,172 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
|
|
|
1992
2186
|
resourceId,
|
|
1993
2187
|
date
|
|
1994
2188
|
]);
|
|
2189
|
+
if (vertical) {
|
|
2190
|
+
const trackHeight = (endHour - startHour) * hourHeight;
|
|
2191
|
+
const vGridLines = `repeating-linear-gradient(to bottom, transparent 0, transparent ${hourHeight - 1}px, ${theme.gridLine} ${hourHeight - 1}px, ${theme.gridLine} ${hourHeight}px)`;
|
|
2192
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2193
|
+
className,
|
|
2194
|
+
style: {
|
|
2195
|
+
fontFamily: theme.fontFamily,
|
|
2196
|
+
color: theme.text,
|
|
2197
|
+
overflowY: "auto",
|
|
2198
|
+
...style
|
|
2199
|
+
},
|
|
2200
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2201
|
+
...slot("header", {
|
|
2202
|
+
base: {
|
|
2203
|
+
display: "flex",
|
|
2204
|
+
position: "sticky",
|
|
2205
|
+
top: 0,
|
|
2206
|
+
zIndex: 2
|
|
2207
|
+
},
|
|
2208
|
+
themed: {
|
|
2209
|
+
borderBottom: `1px solid ${theme.gridLine}`,
|
|
2210
|
+
background: theme.surface
|
|
2211
|
+
}
|
|
2212
|
+
}),
|
|
2213
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ...slot("corner", { base: {
|
|
2214
|
+
width: GUTTER_WIDTH,
|
|
2215
|
+
flex: "none"
|
|
2216
|
+
} }) }), resources.map((resource) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2217
|
+
...slot("resourceLabel", {
|
|
2218
|
+
base: {
|
|
2219
|
+
flex: 1,
|
|
2220
|
+
minWidth: 0,
|
|
2221
|
+
padding: "6px 4px",
|
|
2222
|
+
textAlign: "center",
|
|
2223
|
+
overflow: "hidden",
|
|
2224
|
+
textOverflow: "ellipsis",
|
|
2225
|
+
whiteSpace: "nowrap",
|
|
2226
|
+
boxSizing: "border-box"
|
|
2227
|
+
},
|
|
2228
|
+
themed: {
|
|
2229
|
+
fontSize: 13,
|
|
2230
|
+
fontWeight: 600,
|
|
2231
|
+
borderLeft: `1px solid ${theme.gridLine}`
|
|
2232
|
+
}
|
|
2233
|
+
}),
|
|
2234
|
+
children: resource.title ?? resource.id
|
|
2235
|
+
}, resource.id))]
|
|
2236
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2237
|
+
style: { display: "flex" },
|
|
2238
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2239
|
+
...slot("timeAxis", { base: {
|
|
2240
|
+
position: "relative",
|
|
2241
|
+
width: GUTTER_WIDTH,
|
|
2242
|
+
flex: "none",
|
|
2243
|
+
height: trackHeight
|
|
2244
|
+
} }),
|
|
2245
|
+
children: hours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2246
|
+
...slot("hourTick", {
|
|
2247
|
+
base: {
|
|
2248
|
+
position: "absolute",
|
|
2249
|
+
top: Math.max(0, (h - startHour) * hourHeight - 6),
|
|
2250
|
+
right: 6
|
|
2251
|
+
},
|
|
2252
|
+
themed: {
|
|
2253
|
+
fontSize: 10,
|
|
2254
|
+
color: theme.textMuted
|
|
2255
|
+
}
|
|
2256
|
+
}),
|
|
2257
|
+
children: (0, _super_calendar_core.formatHour)(h, { ampm })
|
|
2258
|
+
}, h))
|
|
2259
|
+
}), resources.map((resource) => {
|
|
2260
|
+
const positioned = byResource.get(resource.id) ?? [];
|
|
2261
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2262
|
+
...slot("row", {
|
|
2263
|
+
base: {
|
|
2264
|
+
flex: 1,
|
|
2265
|
+
minWidth: 0
|
|
2266
|
+
},
|
|
2267
|
+
themed: { borderLeft: `1px solid ${theme.gridLine}` }
|
|
2268
|
+
}),
|
|
2269
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2270
|
+
...slot("track", { base: {
|
|
2271
|
+
position: "relative",
|
|
2272
|
+
height: trackHeight
|
|
2273
|
+
} }),
|
|
2274
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2275
|
+
"aria-hidden": true,
|
|
2276
|
+
...slot("gridLines", {
|
|
2277
|
+
base: {
|
|
2278
|
+
position: "absolute",
|
|
2279
|
+
inset: 0,
|
|
2280
|
+
pointerEvents: "none"
|
|
2281
|
+
},
|
|
2282
|
+
themed: { backgroundImage: vGridLines }
|
|
2283
|
+
})
|
|
2284
|
+
}), positioned.map((pe, idx) => {
|
|
2285
|
+
const key = `${resource.id}:${idx}`;
|
|
2286
|
+
const active = drag?.key === key ? drag : null;
|
|
2287
|
+
const startH = active ? active.startHours : pe.startHours;
|
|
2288
|
+
const durH = active ? active.durationHours : pe.durationHours;
|
|
2289
|
+
const top = clamp(startH - startHour, 0, endHour - startHour) * hourHeight;
|
|
2290
|
+
const bottom = clamp(startH + durH - startHour, 0, endHour - startHour) * hourHeight;
|
|
2291
|
+
const height = Math.max(bottom - top, 2);
|
|
2292
|
+
const lanePct = 100 / pe.columns;
|
|
2293
|
+
const onPress = () => onPressEvent?.(pe.event);
|
|
2294
|
+
const args = {
|
|
2295
|
+
event: pe.event,
|
|
2296
|
+
width: 0,
|
|
2297
|
+
height,
|
|
2298
|
+
onPress
|
|
2299
|
+
};
|
|
2300
|
+
const draggable = !!onDragEvent;
|
|
2301
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2302
|
+
type: "button",
|
|
2303
|
+
onClick: draggable ? void 0 : onPress,
|
|
2304
|
+
"aria-label": pe.event.title,
|
|
2305
|
+
...dataState({ "data-dragging": !!active }),
|
|
2306
|
+
onPointerDown: draggable ? (e) => beginDrag(e, key, "move", pe.startHours, pe.durationHours) : void 0,
|
|
2307
|
+
onPointerMove: draggable ? moveDrag : void 0,
|
|
2308
|
+
onPointerUp: draggable ? (e) => endDrag(e, pe.event, onPress) : void 0,
|
|
2309
|
+
onPointerCancel: draggable ? cancelDrag : void 0,
|
|
2310
|
+
...slot("event", { base: {
|
|
2311
|
+
position: "absolute",
|
|
2312
|
+
top,
|
|
2313
|
+
height,
|
|
2314
|
+
left: `${pe.column * lanePct}%`,
|
|
2315
|
+
width: `${lanePct}%`,
|
|
2316
|
+
padding: 1,
|
|
2317
|
+
border: "none",
|
|
2318
|
+
background: "transparent",
|
|
2319
|
+
cursor: draggable ? "grab" : "pointer",
|
|
2320
|
+
touchAction: draggable ? "none" : "auto",
|
|
2321
|
+
font: "inherit",
|
|
2322
|
+
textAlign: "left",
|
|
2323
|
+
boxSizing: "border-box",
|
|
2324
|
+
zIndex: active ? 3 : 1,
|
|
2325
|
+
opacity: active ? .85 : 1
|
|
2326
|
+
} }),
|
|
2327
|
+
children: [Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultBar, {
|
|
2328
|
+
...args,
|
|
2329
|
+
theme,
|
|
2330
|
+
boxProps: slot("eventBox")
|
|
2331
|
+
}), draggable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2332
|
+
"aria-hidden": true,
|
|
2333
|
+
onPointerDown: (e) => {
|
|
2334
|
+
e.stopPropagation();
|
|
2335
|
+
beginDrag(e, key, "resize", pe.startHours, pe.durationHours);
|
|
2336
|
+
},
|
|
2337
|
+
style: {
|
|
2338
|
+
position: "absolute",
|
|
2339
|
+
left: 0,
|
|
2340
|
+
right: 0,
|
|
2341
|
+
bottom: 0,
|
|
2342
|
+
height: 8,
|
|
2343
|
+
cursor: "ns-resize",
|
|
2344
|
+
touchAction: "none"
|
|
2345
|
+
}
|
|
2346
|
+
}) : null]
|
|
2347
|
+
}, idx);
|
|
2348
|
+
})]
|
|
2349
|
+
})
|
|
2350
|
+
}, resource.id);
|
|
2351
|
+
})]
|
|
2352
|
+
})]
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
1995
2355
|
const gridLines = `repeating-linear-gradient(to right, transparent 0, transparent ${hourWidth - 1}px, ${theme.gridLine} ${hourWidth - 1}px, ${theme.gridLine} ${hourWidth}px)`;
|
|
1996
2356
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1997
2357
|
className,
|