UNPKG

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
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;