@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.78 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 { 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, DatePicker as default };
globalThis.__vuiVersion__ = "5.3.0-alpha.2"
//# sourceMappingURL=datePicker.js.map