UNPKG

react95

Version:

Refreshed Windows95 UI components for modern web apps - React95

154 lines (149 loc) 5.85 kB
import React__default, { forwardRef, useState, useCallback, useMemo } from 'react'; import styled from 'styled-components'; import { Button } from '../Button/Button.mjs'; import { NumberInput } from '../NumberInput/NumberInput.mjs'; import { ScrollView } from '../ScrollView/ScrollView.mjs'; import { Select } from '../Select/Select.mjs'; import { Toolbar } from '../Toolbar/Toolbar.mjs'; import { Window } from '../Window/Window.mjs'; import { WindowHeader } from '../Window/WindowHeader.mjs'; import { WindowContent } from '../Window/WindowContent.mjs'; const Calendar = styled(ScrollView)` width: 234px; margin: 1rem 0; background: ${({ theme }) => theme.canvas}; `; const WeekDays = styled.div` display: flex; background: ${({ theme }) => theme.materialDark}; color: #dfe0e3; `; const Dates = styled.div` display: flex; flex-wrap: wrap; `; const DateItem = styled.div` text-align: center; height: 1.5em; line-height: 1.5em; width: 14.28%; `; const DateItemContent = styled.span` cursor: pointer; background: ${({ active, theme }) => active ? theme.hoverBackground : "transparent"}; color: ${({ active, theme }) => active ? theme.canvasTextInvert : theme.canvasText}; &:hover { border: 2px dashed ${({ theme, active }) => active ? "none" : theme.materialDark}; } `; const months = [ { value: 0, label: "January" }, { value: 1, label: "February" }, { value: 2, label: "March" }, { value: 3, label: "April" }, { value: 4, label: "May" }, { value: 5, label: "June" }, { value: 6, label: "July" }, { value: 7, label: "August" }, { value: 8, label: "September" }, { value: 9, label: "October" }, { value: 10, label: "November" }, { value: 11, label: "December" } ]; function daysInMonth(year, month) { return new Date(year, month + 1, 0).getDate(); } function dayIndex(year, month, day) { return new Date(year, month, day).getDay(); } function convertDateToState(stringDate) { const date = new Date(Date.parse(stringDate)); const day = date.getUTCDate(); const month = date.getUTCMonth(); const year = date.getUTCFullYear(); return { day, month, year }; } const DatePicker = forwardRef(({ className, date: initialDate = new Date().toISOString(), onAccept, onCancel, shadow = true }, ref) => { const [date, setDate] = useState(() => convertDateToState(initialDate)); const { year, month, day } = date; const handleMonthSelect = useCallback(({ value: monthSelected }) => { setDate((currentDate) => ({ ...currentDate, month: monthSelected })); }, []); const handleYearSelect = useCallback((yearSelected) => { setDate((currentDate) => ({ ...currentDate, year: yearSelected })); }, []); const handleDaySelect = useCallback((daySelected) => { setDate((currentDate) => ({ ...currentDate, day: daySelected })); }, []); const handleAccept = useCallback(() => { const chosenDate = [date.year, date.month + 1, date.day].map((part) => String(part).padStart(2, "0")).join("-"); onAccept === null || onAccept === void 0 ? void 0 : onAccept(chosenDate); }, [date.day, date.month, date.year, onAccept]); const dayPickerItems = useMemo(() => { const items = Array.from({ length: 42 }); const firstDayIndex = dayIndex(year, month, 1); let itemDay = day; const daysNumber = daysInMonth(year, month); itemDay = itemDay < daysNumber ? itemDay : daysNumber; items.forEach((_, i) => { if (i >= firstDayIndex && i < daysNumber + firstDayIndex) { const dayNumber = i - firstDayIndex + 1; items[i] = React__default.createElement( DateItem, { key: i, onClick: () => { handleDaySelect(dayNumber); } }, React__default.createElement(DateItemContent, { active: dayNumber === itemDay }, dayNumber) ); } else { items[i] = React__default.createElement(DateItem, { key: i }); } }); return items; }, [day, handleDaySelect, month, year]); return React__default.createElement( Window, { className, ref, shadow, style: { margin: 20 } }, React__default.createElement( WindowHeader, null, React__default.createElement("span", { role: "img", "aria-label": "\u{1F4C6}" }, "\u{1F4C6}"), "Date" ), React__default.createElement( WindowContent, null, React__default.createElement( Toolbar, { noPadding: true, style: { justifyContent: "space-between" } }, React__default.createElement(Select, { options: months, value: month, onChange: handleMonthSelect, width: 128, menuMaxHeight: 200 }), React__default.createElement(NumberInput, { value: year, onChange: handleYearSelect, width: 100 }) ), React__default.createElement( Calendar, null, React__default.createElement( WeekDays, null, React__default.createElement(DateItem, null, "S"), React__default.createElement(DateItem, null, "M"), React__default.createElement(DateItem, null, "T"), React__default.createElement(DateItem, null, "W"), React__default.createElement(DateItem, null, "T"), React__default.createElement(DateItem, null, "F"), React__default.createElement(DateItem, null, "S") ), React__default.createElement(Dates, null, dayPickerItems) ), React__default.createElement( Toolbar, { noPadding: true, style: { justifyContent: "space-between" } }, React__default.createElement(Button, { fullWidth: true, onClick: onCancel, disabled: !onCancel }, "Cancel"), React__default.createElement(Button, { fullWidth: true, onClick: onAccept ? handleAccept : void 0, disabled: !onAccept }, "OK") ) ) ); }); DatePicker.displayName = "DatePicker"; export { DatePicker as DatePicker__UNSTABLE };