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.

169 lines (167 loc) • 5.75 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 { useEffect, useRef, useState } from "react"; import { 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(!selectedDate && autoOpened); const [isInvalidInputDate, setIsInvalidInputDate] = useState(true); const [isInvalidSelectedDate, setIsInvalidSelectedDate] = useState(!selectedDate); const initialDateRef = useRef(selectedDateProps); const isClearButtonVisible = showClearButton && initialDateRef.current; 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); initialDateRef.current = selectedDateProps; } }, [isOpen, selectedDateProps]); useEffect(() => { setIsInvalidSelectedDate(selectedDate && !isStartDateInRange(selectedDate) || selectedDate && !isEndDateInRange(selectedDate) || selectedDate && !isValidDateRange(selectedDate) || !selectedDate); }, [selectedDate]); const onApplyDates = (date) => { onSelected?.(date); initialDateRef.current = date; setIsOpen(false); }; const onClear = () => { onClose(); onSelected?.(void 0); }; const onClose = () => { setSelectedDate(void 0); setIsOpen(false); }; const onToggle = () => { if (isOpen) onClose(); setIsOpen(!isOpen); }; const selectDate = (range) => setSelectedDate(range?.startDate); const onDateInputValidate = (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 && !isStartDateInRange(date), "Invalid date"], [!!boundaries?.endDate && !isEndDateInRange(date), "Invalid date"] ].filter(([result]) => result); if (validateErrorPair) { const [_, message] = validateErrorPair; setIsInvalidInputDate(true); return message; } } return ""; }; return /* @__PURE__ */ jsx(Box, { className: cs("vui-datePicker", className), position: "relative", ref, ...styles, ...rest, children: /* @__PURE__ */ jsxs(Popover, { isOpen, onClose: () => setIsOpen(false), placement: placement ? placement : popupPosition === "right" ? "bottom-end" : void 0, children: [/* @__PURE__ */ jsx(Popover.Trigger, { as: Box, onClick: onToggle, children }), /* @__PURE__ */ jsxs(Popover.Content, { column: true, children: [ !!slotTop && /* @__PURE__ */ jsx(Box, { px: 2, children: slotTop }), /* @__PURE__ */ jsx(Box, { display: "block", mb: 0, mt: 2, mx: 2, children: /* @__PURE__ */ jsx(DateInput, { autoFocus: true, initialDate: selectedDate, onChange: (newDate) => setSelectedDate(newDate), onValidate: onDateInputValidate, setValidateStatus: (inValid) => setIsInvalidInputDate(!inValid) }) }), /* @__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__ */ jsx(Box, { overflow: "unset", children: /* @__PURE__ */ jsxs(Box, { alignItems: "center", flex: 1, ml: "auto", pb: 2, px: 2, children: [isClearButtonVisible && /* @__PURE__ */ jsx(LineButton, { flex: 1, onClick: onClear, size: "md", children: "Clear" }), /* @__PURE__ */ jsx(Button, { disabled: isInvalidSelectedDate || isInvalidInputDate, flex: 1, ml: isClearButtonVisible ? 1 : 0, onClick: () => onApplyDates(selectedDate), size: "md", children: "Apply" })] }) }), !!slotBottom && /* @__PURE__ */ jsx(Box, { px: 2, children: slotBottom }) ] })] }) }); }); DatePicker.displayName = "DatePicker"; //#endregion export { DatePicker as default }; globalThis.__vuiVersion__ = "5.3.0-alpha.2" //# sourceMappingURL=datePicker.js.map