Skip to content

Commit f207540

Browse files
author
Marcin Charmułowicz
committed
Merge remote-tracking branch 'onesine/master'
Conflicts: src/components/Datepicker.tsx src/types/index.ts
2 parents cac5cb4 + 8dbe933 commit f207540

File tree

9 files changed

+227
-134
lines changed

9 files changed

+227
-134
lines changed

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-tailwindcss-datepicker",
3-
"version": "1.4.2",
3+
"version": "1.5.1",
44
"description": "A modern React Datepicker using Tailwind CSS 3",
55
"main": "dist/index.cjs.js",
66
"module": "dist/index.esm.js",
@@ -40,10 +40,11 @@
4040
"react": "^17.0.2 || ^18.2.0"
4141
},
4242
"devDependencies": {
43-
"@rollup/plugin-commonjs": "^22.0.1",
44-
"@rollup/plugin-node-resolve": "^13.3.0",
45-
"@rollup/plugin-typescript": "^9.0.2",
43+
"@rollup/plugin-commonjs": "^24.0.1",
44+
"@rollup/plugin-node-resolve": "^15.0.1",
45+
"@rollup/plugin-typescript": "^11.0.0",
4646
"@tailwindcss/forms": "^0.5.3",
47+
"@types/node": "18.14.5",
4748
"@types/react": "^18.0.21",
4849
"@typescript-eslint/eslint-plugin": "^5.45.0",
4950
"@typescript-eslint/parser": "^5.45.0",

src/components/Calendar/Days.tsx

Lines changed: 108 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import React, { useCallback, useContext } from "react";
55
import { BG_COLOR, TEXT_COLOR } from "../../constants";
66
import DatepickerContext from "../../contexts/DatepickerContext";
77
import { formatDate, nextMonth, previousMonth, classNames as cn } from "../../helpers";
8+
import { Period } from "../../types";
89

910
dayjs.extend(isBetween);
1011

@@ -240,39 +241,127 @@ const Days: React.FC<Props> = ({
240241
[activeDateData, hoverClassByDay, isDateDisabled]
241242
);
242243

244+
const checkIfHoverPeriodContainsDisabledPeriod = useCallback(
245+
(hoverPeriod: Period) => {
246+
if (!Array.isArray(disabledDates)) {
247+
return false;
248+
}
249+
for (let i = 0; i < disabledDates.length; i++) {
250+
if (
251+
dayjs(hoverPeriod.start).isBefore(disabledDates[i].startDate) &&
252+
dayjs(hoverPeriod.end).isAfter(disabledDates[i].endDate)
253+
) {
254+
return true;
255+
}
256+
}
257+
return false;
258+
},
259+
[disabledDates]
260+
);
261+
262+
const getMetaData = useCallback(() => {
263+
return {
264+
previous: previousMonth(calendarData.date),
265+
current: calendarData.date,
266+
next: nextMonth(calendarData.date)
267+
};
268+
}, [calendarData.date]);
269+
243270
const hoverDay = useCallback(
244271
(day: number, type: string) => {
245-
const object = {
246-
previous: previousMonth(calendarData.date),
247-
current: calendarData.date,
248-
next: nextMonth(calendarData.date)
249-
};
272+
const object = getMetaData();
250273
const newDate = object[type as keyof typeof object];
251274
const newHover = `${newDate.year()}-${newDate.month() + 1}-${
252275
day >= 10 ? day : "0" + day
253276
}`;
254277

255278
if (period.start && !period.end) {
279+
const hoverPeriod = { ...period, end: newHover };
256280
if (dayjs(newHover).isBefore(dayjs(period.start))) {
257-
changePeriod({
258-
start: null,
259-
end: period.start
260-
});
281+
hoverPeriod.start = newHover;
282+
hoverPeriod.end = period.start;
283+
if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) {
284+
changePeriod({
285+
start: null,
286+
end: period.start
287+
});
288+
}
289+
}
290+
if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) {
291+
changeDayHover(newHover);
261292
}
262-
changeDayHover(newHover);
263293
}
264294

265295
if (!period.start && period.end) {
296+
const hoverPeriod = { ...period, start: newHover };
266297
if (dayjs(newHover).isAfter(dayjs(period.end))) {
267-
changePeriod({
268-
start: period.end,
269-
end: null
270-
});
298+
hoverPeriod.start = period.end;
299+
hoverPeriod.end = newHover;
300+
if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) {
301+
changePeriod({
302+
start: period.end,
303+
end: null
304+
});
305+
}
306+
}
307+
if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) {
308+
changeDayHover(newHover);
271309
}
272-
changeDayHover(newHover);
273310
}
274311
},
275-
[calendarData.date, changeDayHover, changePeriod, period.end, period.start]
312+
[
313+
changeDayHover,
314+
changePeriod,
315+
checkIfHoverPeriodContainsDisabledPeriod,
316+
getMetaData,
317+
period
318+
]
319+
);
320+
321+
const handleClickDay = useCallback(
322+
(day: number, type: "previous" | "current" | "next") => {
323+
function continueClick() {
324+
if (type === "previous") {
325+
onClickPreviousDays(day);
326+
}
327+
328+
if (type === "current") {
329+
onClickDay(day);
330+
}
331+
332+
if (type === "next") {
333+
onClickNextDays(day);
334+
}
335+
}
336+
337+
if (disabledDates?.length) {
338+
const object = getMetaData();
339+
const newDate = object[type as keyof typeof object];
340+
const clickDay = `${newDate.year()}-${newDate.month() + 1}-${
341+
day >= 10 ? day : "0" + day
342+
}`;
343+
344+
if (period.start && !period.end) {
345+
dayjs(clickDay).isSame(dayHover) && continueClick();
346+
} else if (!period.start && period.end) {
347+
dayjs(clickDay).isSame(dayHover) && continueClick();
348+
} else {
349+
continueClick();
350+
}
351+
} else {
352+
continueClick();
353+
}
354+
},
355+
[
356+
dayHover,
357+
disabledDates?.length,
358+
getMetaData,
359+
onClickDay,
360+
onClickNextDays,
361+
onClickPreviousDays,
362+
period.end,
363+
period.start
364+
]
276365
);
277366

