1228f0a50e
- Update hover effect to highlight 30-minute time slots instead of 1-hour slots - Reset slot label opacity to full visibility when viewing other weeks/days
106 lines
3.2 KiB
TypeScript
106 lines
3.2 KiB
TypeScript
export interface MouseHandlersProps {
|
|
calendarEl: HTMLElement;
|
|
}
|
|
|
|
export const createMouseHandlers = (props: MouseHandlersProps) => {
|
|
const { calendarEl } = props;
|
|
|
|
const handleMouseMove = (e: MouseEvent) => {
|
|
const timegridEl = calendarEl.querySelector(".fc-timegrid-body");
|
|
if (!timegridEl) return;
|
|
|
|
const allDayTable = calendarEl.querySelector(".fc-scrollgrid-sync-table");
|
|
if (allDayTable) {
|
|
const allDayRect = allDayTable.getBoundingClientRect();
|
|
if (e.clientY >= allDayRect.top && e.clientY <= allDayRect.bottom) {
|
|
timegridEl
|
|
.querySelectorAll(".hour-highlight")
|
|
.forEach((el: Element) => el.remove());
|
|
return;
|
|
}
|
|
}
|
|
|
|
const target = e.target as HTMLElement;
|
|
if (target && target.closest(".fc-timegrid-slot-label")) {
|
|
timegridEl
|
|
.querySelectorAll(".hour-highlight")
|
|
.forEach((el: Element) => el.remove());
|
|
return;
|
|
}
|
|
|
|
const dayColumns = timegridEl.querySelectorAll(".fc-timegrid-col");
|
|
if (dayColumns.length === 0) return;
|
|
|
|
timegridEl
|
|
.querySelectorAll(".hour-highlight")
|
|
.forEach((el: Element) => el.remove());
|
|
|
|
let targetColumn: Element | null = null;
|
|
for (const column of dayColumns) {
|
|
const rect = column.getBoundingClientRect();
|
|
if (e.clientX >= rect.left && e.clientX <= rect.right) {
|
|
targetColumn = column;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (targetColumn) {
|
|
const rect = targetColumn.getBoundingClientRect();
|
|
const relativeY = e.clientY - rect.top;
|
|
const slotHeight = rect.height / 48;
|
|
const slotIndex = Math.floor(relativeY / slotHeight);
|
|
|
|
if (relativeY >= 0 && relativeY <= rect.height) {
|
|
const highlight = document.createElement("div");
|
|
highlight.className = "hour-highlight";
|
|
highlight.style.top = `${slotIndex * slotHeight}px`;
|
|
highlight.style.height = `${slotHeight}px`;
|
|
|
|
(targetColumn as HTMLElement).style.position = "relative";
|
|
targetColumn.appendChild(highlight);
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleMouseLeave = () => {
|
|
const timegridEl = calendarEl.querySelector(".fc-timegrid-body");
|
|
if (timegridEl) {
|
|
timegridEl
|
|
.querySelectorAll(".hour-highlight")
|
|
.forEach((el: Element) => el.remove());
|
|
}
|
|
};
|
|
|
|
const addMouseEventListeners = () => {
|
|
calendarEl.addEventListener("mousemove", handleMouseMove);
|
|
calendarEl.addEventListener("mouseleave", handleMouseLeave);
|
|
|
|
(calendarEl as any).__calendarMouseMoveHandler = handleMouseMove;
|
|
(calendarEl as any).__calendarMouseLeaveHandler = handleMouseLeave;
|
|
};
|
|
|
|
const removeMouseEventListeners = () => {
|
|
if ((calendarEl as any).__calendarMouseMoveHandler) {
|
|
calendarEl.removeEventListener(
|
|
"mousemove",
|
|
(calendarEl as any).__calendarMouseMoveHandler
|
|
);
|
|
delete (calendarEl as any).__calendarMouseMoveHandler;
|
|
}
|
|
if ((calendarEl as any).__calendarMouseLeaveHandler) {
|
|
calendarEl.removeEventListener(
|
|
"mouseleave",
|
|
(calendarEl as any).__calendarMouseLeaveHandler
|
|
);
|
|
delete (calendarEl as any).__calendarMouseLeaveHandler;
|
|
}
|
|
};
|
|
|
|
return {
|
|
handleMouseMove,
|
|
handleMouseLeave,
|
|
addMouseEventListeners,
|
|
removeMouseEventListeners,
|
|
};
|
|
};
|