@tamu-dor/mui-daterange-picker-plus
Version:
A modern Typescript/JavaScript library for simplifying date-range related operations and enhancing date-picker components in web applications. It provides a range of utilities, including date formatting, parsing, and a fully customizable date range picker
1,563 lines (1,538 loc) • 46 kB
JavaScript
// src/components/Sections.tsx
import {
Divider as Divider3,
FormControl as FormControl2,
MenuItem as MenuItem2,
Select as Select2,
Typography as Typography5,
alpha as alpha4,
useTheme as useTheme6,
Unstable_Grid2 as Grid28
} from "@mui/material";
import { differenceInCalendarMonths } from "date-fns";
// src/components/Sections.DefinedRanges.tsx
import "react";
import { isSameDay } from "date-fns";
import {
Box,
List,
ListItem,
ListItemButton,
ListItemText,
alpha,
useTheme,
Unstable_Grid2 as Grid2
} from "@mui/material";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var isSameRange = (first, second) => {
const { startDate: fStart, endDate: fEnd } = first;
const { startDate: sStart, endDate: sEnd } = second;
if (fStart && sStart && fEnd && sEnd) {
return isSameDay(fStart, sStart) && isSameDay(fEnd, sEnd);
}
return false;
};
var DefinedRanges = ({
ranges,
setRange,
selectedRange
}) => {
const theme = useTheme();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Grid2, { xs: "auto", children: /* @__PURE__ */ jsx(
Box,
{
height: "54px",
sx: {
backgroundColor: alpha(theme.palette.grey[400], 0.1)
}
}
) }),
/* @__PURE__ */ jsx(Grid2, { xs: true, children: /* @__PURE__ */ jsx(
List,
{
sx: {
pt: "10px"
},
children: ranges.map((range, idx) => /* @__PURE__ */ jsx(
ListItem,
{
disablePadding: true,
onClick: () => setRange(range),
sx: [
isSameRange(range, selectedRange) ? {
backgroundColor: alpha(theme.palette.grey[600], 0.1)
} : {}
],
children: /* @__PURE__ */ jsx(
ListItemButton,
{
disableRipple: true,
dense: true,
sx: {
p: {
xs: "8px",
md: "12px"
},
height: "32px",
".mui-tlelie-MuiListItemText-root": {
my: 0
}
},
children: /* @__PURE__ */ jsx(
ListItemText,
{
primaryTypographyProps: {
sx: [
isSameRange(range, selectedRange) ? {
color: alpha(theme.palette.grey[800], 1)
} : {
color: alpha(theme.palette.grey[600], 1)
},
{
fontFamily: "Roboto",
fontSize: 13,
fontWeight: 400
}
]
},
children: range.label
}
)
}
)
},
idx
))
}
) })
] });
};
// src/components/Sections.DuelCalender.tsx
import { isSameMonth as isSameMonth3 } from "date-fns";
import { Divider, Unstable_Grid2 as Grid24 } from "@mui/material";
// src/components/Month.tsx
import "react";
import {
getDate,
isSameMonth as isSameMonth2,
isToday,
format,
isWithinInterval as isWithinInterval2
} from "date-fns";
import {
Typography as Typography3,
useTheme as useTheme4,
alpha as alpha3,
Unstable_Grid2 as Grid23
} from "@mui/material";
// src/utils/index.ts
import {
startOfWeek,
startOfMonth,
endOfWeek,
endOfMonth,
isBefore,
addDays,
isSameDay as isSameDay2,
isWithinInterval,
isSameMonth,
addMonths,
parseISO,
isValid,
min,
max
} from "date-fns";
var chunks = (array, size) => Array.from(
{ length: Math.ceil(array.length / size) },
(_v, i) => array.slice(i * size, i * size + size)
);
var getDaysInMonth = (date, locale) => {
const startWeek = startOfWeek(startOfMonth(date), { locale });
const endWeek = endOfWeek(endOfMonth(date), { locale });
const days = [];
for (let curr = startWeek; isBefore(curr, endWeek); ) {
days.push(curr);
curr = addDays(curr, 1);
}
return days;
};
var isStartOfRange = ({ startDate }, day) => startDate && isSameDay2(day, startDate);
var isEndOfRange = ({ endDate }, day) => endDate && isSameDay2(day, endDate);
var inDateRange = ({ startDate, endDate }, day) => startDate && endDate && (isWithinInterval(day, { start: startDate, end: endDate }) || isSameDay2(day, startDate) || isSameDay2(day, endDate));
var isRangeSameDay = ({ startDate, endDate }) => {
if (startDate && endDate) {
return isSameDay2(startDate, endDate);
}
return false;
};
var parseOptionalDate = (date, defaultValue) => {
if (date) {
const parsed = date instanceof Date ? date : parseISO(date);
if (isValid(parsed)) return parsed;
}
return defaultValue;
};
var getValidatedMonths = (range, minDate, maxDate) => {
const { startDate, endDate } = range;
if (startDate && endDate) {
const newStart = max([startDate, minDate]);
const newEnd = min([endDate, maxDate]);
return [
newStart,
isSameMonth(newStart, newEnd) ? addMonths(newStart, 1) : newEnd
];
}
return [startDate, endDate];
};
// src/components/Month.Header.tsx
import { getMonth, getYear, setMonth, setYear } from "date-fns";
import {
FormControl,
IconButton,
MenuItem,
Select,
useTheme as useTheme2,
Typography,
Unstable_Grid2 as Grid22
} from "@mui/material";
import {
KeyboardArrowDown,
KeyboardArrowRight,
KeyboardArrowLeft
} from "@mui/icons-material";
// src/Constants/index.ts
import { addYears, endOfYear, startOfYear } from "date-fns";
var AVAILABLE_MIN_DATE = startOfYear(addYears(/* @__PURE__ */ new Date(), -10));
var AVAILABLE_MAX_DATE = endOfYear(addYears(/* @__PURE__ */ new Date(), 10));
// src/components/Month.Header.tsx
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
var generateYears = ({ start, end }) => {
const count = end - start + 1;
return Array(count).fill(0).map((_y, i) => start + i);
};
var MonthHeader = ({
minDate,
maxDate,
currentDate,
setDate,
nextDisabled,
prevDisabled,
onClickNext,
onClickPrevious,
locale
}) => {
const theme = useTheme2();
const availableYearRange = {
start: (minDate || AVAILABLE_MIN_DATE).getFullYear(),
end: (maxDate || AVAILABLE_MAX_DATE).getFullYear()
};
const MONTHS = Array.from(
{ length: 12 },
(_, index) => typeof locale !== "undefined" ? locale.localize?.month(index, {
width: "abbreviated",
context: "standalone"
}) : [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
][index]
);
const handleMonthChange = (event) => {
setDate(setMonth(currentDate, parseInt(event.target.value, 10)));
};
const handleYearChange = (event) => {
setDate(setYear(currentDate, parseInt(event.target.value, 10)));
};
const currentMonth = getMonth(currentDate);
const currentYear = getYear(currentDate);
const minYear = getYear(minDate);
const maxYear = getYear(maxDate);
const minMonthID = getMonth(minDate);
const maxMonthID = getMonth(maxDate);
const isDisabled = (month) => {
if (currentYear === minYear || currentYear === maxYear) {
if (currentYear === minYear && month < minMonthID) {
return true;
}
if (currentYear === maxYear && month > maxMonthID) {
return true;
}
}
return false;
};
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
/* @__PURE__ */ jsx2(Grid22, { xs: "auto", ml: "10px", container: true, children: /* @__PURE__ */ jsx2(
IconButton,
{
disableRipple: true,
size: "small",
color: "secondary",
className: "Mui-upon-secondary-bg",
disabled: prevDisabled,
onClick: onClickPrevious,
sx: {
borderRadius: "8px",
color: theme.palette.grey[600],
".MuiSvgIcon-root": {
color: theme.palette.grey[600]
},
"&:hover": {
backgroundColor: theme.palette.grey[100]
},
"&.Mui-disabled": {
backgroundColor: "transparent"
},
"&.Mui-upon-secondary-bg": {
// backgroundColor: grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[200]
}
}
},
children: /* @__PURE__ */ jsx2(
KeyboardArrowLeft,
{
fontSize: "small",
sx: {
fill: prevDisabled ? `${theme.palette.grey[400]}` : "secondary"
}
}
)
}
) }),
/* @__PURE__ */ jsx2(Grid22, { xsOffset: "auto", xs: "auto", container: true, children: /* @__PURE__ */ jsx2(FormControl, { children: /* @__PURE__ */ jsx2(
Select,
{
SelectDisplayProps: {
style: {
minHeight: "unset"
}
},
variant: "outlined",
size: "small",
defaultValue: currentYear,
IconComponent: (props) => /* @__PURE__ */ jsx2(
KeyboardArrowDown,
{
fontSize: "small",
sx: {
fill: theme.palette.grey[400]
},
...props
}
),
slotProps: {
root: {
sx: {
width: {
sm: "100px",
md: "120px"
},
height: "30px",
backgroundColor: "#fff"
}
}
},
MenuProps: {
disablePortal: true,
PaperProps: {
sx: {
width: "auto",
maxHeight: "224px",
boxShadow: "rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px"
}
}
},
value: currentMonth,
onChange: handleMonthChange,
children: MONTHS.map((month, idx) => {
return /* @__PURE__ */ jsx2(MenuItem, { value: idx, disabled: isDisabled(idx), children: /* @__PURE__ */ jsx2(
Typography,
{
noWrap: true,
sx: {
fontSize: "14px"
},
children: month
}
) }, month);
})
}
) }) }),
/* @__PURE__ */ jsx2(Grid22, { xsOffset: "auto", xs: "auto", container: true, children: /* @__PURE__ */ jsx2(FormControl, { children: /* @__PURE__ */ jsx2(
Select,
{
variant: "outlined",
size: "small",
defaultValue: currentYear,
SelectDisplayProps: {
style: {
minHeight: "unset"
}
},
IconComponent: (props) => /* @__PURE__ */ jsx2(
KeyboardArrowDown,
{
fontSize: "small",
sx: {
fill: theme.palette.grey[400]
},
...props
}
),
slotProps: {
root: {
sx: {
height: "30px",
backgroundColor: "#fff"
}
}
},
MenuProps: {
disablePortal: true,
PaperProps: {
sx: {
width: "auto",
maxHeight: "224px",
boxShadow: "rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px"
}
}
},
value: getYear(currentDate),
onChange: handleYearChange,
children: generateYears(availableYearRange).map((year) => {
return /* @__PURE__ */ jsx2(MenuItem, { value: year, children: /* @__PURE__ */ jsx2(
Typography,
{
sx: {
fontSize: "14px"
},
children: year
}
) }, year);
})
}
) }) }),
/* @__PURE__ */ jsx2(Grid22, { mr: "10px", xsOffset: "auto", xs: "auto", container: true, children: /* @__PURE__ */ jsx2(
IconButton,
{
disableRipple: true,
size: "small",
color: "secondary",
className: "Mui-upon-secondary-bg",
disabled: nextDisabled,
onClick: onClickNext,
sx: {
borderRadius: "8px",
color: theme.palette.grey[600],
".MuiSvgIcon-root": {
color: theme.palette.grey[600]
},
"&:hover": {
backgroundColor: theme.palette.grey[100]
},
"&.Mui-disabled": {
backgroundColor: "transparent"
},
"&.Mui-upon-secondary-bg": {
"&:hover": {
backgroundColor: theme.palette.grey[200]
}
}
},
children: /* @__PURE__ */ jsx2(
KeyboardArrowRight,
{
fontSize: "small",
sx: {
fill: nextDisabled ? `${theme.palette.grey[400]}` : "secondary"
}
}
)
}
) })
] });
};
// src/components/Day.tsx
import "react";
import { IconButton as IconButton2, Typography as Typography2, Box as Box2, useTheme as useTheme3, alpha as alpha2 } from "@mui/material";
import { jsx as jsx3 } from "react/jsx-runtime";
var Day = ({
startOfRange,
endOfRange,
disabled,
hidden,
highlighted,
outlined,
filled,
onClick,
onHover,
value,
hideOutsideMonthDays = true
}) => {
const theme = useTheme3();
return /* @__PURE__ */ jsx3(
Box2,
{
sx: {
display: "flex",
borderRadius: startOfRange ? "50% 0 0 50%" : endOfRange ? "0 50% 50% 0" : void 0,
backgroundColor: !disabled && highlighted ? alpha2(theme.palette.primary.main, 0.1) : void 0
},
children: /* @__PURE__ */ jsx3(
IconButton2,
{
disableRipple: true,
color: "primary",
sx: {
":hover": {
backgroundColor: alpha2(theme.palette.primary.light, 0.2)
},
borderRadius: "8px",
height: "36px",
width: "36px",
padding: 0,
border: !disabled && outlined ? `1px solid ${theme.palette.primary.main}` : void 0,
...!disabled && filled ? {
"&:hover": {
backgroundColor: theme.palette.primary.main
},
backgroundColor: theme.palette.primary.main
} : {}
},
disabled,
onClick,
onMouseOver: onHover,
children: /* @__PURE__ */ jsx3(
Typography2,
{
sx: {
fontSize: "14px",
visibility: hidden && hideOutsideMonthDays ? "hidden" : "visible",
color: !disabled ? filled ? theme.palette.primary.contrastText : theme.palette.text.primary : theme.palette.text.secondary
},
children: value
}
)
}
)
}
);
};
// src/components/Month.tsx
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
var Month = (props) => {
const theme = useTheme4();
const {
helpers,
handlers,
currentDate,
otherDate,
dateRange,
marker,
setMonth: setMonth2,
minDate,
maxDate,
locale,
hideOutsideMonthDays
} = props;
const weekStartsOn = locale?.options?.weekStartsOn || 0;
const WEEK_DAYS = Array.from(
{ length: 7 },
(_, index) => typeof locale !== "undefined" ? locale.localize?.day((index + weekStartsOn) % 7, {
width: "short",
context: "standalone"
}) : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][index]
);
const [back, forward] = props.navState;
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
/* @__PURE__ */ jsx4(
Grid23,
{
container: true,
justifyContent: "space-between",
alignItems: "center",
sx: {
height: "55px",
backgroundColor: alpha3(theme.palette.grey[400], 0.1)
},
children: /* @__PURE__ */ jsx4(
MonthHeader,
{
minDate,
maxDate,
marker,
currentDate,
otherDate,
setDate: setMonth2,
nextDisabled: !forward,
prevDisabled: !back,
onClickPrevious: () => handlers.handleClickNavIcon(marker, -1 /* Previous */),
onClickNext: () => handlers.handleClickNavIcon(marker, 1 /* Next */),
locale
}
)
}
),
/* @__PURE__ */ jsx4(
Grid23,
{
container: true,
justifyContent: "center",
sx: {
margin: "16px 24px 0 24px"
},
children: WEEK_DAYS.map((day, index) => /* @__PURE__ */ jsx4(Grid23, { container: true, width: "36px", justifyContent: "center", children: /* @__PURE__ */ jsx4(
Typography3,
{
color: "textSecondary",
sx: {
fontSize: "12px"
},
children: day
},
index
) }, index))
}
),
/* @__PURE__ */ jsx4(
Grid23,
{
container: true,
direction: "column",
sx: {
margin: "24px"
},
children: chunks(getDaysInMonth(currentDate, locale), 7).map((week, idx) => /* @__PURE__ */ jsx4(Grid23, { container: true, direction: "row", justifyContent: "center", children: week.map((day) => {
const isStart = isStartOfRange(dateRange, day);
const isEnd = isEndOfRange(dateRange, day);
const isRangeOneDay = isRangeSameDay(dateRange);
const highlighted = inDateRange(dateRange, day) || helpers.isInHoverRange(day);
return /* @__PURE__ */ jsx4(
Day,
{
filled: isStart || isEnd,
outlined: isToday(day),
highlighted: highlighted && !isRangeOneDay,
disabled: !isSameMonth2(currentDate, day) || !(isWithinInterval2(day, { start: minDate, end: maxDate }) || isStartOfRange(
{
startDate: minDate,
endDate: maxDate
},
day
)),
hidden: !isSameMonth2(currentDate, day),
hideOutsideMonthDays,
startOfRange: isStart && !isRangeOneDay,
endOfRange: isEnd && !isRangeOneDay,
onClick: () => handlers.handleClickDateNumber(day),
onHover: () => handlers.handleHoverDateNumber(day),
value: getDate(day)
},
format(day, "dd-MM-yyyy")
);
}) }, idx))
}
)
] });
};
// src/Constants/markers.ts
var MARKERS = {
FIRST_MONTH: Symbol("firstMonth"),
SECOND_MONTH: Symbol("secondMonth"),
SINGLE_MONTH: Symbol("singleMonth")
};
// src/components/Sections.DuelCalender.tsx
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
var DuelCalender = ({
firstMonth,
secondMonth,
handleSetFirstMonth,
handleSetSecondMonth,
canNavigateCloser,
commonProps,
locale,
hideOutsideMonthDays
}) => {
const canNavigateBack = !isSameMonth3(firstMonth, commonProps.minDate);
const canNavigateForward = !isSameMonth3(secondMonth, commonProps.maxDate);
return /* @__PURE__ */ jsxs4(
Grid24,
{
xs: 12,
container: true,
direction: {
xs: "column",
md: "row"
},
justifyContent: "center",
children: [
/* @__PURE__ */ jsx5(Grid24, { xs: "auto", container: true, direction: "column", children: /* @__PURE__ */ jsx5(
Month,
{
...commonProps,
currentDate: firstMonth,
otherDate: secondMonth,
setMonth: handleSetFirstMonth,
navState: [canNavigateBack, canNavigateCloser],
marker: MARKERS.FIRST_MONTH,
locale,
hideOutsideMonthDays
}
) }),
/* @__PURE__ */ jsx5(Grid24, { xs: "auto", children: /* @__PURE__ */ jsx5(Divider, { orientation: "vertical" }) }),
/* @__PURE__ */ jsx5(Grid24, { xs: "auto", container: true, direction: "column", children: /* @__PURE__ */ jsx5(
Month,
{
...commonProps,
currentDate: secondMonth,
otherDate: firstMonth,
setMonth: handleSetSecondMonth,
navState: [canNavigateCloser, canNavigateForward],
marker: MARKERS.SECOND_MONTH,
locale,
hideOutsideMonthDays
}
) })
]
}
);
};
// src/components/Sections.tsx
import { useMemo, useState } from "react";
// src/components/Sections.Footer.tsx
import { format as format2 } from "date-fns";
import {
Divider as Divider2,
styled as styled2,
useTheme as useTheme5,
Typography as Typography4,
Unstable_Grid2 as Grid26
} from "@mui/material";
// src/components/Actions.tsx
import { styled, Button, Unstable_Grid2 as Grid25 } from "@mui/material";
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
var CancelButtonStyled = styled(Button)(({ theme }) => ({
textTransform: "none",
fontSize: 13,
fontWeight: 400,
borderRadius: "8px",
marginRight: "8px",
padding: "0 16px",
height: "36px",
color: theme.palette.grey[600],
"&:hover": {
backgroundColor: theme.palette.grey[100]
}
}));
var ApplyButtonStyled = styled(Button)({
fontSize: 13,
fontWeight: 400,
borderRadius: "8px",
textTransform: "none",
height: "36px",
padding: "0 16px"
});
var Actions = ({
onCloseCallback,
onSubmit,
labels
}) => {
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
/* @__PURE__ */ jsx6(Grid25, { children: /* @__PURE__ */ jsx6(
CancelButtonStyled,
{
disableRipple: true,
disableElevation: true,
variant: "text",
onClick: onCloseCallback,
children: labels?.cancel || "Cancel"
}
) }),
/* @__PURE__ */ jsx6(Grid25, { children: /* @__PURE__ */ jsx6(
ApplyButtonStyled,
{
disableRipple: true,
disableElevation: true,
type: "submit",
variant: "contained",
color: "primary",
onClick: onSubmit,
children: labels?.apply || "Apply"
}
) })
] });
};
// src/components/Sections.Footer.tsx
import {
KeyboardDoubleArrowDown,
KeyboardDoubleArrowRight
} from "@mui/icons-material";
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
var PreviewDateTypoStyled = styled2(Typography4)(({ theme }) => ({
position: "relative",
top: "1px",
minWidth: "130px",
fontSize: 14,
lineHeight: "14px",
color: theme.palette.grey[800]
}));
var PreviewDateMessageTypoStyled = styled2(Typography4)(({ theme }) => ({
position: "relative",
top: "1px",
minWidth: "130px",
fontSize: 14,
lineHeight: "14px",
color: theme.palette.grey[500]
}));
var Footer = ({
startDate,
endDate,
locale,
labels,
onCloseCallback,
onSubmit,
RangeSeparatorIcons,
single
}) => {
const theme = useTheme5();
const previewDate = (date) => {
return format2(date, "dd MMMM yyyy", { locale });
};
const IconXs = RangeSeparatorIcons?.xs || KeyboardDoubleArrowDown;
const IconMd = RangeSeparatorIcons?.md || KeyboardDoubleArrowRight;
if (single) {
return /* @__PURE__ */ jsx7(
Grid26,
{
xs: "auto",
container: true,
justifyContent: "flex-end",
children: /* @__PURE__ */ jsx7(Actions, { onCloseCallback, onSubmit, labels: labels?.actions })
}
);
} else {
return /* @__PURE__ */ jsxs6(Fragment5, { children: [
/* @__PURE__ */ jsxs6(
Grid26,
{
xs: true,
container: true,
gap: "8px",
direction: {
xs: "column",
md: "row"
},
justifyContent: "flex-start",
alignItems: "center",
children: [
startDate ? /* @__PURE__ */ jsx7(
PreviewDateTypoStyled,
{
textAlign: {
xs: "center",
md: "left"
},
children: previewDate(startDate)
}
) : /* @__PURE__ */ jsx7(
PreviewDateMessageTypoStyled,
{
textAlign: {
xs: "center",
md: "left"
},
children: labels?.footer?.startDate || "Start Date"
}
),
/* @__PURE__ */ jsx7(
IconXs,
{
fontSize: "small",
sx: {
fill: theme.palette.grey[400],
display: {
xs: "block",
md: "none"
}
}
}
),
/* @__PURE__ */ jsx7(
IconMd,
{
fontSize: "small",
sx: {
fill: theme.palette.grey[400],
display: {
xs: "none",
md: "block"
}
}
}
),
endDate ? /* @__PURE__ */ jsx7(
PreviewDateTypoStyled,
{
textAlign: {
xs: "center",
md: "left"
},
children: previewDate(endDate)
}
) : /* @__PURE__ */ jsx7(
PreviewDateMessageTypoStyled,
{
textAlign: {
xs: "center",
md: "left"
},
children: labels?.footer?.endDate || "End Date"
}
)
]
}
),
/* @__PURE__ */ jsx7(
Grid26,
{
display: {
xs: "block",
md: "none"
},
children: /* @__PURE__ */ jsx7(Divider2, { orientation: "horizontal" })
}
),
/* @__PURE__ */ jsx7(Grid26, { xs: "auto", container: true, justifyContent: "flex-end", children: /* @__PURE__ */ jsx7(Actions, { onCloseCallback, onSubmit, labels: labels?.actions }) })
] });
}
};
// src/components/Sections.tsx
import { KeyboardArrowDown as KeyboardArrowDown2 } from "@mui/icons-material";
// src/components/Sections.SingleCalender.tsx
import { isSameMonth as isSameMonth4 } from "date-fns";
import { Unstable_Grid2 as Grid27 } from "@mui/material";
import { jsx as jsx8 } from "react/jsx-runtime";
var SingleCalender = ({
firstMonth,
secondMonth,
handleSetSingleMonth,
commonProps,
locale,
hideOutsideMonthDays
}) => {
const canNavigateBack = !isSameMonth4(firstMonth, commonProps.minDate);
const canNavigateForward = !isSameMonth4(firstMonth, commonProps.maxDate);
return /* @__PURE__ */ jsx8(
Grid27,
{
xs: 12,
container: true,
direction: {
xs: "column",
md: "row"
},
justifyContent: "center",
children: /* @__PURE__ */ jsx8(Grid27, { xs: "auto", container: true, direction: "column", children: /* @__PURE__ */ jsx8(
Month,
{
...commonProps,
currentDate: firstMonth,
otherDate: secondMonth,
setMonth: handleSetSingleMonth,
navState: [canNavigateBack, canNavigateForward],
marker: MARKERS.SINGLE_MONTH,
locale,
hideOutsideMonthDays
}
) })
}
);
};
// src/components/Sections.tsx
import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
var Sections = (props) => {
const theme = useTheme6();
const {
dateRange,
ranges,
minDate,
maxDate,
firstMonth,
secondMonth,
handleSetFirstMonth,
handleSetSecondMonth,
handleSetSingleMonth,
handleClickDefinedRange,
helpers,
handlers,
locale,
labels,
hideActionButtons = false,
hideDefaultRanges = false,
hideOutsideMonthDays,
RangeSeparatorIcons,
onCloseCallback,
footerRequired,
single
} = props;
const { startDate, endDate } = dateRange;
const canNavigateCloser = differenceInCalendarMonths(secondMonth, firstMonth) >= 2;
const commonProps = {
dateRange,
minDate,
maxDate,
helpers,
handlers
};
const [selectedRange, setSelectedRange] = useState("");
const [selectedRangeObj, setSelectedRangeObj] = useState(void 0);
const onChangeSelectedRange = (e) => {
const selectedRange2 = ranges.find(
(range) => range.label === e.target.value
);
if (selectedRange2) {
setSelectedRange(selectedRange2.label);
setSelectedRangeObj(selectedRange2);
handleClickDefinedRange(selectedRange2);
}
};
const isRangeSameDay2 = (sd1, ed1, sd2, ed2) => {
return sd1.getDate() === sd2.getDate() && sd1.getMonth() === sd2.getMonth() && sd1.getFullYear() === sd2.getFullYear() && ed1.getDate() === ed2.getDate() && ed1.getMonth() === ed2.getMonth() && ed1.getFullYear() === ed2.getFullYear();
};
useMemo(() => {
if (selectedRangeObj && dateRange.startDate && dateRange.endDate) {
const { startDate: sd1, endDate: ed1 } = dateRange;
const { startDate: sd2, endDate: ed2 } = selectedRangeObj;
if (sd1 && ed1 && sd2 && ed2) {
if (isRangeSameDay2(sd1, ed1, sd2, ed2)) {
return;
}
setSelectedRange("");
}
}
}, [selectedRangeObj, dateRange]);
return /* @__PURE__ */ jsxs7(
Grid28,
{
container: true,
sx: {
borderRadius: "16px",
backgroundColor: "#fff",
overflow: "hidden"
},
children: [
/* @__PURE__ */ jsx9(
Grid28,
{
xs: "auto",
container: true,
direction: "column",
className: "DRP-Defined-Ranges",
display: { xs: "none", md: hideDefaultRanges ? "none" : "flex" },
children: /* @__PURE__ */ jsx9(
DefinedRanges,
{
selectedRange: dateRange,
ranges,
setRange: handleClickDefinedRange
}
)
}
),
/* @__PURE__ */ jsx9(
Grid28,
{
xs: "auto",
display: { xs: "none", md: hideDefaultRanges ? "none" : "block" },
children: /* @__PURE__ */ jsx9(Divider3, { orientation: "vertical" })
}
),
/* @__PURE__ */ jsxs7(Grid28, { xs: true, container: true, direction: "column", children: [
/* @__PURE__ */ jsx9(
Grid28,
{
display: { xs: hideDefaultRanges ? "none" : "flex", md: "none" },
container: true,
height: "48px",
alignItems: "center",
px: "16px",
sx: { backgroundColor: alpha4(theme.palette.grey[400], 0.1) },
children: /* @__PURE__ */ jsxs7(
Grid28,
{
xs: 12,
container: true,
justifyContent: "space-between",
alignItems: "center",
children: [
/* @__PURE__ */ jsx9(
Typography5,
{
sx: {
fontSize: "14px"
},
children: labels?.predefinedRanges || "Quick Select"
}
),
/* @__PURE__ */ jsx9(FormControl2, { children: /* @__PURE__ */ jsx9(
Select2,
{
displayEmpty: true,
SelectDisplayProps: {
style: {
minHeight: "unset"
}
},
variant: "outlined",
size: "small",
IconComponent: (props2) => /* @__PURE__ */ jsx9(
KeyboardArrowDown2,
{
fontSize: "small",
sx: {
fill: theme.palette.grey[400]
},
...props2
}
),
slotProps: {
root: {
sx: {
height: "30px",
backgroundColor: "#fff"
}
}
},
MenuProps: {
disablePortal: true,
PaperProps: {
sx: {
width: "auto",
maxHeight: "224px",
boxShadow: "rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px"
}
}
},
value: selectedRange,
onChange: onChangeSelectedRange,
children: ranges.map((range) => {
return /* @__PURE__ */ jsx9(MenuItem2, { value: range.label, children: /* @__PURE__ */ jsx9(
Typography5,
{
sx: {
fontSize: "14px"
},
children: range.label
}
) }, range.label);
})
}
) })
]
}
)
}
),
/* @__PURE__ */ jsx9(Grid28, { display: { xs: "block", md: "none" }, children: /* @__PURE__ */ jsx9(Divider3, {}) }),
/* @__PURE__ */ jsx9(Grid28, { container: true, display: { xs: "flex", md: single ? "flex" : "none" }, children: /* @__PURE__ */ jsx9(
SingleCalender,
{
firstMonth,
secondMonth,
handleSetSingleMonth,
canNavigateCloser,
commonProps,
hideOutsideMonthDays,
locale
}
) }),
/* @__PURE__ */ jsx9(Grid28, { flex: 1, display: { xs: "none", md: single ? "none" : "flex" }, container: true, children: /* @__PURE__ */ jsx9(
DuelCalender,
{
firstMonth,
secondMonth,
handleSetFirstMonth,
handleSetSecondMonth,
canNavigateCloser,
commonProps,
hideOutsideMonthDays,
locale
}
) }),
footerRequired ? /* @__PURE__ */ jsxs7(Fragment6, { children: [
/* @__PURE__ */ jsx9(Grid28, { display: hideActionButtons ? "none" : "block", children: /* @__PURE__ */ jsx9(Divider3, {}) }),
/* @__PURE__ */ jsx9(
Grid28,
{
display: hideActionButtons ? "none" : "flex",
xs: "auto",
container: true,
alignItems: {
xs: "normal",
md: "center"
},
justifyContent: {
xs: "center",
md: "flex-end"
},
direction: {
xs: "column",
md: "row"
},
p: "16px",
gap: "16px",
children: /* @__PURE__ */ jsx9(
Footer,
{
startDate,
endDate,
locale,
labels,
onCloseCallback,
onSubmit: handlers.handleClickSubmit,
RangeSeparatorIcons,
single
}
)
}
)
] }) : null
] })
]
}
);
};
// src/hooks/useDateRangePicker.ts
import {
addDays as addDays3,
addMonths as addMonths3,
differenceInDays,
isAfter,
isBefore as isBefore2,
isSameDay as isSameDay3,
isSameMonth as isSameMonth5,
isWithinInterval as isWithinInterval3,
lastDayOfMonth,
max as max2,
min as min2
} from "date-fns";
// src/defaults.ts
import {
addDays as addDays2,
startOfWeek as startOfWeek2,
endOfWeek as endOfWeek2,
addWeeks,
startOfMonth as startOfMonth2,
endOfMonth as endOfMonth2,
addMonths as addMonths2,
startOfYear as startOfYear2,
endOfYear as endOfYear2,
addYears as addYears2
} from "date-fns";
var getDefaultRanges = (date, locale) => [
{
label: "Today",
startDate: date,
endDate: date
},
{
label: "Yesterday",
startDate: addDays2(date, -1),
endDate: addDays2(date, -1)
},
{
label: "This Week",
startDate: startOfWeek2(date, { locale }),
endDate: endOfWeek2(date, { locale })
},
{
label: "Last Week",
startDate: startOfWeek2(addWeeks(date, -1), { locale }),
endDate: endOfWeek2(addWeeks(date, -1), { locale })
},
{
label: "Last 7 Days",
startDate: addWeeks(date, -1),
endDate: date
},
{
label: "This Month",
startDate: startOfMonth2(date),
endDate: endOfMonth2(date)
},
{
label: "Last Month",
startDate: startOfMonth2(addMonths2(date, -1)),
endDate: endOfMonth2(addMonths2(date, -1))
},
{
label: "This Year",
startDate: startOfYear2(date),
endDate: endOfYear2(date)
},
{
label: "Last Year",
startDate: startOfYear2(addYears2(date, -1)),
endDate: endOfYear2(addYears2(date, -1))
}
];
// src/hooks/useDateRangePicker.ts
import { useState as useState2 } from "react";
var useDateRangePicker = (props) => {
const today = /* @__PURE__ */ new Date();
const {
onChange: onChangeCallback,
onSubmit: onSubmitCallback,
initialDateRange,
minDate,
maxDate,
minDays,
maxDays,
dateRange,
definedRanges = getDefaultRanges(/* @__PURE__ */ new Date(), props.locale),
locale
} = props;
const minValidDate = parseOptionalDate(minDate, AVAILABLE_MIN_DATE);
const maxValidDate = parseOptionalDate(maxDate, AVAILABLE_MAX_DATE);
const [initialFirstMonth, initialSecondMonth] = getValidatedMonths(
initialDateRange || {},
minValidDate,
maxValidDate
);
const [internalDateRange, setInternalDateRange] = useState2({
...initialDateRange
});
const [hoverDay, setHoverDay] = useState2();
const [firstMonth, setFirstMonth] = useState2(
initialFirstMonth || today
);
const [secondMonth, setSecondMonth] = useState2(
initialSecondMonth || addMonths3(firstMonth, 1)
);
const { startDate, endDate } = dateRange || internalDateRange;
const handleSetFirstMonth = (date) => {
if (isBefore2(date, secondMonth)) {
if (isAfter(date, minValidDate)) {
setFirstMonth(date);
return;
} else {
setFirstMonth(lastDayOfMonth(minValidDate));
return;
}
} else {
if (isBefore2(addMonths3(date, 1), maxValidDate)) {
setFirstMonth(date);
setSecondMonth(addMonths3(date, 1));
return;
} else {
setSecondMonth(maxValidDate);
setFirstMonth(addMonths3(maxValidDate, -1));
}
}
};
const handleSetSecondMonth = (date) => {
if (isAfter(date, firstMonth)) {
if (isBefore2(date, maxValidDate)) {
setSecondMonth(date);
return;
} else {
setSecondMonth(lastDayOfMonth(maxValidDate));
return;
}
} else {
if (isAfter(addMonths3(date, -1), minValidDate)) {
setSecondMonth(date);
setFirstMonth(addMonths3(date, -1));
return;
} else {
setFirstMonth(minValidDate);
setSecondMonth(addMonths3(minValidDate, 1));
}
}
};
const handleSetSingleMonth = (date) => {
if (isAfter(date, minValidDate) && isBefore2(date, maxValidDate)) {
setFirstMonth(date);
return;
} else if (isBefore2(date, minValidDate) || isSameDay3(date, minValidDate)) {
setFirstMonth(minValidDate);
return;
} else if (isAfter(date, maxValidDate) || isSameDay3(date, maxValidDate)) {
setFirstMonth(maxValidDate);
return;
}
};
const handleClickDefinedRange = (range) => {
let { startDate: newStart, endDate: newEnd } = range;
if (newStart && newEnd) {
const diff = differenceInDays(newEnd, newStart);
range.startDate = newStart = max2([newStart, minValidDate]);
if (minDays && diff < minDays) {
range.endDate = newEnd = min2([
addDays3(newStart, minDays),
maxValidDate
]);
} else if (maxDays && diff > maxDays) {
range.endDate = newEnd = min2([
addDays3(newStart, maxDays),
maxValidDate
]);
} else {
range.endDate = newEnd = min2([newEnd, maxValidDate]);
}
if (!dateRange) setInternalDateRange(range);
onChangeCallback && onChangeCallback(range);
setFirstMonth(newStart);
setSecondMonth(
isSameMonth5(newStart, newEnd) ? addMonths3(newStart, 1) : newEnd
);
} else {
if (!dateRange) setInternalDateRange({});
onChangeCallback && onChangeCallback({});
setFirstMonth(today);
setSecondMonth(addMonths3(firstMonth, 1));
}
};
const handleClickDateNumber = (day) => {
if (startDate && !endDate && !isBefore2(day, startDate)) {
const diff = differenceInDays(day, startDate);
let newDay;
if (minDays && diff < minDays) {
newDay = min2([addDays3(startDate, minDays), maxValidDate]);
} else if (maxDays && diff > maxDays) {
newDay = min2([addDays3(startDate, maxDays), maxValidDate]);
} else {
newDay = day;
}
const newRange = { startDate, endDate: newDay };
onChangeCallback && onChangeCallback(newRange);
if (!dateRange) setInternalDateRange(newRange);
} else if (minDays === 0 && maxDays === 0) {
const newRange = { startDate: day, endDate: day };
if (!dateRange) setInternalDateRange(newRange);
onChangeCallback && onChangeCallback(newRange);
} else if (minDays && maxDays) {
const newEndDay = addDays3(day, maxDays);
const newRange = { startDate: day, endDate: newEndDay };
if (!dateRange) setInternalDateRange(newRange);
onChangeCallback && onChangeCallback(newRange);
} else {
if (!dateRange)
setInternalDateRange({ startDate: day, endDate: void 0 });
}
setHoverDay(day);
};
const handleClickSubmit = () => {
const { startDate: startDate2, endDate: endDate2 } = dateRange || internalDateRange;
if (onSubmitCallback && startDate2 && endDate2) {
onSubmitCallback(dateRange || internalDateRange);
}
};
const handleClickNavIcon = (marker, action) => {
if (marker === MARKERS.SINGLE_MONTH) {
setFirstMonth(addMonths3(firstMonth, action));
setSecondMonth(addMonths3(secondMonth, action));
return;
}
if (marker === MARKERS.FIRST_MONTH) {
const firstNew = addMonths3(firstMonth, action);
if (isBefore2(firstNew, secondMonth)) setFirstMonth(firstNew);
} else {
const secondNew = addMonths3(secondMonth, action);
if (isBefore2(firstMonth, secondNew)) setSecondMonth(secondNew);
}
};
const handleHoverDateNumber = (date) => {
if (startDate && !endDate) {
if (!hoverDay || !isSameDay3(date, hoverDay)) {
setHoverDay(date);
}
}
};
const isInHoverRange = (day) => startDate && !endDate && hoverDay && isAfter(hoverDay, startDate) && isWithinInterval3(day, { start: startDate, end: hoverDay });
const helpers = {
isInHoverRange
};
const handlers = {
handleClickDateNumber,
handleClickSubmit,
handleClickNavIcon,
handleHoverDateNumber
};
return {
dateRange: dateRange || internalDateRange,
ranges: definedRanges,
minDate: minValidDate,
maxDate: maxValidDate,
firstMonth,
secondMonth,
handleSetFirstMonth,
handleSetSecondMonth,
handleSetSingleMonth,
handleClickDefinedRange,
helpers,
handlers,
locale
};
};
// src/DateRangePicker.tsx
import { jsx as jsx10 } from "react/jsx-runtime";
var DateRangePicker = (props) => {
const { customProps, ...dateRangePickerProps } = props;
const onSubmit = customProps?.onSubmit;
const { ...computedProps } = useDateRangePicker({
...dateRangePickerProps,
onSubmit
});
return /* @__PURE__ */ jsx10(Sections, { ...dateRangePickerProps, ...computedProps, ...customProps });
};
// src/PickerModal.tsx
import { Dialog, useTheme as useTheme7, Popover, useMediaQuery } from "@mui/material";
import { jsx as jsx11 } from "react/jsx-runtime";
var PickerModal = ({
modalProps,
customProps,
...dateRangePickerProps
}) => {
const theme = useTheme7();
const isMobileView = useMediaQuery(theme.breakpoints.down("md"));
if (isMobileView) {
const { open, onClose } = modalProps;
return /* @__PURE__ */ jsx11(Dialog, { open, onClose, children: /* @__PURE__ */ jsx11(
DateRangePicker,
{
...dateRangePickerProps,
customProps,
footerRequired: true
}
) });
}
return /* @__PURE__ */ jsx11(Popover, { ...modalProps, children: /* @__PURE__ */ jsx11(
DateRangePicker,
{
...dateRangePickerProps,
customProps,
footerRequired: true
}
) });
};
// src/PickerBase.tsx
import { jsx as jsx12 } from "react/jsx-runtime";
var PickerBase = (props) => {
return /* @__PURE__ */ jsx12(DateRangePicker, { ...props });
};
export {
PickerBase,
PickerModal
};