puppy-lib-components
Version:
A modern TypeScript React component library with generic UI components and football pickem domain components
98 lines (97 loc) • 4.97 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useCallback, useMemo } from 'react';
import { useMediaQuery, useTheme } from '@mui/material';
import { DateInput } from './DateInput';
import { DesktopPicker } from './DesktopPicker';
import { MobilePicker } from './MobilePicker';
import { formatDisplayValue } from './utils';
export const DateRangePicker = ({ value, defaultValue, onChange, onAccept, onClose, onOpen, label, placeholder = 'Select date range', disabled = false, readOnly = false, required = false, error = false, errorMessage, helperText, format = 'MM/dd/yyyy', minDate, maxDate, disableFuture = false, disablePast = false, shouldDisableDate, closeOnSelect = true, calendars = 2, showDaysOutsideCurrentMonth = false, displayWeekNumber = false, name, id, className, open: controlledOpen, rangePosition: controlledRangePosition, onRangePositionChange, autoFocus = false, size = 'medium', clearable = true, renderInput, }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const [internalValue, setInternalValue] = useState(defaultValue || { start: null, end: null });
const [internalOpen, setInternalOpen] = useState(false);
const [internalRangePosition, setInternalRangePosition] = useState('start');
const [anchorEl, setAnchorEl] = useState(null);
const currentValue = value || internalValue;
const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;
const rangePosition = controlledRangePosition !== undefined ? controlledRangePosition : internalRangePosition;
const handleOpen = useCallback((event) => {
if (disabled || readOnly)
return;
setAnchorEl(event.currentTarget);
if (controlledOpen === undefined) {
setInternalOpen(true);
}
onOpen?.();
}, [disabled, readOnly, controlledOpen, onOpen]);
const handleClose = useCallback(() => {
setAnchorEl(null);
if (controlledOpen === undefined) {
setInternalOpen(false);
}
onClose?.();
}, [controlledOpen, onClose]);
const handleDateChange = useCallback((date, calendarIndex = 0) => {
const newValue = { ...currentValue };
if (rangePosition === 'start') {
newValue.start = date;
if (!newValue.end || date > newValue.end) {
newValue.end = null;
}
}
else {
newValue.end = date;
if (!newValue.start || date < newValue.start) {
newValue.start = null;
}
}
if (value === undefined) {
setInternalValue(newValue);
}
onChange?.(newValue);
// Auto-close if both dates are selected and closeOnSelect is true
if (closeOnSelect && newValue.start && newValue.end) {
onAccept?.(newValue);
handleClose();
}
}, [currentValue, rangePosition, value, onChange, closeOnSelect, onAccept, handleClose]);
const handleRangePositionChange = useCallback((position) => {
if (controlledRangePosition === undefined) {
setInternalRangePosition(position);
}
onRangePositionChange?.(position);
}, [controlledRangePosition, onRangePositionChange]);
const handleClear = useCallback(() => {
const newValue = { start: null, end: null };
if (value === undefined) {
setInternalValue(newValue);
}
onChange?.(newValue);
}, [value, onChange]);
const handleAccept = useCallback(() => {
onAccept?.(currentValue);
handleClose();
}, [onAccept, currentValue, handleClose]);
const displayValue = useMemo(() => {
return formatDisplayValue(currentValue, format);
}, [currentValue, format]);
const hasValue = Boolean(currentValue.start || currentValue.end);
const commonPickerProps = {
open: isOpen,
onClose: handleClose,
currentValue,
rangePosition,
onRangePositionChange: handleRangePositionChange,
onDateChange: handleDateChange,
onAccept: handleAccept,
onClear: handleClear,
clearable,
minDate,
maxDate,
disableFuture,
disablePast,
shouldDisableDate,
showDaysOutsideCurrentMonth,
};
return (_jsxs(_Fragment, { children: [_jsx(DateInput, { value: displayValue, placeholder: placeholder, label: label, disabled: disabled, readOnly: readOnly, required: required, error: error, errorMessage: errorMessage, helperText: helperText, name: name, id: id, size: size, autoFocus: autoFocus, clearable: clearable, hasValue: hasValue, onOpen: handleOpen, onClear: handleClear, renderInput: renderInput, className: className }), isMobile ? (_jsx(MobilePicker, { ...commonPickerProps })) : (_jsx(DesktopPicker, { ...commonPickerProps, anchorEl: anchorEl, calendars: calendars }))] }));
};