Skip to content

Commit f22e5fe

Browse files
committed
fix: week range disabled logic is different
1 parent 55d8314 commit f22e5fe

File tree

6 files changed

+145
-25
lines changed

6 files changed

+145
-25
lines changed

src/RangePicker.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,9 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
308308

309309
// ========================= Disable Date ==========================
310310
const [disabledStartDate, disabledEndDate] = useRangeDisabled({
311+
picker,
311312
selectedValue,
313+
locale,
312314
disabled: mergedDisabled,
313315
disabledDate,
314316
generateConfig,

src/generate/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface GenerateConfig<DateType> {
1616
setYear: (value: DateType, year: number) => DateType;
1717
setMonth: (value: DateType, month: number) => DateType;
1818
setDate: (value: DateType, date: number) => DateType;
19+
setWeekDay: (value: DateType, day: number) => DateType;
1920
setHour: (value: DateType, hour: number) => DateType;
2021
setMinute: (value: DateType, minute: number) => DateType;
2122
setSecond: (value: DateType, second: number) => DateType;

src/generate/moment.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ const generateConfig: GenerateConfig<Moment> = {
3939
clone.month(month);
4040
return clone;
4141
},
42+
setWeekDay: (date, day) => {
43+
const clone = date.clone();
44+
clone.locale('en_US');
45+
clone.weekday(day);
46+
return clone;
47+
},
4248
setDate: (date, num) => {
4349
const clone = date.clone();
4450
clone.date(num);

src/hooks/useRangeDisabled.ts

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,84 @@
1-
import { RangeValue } from '../interface';
1+
import * as React from 'react';
2+
import { RangeValue, PickerMode, Locale } from '../interface';
23
import { getValue } from '../utils/miscUtil';
34
import { GenerateConfig } from '../generate';
45
import { isSameDate } from '../utils/dateUtil';
6+
import useWeekDisabled from './useWeekDisabled';
57

68
export default function useRangeDisabled<DateType>({
9+
picker,
10+
locale,
711
selectedValue,
812
disabledDate,
913
disabled,
1014
generateConfig,
1115
}: {
16+
picker: PickerMode;
1217
selectedValue: RangeValue<DateType>;
1318
disabledDate?: (date: DateType) => boolean;
1419
disabled: [boolean, boolean];
20+
locale: Locale;
1521
generateConfig: GenerateConfig<DateType>;
1622
}) {
1723
const startDate = getValue(selectedValue, 0);
1824
const endDate = getValue(selectedValue, 1);
1925

20-
function disabledStartDate(date: DateType) {
21-
if (disabledDate && disabledDate(date)) {
22-
return true;
23-
}
26+
const disabledStartDate = React.useCallback(
27+
(date: DateType) => {
28+
if (disabledDate && disabledDate(date)) {
29+
return true;
30+
}
2431

25-
if (disabled[1] && endDate) {
26-
return (
27-
!isSameDate(generateConfig, date, endDate) &&
28-
generateConfig.isAfter(date, endDate)
29-
);
30-
}
32+
if (disabled[1] && endDate) {
33+
return (
34+
!isSameDate(generateConfig, date, endDate) &&
35+
generateConfig.isAfter(date, endDate)
36+
);
37+
}
3138

32-
return false;
33-
}
39+
return false;
40+
},
41+
[disabledDate, disabled[1], endDate],
42+
);
43+
44+
const disableEndDate = React.useCallback(
45+
(date: DateType) => {
46+
if (disabledDate && disabledDate(date)) {
47+
return true;
48+
}
49+
50+
if (startDate) {
51+
const compareStartDate =
52+
picker === 'week' ? generateConfig.addDate(startDate, -7) : startDate;
53+
54+
return (
55+
!isSameDate(generateConfig, date, compareStartDate) &&
56+
generateConfig.isAfter(compareStartDate, date)
57+
);
58+
}
59+
60+
return false;
61+
},
62+
[disabledDate, startDate, picker],
63+
);
3464

35-
function disableEndDate(date: DateType) {
36-
if (disabledDate && disabledDate(date)) {
37-
return true;
38-
}
65+
// Handle week date disabled
66+
const sharedWeekDisabledConfig = {
67+
generateConfig,
68+
locale,
69+
};
3970

40-
if (startDate) {
41-
return (
42-
!isSameDate(generateConfig, date, startDate) &&
43-
generateConfig.isAfter(startDate, date)
44-
);
45-
}
71+
const [disabledStartWeekDate] = useWeekDisabled({
72+
...sharedWeekDisabledConfig,
73+
disabledDate: disabledStartDate,
74+
});
75+
const [disabledEndWeekDate] = useWeekDisabled({
76+
...sharedWeekDisabledConfig,
77+
disabledDate: disableEndDate,
78+
});
4679

47-
return false;
80+
if (picker === 'week') {
81+
return [disabledStartWeekDate, disabledEndWeekDate];
4882
}
4983

5084
return [disabledStartDate, disableEndDate];

src/hooks/useWeekDisabled.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import * as React from 'react';
2+
import { GenerateConfig } from '../generate';
3+
import { Locale } from '../interface';
4+
5+
export default function useWeekDisabled<DateType>({
6+
disabledDate,
7+
locale,
8+
generateConfig,
9+
}: {
10+
disabledDate: (date: DateType) => boolean;
11+
locale: Locale;
12+
generateConfig: GenerateConfig<DateType>;
13+
}): [(date: DateType) => boolean] {
14+
const disabledCache = React.useMemo(() => new Map<string, boolean>(), [
15+
disabledDate,
16+
]);
17+
const firstDay = React.useMemo(
18+
() => generateConfig.locale.getWeekFirstDay(locale.locale),
19+
[locale.locale],
20+
);
21+
22+
function disabledWeekDate(date: DateType): boolean {
23+
const weekStr = generateConfig.locale.format(
24+
locale.locale,
25+
date,
26+
'YYYY-WW',
27+
);
28+
29+
if (!disabledCache.has(weekStr)) {
30+
const weekDay = generateConfig.getWeekDay(date);
31+
let weekStartDate: DateType;
32+
33+
// Set start week date
34+
if (weekDay < firstDay) {
35+
weekStartDate = generateConfig.setWeekDay(
36+
generateConfig.addDate(date, -7),
37+
firstDay,
38+
);
39+
} else {
40+
weekStartDate = generateConfig.setWeekDay(date, firstDay);
41+
}
42+
43+
// Loop to find disabled status
44+
let disabled = false;
45+
for (let i = 0; i < 7; i += 1) {
46+
const currentDate = generateConfig.setWeekDay(weekStartDate, i);
47+
if (disabledDate(currentDate)) {
48+
disabled = true;
49+
break;
50+
}
51+
}
52+
53+
disabledCache.set(weekStr, disabled);
54+
}
55+
56+
return disabledCache.get(weekStr)!;
57+
}
58+
59+
return [disabledWeekDate];
60+
}

src/utils/dateUtil.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { noteOnce } from 'rc-util/lib/warning';
22
import { GenerateConfig } from '../generate';
3-
import { NullableDateType, PickerMode } from '../interface';
3+
import { NullableDateType, PickerMode, Locale } from '../interface';
44

55
export const WEEK_DAY_COUNT = 7;
66

@@ -109,6 +109,23 @@ export function isSameWeek<DateType>(
109109
);
110110
}
111111

112+
export function isSameWeekDay<DateType>(
113+
generateConfig: GenerateConfig<DateType>,
114+
week1: NullableDateType<DateType>,
115+
week2: NullableDateType<DateType>,
116+
locale: Locale,
117+
) {
118+
const equal = isNullEqual(week1, week2);
119+
if (typeof equal === 'boolean') {
120+
return equal;
121+
}
122+
123+
return (
124+
generateConfig.locale.format(locale.locale, week1!, 'YYYY-WW') ===
125+
generateConfig.locale.format(locale.locale, week2!, 'YYYY-WW')
126+
);
127+
}
128+
112129
export function isEqual<DateType>(
113130
generateConfig: GenerateConfig<DateType>,
114131
value1: NullableDateType<DateType>,

0 commit comments

Comments
 (0)