UNPKG

@veracity/vui

Version:

Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.

132 lines (130 loc) 4.31 kB
import { cs } from "../utils/styles.js"; import { omitThemingProps, useStyleConfig } from "../core/theme.js"; import vui from "../core/vui.js"; import { Box } from "../box/box.js"; import { DayPicker } from "./components/dayPicker.js"; import { isDay, isExact, isFrom, isMonth, isTo, isYear, processSelectMonth, processSelectYear, processViewDate } from "./utils.js"; import { CalendarHeader } from "./components/calendarHeader.js"; import { MonthPicker } from "./components/monthPicker.js"; import { YearPicker } from "./components/yearPicker.js"; import { useCalendar } from "./hooks/useCalendar.js"; import { useDefaultViewMonth } from "./hooks/useDefaultViewMonth.js"; import { useCallback, useEffect, useRef, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/calendar/calendar.tsx /** Displays calendar. */ const Calendar = vui((props, ref) => { const { boundaries, className, fixedNumberOfWeeks = false, disabled, isStartDate, mode, onSelectDates, selectedDates, ...rest } = omitThemingProps(props); const styles = useStyleConfig("Calendar", props); const currentDateRef = useRef(isFrom(mode) || isExact(mode) ? selectedDates?.startDate : selectedDates?.endDate); const defaultViewMonth = useDefaultViewMonth({ boundaries, selectedDate: currentDateRef.current, isStartDate }); const [timeUnitMode, setTimeUnitMode] = useState("day"); const [viewDate, setViewDate] = useState(defaultViewMonth); const calendar = useCalendar({ boundaries, mode, selectedDates, timeUnitMode, viewDate, fixedNumberOfWeeks }); /** * Effect to reset viewDate when selectedDates changes (onReset) * Compare timestamps to avoid resetting the view when the object reference changes but the date value hasn't. */ useEffect(() => { const newDate = isFrom(mode) || isExact(mode) ? selectedDates?.startDate : selectedDates?.endDate; if (newDate?.getTime() !== currentDateRef.current?.getTime()) { currentDateRef.current = newDate; if (newDate) setViewDate(newDate); } }, [selectedDates, mode]); /** * Send update date to parent component */ const updateDateState = useCallback((newDate) => { const dateRange = { ...selectedDates }; if (isTo(mode)) dateRange.endDate = newDate; else dateRange.startDate = newDate; if (newDate && !disabled) onSelectDates?.(dateRange); }, [ selectedDates, mode, disabled, onSelectDates ]); /** * Handles clicking next/prev in header */ const onChangeViewItem = useCallback((direction) => { const newViewMonth = processViewDate(viewDate, direction, timeUnitMode, calendar.items); if (newViewMonth) setViewDate(newViewMonth); }, [ viewDate, timeUnitMode, calendar.items ]); /** * Handles clicking on a day, month or year cell. The active timeUnitMode decides * how the clicked date is processed and which unit to drill down into next. */ const onSelect = useCallback((clickedDate) => () => { let processedDate = clickedDate; if (isMonth(timeUnitMode)) { processedDate = processSelectMonth(clickedDate, mode, boundaries); setTimeUnitMode("day"); } else if (isYear(timeUnitMode)) { processedDate = processSelectYear(clickedDate, mode, boundaries); setTimeUnitMode("month"); } updateDateState(processedDate); setViewDate(processedDate); }, [ timeUnitMode, mode, boundaries, updateDateState ]); return /* @__PURE__ */ jsxs(Box, { className: cs("vui-calendar", className), column: true, cursor: "default", minW: 280, position: "relative", ref, w: "fit-content", ...styles, ...rest, children: [ /* @__PURE__ */ jsx(CalendarHeader, { nextDisabled: calendar.nextDisabled, onChangeViewItem, onSetTimeUnitMode: setTimeUnitMode, prevDisabled: calendar.prevDisabled, timeUnitMode, viewMonth: viewDate }), isDay(timeUnitMode) && /* @__PURE__ */ jsx(DayPicker, { calendar, onSelectDay: onSelect }), isMonth(timeUnitMode) && /* @__PURE__ */ jsx(MonthPicker, { calendar, onSelectMonth: onSelect }), isYear(timeUnitMode) && /* @__PURE__ */ jsx(YearPicker, { calendar, onSelectYear: onSelect }) ] }); }); Calendar.displayName = "Calendar"; //#endregion export { Calendar, Calendar as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=calendar.js.map