278367
return (
@@ -283,7 +372,7 @@ const Days: React.FC<Props> = ({
283372
key={index}
284373
disabled={isDateDisabled(item, "previous")}
285374
className="flex items-center justify-center text-gray-400 h-12 w-12 lg:w-10 lg:h-10"
286-
onClick={() => onClickPreviousDays(item)}
375+
onClick={() => handleClickDay(item, "previous")}
287376
onMouseOver={() => {
288377
hoverDay(item, "previous");
289378
}}
@@ -298,9 +387,7 @@ const Days: React.FC<Props> = ({
298387
key={index}
299388
disabled={isDateDisabled(item, "current")}
300389
className={`${buttonClass(item, "current")}`}
301-
onClick={() => {
302-
onClickDay(item);
303-
}}
390+
onClick={() => handleClickDay(item, "current")}
304391
onMouseOver={() => {
305392
hoverDay(item, "current");
306393
}}
@@ -315,9 +402,7 @@ const Days: React.FC<Props> = ({
315402
key={index}
316403
disabled={isDateDisabled(index, "next")}
317404
className="flex items-center justify-center text-gray-400 h-12 w-12 lg:w-10 lg:h-10"
318-
onClick={() => {
319-
onClickNextDays(item);
320-
}}
405+
onClick={() => handleClickDay(item, "next")}
321406
onMouseOver={() => {
322407
hoverDay(item, "next");
323408
}}

src/components/Datepicker.tsx

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,11 @@ import { COLORS, DATE_FORMAT, DEFAULT_COLOR, LANGUAGE } from "../constants";
99
import DatepickerContext from "../contexts/DatepickerContext";
1010
import { formatDate, nextMonth, previousMonth } from "../helpers";
1111
import useOnClickOutside from "../hooks";
12-
import { Period, DateValueType, DateType, DateRangeType, ClassNamesTypeProp } from "../types";
12+
import { Period, DatepickerType } from "../types";
1313

1414
import { Arrow, VerticalDash } from "./utils";
1515

16-
interface Props {
17-
primaryColor?: string;
18-
value: DateValueType;
19-
onChange: (value: DateValueType, e?: HTMLInputElement | null | undefined) => void;
20-
useRange?: boolean;
21-
showFooter?: boolean;
22-
showShortcuts?: boolean;
23-
configs?: {
24-
shortcuts?: {
25-
today?: string;
26-
yesterday?: string;
27-
past?: (period: number) => string;
28-
currentMonth?: string;
29-
pastMonth?: string;
30-
} | null;
31-
footer?: {
32-
cancel?: string;
33-
apply?: string;
34-
} | null;
35-
} | null;
36-
asSingle?: boolean;
37-
placeholder?: string;
38-
separator?: string;
39-
startFrom?: Date | null;
40-
i18n?: string;
41-
disabled?: boolean;
42-
classNames?: ClassNamesTypeProp;
43-
inputClassName?: ((className: string) => string) | string | null;
44-
containerClassName?: ((className: string) => string) | string | null;
45-
toggleClassName?: ((className: string) => string) | string | null;
46-
toggleIcon?: (open: boolean) => React.ReactNode;
47-
inputId?: string;
48-
inputName?: string;
49-
displayFormat?: string;
50-
readOnly?: boolean;
51-
minDate?: DateType | null;
52-
maxDate?: DateType | null;
53-
disabledDates?: DateRangeType[] | null;
54-
startWeekOn?: string | null;
55-
}
56-
57-
const Datepicker: React.FC<Props> = ({
16+
const Datepicker: React.FC<DatepickerType> = ({
5817
primaryColor = "blue",
5918
value = null,
6019
onChange,
@@ -83,9 +42,9 @@ const Datepicker: React.FC<Props> = ({
8342
classNames = undefined
8443
}) => {
8544
// Ref
86-
const containerRef = useRef<HTMLDivElement>(null);
87-
const calendarContainerRef = useRef<HTMLDivElement>(null);
88-
const arrowRef = useRef<HTMLDivElement>(null);
45+
const containerRef = useRef<HTMLDivElement | null>(null);
46+
const calendarContainerRef = useRef<HTMLDivElement | null>(null);
47+
const arrowRef = useRef<HTMLDivElement | null>(null);
8948

9049
// State
9150
const [firstDate, setFirstDate] = useState<dayjs.Dayjs>(

src/components/Footer.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import dayjs from "dayjs";
12
import React, { useCallback, useContext } from "react";
23

4+
import { DATE_FORMAT } from "../constants";
35
import DatepickerContext from "../contexts/DatepickerContext";
46

57
import { PrimaryButton, SecondaryButton } from "./utils";
@@ -32,8 +34,8 @@ const Footer: React.FC = () => {
3234
onClick={() => {
3335
if (period.start && period.end) {
3436
changeDatepickerValue({
35-
startDate: period.start,
36-
endDate: period.end
37+
startDate: dayjs(period.start).format(DATE_FORMAT),
38+
endDate: dayjs(period.end).format(DATE_FORMAT)
3739
});
3840
hideDatepicker();
3941
}

src/components/Shortcuts.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import dayjs from "dayjs";
22
import React, { useCallback, useContext, useMemo } from "react";
33

4-
import { DEFAULT_SHORTCUTS, TEXT_COLOR } from "../constants";
4+
import { TEXT_COLOR } from "../constants";
5+
import DEFAULT_SHORTCUTS from "../constants/shortcuts";
56
import DatepickerContext from "../contexts/DatepickerContext";
67
import { Period, ShortcutsItem } from "../types";
78

src/constants/index.ts

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
import dayjs from "dayjs";
2-
3-
import { formatDate, previousMonth } from "../helpers";
4-
5-
import { ShortcutsItem } from "types";
6-
71
export const COLORS = [
82
"blue",
93
"orange",
@@ -283,54 +277,3 @@ export const BUTTON_COLOR = {
283277
rose: "focus:ring-rose-500/50 focus:bg-rose-100/50"
284278
}
285279
};
286-
287-
export const DEFAULT_SHORTCUTS: {
288-
[key in string]: ShortcutsItem | ShortcutsItem[];
289-
} = {
290-
today: {
291-
text: "Today",
292-
period: {
293-
start: formatDate(dayjs()),
294-
end: formatDate(dayjs())
295-
}
296-
},
297-
yesterday: {
298-
text: "Yesterday",
299-
period: {
300-
start: formatDate(dayjs().subtract(1, "d")),
301-
end: formatDate(dayjs().subtract(1, "d"))
302-
}
303-
},
304-
past: [
305-
{
306-
daysNumber: 7,
307-
text: "Last 7 days",
308-
period: {
309-
start: formatDate(dayjs().subtract(7, "d")),
310-
end: formatDate(dayjs())
311-
}
312-
},
313-
{
314-
daysNumber: 30,
315-
text: "Last 30 days",
316-
period: {
317-
start: formatDate(dayjs().subtract(30, "d")),
318-
end: formatDate(dayjs())
319-
}
320-
}
321-
],
322-
currentMonth: {
323-
text: "This month",
324-
period: {
325-
start: formatDate(dayjs().startOf("month")),
326-
end: formatDate(dayjs().endOf("month"))
327-
}
328-
},
329-
pastMonth: {
330-
text: "Last month",
331-
period: {
332-
start: formatDate(previousMonth(dayjs()).startOf("month")),
333-
end: formatDate(previousMonth(dayjs()).endOf("month"))
334-
}
335-
}
336-
};

0 commit comments

Comments
 (0)