UNPKG

@i-novus/ui-core

Version:

Базовые UI компоненты

98 lines (97 loc) 4.91 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useCallback, useLayoutEffect, useRef, useState } from 'react'; import ReactCalendar from 'react-calendar'; import classNames from 'classnames'; import { useConfigProvider } from '../../core'; import { Navigation } from './Navigation'; import { EChangeType } from './types'; import { TimePicker } from './Navigation/TimePicker'; const getWeekDayShortLabels = (locale, date) => { return new Intl .DateTimeFormat(locale || 'ru', { weekday: 'short' }) .format(date); }; const monthShortNames = [ 'Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек', ]; const getMonthShortName = (locale, date) => { const monthIndex = date.getMonth(); return monthShortNames[monthIndex] || ''; }; const TODAY = new Date(); const BEGINNING_OF_CENTURY = new Date('1900').getFullYear(); const DEFAULT_VIEW = 'month'; const MIN_YEAR = BEGINNING_OF_CENTURY; const MAX_YEAR = TODAY.getFullYear() + 100; const prepareDate = (value, time) => { const date = new Date(value); date.setHours(Number(time.hours), Number(time.minutes), Number(time.seconds)); return date; }; export const Calendar = forwardRef((props, ref) => { const { className, prefix, locale = 'ru', activeStartDate, style, view = DEFAULT_VIEW, onSelect, onMouseEnter, onMouseLeave, minDate, maxDate, dateAccuracy, } = props; const { getPrefix } = useConfigProvider(); const prefixCls = getPrefix(prefix); const calendarContainerRef = useRef(null); const [calendarInitialDate, setCalendarInitialDate] = useState(activeStartDate || TODAY); const [userSelectedDate, setUserSelectedDate] = useState(activeStartDate || TODAY); const [time, setTime] = useState({ hours: '0', minutes: '0', seconds: '0' }); const showTimePicker = !!dateAccuracy && ['minute', 'full'].includes(dateAccuracy); // #region date select handlers const handleChangeTime = useCallback((value) => { setTime(value); onSelect?.(prepareDate(userSelectedDate, value), { changedType: EChangeType.TIME }); }, [onSelect, userSelectedDate]); const handleCalendarDateSelect = useCallback((date) => { setUserSelectedDate((selectedDate) => { if (date.toISOString() === selectedDate?.toISOString()) { return selectedDate; } return date; }); }, []); const handleActiveStartDateChange = useCallback(({ action, activeStartDate }) => { if ((action.startsWith('next') || action.startsWith('prev')) && activeStartDate) { setCalendarInitialDate(activeStartDate); } }, []); const handleClickMonth = useCallback((value) => { handleCalendarDateSelect(value); onSelect?.(prepareDate(value, time), { changedType: EChangeType.MONTH }); }, [handleCalendarDateSelect, onSelect, time]); const handleChange = useCallback((value) => { if (Array.isArray(value) || !value) { return; } handleCalendarDateSelect(value); onSelect?.(prepareDate(value, time), { changedType: EChangeType.DATE }); }, [handleCalendarDateSelect, onSelect, time]); // #endregion useLayoutEffect(() => { if (!activeStartDate) { return; } setTime({ hours: activeStartDate.getHours().toString(), minutes: activeStartDate.getMinutes().toString(), seconds: activeStartDate.getSeconds().toString(), }); setUserSelectedDate(activeStartDate); setCalendarInitialDate(activeStartDate); }, [activeStartDate]); return (_jsxs("div", { ref: calendarContainerRef, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, className: classNames(`${prefixCls}-calendar`, className), style: style, children: [_jsx(Navigation, { prefix: prefixCls, view: view, initialDate: calendarInitialDate, minYear: minDate?.getFullYear() ?? MIN_YEAR, maxYear: maxDate?.getFullYear() ?? MAX_YEAR, onActiveStartDateChange: handleActiveStartDateChange }), _jsx(ReactCalendar, { inputRef: ref, showNeighboringMonth: false, showNavigation: false, formatShortWeekday: getWeekDayShortLabels, formatMonth: getMonthShortName, locale: locale, className: (classNames(`${prefixCls}-react-calendar`, { [`${prefixCls}-react-calendar--with-timepicker`]: showTimePicker, })), activeStartDate: calendarInitialDate, value: userSelectedDate, view: view, minDate: minDate, maxDate: maxDate, onChange: handleChange, onClickMonth: handleClickMonth, onActiveStartDateChange: handleActiveStartDateChange }), showTimePicker && (_jsx(TimePicker, { prefix: prefixCls, value: time, onChange: handleChangeTime, dateAccuracy: dateAccuracy }))] })); }); Calendar.displayName = 'Calendar';