UNPKG

mobile-react-infinite-calendar

Version:

A mobile-optimized infinite scroll calendar component for React

33 lines (32 loc) 4.49 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { memo, useMemo } from 'react'; import { format } from 'date-fns'; import { cn } from '../utils/cn'; import { getDateFnsLocale, getCommonText, getYearSuffix, getMonthSuffix, isKoreanLocale } from '../utils/localeUtils'; import { createYearRange } from '../constants/calendar'; const DateSelector = memo(function DateSelector({ show, selectedYear, selectedMonth, showYearDropdown, showMonthDropdown, locale, onClose, onConfirm, onYearSelect, onMonthSelect, onToggleYearDropdown, onToggleMonthDropdown }) { const currentLocale = getDateFnsLocale(locale); const yearSuffix = getYearSuffix(locale); const monthSuffix = getMonthSuffix(locale); const cancelText = getCommonText('cancel', locale); const confirmText = getCommonText('confirm', locale); // 연도 범위 생성 (메모이제이션) const yearRange = useMemo(() => createYearRange(selectedYear - 5, 10), [selectedYear]); // 월 배열 생성 (메모이제이션) const months = useMemo(() => Array.from({ length: 12 }, (_, i) => i + 1), []); // 월 표시 텍스트 생성 (메모이제이션) const getMonthDisplayText = useMemo(() => { return (month) => { if (isKoreanLocale(locale)) { return `${month}${monthSuffix}`; } return format(new Date(2024, month - 1), 'MMMM', { locale: currentLocale }); }; }, [locale, monthSuffix, currentLocale]); if (!show) { return null; } return (_jsxs("div", { className: "relative", children: [_jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 z-40", onClick: onClose }), _jsx("div", { className: "absolute top-2 left-1/2 transform -translate-x-1/2 bg-white border border-gray-200 rounded-lg shadow-lg p-3 z-50 w-72", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex gap-2 items-start", children: [_jsxs("div", { className: "flex-1 relative", children: [_jsxs("button", { onClick: onToggleYearDropdown, className: "w-full px-3 py-3 text-sm border border-gray-300 rounded-md bg-white text-left flex items-center justify-between hover:border-blue-500 touch-manipulation", style: { WebkitTapHighlightColor: 'transparent' }, children: [_jsxs("span", { children: [selectedYear, yearSuffix] }), _jsx("span", { className: "text-gray-400", children: "\u25BC" })] }), showYearDropdown && (_jsx("div", { className: "absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-10 max-h-40 overflow-y-auto", children: yearRange.map((year) => (_jsxs("button", { onClick: () => onYearSelect(year), className: cn("w-full px-3 py-3 text-sm text-left hover:bg-blue-50 hover:text-blue-600 touch-manipulation", year === selectedYear && "bg-blue-100 text-blue-600"), style: { WebkitTapHighlightColor: 'transparent' }, children: [year, yearSuffix] }, year))) }))] }), _jsxs("div", { className: "flex-1 relative", children: [_jsxs("button", { onClick: onToggleMonthDropdown, className: "w-full px-3 py-3 text-sm border border-gray-300 rounded-md bg-white text-left flex items-center justify-between hover:border-blue-500 touch-manipulation", style: { WebkitTapHighlightColor: 'transparent' }, children: [_jsx("span", { children: getMonthDisplayText(selectedMonth) }), _jsx("span", { className: "text-gray-400", children: "\u25BC" })] }), showMonthDropdown && (_jsx("div", { className: "absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-10 max-h-40 overflow-y-auto", children: months.map((month) => (_jsx("button", { onClick: () => onMonthSelect(month), className: cn("w-full px-3 py-2 text-sm text-left hover:bg-blue-50 hover:text-blue-600", month === selectedMonth && "bg-blue-100 text-blue-600"), children: getMonthDisplayText(month) }, month))) }))] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: onClose, className: "flex-1 px-3 py-3 text-sm bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 transition-colors touch-manipulation", style: { WebkitTapHighlightColor: 'transparent' }, children: cancelText }), _jsx("button", { onClick: onConfirm, className: "flex-1 px-3 py-3 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors touch-manipulation", style: { WebkitTapHighlightColor: 'transparent' }, children: confirmText })] })] }) })] })); }); DateSelector.displayName = 'DateSelector'; export { DateSelector };