1.0.3 • Published 6 months ago

@tamu-dor/mui-daterange-picker-plus v1.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

Preview

Desktop Screenshot

MUI DateRange Picker Plus

An advanced and highly customizable Date Range Picker component for Material-UI (MUI).

npm version License

View Demo here

Edit mui-daterange-picker-plus

Table of Contents

Features

  • Date Range Selection: Select a date range with ease.
  • Rich UI/UX: Enjoy an enhanced user experience with a feature-rich Date Range Picker.
  • Responsive Design: Works seamlessly on all devices and screen sizes (Mobile Optimized).
  • Customization: A large set of customization options to meet your specific needs.
  • Min and Max Date: Set minimum and maximum selectable dates.
  • Defined Ranges: Use predefined date ranges for quick selection. You can add your custom ranges as well.
  • Event Handling: Easily handle changes and submissions with customizable callbacks.
  • Locale Support: Localized date formatting for a global audience.

Installation

Install the MUI Date Range Picker package via npm:

npm install mui-daterange-picker-plus

Usage with Examples

1. Picker Model (Basic)

import { useState } from "react";
import Button from "@mui/material/Button";
import { PickerModal } from "mui-daterange-picker-plus/dist";
import type { DateRange } from "mui-daterange-picker-plus/dist";

export default function YourComponent() {
   // state + handlers for the Modal
  const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };
  const handleClose = () => {
    setAnchorEl(null);
  };
  const open = Boolean(anchorEl);

 // state + handlers for the DateRange Value
  const [dateRangeOnChange, setDateRangeOnChange] = useState<DateRange>({});
  const [dateRangeOnSubmit, setDateRangeOnSubmit] = useState<DateRange>({});
  const handleSetDateRangeOnChange = (dateRange: DateRange) => {
    setDateRangeOnChange(dateRange);
    handleSetDateRangeOnSubmit({});
  };
  const handleSetDateRangeOnSubmit = (dateRange: DateRange) => {
    setDateRangeOnSubmit(dateRange);
    // handleClose(); // close the modal
  };

  console.log("dateRangeOnChange", dateRangeOnChange);
  console.log("dateRangeOnSubmit", dateRangeOnSubmit);

  return (
    <>
      <Button variant="contained" onClick={handleClick}>
        View Picker Model
      </Button>
      <PickerModal
        onChange={(range: DateRange) => handleSetDateRangeOnChange(range)}
        customProps={{
          onSubmit: (range: DateRange) => handleSetDateRangeOnSubmit(range),
          onCloseCallback: handleClose,
        }}
        modalProps={{
          open,
          anchorEl,
          onClose: handleClose,
          slotProps: {
            paper: {
              sx: {
                borderRadius: "16px",
                boxShadow: "rgba(0, 0, 0, 0.21) 0px 0px 4px",
              },
            },
          },
          anchorOrigin: {
            vertical: "bottom",
            horizontal: "left",
          },
        }}
      />
    </>
  );
}

2. Picker Base (Basic)

import { useState } from "react";
import { PickerBase } from "mui-daterange-picker-plus/dist";
import type { DateRange } from "mui-daterange-picker-plus/dist";

export default function YourComponent() {
  // state + handlers for the DateRange Value
  const [dateRangeOnChange, setDateRangeOnChange] = useState<DateRange>({});
  const handleSetDateRangeOnChange = (dateRange: DateRange) => {
    setDateRangeOnChange(dateRange);
  };

  console.log("dateRangeOnChange", dateRangeOnChange);

  return (
    <PickerBase
      onChange={(range: DateRange) => handleSetDateRangeOnChange(range)}
    />
  );
}

3. Picker Model (Advanced)

import { useState } from "react";
import Button from "@mui/material/Button";
import { PickerModal } from "mui-daterange-picker-plus/dist";
import type { DateRange } from "mui-daterange-picker-plus/dist";
import ArrowCircleRightIcon from "@mui/icons-material/ArrowCircleRight";
import ArrowCircleDownIcon from "@mui/icons-material/ArrowCircleDown";

export default function YourComponent() {
  // state + handlers for the Modal
  const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };
  const handleClose = () => {
    setAnchorEl(null);
  };
  const open = Boolean(anchorEl);

 // state + handlers for the DateRange Value
  const [dateRangeOnChange, setDateRangeOnChange] = useState<DateRange>({});
  const [dateRangeOnSubmit, setDateRangeOnSubmit] = useState<DateRange>({});
  const handleSetDateRangeOnChange = (dateRange: DateRange) => {
    setDateRangeOnChange(dateRange);
    handleSetDateRangeOnSubmit({});
  };
  const handleSetDateRangeOnSubmit = (dateRange: DateRange) => {
    setDateRangeOnSubmit(dateRange);
    // handleClose(); // close the modal
  };

  console.log("dateRangeOnChange", dateRangeOnChange);
  console.log("dateRangeOnSubmit", dateRangeOnSubmit);

  return (
    <>
      <Button variant="contained" onClick={handleClick}>
        View Picker Model
      </Button>
      <PickerModal
        hideOutsideMonthDays={false}
        initialDateRange={{
          startDate: new Date(),
          endDate: new Date("2024-12-31"),
        }}
        minDate={new Date("2023-08-02")}
        maxDate={new Date("2025-02-04")}
        onChange={(range: DateRange) => handleSetDateRangeOnChange(range)}
        customProps={{
          onSubmit: (range: DateRange) => handleSetDateRangeOnSubmit(range),
          onCloseCallback: handleClose,
          RangeSeparatorIcons: {
            xs: ArrowCircleDownIcon,
            md: ArrowCircleRightIcon,
          },
        }}
        modalProps={{
          open,
          anchorEl,
          onClose: handleClose,
          slotProps: {
            paper: {
              sx: {
                borderRadius: "16px",
                boxShadow: "rgba(0, 0, 0, 0.21) 0px 0px 4px",
              },
            },
          },
          anchorOrigin: {
            vertical: "bottom",
            horizontal: "left",
          },
        }}
      />
    </>
  );
}

