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.

168 lines (166 loc) 6.32 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 { Button } from "../button/button.js"; import { LineButton } from "../button/buttons.js"; import { maxDateTimestamp, minDateTimestamp } from "../calendar/consts.js"; import { Calendar } from "../calendar/calendar.js"; import Popover from "../popover/popover.js"; import { DateInput } from "./dateInput.js"; import { useCallback, useEffect, useRef, useState } from "react"; import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime"; //#region src/datePicker/datePicker.tsx /** Select or input a date. */ const DatePicker = vui((props, ref) => { const { autoOpened, boundaries, popupPosition, placement, selectedDate: selectedDateProps, showClearButton, slotBottom, slotTop, onSelected, children, className, ...rest } = omitThemingProps(props); const styles = useStyleConfig("DatePicker", props); const [selectedDate, setSelectedDate] = useState(selectedDateProps); const [isOpen, setIsOpen] = useState(!selectedDateProps && !!autoOpened); const [isInvalidInputDate, setIsInvalidInputDate] = useState(true); const [isInvalidSelectedDate, setIsInvalidSelectedDate] = useState(!selectedDate); const [isClearButtonVisible, setIsClearButtonVisible] = useState(!!(showClearButton && selectedDateProps)); const initialDateRef = useRef(selectedDateProps); const isStartDateInRange = (date) => !!boundaries?.startDate && !!date ? date.getTime() - boundaries.startDate.getTime() >= 0 : true; const isEndDateInRange = (date) => !!boundaries?.endDate && !!date ? date.getTime() - boundaries.endDate.getTime() <= 0 : true; const isValidDateRange = (date) => { const minDateTime = new Date(minDateTimestamp); const maxDateTime = new Date(maxDateTimestamp); return date >= minDateTime && date <= maxDateTime; }; useEffect(() => { if (!isOpen) { setSelectedDate(selectedDateProps); setIsClearButtonVisible(!!(showClearButton && selectedDateProps)); initialDateRef.current = selectedDateProps; } }, [ isOpen, selectedDateProps, showClearButton ]); useEffect(() => { setIsInvalidSelectedDate(selectedDate && !isStartDateInRange(selectedDate) || selectedDate && !isEndDateInRange(selectedDate) || selectedDate && !isValidDateRange(selectedDate) || !selectedDate); }, [selectedDate]); const onApplyDates = useCallback((date, close) => { onSelected?.(date); initialDateRef.current = date; setIsClearButtonVisible(!!(showClearButton && date)); close?.(); }, [onSelected, showClearButton]); const onClear = useCallback((close) => { setSelectedDate(void 0); onSelected?.(void 0); close?.(); }, [onSelected]); const handlePopoverOpen = useCallback(() => setIsOpen(true), []); const handlePopoverClose = useCallback(() => setIsOpen(false), []); const selectDate = (range) => setSelectedDate(range?.startDate); const onDateInputValidate = useCallback((date) => { const minDateTime = new Date(minDateTimestamp); const maxDateTime = new Date(maxDateTimestamp); if (date) { const [validateErrorPair] = [ [isNaN(date.getTime()), "Supported format is YYYY-MM-DD"], [date < minDateTime, "Invalid date, the minimum date time is 1753-01-02"], [date > maxDateTime, "Invalid date, the maximum date time is 9000-12-31"], [!!boundaries?.startDate && date.getTime() - boundaries.startDate.getTime() < 0, "Invalid date"], [!!boundaries?.endDate && date.getTime() - boundaries.endDate.getTime() > 0, "Invalid date"] ].filter(([result]) => result); if (validateErrorPair) { const [_, message] = validateErrorPair; setIsInvalidInputDate(true); return message; } } return ""; }, [boundaries]); const onDateInputChange = useCallback((date) => setSelectedDate(date), []); const onDateInputValidateStatus = useCallback((inValid) => setIsInvalidInputDate(!inValid), []); return /* @__PURE__ */ jsx(Box, { className: cs("vui-datePicker", className), position: "relative", ref, ...styles, ...rest, children: /* @__PURE__ */ jsx(Popover, { defaultIsOpen: !selectedDateProps && autoOpened, onClose: handlePopoverClose, onOpen: handlePopoverOpen, placement: placement ? placement : popupPosition === "right" ? "bottom-end" : void 0, children: ({ close }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Popover.Trigger, { as: Box, children }), /* @__PURE__ */ jsxs(Popover.Content, { column: true, children: [ !!slotTop && /* @__PURE__ */ jsx(Box, { px: 2, children: slotTop }), /* @__PURE__ */ jsx(Box, { display: "block", mt: 2, mx: 2, children: /* @__PURE__ */ jsx(DateInput, { autoFocus: true, initialDate: selectedDate, onChange: onDateInputChange, onValidate: onDateInputValidate, setValidateStatus: onDateInputValidateStatus }) }), /* @__PURE__ */ jsx(Box, { mx: 2, my: 1, children: /* @__PURE__ */ jsx(Calendar, { boundaries: boundaries ?? { startDate: void 0, endDate: void 0 }, fixedNumberOfWeeks: true, fontWeight: 500, minH: 200, mode: "exact", onSelectDates: (range) => selectDate(range), selectedDates: { startDate: selectedDate, endDate: void 0 }, w: "100%" }) }), /* @__PURE__ */ jsxs(Box, { alignItems: "center", flex: 1, ml: "auto", pb: 2, px: 2, children: [isClearButtonVisible && /* @__PURE__ */ jsx(LineButton, { flex: 1, onClick: () => onClear(close), size: "md", children: "Clear" }), /* @__PURE__ */ jsx(Button, { disabled: isInvalidSelectedDate || isInvalidInputDate, flex: 1, ml: isClearButtonVisible ? 1 : 0, onClick: () => onApplyDates(selectedDate, close), size: "md", children: "Apply" })] }), !!slotBottom && /* @__PURE__ */ jsx(Box, { px: 2, children: slotBottom }) ] })] }) }) }); }); DatePicker.displayName = "DatePicker"; //#endregion export { DatePicker, DatePicker as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=datePicker.js.map