jwf-year-calendar
Version:
A full react version of Paul-DS' js-year-calendar, https://github.com/year-calendar/js-year-calendar. Built with support from JWF Process Solutions Ltd.
124 lines (123 loc) • 7.5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useEffect, useRef } from 'react';
import Month from '../month/Month';
import Year from './Year';
import { sanitizeDataSource } from './SanitizedDataSource';
import hideContextMenu from './HideContextMenu';
import { relevantEvents } from '../../lib/dates';
import { determineGridCols, showYearEnd, showYearMiddle, orderDates, isTailwindColor } from '../../lib/utils';
const YearCentre = (props) => {
return _jsx(Year, { className: `${props.className} hover:bg-gray-200 `, onClick: props.onClick, year: props.year });
};
const YearMiddle = (props) => {
return (_jsx(Year, { className: `${props.className} hover:bg-gray-200 hover:opacity-50 opacity-50`, onClick: props.onClick, year: props.year }));
};
const YearEnd = (props) => {
return (_jsx(Year, { className: `${props.className} hover:bg-gray-200 hover:opacity-25 opacity-25`, onClick: props.onClick, year: props.year }));
};
const MyCalendar = (props) => {
const myCalendarRef = useRef(null);
const [containerWidth, setContainerWidth] = useState(0);
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
const [contextMenuItems, setContextMenuItems] = useState({
hoverIndex: 0,
visible: false,
});
const [contextMenu, setContextMenu] = useState({
visible: false,
x: 0,
y: 0,
day: 0,
month: 0,
year: 0,
});
const [internalYear, setInternalYear] = useState(props.year || new Date().getFullYear());
let sanitizedDataSource = [];
if (props.dataSource) {
sanitizedDataSource = sanitizeDataSource(props.dataSource);
}
const handleSetEndDate = (d) => {
if (props.enableRangeSelection) {
setEndDate(d);
}
};
const handleSetStartDate = (d) => {
if (props.enableRangeSelection) {
setStartDate(d);
}
};
const handleSetYear = (y) => {
setInternalYear(y);
if (props.onYearChanged) {
props.onYearChanged({ currentYear: y });
}
};
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
useEffect(() => {
let newWidth = 0;
if (myCalendarRef?.current) {
newWidth = myCalendarRef.current.clientWidth;
}
setContainerWidth(newWidth);
}, [myCalendarRef.current?.clientWidth]);
useEffect(() => {
const handleResize = () => {
setWindowWidth(window.innerWidth);
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, [window.innerWidth]);
const handleShowContextMenuItems = (i) => {
setContextMenuItems({ hoverIndex: i, visible: true });
};
useEffect(() => {
const handleHideContextMenu = (e) => {
hideContextMenu(e, contextMenu, setContextMenu);
};
document.addEventListener('click', handleHideContextMenu);
return () => {
document.removeEventListener('click', handleHideContextMenu);
};
}, [contextMenu]);
const gridCols = determineGridCols(windowWidth, containerWidth);
const getColorDiv = (e) => {
if (isTailwindColor(e.color)) {
return _jsx("div", { className: `${e.color} h-9` });
}
return _jsx("div", { className: 'flex-none h-full w-1 ', style: { backgroundColor: e.color } });
};
const year = props.year || internalYear;
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "border border-1", children: _jsxs("div", { className: `flex items-center justify-center`, children: [_jsx("button", { className: 'font-bold h-11 hover:bg-gray-200 px-2.5 text-2xl w-7', onClick: () => handleSetYear(props.year ? props.year - 1 : year - 1), children: '‹' }), showYearEnd(windowWidth, containerWidth) && _jsx(YearEnd, { onClick: y => handleSetYear(y), year: year - 2 }), showYearMiddle(windowWidth, containerWidth) && (_jsx(YearMiddle, { onClick: y => handleSetYear(y), year: year - 1 })), _jsx(YearCentre, { onClick: y => handleSetYear(y), year: year }), showYearMiddle(windowWidth, containerWidth) && (_jsx(YearMiddle, { onClick: y => handleSetYear(y), year: year + 1 })), showYearEnd(windowWidth, containerWidth) && _jsx(YearEnd, { onClick: y => handleSetYear(y), year: year + 2 }), _jsx("button", { className: 'font-bold h-11 hover:bg-gray-200 px-2.5 text-2xl w-7', onClick: () => handleSetYear(year + 1), children: '›' })] }) }), _jsx("div", { className: `grid ${gridCols} justify-items-center mt-5 select-none text-center text-sm w-full`, ref: myCalendarRef, onMouseDown: () => handleSetEndDate(null), onMouseUp: e => {
if (startDate && e.button === 0 && props.onRangeSelected) {
props.onRangeSelected(orderDates(startDate, endDate || startDate));
}
handleSetStartDate(null);
return false;
}, onMouseLeave: () => handleSetStartDate(null), children: months.map((month, index) => {
return (_jsx(Month, { darkMode: props.darkMode, dataSource: sanitizedDataSource, disabledWeekDays: props.disabledWeekDays, endDate: endDate, index: index, setContextMenu: setContextMenu, setEndDate: handleSetEndDate, setStartDate: handleSetStartDate, startDate: startDate, title: month, weekStart: props.weekStart, year: year }, index));
}) }), contextMenu.visible && (_jsx("div", { className: "absolute", onContextMenu: e => e.preventDefault(), onMouseLeave: () => setContextMenuItems({ hoverIndex: 0, visible: false }), style: { top: contextMenu.y, left: contextMenu.x }, children: relevantEvents({ ...contextMenu }, sanitizedDataSource).map((event, i) => {
return (_jsxs("div", { className: "flex relative", children: [_jsxs("div", { id: "contextmenutile", className: `border border-gray-200 border-solid cursor-pointer flex items-center ${props.darkMode
? 'bg-gray-800 hover:bg-gray-600 text-white'
: 'bg-white hover:bg-gray-200 text-black'} h-9 shadow-xl select-none w-full`, onMouseEnter: () => handleShowContextMenuItems(i), children: [getColorDiv(event), _jsx("div", { className: 'flex-auto inline pl-2 ', children: event.name }), _jsx("div", { className: 'flex-none inline px-2', children: '›' })] }), i === contextMenuItems.hoverIndex && contextMenuItems.visible && (_jsx("div", { className: "flex", children: _jsx("div", { className: 'absolute flex flex-col w-max', children: props.contextMenuItems?.map((item, index) => (_jsx("div", { onClick: () => item.onClick(event), className: `border border-gray-200 border-solid cursor-pointer ${props.darkMode
? 'bg-slate-800 hover:bg-slate-600 text-white'
: 'bg-white hover:bg-slate-200 text-black'} flex-auto flex h-9 hover: items-center px-2 shadow-xl select-none w-full`, children: item.text }, index))) }) }))] }, i));
}) }))] }));
};
export default MyCalendar;