@momo-kits/calendar 0.169.7 → 0.169.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CalendarPro.tsx +41 -35
- package/HeaderControl.tsx +2 -4
- package/LunarDateConverter.ts +16 -9
- package/MonthList.tsx +20 -13
- package/TabHeader.tsx +6 -4
- package/Util.ts +3 -0
- package/index.tsx +19 -17
- package/package.json +1 -1
package/CalendarPro.tsx
CHANGED
|
@@ -28,9 +28,14 @@ import {
|
|
|
28
28
|
import { ContainerContext } from './ContainerContext';
|
|
29
29
|
import styles from './styles';
|
|
30
30
|
|
|
31
|
+
const DEFAULT_RANGE_MONTHS = 12;
|
|
32
|
+
const SCROLL_TO_SELECTED_DELAY = 500;
|
|
33
|
+
const WEEKDAYS = [1, 2, 3, 4, 5, 6, 7];
|
|
34
|
+
const FIRST_WEEKEND_DAY = 6;
|
|
35
|
+
|
|
31
36
|
/** Holidays to list: lunar-only ones are hidden while lunar dates are off. */
|
|
32
|
-
const getVisibleHolidays = (holidays: Holidays[],
|
|
33
|
-
if (
|
|
37
|
+
const getVisibleHolidays = (holidays: Holidays[], isLunarShown: boolean) => {
|
|
38
|
+
if (isLunarShown) {
|
|
34
39
|
return holidays;
|
|
35
40
|
}
|
|
36
41
|
return holidays.filter(item => !item.lunar || item.mixedLabel);
|
|
@@ -67,31 +72,31 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
67
72
|
const headerControlRef = useRef<HeaderControlRef>(null);
|
|
68
73
|
const monthListRef = useRef<MonthListRef>(null);
|
|
69
74
|
|
|
70
|
-
// An invalid bound falls back to
|
|
75
|
+
// An invalid bound falls back to a year from the other one (or today).
|
|
71
76
|
const [minDate, maxDate] = useMemo(() => {
|
|
72
77
|
let max = moment(propMaxDate);
|
|
73
78
|
let min = moment(propMinDate);
|
|
74
79
|
const maxValid = max.isValid();
|
|
75
80
|
const minValid = min.isValid();
|
|
76
81
|
if (!maxValid && !minValid) {
|
|
77
|
-
max = moment().add(
|
|
82
|
+
max = moment().add(DEFAULT_RANGE_MONTHS, 'months');
|
|
78
83
|
min = moment();
|
|
79
84
|
} else if (!maxValid && minValid) {
|
|
80
|
-
max = min.clone().add(
|
|
85
|
+
max = min.clone().add(DEFAULT_RANGE_MONTHS, 'months');
|
|
81
86
|
} else if (maxValid && !minValid) {
|
|
82
|
-
min = max.clone().subtract(
|
|
87
|
+
min = max.clone().subtract(DEFAULT_RANGE_MONTHS, 'months');
|
|
83
88
|
}
|
|
84
89
|
return [min, max];
|
|
85
90
|
}, [propMinDate, propMaxDate]);
|
|
86
91
|
|
|
87
92
|
const [startDate, setStartDate] = useState<Moment>(propStartDate);
|
|
88
93
|
const [endDate, setEndDate] = useState<Moment | null>(propEndDate || null);
|
|
89
|
-
const [
|
|
94
|
+
const [isLunarShown, setIsLunarShown] = useState(!!propIsShowLunar);
|
|
90
95
|
const [tabSelected, setTabSelected] = useState<number>(0);
|
|
91
96
|
const [holidays, setHolidays] = useState<Holidays[]>([]);
|
|
92
97
|
const [temp, setTemp] = useState<any[]>([]);
|
|
93
98
|
const [headerKey, setHeaderKey] = useState<string>('');
|
|
94
|
-
const [
|
|
99
|
+
const [isOwnUpdate, setIsOwnUpdate] = useState(false);
|
|
95
100
|
|
|
96
101
|
useImperativeHandle(ref, () => ({
|
|
97
102
|
setDoubleDateAndTabIndex: (
|
|
@@ -107,21 +112,21 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
107
112
|
|
|
108
113
|
// Follow the isShowLunar prop, except right after the user toggled it.
|
|
109
114
|
useEffect(() => {
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
} else if (propIsShowLunar !==
|
|
113
|
-
|
|
115
|
+
if (isOwnUpdate) {
|
|
116
|
+
setIsOwnUpdate(false);
|
|
117
|
+
} else if (propIsShowLunar !== isLunarShown) {
|
|
118
|
+
setIsLunarShown(!!propIsShowLunar);
|
|
114
119
|
}
|
|
115
|
-
}, [
|
|
120
|
+
}, [isOwnUpdate, propIsShowLunar, isLunarShown]);
|
|
116
121
|
|
|
117
122
|
useEffect(() => {
|
|
118
123
|
const timer = setTimeout(() => {
|
|
119
124
|
monthListRef.current?.scrollToMonth(propSelectedDate);
|
|
120
|
-
},
|
|
125
|
+
}, SCROLL_TO_SELECTED_DELAY);
|
|
121
126
|
return () => clearTimeout(timer);
|
|
122
127
|
}, [propSelectedDate]);
|
|
123
128
|
|
|
124
|
-
const
|
|
129
|
+
const handleChooseDay = (day: Moment) => {
|
|
125
130
|
if (isDoubleDateMode) {
|
|
126
131
|
if (tabSelected === 1) {
|
|
127
132
|
if (startDate && day >= startDate) {
|
|
@@ -142,7 +147,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
142
147
|
|
|
143
148
|
const executeProcessAfterScrollCalendar = (date: Moment, key: string) => {
|
|
144
149
|
const allHolidays = Util.getHolidaysInMonth(moment(date));
|
|
145
|
-
const filtered = getVisibleHolidays(allHolidays,
|
|
150
|
+
const filtered = getVisibleHolidays(allHolidays, isLunarShown);
|
|
146
151
|
headerControlRef.current?.onUpdateInfo({ date });
|
|
147
152
|
headerRef.current = date.clone().startOf('month');
|
|
148
153
|
setHolidays(allHolidays);
|
|
@@ -150,7 +155,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
150
155
|
setHeaderKey(key);
|
|
151
156
|
};
|
|
152
157
|
|
|
153
|
-
const
|
|
158
|
+
const handleScrollCalendar = (info: {
|
|
154
159
|
date: Moment;
|
|
155
160
|
key: string;
|
|
156
161
|
currentIndex: number;
|
|
@@ -160,16 +165,16 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
160
165
|
}
|
|
161
166
|
};
|
|
162
167
|
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
const next = !
|
|
168
|
+
const handleToggleLunar = () => {
|
|
169
|
+
setIsOwnUpdate(true);
|
|
170
|
+
const next = !isLunarShown;
|
|
166
171
|
const filtered = getVisibleHolidays(holidays, next);
|
|
167
172
|
onCallbackCalendar?.('lunar', next);
|
|
168
|
-
|
|
173
|
+
setIsLunarShown(next);
|
|
169
174
|
setTemp(filtered);
|
|
170
175
|
};
|
|
171
176
|
|
|
172
|
-
const
|
|
177
|
+
const handlePressBackArrow = () => {
|
|
173
178
|
const prev = headerRef.current
|
|
174
179
|
.clone()
|
|
175
180
|
.startOf('month')
|
|
@@ -181,7 +186,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
181
186
|
}
|
|
182
187
|
};
|
|
183
188
|
|
|
184
|
-
const
|
|
189
|
+
const handlePressNextArrow = () => {
|
|
185
190
|
const next = headerRef.current.clone().startOf('month').add(1, 'months');
|
|
186
191
|
if (next.isSameOrBefore(maxDate, 'month')) {
|
|
187
192
|
headerRef.current = next;
|
|
@@ -205,15 +210,15 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
205
210
|
<HeaderControl
|
|
206
211
|
ref={headerControlRef}
|
|
207
212
|
selectedDate={propSelectedDate}
|
|
208
|
-
onPressBackArrow={
|
|
209
|
-
onPressNextArrow={
|
|
213
|
+
onPressBackArrow={handlePressBackArrow}
|
|
214
|
+
onPressNextArrow={handlePressNextArrow}
|
|
210
215
|
/>
|
|
211
216
|
<View style={styles.blueSeperator} />
|
|
212
217
|
<View>
|
|
213
218
|
<View style={styles.viewDay}>
|
|
214
|
-
{
|
|
219
|
+
{WEEKDAYS.map(dayIdx => {
|
|
215
220
|
let dayColor = theme.colors.text.default;
|
|
216
|
-
if (dayIdx >=
|
|
221
|
+
if (dayIdx >= FIRST_WEEKEND_DAY) {
|
|
217
222
|
dayColor = theme.colors.error.primary;
|
|
218
223
|
}
|
|
219
224
|
return (
|
|
@@ -223,7 +228,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
223
228
|
typography="label_s_medium"
|
|
224
229
|
style={[
|
|
225
230
|
styles.textDay,
|
|
226
|
-
{ width: (size.width - Spacing.S * 2) /
|
|
231
|
+
{ width: (size.width - Spacing.S * 2) / WEEKDAYS.length },
|
|
227
232
|
]}
|
|
228
233
|
>
|
|
229
234
|
{translate?.(Util.mapWeeKDate(dayIdx))}
|
|
@@ -237,9 +242,9 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
237
242
|
maxDate={maxDate}
|
|
238
243
|
startDate={startDate!}
|
|
239
244
|
endDate={endDate!}
|
|
240
|
-
onChoose={
|
|
241
|
-
onScrollCalendar={
|
|
242
|
-
isShowLunar={!isOffLunar &&
|
|
245
|
+
onChoose={handleChooseDay}
|
|
246
|
+
onScrollCalendar={handleScrollCalendar}
|
|
247
|
+
isShowLunar={!isOffLunar && isLunarShown}
|
|
243
248
|
isDoubleDateMode={isDoubleDateMode}
|
|
244
249
|
tabSelected={tabSelected}
|
|
245
250
|
holidays={holidays}
|
|
@@ -257,8 +262,8 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
257
262
|
]}
|
|
258
263
|
>
|
|
259
264
|
<CheckBox
|
|
260
|
-
onChange={
|
|
261
|
-
value={
|
|
265
|
+
onChange={handleToggleLunar}
|
|
266
|
+
value={isLunarShown}
|
|
262
267
|
label={translate?.('showLunar')}
|
|
263
268
|
/>
|
|
264
269
|
</View>
|
|
@@ -273,8 +278,9 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
273
278
|
const day = item.day > 9 ? item.day : `0${item.day}`;
|
|
274
279
|
const month = item.month > 9 ? item.month : `0${item.month}`;
|
|
275
280
|
const labelDate = `${day}/${month}`;
|
|
276
|
-
const
|
|
277
|
-
const
|
|
281
|
+
const shownMixedLabel = isLunarShown && item.mixedLabel;
|
|
282
|
+
const labelHoliday = shownMixedLabel || item.label;
|
|
283
|
+
const labelHighlight = isLunarShown ? item.highlight || '' : '';
|
|
278
284
|
return (
|
|
279
285
|
<View style={styles.row} key={idx.toString()}>
|
|
280
286
|
<Text
|
package/HeaderControl.tsx
CHANGED
|
@@ -24,12 +24,10 @@ const HeaderControl: ForwardRefRenderFunction<
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
useImperativeHandle(ref, () => ({
|
|
27
|
-
onUpdateInfo,
|
|
27
|
+
onUpdateInfo: updateInfo,
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
|
-
const
|
|
31
|
-
date: React.SetStateAction<{ date: moment.Moment }>,
|
|
32
|
-
) => {
|
|
30
|
+
const updateInfo = (date: React.SetStateAction<{ date: moment.Moment }>) => {
|
|
33
31
|
setInfo(date);
|
|
34
32
|
};
|
|
35
33
|
|
package/LunarDateConverter.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
const MIN_YEAR = 1900;
|
|
2
|
+
const LONG_MONTH_DAYS = 30;
|
|
3
|
+
const SHORT_MONTH_DAYS = 29;
|
|
4
|
+
const MAX_MONTHS_WITH_LEAP = 13;
|
|
5
|
+
|
|
6
|
+
/** Lunar date record that `SolarToLunar` fills; used with `new`. */
|
|
1
7
|
function Lunar(this: any) {
|
|
2
8
|
this.isleap = false;
|
|
3
9
|
this.lunarDay = 0;
|
|
@@ -5,6 +11,7 @@ function Lunar(this: any) {
|
|
|
5
11
|
this.lunarYear = 0;
|
|
6
12
|
}
|
|
7
13
|
|
|
14
|
+
/** Solar date record that `SolarFromInt` fills; used with `new`. */
|
|
8
15
|
function Solar(this: any) {
|
|
9
16
|
this.solarDay = 0;
|
|
10
17
|
this.solarMonth = 0;
|
|
@@ -133,11 +140,10 @@ function LunarSolarConverter(this: any) {
|
|
|
133
140
|
lunarDay: number;
|
|
134
141
|
}) {
|
|
135
142
|
const firstTableYear = this.lunar_month_days[0];
|
|
136
|
-
const minLunarYear = 1900;
|
|
137
143
|
const maxLunarYear = firstTableYear + this.lunar_month_days.length - 1;
|
|
138
|
-
if (lunar.lunarYear <
|
|
144
|
+
if (lunar.lunarYear < MIN_YEAR || lunar.lunarYear > maxLunarYear) {
|
|
139
145
|
throw new Error(
|
|
140
|
-
`LunarToSolar: year ${lunar.lunarYear} out of supported range ${
|
|
146
|
+
`LunarToSolar: year ${lunar.lunarYear} out of supported range ${MIN_YEAR}-${maxLunarYear}`,
|
|
141
147
|
);
|
|
142
148
|
}
|
|
143
149
|
const days = this.lunar_month_days[lunar.lunarYear - firstTableYear];
|
|
@@ -152,7 +158,8 @@ function LunarSolarConverter(this: any) {
|
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
160
|
for (let i = 0; i < loopend; i++) {
|
|
155
|
-
|
|
161
|
+
const isLongMonth = this.GetBitInt(days, 1, 12 - i) === 1;
|
|
162
|
+
offset += isLongMonth ? LONG_MONTH_DAYS : SHORT_MONTH_DAYS;
|
|
156
163
|
}
|
|
157
164
|
offset += lunar.lunarDay;
|
|
158
165
|
|
|
@@ -170,11 +177,10 @@ function LunarSolarConverter(this: any) {
|
|
|
170
177
|
solarMonth: number;
|
|
171
178
|
solarDay: number;
|
|
172
179
|
}) {
|
|
173
|
-
const minSolarYear = 1900;
|
|
174
180
|
const maxSolarYear = this.solar_1_1[0] + this.solar_1_1.length - 1;
|
|
175
|
-
if (solar.solarYear <
|
|
181
|
+
if (solar.solarYear < MIN_YEAR || solar.solarYear > maxSolarYear) {
|
|
176
182
|
throw new Error(
|
|
177
|
-
`SolarToLunar: year ${solar.solarYear} out of supported range ${
|
|
183
|
+
`SolarToLunar: year ${solar.solarYear} out of supported range ${MIN_YEAR}-${maxSolarYear}`,
|
|
178
184
|
);
|
|
179
185
|
}
|
|
180
186
|
// @ts-ignore
|
|
@@ -200,8 +206,9 @@ function LunarSolarConverter(this: any) {
|
|
|
200
206
|
let lunarM = 1;
|
|
201
207
|
offset += 1;
|
|
202
208
|
|
|
203
|
-
for (let i = 0; i <
|
|
204
|
-
const
|
|
209
|
+
for (let i = 0; i < MAX_MONTHS_WITH_LEAP; i++) {
|
|
210
|
+
const isLongMonth = this.GetBitInt(days, 1, 12 - i) === 1;
|
|
211
|
+
const dm = isLongMonth ? LONG_MONTH_DAYS : SHORT_MONTH_DAYS;
|
|
205
212
|
if (offset > dm) {
|
|
206
213
|
lunarM++;
|
|
207
214
|
offset -= dm;
|
package/MonthList.tsx
CHANGED
|
@@ -22,10 +22,13 @@ import Month from './Month';
|
|
|
22
22
|
import { MonthListProps, MonthListRef } from './types';
|
|
23
23
|
|
|
24
24
|
const MAX_RENDER_PER_BATCH = Platform.OS === 'android' ? 1 : 12;
|
|
25
|
+
const ROW_HEIGHT = 48;
|
|
26
|
+
const DAYS_PER_WEEK = 7;
|
|
25
27
|
|
|
26
28
|
// @ts-ignore
|
|
27
29
|
const converter = new LunarDateConverter();
|
|
28
30
|
|
|
31
|
+
/** Whether both moments fall in the same month of the same year. */
|
|
29
32
|
const isSameMonth = (a: Moment, b: Moment) => {
|
|
30
33
|
return a.year() === b.year() && a.month() === b.month();
|
|
31
34
|
};
|
|
@@ -53,15 +56,15 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
53
56
|
} = props;
|
|
54
57
|
|
|
55
58
|
const size = useContext(ContainerContext);
|
|
56
|
-
const
|
|
59
|
+
const scaledRowHeight = useScaleSize(ROW_HEIGHT);
|
|
57
60
|
const listRef = useRef<FlatList>(null);
|
|
58
61
|
const currentKey = useRef<string | null>(null);
|
|
59
62
|
const targetIndex = useRef<number | null>(null);
|
|
60
63
|
const [heightStyle, setHeightStyle] = useState({});
|
|
61
64
|
const onScrollCalendarRef = useRef(onScrollCalendar);
|
|
62
65
|
onScrollCalendarRef.current = onScrollCalendar;
|
|
63
|
-
const
|
|
64
|
-
|
|
66
|
+
const scaledRowHeightRef = useRef(scaledRowHeight);
|
|
67
|
+
scaledRowHeightRef.current = scaledRowHeight;
|
|
65
68
|
|
|
66
69
|
const data = useMemo(() => {
|
|
67
70
|
const months: { date: Moment; dateList: any[] }[] = [];
|
|
@@ -93,9 +96,10 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
93
96
|
}
|
|
94
97
|
cursor.subtract(1, 'days');
|
|
95
98
|
weekday = cursor.isoWeekday();
|
|
96
|
-
if (weekday !==
|
|
99
|
+
if (weekday !== DAYS_PER_WEEK) {
|
|
100
|
+
const trailingDays = DAYS_PER_WEEK - weekday;
|
|
97
101
|
dayList.push(
|
|
98
|
-
...new Array(
|
|
102
|
+
...new Array(trailingDays).fill(0).map(() => ({ isEmpty: true })),
|
|
99
103
|
);
|
|
100
104
|
}
|
|
101
105
|
months.push({ date: d, dateList: dayList });
|
|
@@ -132,9 +136,12 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
132
136
|
});
|
|
133
137
|
}, [size.width]);
|
|
134
138
|
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
const handleScroll = useCallback(
|
|
140
|
+
(e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
141
|
+
scrollOffset.current = e.nativeEvent.contentOffset.x;
|
|
142
|
+
},
|
|
143
|
+
[],
|
|
144
|
+
);
|
|
138
145
|
|
|
139
146
|
const scrollToMonth = useCallback(
|
|
140
147
|
(month: Moment) => {
|
|
@@ -151,7 +158,7 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
151
158
|
|
|
152
159
|
useImperativeHandle(ref, () => ({ scrollToMonth }));
|
|
153
160
|
|
|
154
|
-
const
|
|
161
|
+
const handleViewableChange = useRef(({ changed }: { changed: any[] }) => {
|
|
155
162
|
const visible = changed.find(token => token.isViewable);
|
|
156
163
|
// Ignore months passed while animating to a scrollToMonth target.
|
|
157
164
|
const isScrollingToTarget = targetIndex.current !== null;
|
|
@@ -164,8 +171,8 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
164
171
|
if (onScrollCalendarRef.current && item && currentKey.current !== key) {
|
|
165
172
|
currentKey.current = key;
|
|
166
173
|
try {
|
|
167
|
-
const rowHeight =
|
|
168
|
-
const rowsHeight = (rowHeight * item.dateList.length) /
|
|
174
|
+
const rowHeight = scaledRowHeightRef.current;
|
|
175
|
+
const rowsHeight = (rowHeight * item.dateList.length) / DAYS_PER_WEEK;
|
|
169
176
|
setHeightStyle({ height: rowsHeight + Spacing.L * 2 + Spacing.XS });
|
|
170
177
|
} catch {
|
|
171
178
|
setHeightStyle({});
|
|
@@ -253,7 +260,7 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
253
260
|
showsHorizontalScrollIndicator={false}
|
|
254
261
|
keyExtractor={keyExtractor}
|
|
255
262
|
onScrollToIndexFailed={() => {}}
|
|
256
|
-
onScroll={
|
|
263
|
+
onScroll={handleScroll}
|
|
257
264
|
onScrollBeginDrag={() => {
|
|
258
265
|
targetIndex.current = null;
|
|
259
266
|
}}
|
|
@@ -261,7 +268,7 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
261
268
|
initialNumToRender={3}
|
|
262
269
|
maxToRenderPerBatch={MAX_RENDER_PER_BATCH}
|
|
263
270
|
windowSize={1}
|
|
264
|
-
onViewableItemsChanged={
|
|
271
|
+
onViewableItemsChanged={handleViewableChange}
|
|
265
272
|
initialScrollIndex={currentScrollIndex}
|
|
266
273
|
getItemLayout={getItemLayout}
|
|
267
274
|
viewabilityConfig={viewabilityConfig}
|
package/TabHeader.tsx
CHANGED
|
@@ -15,7 +15,9 @@ import { TabHeaderProps, TabHeaderRef } from './types';
|
|
|
15
15
|
const TabHeader = forwardRef<TabHeaderRef, TabHeaderProps>((props, ref) => {
|
|
16
16
|
const { label, disabled, id, onChangeTab } = props;
|
|
17
17
|
const { theme, translate } = useContext(ApplicationContext);
|
|
18
|
-
const [
|
|
18
|
+
const [isActive, setIsActive] = useState<boolean | undefined>(
|
|
19
|
+
props.activeTab,
|
|
20
|
+
);
|
|
19
21
|
const [date, setDate] = useState<Moment.Moment | undefined>(
|
|
20
22
|
props.date ? Moment(props.date) : undefined,
|
|
21
23
|
);
|
|
@@ -23,15 +25,15 @@ const TabHeader = forwardRef<TabHeaderRef, TabHeaderProps>((props, ref) => {
|
|
|
23
25
|
useImperativeHandle(ref, () => ({
|
|
24
26
|
updateView: (nextDate, activeTab) => {
|
|
25
27
|
setDate(nextDate ? Moment(nextDate) : undefined);
|
|
26
|
-
|
|
28
|
+
setIsActive(activeTab);
|
|
27
29
|
},
|
|
28
|
-
setActiveTab:
|
|
30
|
+
setActiveTab: setIsActive,
|
|
29
31
|
}));
|
|
30
32
|
|
|
31
33
|
const weekday = (day: Moment.Moment) => {
|
|
32
34
|
return translate?.(Util.WEEKDAYSFROMMOMENT[day.day()]);
|
|
33
35
|
};
|
|
34
|
-
const isHighlighted =
|
|
36
|
+
const isHighlighted = isActive && !disabled;
|
|
35
37
|
|
|
36
38
|
const formattedDate = date ? date.format('DD/MM/YYYY') : '';
|
|
37
39
|
const dayOfWeek = date ? `${weekday(date)}, ` : '';
|
package/Util.ts
CHANGED
|
@@ -13,14 +13,17 @@ const Solar = (momentDate: moment.Moment) => ({
|
|
|
13
13
|
solarYear: momentDate.year(),
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
/** Two-digit day or month: 7 → `07`. */
|
|
16
17
|
const padTwoDigits = (value: number) => {
|
|
17
18
|
return value < 10 ? `0${value}` : `${value}`;
|
|
18
19
|
};
|
|
19
20
|
|
|
21
|
+
/** `YYYY-MM-DD` string that `moment()` parses as a local date. */
|
|
20
22
|
const formatYYYYMMDD = (dd: number, mm: number, yyyy: any) => {
|
|
21
23
|
return `${yyyy}-${padTwoDigits(mm)}-${padTwoDigits(dd)}`;
|
|
22
24
|
};
|
|
23
25
|
|
|
26
|
+
/** `DD/MM` key that groups holidays by day. */
|
|
24
27
|
const formatDDMM = (dd: number, mm: number) => {
|
|
25
28
|
return `${padTwoDigits(dd)}/${padTwoDigits(mm)}`;
|
|
26
29
|
};
|
package/index.tsx
CHANGED
|
@@ -15,6 +15,8 @@ import { ContainerContext } from './ContainerContext';
|
|
|
15
15
|
import styles from './styles';
|
|
16
16
|
|
|
17
17
|
const DOUBLE = 'doubleDate';
|
|
18
|
+
const DAY_HEIGHT = 34;
|
|
19
|
+
const PRICE_DAY_HEIGHT = 48;
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Calendar with single or round-trip (`mode="doubleDate"`) selection, lunar
|
|
@@ -22,8 +24,8 @@ const DOUBLE = 'doubleDate';
|
|
|
22
24
|
*/
|
|
23
25
|
const Calendar: React.FC<CalendarProps> = props => {
|
|
24
26
|
const { theme } = useContext(ApplicationContext);
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
+
const scaledPriceDayHeight = useScaleSize(PRICE_DAY_HEIGHT);
|
|
28
|
+
const scaledDayHeight = useScaleSize(DAY_HEIGHT);
|
|
27
29
|
|
|
28
30
|
const currentDate = new Date();
|
|
29
31
|
const minDateDefault = new Date(currentDate);
|
|
@@ -36,7 +38,7 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
36
38
|
id,
|
|
37
39
|
doubleDate: initDoubleDate,
|
|
38
40
|
selectedDate: initialSelectedDate,
|
|
39
|
-
onChangeTab
|
|
41
|
+
onChangeTab,
|
|
40
42
|
onCallbackCalendar,
|
|
41
43
|
isOffLunar,
|
|
42
44
|
isHideHoliday,
|
|
@@ -96,12 +98,12 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
96
98
|
}
|
|
97
99
|
}, []);
|
|
98
100
|
|
|
99
|
-
const
|
|
101
|
+
const handleLayout = (e: LayoutChangeEvent) => {
|
|
100
102
|
setContainerWidth(e.nativeEvent.layout.width);
|
|
101
103
|
};
|
|
102
104
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
+
const handleChangeTab = (tabId: number) => {
|
|
106
|
+
onChangeTab?.(tabId);
|
|
105
107
|
tabSelected.current = tabId;
|
|
106
108
|
cellHeader1.current?.setActiveTab(tabId === 0);
|
|
107
109
|
cellHeader2.current?.setActiveTab(tabId === 1);
|
|
@@ -181,17 +183,17 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
181
183
|
};
|
|
182
184
|
|
|
183
185
|
// Skip the mount run so the initial doubleDate props are kept.
|
|
184
|
-
const
|
|
186
|
+
const hasMounted = useRef(false);
|
|
185
187
|
|
|
186
188
|
useEffect(() => {
|
|
187
|
-
if (
|
|
189
|
+
if (hasMounted.current) {
|
|
188
190
|
updateView();
|
|
189
191
|
} else {
|
|
190
|
-
|
|
192
|
+
hasMounted.current = true;
|
|
191
193
|
}
|
|
192
194
|
}, [selectedDate]);
|
|
193
195
|
|
|
194
|
-
const
|
|
196
|
+
const handleDateChange = (date: moment.Moment) => setSelectedDate(date);
|
|
195
197
|
|
|
196
198
|
const updateHeaderView = () => {
|
|
197
199
|
const { onDateChange, onCTAStateChange } = props;
|
|
@@ -231,12 +233,12 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
231
233
|
});
|
|
232
234
|
};
|
|
233
235
|
|
|
234
|
-
const
|
|
236
|
+
const hasModeMounted = useRef(false);
|
|
235
237
|
useEffect(() => {
|
|
236
|
-
if (
|
|
238
|
+
if (hasModeMounted.current) {
|
|
237
239
|
updateHeaderView();
|
|
238
240
|
} else {
|
|
239
|
-
|
|
241
|
+
hasModeMounted.current = true;
|
|
240
242
|
}
|
|
241
243
|
}, [isDoubleDateMode]);
|
|
242
244
|
|
|
@@ -244,10 +246,10 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
244
246
|
<ContainerContext.Provider
|
|
245
247
|
value={{
|
|
246
248
|
width: containerWidth,
|
|
247
|
-
height: priceList ?
|
|
249
|
+
height: priceList ? scaledPriceDayHeight : scaledDayHeight,
|
|
248
250
|
}}
|
|
249
251
|
>
|
|
250
|
-
<View onLayout={
|
|
252
|
+
<View onLayout={handleLayout} style={[style, styles.scrollView]}>
|
|
251
253
|
<View
|
|
252
254
|
style={[
|
|
253
255
|
{
|
|
@@ -269,7 +271,7 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
269
271
|
cellHeader1={cellHeader1}
|
|
270
272
|
cellHeader2={cellHeader2}
|
|
271
273
|
cellHeaderSingle={cellHeaderSingle}
|
|
272
|
-
onChangeTab={
|
|
274
|
+
onChangeTab={handleChangeTab}
|
|
273
275
|
headerFrom={props.headerFrom}
|
|
274
276
|
headerTo={props.headerTo}
|
|
275
277
|
firstDate={doubleDate.current.first}
|
|
@@ -282,7 +284,7 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
282
284
|
ref={calendarPicker}
|
|
283
285
|
startDate={doubleDate.current.first!}
|
|
284
286
|
endDate={doubleDate.current.second!}
|
|
285
|
-
onDateChange={
|
|
287
|
+
onDateChange={handleDateChange}
|
|
286
288
|
isDoubleDateMode={isDoubleDateMode}
|
|
287
289
|
selectedDate={selectedDate}
|
|
288
290
|
isShowLunar={isShowLunar}
|