daily-toolset
Version:
A lightweight, versatile collection of TypeScript utility functions for everyday development needs. Simplify and streamline your Node.js, React, and Next.js projects with a powerful suite of well-organized helpers for strings, arrays, dates, objects, and
149 lines (148 loc) • 8.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateInput = DateInput;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const FormLabel_1 = require("./FormLabel");
const ClearInput_1 = require("./ClearInput");
const popover_1 = require("../../components/ui/popover");
const Button_1 = require("./Button");
const lu_1 = require("react-icons/lu");
const calendar_1 = require("../../components/ui/calendar");
const InputError_1 = require("./InputError");
const scroll_area_1 = require("../../components/ui/scroll-area");
const formProvider_1 = require("../../form/formProvider");
const dateUtils_1 = require("../../dateUtils");
function DateInput({ isRequired = true, isDisabled = false, isClearable = true, defaultValue, label, name, error, startDate, endDate, placeholder = "dd/mm/yyyy", onChange, }) {
const { formValues, formErrors, updateValue, validateField } = (0, formProvider_1.useForm)();
const [value, setValue] = (0, react_1.useState)(defaultValue);
const [open, setOpen] = (0, react_1.useState)(false);
const id = (0, react_1.useId)();
(0, react_1.useEffect)(() => {
const inputValue = name && formValues[name]
? formValues[name]
: undefined;
if (name && inputValue) {
setValue(inputValue);
}
}, [formValues, name]);
const handleChange = (0, react_1.useCallback)((inputValue) => {
const formatted = (0, dateUtils_1.formatDate)(inputValue, { format: "YYYY-MM-DD" });
const selected = inputValue === value || !inputValue ? undefined : formatted;
validateField(name, selected !== null && selected !== void 0 ? selected : "");
setValue(selected);
onChange ? onChange(selected || "") : updateValue(name, selected);
}, [name, onChange, updateValue, validateField]);
const handleYearAndMonthChange = (0, react_1.useCallback)((year, month) => {
const date = value ? new Date(value) : new Date();
date.setFullYear(year);
date.setMonth(month);
handleChange(date);
}, [handleChange, value]);
const errorData = error
? error
: name
? (formErrors === null || formErrors === void 0 ? void 0 : formErrors[name]) || ""
: "";
return ((0, jsx_runtime_1.jsxs)("div", { className: "explita-input-root", children: [(0, jsx_runtime_1.jsx)(FormLabel_1.Label, { id: id, label: label, isRequired: isRequired }), (0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: open, onOpenChange: setOpen, children: [(0, jsx_runtime_1.jsxs)("div", { children: [isClearable && value && !isDisabled && ((0, jsx_runtime_1.jsx)(ClearInput_1.Clear, { onClick: () => handleChange(undefined) })), (0, jsx_runtime_1.jsx)(popover_1.PopoverTrigger, { asChild: true, children: (0, jsx_runtime_1.jsxs)(Button_1.Button, { variant: "outline", "data-error": errorData.length > 0, "data-empty": !value, "data-clearable": isClearable, className: "date-input", disabled: isDisabled, children: [(0, jsx_runtime_1.jsx)(lu_1.LuCalendar, { size: 16 }), (0, jsx_runtime_1.jsx)("span", { children: value
? (0, dateUtils_1.formatDate)(value, { format: "Month DD, YYYY" })
: placeholder })] }) })] }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "explita-calendar-content explita-popover-content", align: "start", children: (0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "single", selected: value ? new Date(value) : undefined, onSelect: (currentValue) => {
handleChange(currentValue);
setOpen(false);
}, initialFocus: true, fromDate: startDate, toDate: endDate, disabled: isDisabled, defaultMonth: value ? new Date(value) : undefined, classNames: {
root: "explita-calendar-root",
}, captionLabelRenderer: (props) => ((0, jsx_runtime_1.jsx)(YearPicker, { displayMonth: props.displayMonth, startYear: startDate === null || startDate === void 0 ? void 0 : startDate.getFullYear(), endYear: endDate === null || endDate === void 0 ? void 0 : endDate.getFullYear(), handleYearAndMonthChange: handleYearAndMonthChange })) }, value === null || value === void 0 ? void 0 : value.toString()) })] }), (0, jsx_runtime_1.jsx)(InputError_1.InputError, { message: errorData }), (0, jsx_runtime_1.jsx)("input", { type: "hidden", name: name, value: value ? (0, dateUtils_1.formatDate)(value, { format: "YYYY-MM-DD" }) : "", id: id })] }));
}
function YearPicker({ displayMonth, startYear, endYear, handleYearAndMonthChange, }) {
const [isYearOpen, setIsYearOpen] = (0, react_1.useState)(false);
const [isMonthOpen, setIsMonthOpen] = (0, react_1.useState)(false);
const [selectedYear, setSelectedYear] = (0, react_1.useState)(displayMonth
? new Date(displayMonth).getFullYear()
: new Date().getFullYear());
if (typeof displayMonth === "string") {
displayMonth = new Date(displayMonth);
}
if (displayMonth === undefined) {
displayMonth = new Date();
}
const years = (0, react_1.useMemo)(() => {
const start = Number(startYear) || 1950;
const end = Number(endYear) || new Date().getFullYear() + 10;
const yearsList = [];
for (let i = end; i >= start; i--) {
yearsList.push(i);
}
return yearsList;
}, [startYear, endYear]);
function handleSelectYear(year) {
setSelectedYear(year);
setIsYearOpen(!isYearOpen);
setIsMonthOpen(!isMonthOpen);
}
function handleSelectMonth(month) {
handleYearAndMonthChange(selectedYear, month);
setIsMonthOpen(!isMonthOpen);
}
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("span", { role: "button", className: "year-picker-label", "aria-expanded": isYearOpen, onClick: () => setIsYearOpen(!isYearOpen), children: [months[displayMonth.getMonth()].label, " ", displayMonth.getFullYear()] }), (0, jsx_runtime_1.jsxs)("div", { className: "year-picker-root", "data-open": isYearOpen, children: [(0, jsx_runtime_1.jsx)("span", { role: "button", className: "title", onClick: () => setIsYearOpen(!isYearOpen), children: "Select Year" }), (0, jsx_runtime_1.jsx)(scroll_area_1.ScrollArea, { className: "year-picker-scroll-area", children: (0, jsx_runtime_1.jsx)("div", { className: "items", children: years.map((year) => ((0, jsx_runtime_1.jsx)("span", { role: "button", className: "item", "data-active": displayMonth.getFullYear() === year, onClick: () => handleSelectYear(year), children: year }, year))) }) })] }), (0, jsx_runtime_1.jsx)(MonthPicker, { displayMonth: displayMonth, handleSelectMonth: handleSelectMonth, isMonthOpen: isMonthOpen })] }));
}
const months = [
{
value: 0,
label: "Jan",
},
{
value: 1,
label: "Feb",
},
{
value: 2,
label: "Mar",
},
{
value: 3,
label: "Apr",
},
{
value: 4,
label: "May",
},
{
value: 5,
label: "Jun",
},
{
value: 6,
label: "Jul",
},
{
value: 7,
label: "Aug",
},
{
value: 8,
label: "Sep",
},
{
value: 9,
label: "Oct",
},
{
value: 10,
label: "Nov",
},
{
value: 11,
label: "Dec",
},
];
function MonthPicker({ displayMonth, handleSelectMonth, isMonthOpen = false, }) {
if (typeof displayMonth === "string") {
displayMonth = new Date(displayMonth);
}
if (displayMonth === undefined) {
displayMonth = new Date();
}
return ((0, jsx_runtime_1.jsxs)("div", { className: "year-picker-root", "data-open": isMonthOpen, children: [(0, jsx_runtime_1.jsx)("span", { role: "button", className: "title", children: "Select Month" }), (0, jsx_runtime_1.jsx)(scroll_area_1.ScrollArea, { className: "year-picker-scroll-area", children: (0, jsx_runtime_1.jsx)("div", { className: "items", children: months.map((month) => ((0, jsx_runtime_1.jsx)("span", { role: "button", className: "item", "data-active": (displayMonth === null || displayMonth === void 0 ? void 0 : displayMonth.getMonth()) === month.value, onClick: () => {
handleSelectMonth(month.value);
}, children: month.label }, month.value))) }) })] }));
}