98 |
{},
114 | }
115 | : {})}
116 | />
117 |
118 | {hasCalendarIcon && (
119 |
126 | {calendarIcon ?? }
127 |
128 | )}
129 |
130 | )}
131 | >
132 | );
133 | }
134 | );
135 |
136 | export default DatePickerInput;
137 |
--------------------------------------------------------------------------------
/src/DatePickerNP/components/Calendar/Dates/index.tsx:
--------------------------------------------------------------------------------
1 | import { DAYS_OF_WEEK } from "../../../constants/calendar";
2 | import { NEPALI_DATES } from "../../../constants/dates";
3 | import { CalendarDatesProps, WeeksProps } from "../../../types/Calendar";
4 | import {
5 | extractDateData,
6 | getNumberOfDaysInMonth,
7 | getNumberOfDaysInPreviousMonth,
8 | isGreaterThanOrEqualToMinDate,
9 | isLessThanOrEqualToMaxDate,
10 | isValidNepaliDate,
11 | } from "../../../utils";
12 | import { numberConversion } from "../../../utils/number";
13 |
14 | const Weeks = ({ lang }: WeeksProps) => {
15 | return (
16 |
17 | {DAYS_OF_WEEK.map(({ name_en, name_np }) => (
18 |
{lang === "en" ? name_en : name_np}
19 | ))}
20 |
21 | );
22 | };
23 |
24 | const CalendarDates = ({
25 | date,
26 | handleChange,
27 | min,
28 | max,
29 | lang,
30 | calendarStyles,
31 | }: CalendarDatesProps) => {
32 | const numberOfDays = getNumberOfDaysInMonth(date);
33 | const numberOfDaysInPreviousMonth = getNumberOfDaysInPreviousMonth(date);
34 |
35 | const { year, month, day: selectedDate } = extractDateData(date);
36 |
37 | const startingWeekDay = NEPALI_DATES.find((data) => data.year === +year)
38 | ?.startWeek[+month - 1] as number;
39 |
40 | const prevStartPosition = numberOfDaysInPreviousMonth - startingWeekDay + 2;
41 |
42 | const totalNextMonthDays = (numberOfDays + startingWeekDay - 1) % 7;
43 | let currentNextMonthDaysCount =
44 | totalNextMonthDays > 0 ? 7 - totalNextMonthDays : 0;
45 |
46 | const totalCurrentRows =
47 | (startingWeekDay -
48 | 1 +
49 | numberOfDays +
50 | (totalNextMonthDays > 0 ? 7 - totalNextMonthDays : 0)) /
51 | 7;
52 |
53 | // Add one additional row i.e. 7 days, if there are only 5 rows
54 | // to make the calendar height consistent
55 | if (totalCurrentRows === 5)
56 | currentNextMonthDaysCount = currentNextMonthDaysCount + 7;
57 |
58 | return (
59 | <>
60 |
63 | {/* Previous Months days which are in the same first week of current month */}
64 | {Array.from({ length: startingWeekDay - 1 }).map((_, index) => (
65 |
66 | {numberConversion(
67 | lang,
68 | numberOfDaysInPreviousMonth > 0
69 | ? prevStartPosition + index
70 | : undefined
71 | )}
72 |
73 | ))}
74 |
75 | {Array.from({ length: numberOfDays }).map((_, index) => {
76 | const day = index + 1;
77 |
78 | let isDateDisabled = false;
79 |
80 | // check if min and max dates are passed
81 | // this function is causing lagging issue due to many renders and new check for every months
82 | if (min && isValidNepaliDate(min)) {
83 | isDateDisabled = !isGreaterThanOrEqualToMinDate(
84 | date.slice(0, 8) + day,
85 | min
86 | );
87 | }
88 |
89 | // only check the max date if current date is not disabled by min date only
90 | if (!isDateDisabled && max && isValidNepaliDate(max)) {
91 | isDateDisabled = !isLessThanOrEqualToMaxDate(
92 | date.slice(0, 8) + day,
93 | max
94 | );
95 | }
96 |
97 | const isSelected = day === +selectedDate;
98 |
99 | return (
100 |
!isDateDisabled && handleChange(day)}
106 | style={{
107 | ...(isSelected
108 | ? {
109 | color: calendarStyles?.dates?.activeTextColor,
110 | backgroundColor:
111 | calendarStyles?.dates?.activeBackgroundColor,
112 | }
113 | : {
114 | ["--date-picker-np-hover-color" as string]:
115 | calendarStyles?.dates?.hoverBackgroundColor,
116 | }),
117 | }}
118 | >
119 | {numberConversion(lang, day)}
120 |
121 | );
122 | })}
123 |
124 | {/* Upcoming Months days which are in the same last week of current month */}
125 | {Array.from({
126 | length: currentNextMonthDaysCount,
127 | }).map((_, index) => (
128 |
129 | {numberConversion(lang, index + 1)}
130 |
131 | ))}
132 |
133 | >
134 | );
135 | };
136 |
137 | export default CalendarDates;
138 |
--------------------------------------------------------------------------------
/src/DatePickerNP/DatePickerNP.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useLayoutEffect, useRef, useState } from "react";
2 |
3 | import DatePickerInput from "./components/DatePickerInput";
4 | import DatePickerCalendar from "./components/Calendar";
5 | import { DatePickerNPProps } from "./types/DatePickerNP";
6 | import {
7 | DEFAULT_INPUT_CONTAINER_BACKGROUND,
8 | DEFAULT_INPUT_HEIGHT,
9 | } from "./constants/calendar";
10 | import {
11 | calculateCalendarPosition,
12 | clickEvent,
13 | formatDate,
14 | getMenuTopPosition,
15 | isValidNepaliDate,
16 | liesInBetween,
17 | } from "./utils";
18 |
19 | import "./styles/index.css";
20 | import "./styles/calendar-dates.css";
21 | import "./styles/calendar-header.css";
22 | import "./styles/calendar-footer.css";
23 |
24 | const DatePickerNP = ({
25 | value,
26 | onChange,
27 | min,
28 | max,
29 | disabled,
30 | placeholder,
31 | inputElement,
32 | inputContainerStyles = {},
33 | calendarStyles = {},
34 | hasCalendarIcon,
35 | calendarIcon,
36 | calendarColor,
37 | lang = "en",
38 | menuPosition = "auto",
39 | position = "absolute",
40 | }: DatePickerNPProps) => {
41 | const containerRef = useRef