@codeworker.br/govbr-tw-react
Version:
Biblioteca de componentes React usando Tailwind CSS que implementa o Padrão Digital de Governo.
87 lines (86 loc) • 5.53 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from "react";
import Input from "../Input";
import { Button } from "../Button";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCalendarDays } from "@fortawesome/free-solid-svg-icons";
const DatePicker = ({ value, onChange, locale = "pt-BR", // Locale padrão
}) => {
const [isCalendarOpen, setIsCalendarOpen] = useState(false);
const [selectedDate, setSelectedDate] = useState(value || null);
const [currentMonth, setCurrentMonth] = useState(new Date());
// Funções para formatação de datas e nomes de dias/meses
const dateFormatter = new Intl.DateTimeFormat(locale);
const monthFormatter = new Intl.DateTimeFormat(locale, { month: "long" });
const dayFormatter = new Intl.DateTimeFormat(locale, { weekday: "short" });
useEffect(() => {
if (value) {
setSelectedDate(value);
setCurrentMonth(new Date(value.getFullYear(), value.getMonth(), 1));
}
}, [value]);
const handleDateClick = (date) => {
const newDate = new Date(date);
newDate.setHours(0, 0, 0, 0); // Remover horário para garantir precisão na comparação
setSelectedDate(newDate);
if (onChange) {
onChange(newDate);
}
setIsCalendarOpen(false);
};
const handleInputClick = () => {
setIsCalendarOpen(!isCalendarOpen);
};
const changeMonth = (event) => {
const newMonth = parseInt(event.target.value, 10);
setCurrentMonth((prev) => {
const newDate = new Date(prev);
newDate.setMonth(newMonth);
return newDate;
});
};
const changeYear = (event) => {
const newYear = parseInt(event.target.value, 10);
setCurrentMonth((prev) => {
const newDate = new Date(prev);
newDate.setFullYear(newYear);
return newDate;
});
};
const handleYearInputChange = (event) => {
const value = event.target.value;
if (/^\d{4}$/.test(value)) {
changeYear(event);
}
};
const changeMonthByOffset = (offset) => {
setCurrentMonth((prev) => {
const newDate = new Date(prev);
newDate.setMonth(prev.getMonth() + offset);
return newDate;
});
};
const renderCalendar = () => {
if (!isCalendarOpen)
return null;
const startDate = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), 1);
const endDate = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 0);
// Determinar o início do calendário (começar no início da semana)
const calendarStartDate = new Date(startDate);
calendarStartDate.setDate(startDate.getDate() - startDate.getDay());
// Determinar o final do calendário (encontrar o final da semana)
const calendarEndDate = new Date(endDate);
calendarEndDate.setDate(endDate.getDate() + (6 - endDate.getDay()));
const days = [];
for (let d = calendarStartDate; d <= calendarEndDate; d.setDate(d.getDate() + 1)) {
const isCurrentMonth = d.getMonth() === currentMonth.getMonth();
days.push(_jsx("div", { onClick: () => handleDateClick(new Date(d)), className: `size-10 rounded-full cursor-pointer flex justify-center items-center text-govbr-blue-warm-vivid-70 ${(selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.toDateString()) === d.toDateString()
? "!bg-govbr-blue-warm-vivid-70 text-govbr-pure-0"
: "hover:bg-gray-200"} ${!isCurrentMonth ? "text-gray-400" : ""}`, children: d.getDate() }, d.toDateString()));
}
const monthOptions = Array.from({ length: 12 }, (_, i) => (_jsx("option", { value: i, children: new Intl.DateTimeFormat(locale, { month: "long" }).format(new Date(0, i)) }, i)));
return (_jsxs("div", { className: "absolute border border-gray-300 bg-white shadow-lg", children: [_jsxs("div", { className: "flex items-center p-2", children: [_jsx("button", { onClick: () => changeMonthByOffset(-12), className: "px-2", children: "<<" }), _jsx("button", { onClick: () => changeMonthByOffset(-1), className: "px-2", children: "<" }), _jsx("select", { value: currentMonth.getMonth(), onChange: changeMonth, className: "mx-2 border border-gray-300 p-1", children: monthOptions }), _jsx("input", { type: "number", value: currentMonth.getFullYear(), onChange: handleYearInputChange, className: "mx-2 border border-gray-300 p-1 w-24", min: "1900", max: "2100" }), _jsx("button", { onClick: () => changeMonthByOffset(1), className: "px-2", children: ">" }), _jsx("button", { onClick: () => changeMonthByOffset(12), className: "px-2", children: ">>" })] }), _jsxs("div", { className: "grid grid-cols-7 gap-1 p-2", children: [Array.from({ length: 7 }, (_, i) => new Date(0, 0, i)).map((date) => (_jsx("div", { className: "text-center font-bold", children: dayFormatter.format(date) }, date.toDateString()))), days] })] }));
};
return (_jsxs("div", { className: "relative", children: [_jsx(Input, { type: "text", value: selectedDate ? dateFormatter.format(selectedDate) : "", iconPosition: "right", children: _jsx(Button, { size: "icon", variant: "ghost", density: "high", onClick: handleInputClick, children: _jsx(FontAwesomeIcon, { icon: faCalendarDays }) }) }), renderCalendar()] }));
};
export { DatePicker };