4. Picker Base (Advanced)

import { useState } from "react";
import { PickerBase } from "mui-daterange-picker-plus/dist";
import type { DateRange } from "mui-daterange-picker-plus/dist";

export default function YourComponent() {
  // state + handlers for the DateRange Value
  const [dateRangeOnChange, setDateRangeOnChange] = useState<DateRange>({});
  const handleSetDateRangeOnChange = (dateRange: DateRange) => {
    setDateRangeOnChange(dateRange);
  };

  console.log("dateRangeOnChange", dateRangeOnChange);

  return (
    <PickerBase
      hideOutsideMonthDays={false}
      initialDateRange={{
        startDate: new Date("2023-09-15"),
        endDate: new Date("2024-12-31"),
      }}
      minDate={new Date("2023-08-02")}
      maxDate={new Date("2025-02-04")}
      onChange={(range: DateRange) => handleSetDateRangeOnChange(range)}
    />
  );
}

Customization using Props

PickerProps

PropTypeDefaultDescription
initialDateRangeDateRange-Initial date range for the picker.
definedRangesDefinedRange[]-Predefined date ranges for quick selection.
minDateDate \| stringstartOfYear(addYears( new Date(), -10))Minimum selectable date.
maxDateDate \| stringendOfYear(addYears( new Date(), 10))Maximum selectable date.
minDays?number-Minimum selectable days.
maxDays?number-Maximum selectable days.
dateRange?DateRange-Controlled date range for the picker.
onChange(dateRange: DateRange) => void-Callback function triggered on date range change.
localeLocale-Locale for date formatting.
labelsLabels-Customize labels used in UI (Apply, Cancel, Start Date, End Date etc.)
hideDefaultRangesbooleanfalseOption to hide default predefined ranges.
hideOutsideMonthDaysbooleantrueOption to hide days outside the current month.
single?booleanfalseOption to display only a single calendar and select one date.

Make sure to provide initialDateRange within the min and max date.

ModalCustomProps

PropTypeDefaultDescription
onSubmit(dateRange: DateRange) => void-Callback function triggered on date range submission.
onCloseCallback() => void-Callback function triggered on popover close.
RangeSeparatorIconsRangeSeparatorIconsProps-Icons for the range separator in different sizes.
hideActionsButtonsbooleanfalseOption to hide action buttons.

Useful Types

Main Types

import { PopoverProps } from "@mui/material/Popover";
import { PickerProps, ModalCustomProps } from "./utils";

type PickerModalProps = PickerProps & {
  modalProps: PopoverProps;
  customProps: ModalCustomProps;
};

type PickerBaseProps = PickerProps;

In the above examples, the PickerBase has included PickerBaseProps props. Same as that, PickerModal has included PickerModalProps props.

  • The PickerProps, ModalCustomProps types are utility types and you can refer them as per your requirement. ( With or Without Modal)

  • In the below section, you can find the details of the utility types.

  • The PopoverProps is a Material-UI Popover component props. You can refer to the Material-UI Popover API for more details.

Utility Types

import { ElementType } from "react";
import { SvgIconProps } from "@mui/material";
import { Locale } from "date-fns";

type DateRange = {
  startDate?: Date;
  endDate?: Date;
};

type DefinedRange = {
  startDate: Date;
  endDate: Date;
  label: string;
};

type RangeSeparatorIconsProps = {
  xs?: ElementType<SvgIconProps>;
  md?: ElementType<SvgIconProps>;
};

type PickerProps = {
  initialDateRange?: DateRange;
  definedRanges?: DefinedRange[];
  minDate?: Date | string;
  maxDate?: Date | string;
  minDays?: number;
  maxDays?: number;
  dateRange?: DateRange;
  locale?: Locale;
  onChange?: (dateRange: DateRange) => void;
  single?: boolean;
  hideDefaultRanges?: boolean;
  hideOutsideMonthDays?: boolean;
};

type ModalCustomProps = {
  onSubmit?: (dateRange: DateRange) => void;
  onCloseCallback?: () => void;
  RangeSeparatorIcons?: RangeSeparatorIconsProps;
  hideActionButtons?: boolean;
};

You can use these types as per your requirement.

License

This project is licensed under the MIT License.