@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
JavaScript
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